Mercurial > projects > qtd
comparison qt/d1/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 |
---|---|
856 { | 856 { |
857 return sh.slotCount(signalId); | 857 return sh.slotCount(signalId); |
858 } | 858 } |
859 } | 859 } |
860 | 860 |
861 template CheckSlot(Slot, A...) | |
862 { | |
863 static assert(ParameterTupleOf!(Slot).length <= A.length, "Slot " ~ ParameterTypeTuple!(Slot).stringof ~ | |
864 " has more prameters than signal " ~ A.stringof); | |
865 alias CheckSlotImpl!(Slot, 0, A) check; | |
866 } | |
867 | |
868 template CheckSlotImpl(Slot, int i, A...) | |
869 { | |
870 alias ParameterTupleOf!(Slot) SlotArgs; | |
871 static if (i < SlotArgs.length) | |
872 { | |
873 static assert (is(SlotArgs[i] : A[i]), "Argument " ~ __toString(i) ~ | |
874 ":" ~ A[i].stringof ~ " of signal " ~ A.stringof ~ " is not implicitly convertible to parameter " | |
875 ~ SlotArgs[i].stringof ~ " of slot " ~ SlotArgs.stringof); | |
876 alias CheckSlotImpl!(Slot, i + 1, A) next; | |
877 } | |
878 } | |
879 | |
880 public template SignalHandlerOps() | 861 public template SignalHandlerOps() |
881 { | 862 { |
882 static assert (is(typeof(this.signalHandler)), | 863 static assert (is(typeof(this.signalHandler)), |
883 "SignalHandlerOps is already instantiated in " ~ typeof(this).stringof ~ " or one of its base classes"); | 864 "SignalHandlerOps is already instantiated in " ~ typeof(this).stringof ~ " or one of its base classes"); |
884 | 865 |
908 final void unblockSignals() | 889 final void unblockSignals() |
909 { | 890 { |
910 signalHandler.unblockSignals(); | 891 signalHandler.unblockSignals(); |
911 } | 892 } |
912 | 893 |
913 void connect(string signalName, T, R, B...)(T sender, R function(B) dg, ConnectionFlags flags = ConnectionFlags.None) | 894 template connect(string signalName, A...) |
914 { | 895 { |
915 alias findSymbol!(SignalQualifier, T, signalName) sig; | 896 static void connect(T, Func)(T sender, Func func, ConnectionFlags flags = ConnectionFlags.None) |
916 alias CheckSlot!(typeof(fn), sig[2].at) check; | 897 { |
917 auto sh = sender.signalHandler(); | 898 static if (isFnOrDg!(Func)) // D1 has no constraints |
918 auto invoker = Dg(&sh.invokeSlot!(typeof(fn), Fn, sig[2].at)); | 899 { |
919 sh.connect(sig[1], Fn(fn), invoker, flags); | 900 alias findSignal!(T, signalName, Func, A).result sig; |
920 } | 901 auto sh = sender.signalHandler(); |
921 | 902 static if (isFn!(Func)) |
922 void connect(string signalName, T, R, B...)(T sender, R delegate(B) dg, ConnectionFlags flags = ConnectionFlags.None) | 903 alias Fn Callable; |
923 { | 904 else |
924 alias findSymbol!(SignalQualifier, T, signalName) sig; | 905 alias Dg Callable; |
925 alias CheckSlot!(typeof(dg), sig[2].at) check; | 906 auto invoker = Dg(&sh.invokeSlot!(typeof(func), Callable, sig[2..$])); |
926 auto sh = sender.signalHandler(); | 907 sh.connect(sig[1], Callable(func), invoker, flags); |
927 auto invoker = Dg(&sh.invokeSlot!(typeof(dg), Dg, sig[2].at)); | 908 } |
928 sh.connect(sig[1], Dg(dg), invoker, flags); | 909 else |
929 } | 910 { |
930 | 911 static assert(false, "The slot must be a function or delegate type."); |
931 void disconnect(string signalName, T, R, B...)(T sender, R function(B) fn) | 912 } |
932 { | 913 } |
933 alias findSymbol!(SignalQualifier, T, signalName) sig; | 914 } |
934 auto sh = sender.signalHandler(); | 915 |
935 sh.disconnect(sig[1], Fn(fn)); | 916 template disconnect(string signalName, A...) |
936 } | 917 { |
937 | 918 static void connect(T, Func)(T sender, Func func, ConnectionFlags flags = ConnectionFlags.None) |
938 void disconnect(string signalName, T, R, B...)(T sender, R delegate(B) dg) | 919 { |
939 { | 920 static if (isFnOrDg!(Func)) // D1 has no constraints |
940 alias findSymbol!(SignalQualifier, T, signalName) sig; | 921 { |
941 auto sh = sender.signalHandler(); | 922 alias findSignal!(T, signalName, Func, A).result sig; |
942 sh.disconnect(sig[1], Dg(dg)); | 923 auto sh = sender.signalHandler(); |
943 } | 924 static if (isFn!(Func)) |
944 | 925 alias Fn Callable; |
945 debug size_t slotCount(string signalName, T)(T sender) | 926 else |
946 { | 927 alias Dg Callable; |
947 alias findSymbol!(SignalQualifier, T, signalName) sig; | 928 sh.disconnect(sig[1], Callable(func)); |
948 auto sh = sender.signalHandler(); | 929 } |
949 return sh.slotCount(sig[1]); | 930 else |
950 } | 931 { |
932 static assert(false, "The slot must be a function or delegate type."); | |
933 } | |
934 } | |
935 } | |
936 /* | |
937 template slotCount(string signalName, A...) | |
938 { | |
939 debug static void slotCount(T)(T sender) | |
940 { | |
941 alias findSignal!(T, signalName, Func, A).result sig; | |
942 auto sh = sender.signalHandler(); | |
943 return sh.slotCount(sig[1]); | |
944 } | |
945 } | |
946 */ | |
951 } | 947 } |
952 | 948 |
953 /** | 949 /** |
954 New implementation. | 950 New implementation. |
955 */ | 951 */ |
956 | 952 |
957 public bool startsWith(T)(T[] source, T[] pattern) | 953 const string signalPrefix = "__signal"; |
958 { | |
959 return source.length >= pattern.length && source[0 .. pattern.length] == pattern[]; | |
960 } | |
961 | 954 |
962 template TupleWrapper(A...) { alias A at; } | 955 template TupleWrapper(A...) { alias A at; } |
956 | |
957 template isDg(Dg) | |
958 { | |
959 enum { isDg = is(Dg == delegate) } | |
960 } | |
961 | |
962 template isFn(Fn) | |
963 { | |
964 enum { isFn = is(typeof(*Fn.init) == function) } | |
965 } | |
966 | |
967 template isFnOrDg(Dg) | |
968 { | |
969 enum { isFnOrDg = isFn!(Dg) || isDg!(Dg) } | |
970 } | |
963 | 971 |
964 string joinArgs(A...)() | 972 string joinArgs(A...)() |
965 { | 973 { |
966 string res = ""; | 974 string res = ""; |
967 static if(A.length) | 975 static if(A.length) |
971 res ~= "," ~ k.stringof; | 979 res ~= "," ~ k.stringof; |
972 } | 980 } |
973 return res; | 981 return res; |
974 } | 982 } |
975 | 983 |
976 struct SignalQualifier | 984 template SlotPred(T1, T2) |
977 { | 985 { |
978 const string staticSymbolPrefix = "__signal"; | 986 enum { SlotPred = is(T1 : T2) } |
979 const string name = "signal"; | 987 } |
980 | 988 |
981 static bool matches(alias source, string sigName)() | 989 template CheckSlot(alias Needle, alias Source) |
982 { | 990 { |
983 return startsWith(source.at[0], sigName); | 991 static if(Needle.at.length <= Source.at.length) |
984 } | 992 enum { CheckSlot = CheckArgs!(Needle, Source, SlotPred, 0).value } |
985 } | 993 else |
986 | 994 enum { CheckSlot = false } |
987 template staticSymbolName(Qualifier, int id) | 995 } |
988 { | 996 |
989 const string staticSymbolName = Qualifier.staticSymbolPrefix ~ ToString!(id); | 997 template SignalPred(T1, T2) |
998 { | |
999 enum { SignalPred = is(T1 == T2) } | |
1000 } | |
1001 | |
1002 template CheckSignal(alias Needle, alias Source) | |
1003 { | |
1004 static if(Needle.at.length == Source.at.length) | |
1005 enum { CheckSignal = CheckArgs!(Needle, Source, SignalPred, 0).value } | |
1006 else | |
1007 enum { CheckSignal = false } | |
1008 } | |
1009 | |
1010 template CheckArgs(alias Needle, alias Source, alias pred, int i) | |
1011 { | |
1012 static if (i < Needle.at.length) | |
1013 { | |
1014 static if (pred!(Needle.at[i], Source.at[i])) | |
1015 enum { value = CheckArgs!(Needle, Source, pred, i + 1).value } | |
1016 else | |
1017 enum { value = false } | |
1018 } | |
1019 else | |
1020 { | |
1021 enum { value = true } | |
1022 } | |
1023 } | |
1024 | |
1025 template SigByNamePred(string name, SlotArgs...) | |
1026 { | |
1027 template SigByNamePred(source...) | |
1028 { | |
1029 static if (source[0] == name) // only instantiate CheckSlot if names match | |
1030 enum { SigByNamePred = CheckSlot!(TupleWrapper!(SlotArgs), TupleWrapper!(source[2 .. $])) } | |
1031 else | |
1032 enum { SigByNamePred = false } | |
1033 } | |
1034 } | |
1035 | |
1036 template SigBySignPred(string name, SigArgs...) | |
1037 { | |
1038 template SigBySignPred(source...) | |
1039 { | |
1040 static if (source[0] == name) // only instantiate CheckSignal if names match | |
1041 enum { SigBySignPred = CheckSignal!(TupleWrapper!(SigArgs), TupleWrapper!(source[2 .. $])) } | |
1042 else | |
1043 enum { SigBySignPred = false } | |
1044 } | |
1045 } | |
1046 | |
1047 template staticSymbolName(string prefix, int id) | |
1048 { | |
1049 const string staticSymbolName = prefix ~ ToString!(id); | |
990 } | 1050 } |
991 | 1051 |
992 template signatureString(string name, A...) | 1052 template signatureString(string name, A...) |
993 { | 1053 { |
994 const string signatureString = name ~ "(" ~ joinArgs!(A) ~ ")"; | 1054 const string signatureString = name ~ "(" ~ joinArgs!(A) ~ ")"; |
995 } | 1055 } |
996 | 1056 |
997 template findSymbolImpl(Qualifier, C, int id, string key) | 1057 template findSymbolImpl(string prefix, C, int id, alias pred) |
998 { | 1058 { |
999 static if ( is(typeof(mixin("C." ~ staticSymbolName!(Qualifier, id)))) ) | 1059 static if ( is(typeof(mixin("C." ~ staticSymbolName!(prefix, id)))) ) |
1000 { | 1060 { |
1001 mixin ("alias C." ~ staticSymbolName!(Qualifier, id) ~ " current;"); | 1061 mixin ("alias C." ~ staticSymbolName!(prefix, id) ~ " current;"); |
1002 static if ( Qualifier.matches!(TupleWrapper!(current), key)() ) { | 1062 static if (pred!(current)) |
1003 alias current result; | 1063 alias current result; |
1004 } | |
1005 else | 1064 else |
1006 alias findSymbolImpl!(Qualifier, C, id + 1, key).result result; | 1065 alias findSymbolImpl!(prefix, C, id + 1, pred).result result; |
1007 } | 1066 } |
1008 else | 1067 else |
1009 { | 1068 { |
1010 static assert(0, Qualifier.name ~ " " ~ key ~ " not found."); | 1069 alias void result; |
1011 } | 1070 } |
1012 } | 1071 } |
1013 | 1072 |
1014 template findSymbol(Qualifier, C, string key) | 1073 template findSymbol(string prefix, C, alias pred) |
1015 { | 1074 { |
1016 alias findSymbolImpl!(Qualifier, C, 0, key).result findSymbol; | 1075 alias findSymbolImpl!(prefix, C, 0, pred).result findSymbol; |
1076 } | |
1077 | |
1078 template findSignal(C, string name, Receiver, SigArgs...) | |
1079 { | |
1080 alias TupleWrapper!(ParameterTupleOf!(Receiver)) SlotArgsWr; | |
1081 static if (SigArgs.length > 0) | |
1082 { | |
1083 alias findSymbol!(signalPrefix, C, SigBySignPred!(name, SigArgs)) result; | |
1084 static if (is(result == void)) | |
1085 static assert(0, "Signal " ~ name ~ "(" ~ joinArgs!(SigArgs)() ~ ") was not found."); | |
1086 else | |
1087 static if (!CheckSlot!(SlotArgsWr, TupleWrapper!(result[2 .. $]))) | |
1088 static assert(0, "Signature of slot is incompatible with signal " ~ name ~ "."); | |
1089 } | |
1090 else | |
1091 { | |
1092 alias findSymbol!(signalPrefix, C, SigByNamePred!(name, SlotArgsWr.at)) result; | |
1093 static if (is(result == void)) | |
1094 static assert(0, "Signal " ~ name ~ " was not found."); | |
1095 } | |
1017 } | 1096 } |
1018 | 1097 |
1019 | 1098 |
1020 /** | 1099 /** |
1021 Examples: | 1100 Examples: |
1054 mixin SignalImpl!(0, name, A); | 1133 mixin SignalImpl!(0, name, A); |
1055 } | 1134 } |
1056 | 1135 |
1057 template SignalImpl(int index, string name, A...) | 1136 template SignalImpl(int index, string name, A...) |
1058 { | 1137 { |
1059 static if (is(typeof(mixin(typeof(this).stringof ~ ".__sig" ~ ToString!(index))))) | 1138 static if (is(typeof(mixin(typeof(this).stringof ~ ".__signal" ~ ToString!(index))))) |
1060 mixin SignalImpl!(index + 1, name, A); | 1139 mixin SignalImpl!(index + 1, name, A); |
1061 else | 1140 else |
1062 { | 1141 { |
1063 // mixed-in once | 1142 // mixed-in once |
1064 static if (!is(typeof(this.signalHandler))) | 1143 static if (!is(typeof(this.signalHandler))) |
1065 { | 1144 { |
1066 mixin SignalHandlerOps; | 1145 mixin SignalHandlerOps; |
1067 } | 1146 } |
1068 mixin("private static const int __sig" ~ ToString!(index) ~ " = " ~ ToString!(index) ~ ";"); | 1147 mixin("public alias Tuple!(\"" ~ name ~ "\", index, A) __signal" ~ ToString!(index) ~ ";"); |
1069 // mixin("public alias Tuple!(\"" ~ signatureString!(name, A) ~ "\", index, TupleWrapper!(A)) __signal" ~ ToString!(index) ~ ";"); | |
1070 mixin("SignalOps!(" ~ ToString!(index) ~ ", A) " ~ name ~ "(){ return SignalOps!(" | 1148 mixin("SignalOps!(" ~ ToString!(index) ~ ", A) " ~ name ~ "(){ return SignalOps!(" |
1071 ~ ToString!(index) ~ ", A)(signalHandler); }"); | 1149 ~ ToString!(index) ~ ", A)(signalHandler); }"); |
1072 } | 1150 } |
1073 } | 1151 } |
1074 | 1152 |