Main Page | Alphabetical List | Class List | File List | Class Members | File Members

/home/bastiaan/D/project/dcouple/trunk/managed/dcouple/signal.d

Go to the documentation of this file.
00001 /* 00002 00003 Copyright 2004 Bastiaan Veelo 00004 00005 This file is part of dcouple. 00006 00007 Dcouple is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 2 of the License, or 00010 (at your option) any later version. 00011 00012 You are free to negociate a different license with the copyright holder. 00013 00014 Dcouple is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 GNU General Public License for more details. 00018 00019 You should have received a copy of the GNU General Public License 00020 along with dcouple; if not, write to the Free Software 00021 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 00023 Some concepts in this file were inspired by Andy Friesen's listener.d 00024 (http://andy.tadan.us/d/listener.d). 00025 00026 */ 00027 00028 module dcouple.signal; 00029 00030 private import dcouple.slot; 00031 private import dcouple.signalslot; 00032 00033 /+ 00035 00036 interface SignalManager 00037 { 00045 void register(GenericSignal); 00046 } 00047 +/ 00048 00050 //interface GenericSignal 00051 class GenericSignal 00052 { 00054 00055 //void disconnect(); 00056 void disconnect() {} 00057 SignalSlotManager owner() { return null; } 00058 00059 void genericConnect(GenericSlot s) {} 00060 void genericDisconnect(GenericSlot s) {} 00061 00062 uint numberOfArguments() {return 0;} 00063 char[][] arguments() {return DUMMYarguments;} 00064 private: 00065 char[][] DUMMYarguments; // Remove this when we can be an interface. 00066 } 00067 00068 00070 private template SignalGenericCore() { 00072 00075 //this(SignalManager owner) 00076 this(SignalSlotManager owner) 00077 { 00078 _owner = owner; 00079 owner.register(this); 00080 initArguments(); 00081 } 00082 00084 00088 ~this() 00089 { 00090 disconnect(); 00091 /* Strictly spoken, destructors are not allowed to reference 00092 other objects, because the order in which the GC calls 00093 destructors is not defined, so those objects may not exist 00094 anymore. The disconnect() function above breaks this rule 00095 indirectly. But this particular case is OK, because we only 00096 consider references to CompatibleSlots that *are still alive*. 00097 Slots that are already destructed have removed our reference to 00098 them, just like we have removed references to us in other slots 00099 in disconnect(). */ 00100 } 00101 00105 void connect(CompatibleSlot s) 00106 { 00107 if(s in _slots) {} else { 00108 _slots[s] = s; 00109 s.connect(this); 00110 } 00111 } 00112 00113 void genericConnect(GenericSlot gs) 00114 { 00115 CompatibleSlot s = cast(CompatibleSlot) gs; 00116 if( s ) { 00117 connect(s); 00118 } else { 00119 printf("dcouple WARNING: %.*s.%.*s!(", 00120 _owner.classinfo.name, this.classinfo.name); 00121 if(numberOfArguments()>0) printf("%.*s",arguments()[0]); 00122 for(int i=1; i<numberOfArguments();i++) 00123 printf(",%.*s",arguments()[i]); 00124 printf(") is incompatible with %.*s.%.*s!(", 00125 gs.owner().classinfo.name, gs.classinfo.name); 00126 if(gs.numberOfArguments()>0) 00127 printf("%.*s",gs.arguments()[0]); 00128 for(int i=1; i<gs.numberOfArguments();i++) 00129 printf(",%.*s",gs.arguments()[i]); 00130 printf("); not connected. (Sorry, no line number...)\n"); 00131 } 00132 } 00133 00137 void disconnect(CompatibleSlot s) 00138 { 00139 if(s in _slots) { 00140 delete _slots[s]; 00141 s.disconnect(this); 00142 } 00143 } 00144 00145 void genericDisconnect(GenericSlot gs) 00146 { 00147 CompatibleSlot s = cast(CompatibleSlot) gs; 00148 if( s ) { 00149 disconnect(s); 00150 } else { 00151 printf("dcouple WARNING: %.*s.%.*s!(", 00152 _owner.classinfo.name, this.classinfo.name); 00153 if(numberOfArguments()>0) printf("%.*s",arguments()[0]); 00154 for(int i=1; i<numberOfArguments();i++) 00155 printf(",%.*s",arguments()[i]); 00156 printf(") is incompatible with %.*s.%.*s!(", 00157 gs.owner().classinfo.name, gs.classinfo.name); 00158 if(gs.numberOfArguments()>0) 00159 printf("%.*s",gs.arguments()[0]); 00160 for(int i=1; i<gs.numberOfArguments();i++) 00161 printf(",%.*s",gs.arguments()[i]); 00162 printf("); not disconnected. (Sorry, no line " 00163 "number...)\n"); 00164 } 00165 } 00166 00168 00169 void disconnect() 00170 { 00171 foreach(CompatibleSlot s; _slots) disconnect(s); 00172 } 00173 00175 int count() { 00176 return _slots.length; 00177 } 00178 00179 uint numberOfArguments() 00180 { 00181 return _arguments.length; 00182 } 00183 00184 char[][] arguments() {return _arguments;} 00185 00186 SignalSlotManager owner() { return _owner; } 00187 private: 00189 //SignalManager _owner; 00190 SignalSlotManager _owner; 00191 protected: 00193 CompatibleSlot[CompatibleSlot] _slots; // Crashes. 00194 char[][] _arguments; 00195 } 00196 00198 00202 class Signal() : GenericSignal 00203 { 00204 alias Slot!() CompatibleSlot; 00205 mixin SignalGenericCore; 00206 00208 void emit() 00209 { 00210 foreach( CompatibleSlot s; _slots ) s(); 00211 } 00212 00213 void initArguments() {} 00214 } 00215 00216 class Signal(T1) : GenericSignal 00217 { 00218 alias Slot!(T1) CompatibleSlot; 00219 mixin SignalGenericCore; 00220 00222 void emit(T1 t1) 00223 { 00224 foreach( CompatibleSlot s; _slots ) s(t1); 00225 } 00226 00227 void initArguments() 00228 { 00229 _arguments ~= typeid(T1).toString(); 00230 } 00231 } 00232 00233 class Signal(T1,T2) : GenericSignal 00234 { 00235 alias Slot!(T1,T2) CompatibleSlot; 00236 mixin SignalGenericCore; 00237 00239 void emit(T1 t1, T2 t2) 00240 { 00241 foreach( CompatibleSlot s; _slots ) s(t1, t2); 00242 } 00243 00244 void initArguments() 00245 { 00246 _arguments ~= typeid(T1).toString(); 00247 _arguments ~= typeid(T2).toString(); 00248 } 00249 } 00250 00251 class Signal(T1,T2,T3) : GenericSignal 00252 { 00253 alias Slot!(T1,T2,T3) CompatibleSlot; 00254 mixin SignalGenericCore; 00255 00257 void emit(T1 t1, T2 t2, T3 t3) 00258 { 00259 foreach( CompatibleSlot s; _slots ) s(t1, t2, t3); 00260 } 00261 00262 void initArguments() 00263 { 00264 _arguments ~= typeid(T1).toString(); 00265 _arguments ~= typeid(T2).toString(); 00266 _arguments ~= typeid(T3).toString(); 00267 } 00268 } 00269 00270 class Signal(T1,T2,T3,T4) : GenericSignal 00271 { 00272 alias Slot!(T1,T2,T3,T4) CompatibleSlot; 00273 mixin SignalGenericCore; 00274 00276 void emit(T1 t1, T2 t2, T3 t3, T4 t4) 00277 { 00278 foreach( CompatibleSlot s; _slots ) s(t1, t2, t3, t4); 00279 } 00280 00281 void initArguments() 00282 { 00283 _arguments ~= typeid(T1).toString(); 00284 _arguments ~= typeid(T2).toString(); 00285 _arguments ~= typeid(T3).toString(); 00286 _arguments ~= typeid(T4).toString(); 00287 } 00288 } 00289 00290 class Signal(T1,T2,T3,T4,T5) : GenericSignal 00291 { 00292 alias Slot!(T1,T2,T3,T4,T5) CompatibleSlot; 00293 mixin SignalGenericCore; 00294 00296 void emit(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) 00297 { 00298 foreach( CompatibleSlot s; _slots ) s(t1, t2, t3, t4, t5); 00299 } 00300 00301 void initArguments() 00302 { 00303 _arguments ~= typeid(T1).toString(); 00304 _arguments ~= typeid(T2).toString(); 00305 _arguments ~= typeid(T3).toString(); 00306 _arguments ~= typeid(T4).toString(); 00307 _arguments ~= typeid(T5).toString(); 00308 } 00309 } 00310 00311 class Signal(T1,T2,T3,T4,T5,T6) : GenericSignal 00312 { 00313 alias Slot!(T1,T2,T3,T4,T5,T6) CompatibleSlot; 00314 mixin SignalGenericCore; 00315 00317 void emit(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) 00318 { 00319 foreach( CompatibleSlot s; _slots ) s(t1, t2, t3, t4, t5, t6); 00320 } 00321 00322 void initArguments() 00323 { 00324 _arguments ~= typeid(T1).toString(); 00325 _arguments ~= typeid(T2).toString(); 00326 _arguments ~= typeid(T3).toString(); 00327 _arguments ~= typeid(T4).toString(); 00328 _arguments ~= typeid(T5).toString(); 00329 _arguments ~= typeid(T6).toString(); 00330 } 00331 } 00332 00333 class Signal(T1,T2,T3,T4,T5,T6,T7) : GenericSignal 00334 { 00335 alias Slot!(T1,T2,T3,T4,T5,T6,T7) CompatibleSlot; 00336 mixin SignalGenericCore; 00337 00339 void emit(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) 00340 { 00341 foreach( CompatibleSlot s; _slots ) s(t1, t2, t3, t4, t5, t6, t7); 00342 } 00343 00344 void initArguments() 00345 { 00346 _arguments ~= typeid(T1).toString(); 00347 _arguments ~= typeid(T2).toString(); 00348 _arguments ~= typeid(T3).toString(); 00349 _arguments ~= typeid(T4).toString(); 00350 _arguments ~= typeid(T5).toString(); 00351 _arguments ~= typeid(T6).toString(); 00352 _arguments ~= typeid(T7).toString(); 00353 } 00354 }

Generated on Fri Sep 17 05:50:08 2004 for dcouple by doxygen 1.3.8