comparison qt/d2/qt/Signal.d @ 282:256ab6cb8e85

Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both D1 and D2 versions, D1 won't work because of compiler bugs. I am tired of waiting for fixes.
author eldar
date Fri, 16 Oct 2009 02:43:59 +0000
parents 519befd5a5d1
children 1f6923c8cba0
comparison
equal deleted inserted replaced
281:7f2e3ffa1c33 282:256ab6cb8e85
785 public struct SignalOps(int sigId, A...) 785 public struct SignalOps(int sigId, A...)
786 { 786 {
787 private SignalHandler sh; 787 private SignalHandler sh;
788 enum { signalId = sigId } 788 enum { signalId = sigId }
789 789
790 void connect(R, B...)(R function(B) fn, ConnectionFlags flags = ConnectionFlags.None)
791 {
792 alias CheckSlot!(typeof(fn), A) check;
793 auto invoker = Dg(&sh.invokeSlot!(typeof(fn), Fn, A));
794 sh.connect(signalId, Fn(fn), invoker, flags);
795 }
796
797 void connect(R, B...)(R delegate(B) dg, ConnectionFlags flags = ConnectionFlags.None)
798 {
799 alias CheckSlot!(typeof(dg), A) check;
800 auto invoker = Dg(&sh.invokeSlot!(typeof(dg), Dg, A));
801 sh.connect(signalId, Dg(dg), invoker, flags);
802 }
803
804 void disconnect(R, B...)(R function(B) fn)
805 {
806 sh.disconnect(signalId, Fn(fn));
807 }
808
809 void disconnect(R, B...)(R delegate(B) dg)
810 {
811 sh.disconnect(signalId, Dg(dg));
812 }
813
814 void emit(A args) 790 void emit(A args)
815 { 791 {
816 sh.emit(signalId, args); 792 sh.emit(signalId, args);
817 } 793 }
818 794
819 debug size_t slotCount() 795 debug size_t slotCount()
820 { 796 {
821 return sh.slotCount(signalId); 797 return sh.slotCount(signalId);
822 }
823 }
824
825 template CheckSlot(Slot, A...)
826 {
827 static assert(ParameterTypeTuple!(Slot).length <= A.length, "Slot " ~ ParameterTypeTuple!(Slot).stringof ~
828 " has more prameters than signal " ~ A.stringof);
829 alias CheckSlotImpl!(Slot, 0, A) check;
830 }
831
832 template CheckSlotImpl(Slot, int i, A...)
833 {
834 alias ParameterTypeTuple!(Slot) SlotArgs;
835 static if (i < SlotArgs.length)
836 {
837 static assert (is(SlotArgs[i] : A[i]), "Argument " ~ ToString!(i) ~
838 ":" ~ A[i].stringof ~ " of signal " ~ A.stringof ~ " is not implicitly convertible to parameter "
839 ~ SlotArgs[i].stringof ~ " of slot " ~ SlotArgs.stringof);
840 alias CheckSlotImpl!(Slot, i + 1, A) next;
841 } 798 }
842 } 799 }
843 800
844 public template SignalHandlerOps() 801 public template SignalHandlerOps()
845 { 802 {
872 final void unblockSignals() 829 final void unblockSignals()
873 { 830 {
874 signalHandler.unblockSignals(); 831 signalHandler.unblockSignals();
875 } 832 }
876 833
877 void connect(string signalName, this T, R, B...)(R function(B) dg, ConnectionFlags flags = ConnectionFlags.None) 834 template connect(string signalName, A...)
878 { 835 {
879 alias findSymbol!(SignalQualifier, T, signalName) sig; 836 static void connect(T, Func)(T sender, Func func, ConnectionFlags flags = ConnectionFlags.None)
880 alias CheckSlot!(typeof(fn), sig[2].at) check; 837 if (isFnOrDg!(Func))
881 auto sh = signalHandler(); 838 {
882 auto invoker = Dg(&sh.invokeSlot!(typeof(fn), Fn, sig[2].at)); 839 alias findSignal!(T, signalName, Func, A).result sig;
883 sh.connect(sig[1], Fn(fn), invoker, flags); 840 auto sh = sender.signalHandler();
884 } 841 static if (isFn!(Func))
885 842 alias Fn Callable;
886 void connect(string signalName, this T, R, B...)(R delegate(B) dg, ConnectionFlags flags = ConnectionFlags.None) 843 else
887 { 844 alias Dg Callable;
888 alias findSymbol!(SignalQualifier, T, signalName) sig; 845 auto invoker = Dg(&sh.invokeSlot!(typeof(func), Callable, sig[2..$]));
889 alias CheckSlot!(typeof(dg), sig[2].at) check; 846 sh.connect(sig[1], Callable(func), invoker, flags);
890 auto sh = signalHandler(); 847 }
891 auto invoker = Dg(&sh.invokeSlot!(typeof(dg), Dg, sig[2].at)); 848 }
892 sh.connect(sig[1], Dg(dg), invoker, flags); 849
893 } 850 template disconnect(string signalName, A...)
894 851 {
895 void disconnect(string signalName, this T, R, B...)(R function(B) fn) 852 static void connect(T, Func)(T sender, Func func, ConnectionFlags flags = ConnectionFlags.None)
896 { 853 if (isFnOrDg!(Func))
897 alias findSymbol!(SignalQualifier, T, signalName) sig; 854 {
898 auto sh = signalHandler(); 855 alias findSignal!(T, signalName, Func, A).result sig;
899 sh.disconnect(sig[1], Fn(fn)); 856 auto sh = sender.signalHandler();
900 } 857 static if (isFn!(Func))
901 858 alias Fn Callable;
902 void disconnect(string signalName, this T, R, B...)(R delegate(B) dg) 859 else
903 { 860 alias Dg Callable;
904 alias findSymbol!(SignalQualifier, T, signalName) sig; 861 sh.disconnect(sig[1], Callable(func));
905 auto sh = signalHandler(); 862 }
906 sh.disconnect(sig[1], Dg(dg)); 863 }
907 } 864 /*
908 865 template slotCount(string signalName, A...)
909 debug size_t slotCount(string signalName, this T)() 866 {
910 { 867 debug static void slotCount(T)(T sender)
911 alias findSymbol!(SignalQualifier, T, signalName) sig; 868 {
912 auto sh = signalHandler(); 869 alias findSignal!(T, signalName, Func, A).result sig;
913 return sh.slotCount(sig[1]); 870 auto sh = sender.signalHandler();
914 } 871 return sh.slotCount(sig[1]);
872 }
873 }
874 */
915 } 875 }
916 876
917 /** 877 /**
918 New implementation. 878 New implementation.
919 */ 879 */
920 880
921 public bool startsWith(T)(T[] source, T[] pattern) 881 const string signalPrefix = "__signal";
922 {
923 return source.length >= pattern.length && source[0 .. pattern.length] == pattern[];
924 }
925 882
926 template TupleWrapper(A...) { alias A at; } 883 template TupleWrapper(A...) { alias A at; }
884
885 template isDg(Dg)
886 {
887 enum isDg = is(Dg == delegate);
888 }
889
890 template isFn(Fn)
891 {
892 enum isFn = is(typeof(*Fn.init) == function);
893 }
894
895 template isFnOrDg(Dg)
896 {
897 enum isFnOrDg = isFn!(Dg) || isDg!(Dg);
898 }
927 899
928 string joinArgs(A...)() 900 string joinArgs(A...)()
929 { 901 {
930 string res = ""; 902 string res = "";
931 static if(A.length) 903 static if(A.length)
935 res ~= "," ~ k.stringof; 907 res ~= "," ~ k.stringof;
936 } 908 }
937 return res; 909 return res;
938 } 910 }
939 911
940 struct SignalQualifier 912 template SlotPred(T1, T2)
941 { 913 {
942 const string staticSymbolPrefix = "__signal"; 914 enum SlotPred = is(T1 : T2);
943 const string name = "signal"; 915 }
944 916
945 static bool matches(alias source, string sigName)() 917 template CheckSlot(alias Needle, alias Source)
946 { 918 {
947 return startsWith(source.at[0], sigName); 919 static if(Needle.at.length <= Source.at.length)
948 } 920 enum CheckSlot = CheckArgs!(Needle, Source, SlotPred, 0).value;
949 } 921 else
950 922 enum CheckSlot = false;
951 template staticSymbolName(Qualifier, int id) 923 }
952 { 924
953 const string staticSymbolName = Qualifier.staticSymbolPrefix ~ ToString!(id); 925 template SignalPred(T1, T2)
926 {
927 enum SignalPred = is(T1 == T2);
928 }
929
930 template CheckSignal(alias Needle, alias Source)
931 {
932 static if(Needle.at.length == Source.at.length)
933 enum CheckSignal = CheckArgs!(Needle, Source, SignalPred, 0).value;
934 else
935 enum CheckSignal = false;
936 }
937
938 template CheckArgs(alias Needle, alias Source, alias pred, int i)
939 {
940 static if (i < Needle.at.length)
941 {
942 static if (pred!(Needle.at[i], Source.at[i]))
943 enum value = CheckArgs!(Needle, Source, pred, i + 1).value;
944 else
945 enum value = false;
946 }
947 else
948 {
949 enum value = true;
950 }
951 }
952
953 template SigByNamePred(string name, SlotArgs...)
954 {
955 template SigByNamePred(source...)
956 {
957 static if (source[0] == name) // only instantiate CheckSlot if names match
958 enum SigByNamePred = CheckSlot!(TupleWrapper!(SlotArgs), TupleWrapper!(source[2 .. $]));
959 else
960 enum SigByNamePred = false;
961 }
962 }
963
964 template SigBySignPred(string name, SigArgs...)
965 {
966 template SigBySignPred(source...)
967 {
968 static if (source[0] == name) // only instantiate CheckSignal if names match
969 enum SigBySignPred = CheckSignal!(TupleWrapper!(SigArgs), TupleWrapper!(source[2 .. $]));
970 else
971 enum SigBySignPred = false;
972 }
973 }
974
975 template staticSymbolName(string prefix, int id)
976 {
977 const string staticSymbolName = prefix ~ ToString!(id);
954 } 978 }
955 979
956 template signatureString(string name, A...) 980 template signatureString(string name, A...)
957 { 981 {
958 const string signatureString = name ~ "(" ~ joinArgs!(A) ~ ")"; 982 const string signatureString = name ~ "(" ~ joinArgs!(A) ~ ")";
959 } 983 }
960 984
961 template findSymbolImpl(Qualifier, C, int id, string key) 985 template findSymbolImpl(string prefix, C, int id, alias pred)
962 { 986 {
963 static if ( is(typeof(mixin("C." ~ staticSymbolName!(Qualifier, id)))) ) 987 static if ( is(typeof(mixin("C." ~ staticSymbolName!(prefix, id)))) )
964 { 988 {
965 mixin ("alias C." ~ staticSymbolName!(Qualifier, id) ~ " current;"); 989 mixin ("alias C." ~ staticSymbolName!(prefix, id) ~ " current;");
966 static if ( Qualifier.matches!(TupleWrapper!(current), key)() ) { 990 static if (pred!current)
967 alias current result; 991 alias current result;
968 }
969 else 992 else
970 alias findSymbolImpl!(Qualifier, C, id + 1, key).result result; 993 alias findSymbolImpl!(prefix, C, id + 1, pred).result result;
971 } 994 }
972 else 995 else
973 { 996 {
974 static assert(0, Qualifier.name ~ " " ~ key ~ " not found."); 997 alias void result;
975 } 998 }
976 } 999 }
977 1000
978 template findSymbol(Qualifier, C, string key) 1001 template findSymbol(string prefix, C, alias pred)
979 { 1002 {
980 alias findSymbolImpl!(Qualifier, C, 0, key).result findSymbol; 1003 alias findSymbolImpl!(prefix, C, 0, pred).result findSymbol;
1004 }
1005
1006 template findSignal(C, string name, Receiver, SigArgs...)
1007 {
1008 alias TupleWrapper!(ParameterTypeTuple!Receiver) SlotArgsWr;
1009 static if (SigArgs.length > 0)
1010 {
1011 alias findSymbol!(signalPrefix, C, SigBySignPred!(name, SigArgs)) result;
1012 static if (is(result == void))
1013 static assert(0, "Signal " ~ name ~ "(" ~ joinArgs!SigArgs() ~ ") was not found.");
1014 else
1015 static if (!CheckSlot!(SlotArgsWr, TupleWrapper!(result[2 .. $])))
1016 static assert(0, "Signature of slot is incompatible with signal " ~ name ~ ".");
1017 }
1018 else
1019 {
1020 alias findSymbol!(signalPrefix, C, SigByNamePred!(name, SlotArgsWr.at)) result;
1021 static if (is(result == void))
1022 static assert(0, "Signal " ~ name ~ " was not found.");
1023 }
981 } 1024 }
982 1025
983 /** ---------------- */ 1026 /** ---------------- */
984 1027
985 1028
1020 mixin SignalImpl!(0, name, A); 1063 mixin SignalImpl!(0, name, A);
1021 } 1064 }
1022 1065
1023 template SignalImpl(int index, string name, A...) 1066 template SignalImpl(int index, string name, A...)
1024 { 1067 {
1025 static if (is(typeof(mixin(typeof(this).stringof ~ ".__sig" ~ ToString!(index))))) 1068 static if (is(typeof(mixin(typeof(this).stringof ~ ".__signal" ~ ToString!(index)))))
1026 mixin SignalImpl!(index + 1, name, A); 1069 mixin SignalImpl!(index + 1, name, A);
1027 else 1070 else
1028 { 1071 {
1029 // mixed-in once 1072 // mixed-in once
1030 static if (!is(typeof(this.signalHandler))) 1073 static if (!is(typeof(this.signalHandler)))
1031 { 1074 {
1032 mixin SignalHandlerOps; 1075 mixin SignalHandlerOps;
1033 } 1076 }
1034 /* deprecated */ mixin("private static const int __sig" ~ ToString!(index) ~ " = " ~ ToString!(index) ~ ";"); 1077 mixin("public alias TypeTuple!(\"" ~ name ~ "\", index, A) __signal" ~ ToString!(index) ~ ";");
1035 // mixin("public alias TypeTuple!(\"" ~ signatureString!(name, A) ~ "\", index, TupleWrapper!(A)) __signal" ~ ToString!(index) ~ ";");
1036 mixin("SignalOps!(" ~ ToString!(index) ~ ", A) " ~ name ~ "(){ return SignalOps!(" 1078 mixin("SignalOps!(" ~ ToString!(index) ~ ", A) " ~ name ~ "(){ return SignalOps!("
1037 ~ ToString!(index) ~ ", A)(signalHandler); }"); 1079 ~ ToString!(index) ~ ", A)(signalHandler); }");
1038 } 1080 }
1039 } 1081 }
1040 1082