arbeit
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

signalCall.h

Go to the documentation of this file.
00001 /*
00002 * $Id: signalCall.h,v 1.3 2003/09/22 09:28:34 jmk Exp $
00003 */
00004 ///////////////////////////////////////////////////////////////////////////
00005 //              _____________  ______________________    __   __  _____
00006 //             /  ________  |  |   ___   ________   /   |  \ /  \   |
00007 //            |  |       |  |_ |  |_ |  |       /  /    \__  |      |
00008 //            |  |  ___  |  || |  || |  |      /  /        | |      |
00009 //            |  | |   \ |  || |  || |  |     /  /      \__/ \__/ __|__
00010 //            |  | |_@  ||  || |  || |  |    /  /          Institute
00011 //            |  |___/  ||  ||_|  || |  |   /  /_____________________
00012 //             \_______/  \______/ | |__|  /___________________________
00013 //                        |  |__|  |
00014 //                         \______/
00015 //                    University of Utah       
00016 //                           2002
00017 //
00018 // By Joe Kniss, with help from Yarden Livnat
00019 ///////////////////////////////////////////////////////////////////////////
00020 
00021 //signalCall.h
00022 
00023 #ifndef __GUTZ_SIGNAL_CALLS_DOT_H
00024 #define __GUTZ_SIGNAL_CALLS_DOT_H
00025 
00026 #include <iostream>
00027 #include <vector>
00028 
00029 namespace gutz {
00030 
00031 //// there is nothing in this header that should be of concern to users
00032 ////  of the gutz::signals API, you can ignore these classes, they are 
00033 ////  only for internal framework use.  "HAS_SLOTS" is declared in this
00034 ////  file but its use is discussed in <signalGutz.h>.  
00035 
00036 /////////////////////////////////////////////////////////////////////////
00037 /// the "Not Applicable" class, just an empty class for typeing and 
00038 ///  partial specialization... (Nil Argument?? :)
00039 class _NA {};
00040 typedef const _NA NA;
00041 ///
00042 /////////////////////////////////////////////////////////////////////////
00043 
00044 /// forward decl
00045 class SignalIF;
00046 /// ignore this! it is the name of a member variable in
00047 ///   classes supporting slots, used with HAS_SLOTS, and 
00048 ///   in "calls" to access the member variable.
00049 #define G_SIG_TRACK _sigtrack_
00050 
00051 /////////////////////////////////////////////////////////////////////////
00052 ///  Signal Tracker...
00053 /// Users can ignore this class, NOT FOR GENERAL USE.
00054 /// just some framework stuff related to insuring that
00055 /// when an object deletes, we don't get seg faults because
00056 /// a signal didn't know about it.
00057 ///
00058 /// TODO: need to figure out how to copy signals!
00059 ///
00060 ///  This system works if an instance SignalTracker is declared in
00061 ///    a class recieving signals (has slots), since this object is destructed
00062 ///    with the owning object it will detatch all signals it recieves. 
00063 ///    This way, when an object with slots destructs, we won't get runtime
00064 ///    seg-faults when a signal is sent to an object that no longer exists.
00065 ///  This is why we have #HAS_SLOTS, it adds one of these to the class 
00066 ///    with a specific variable name that _Call will use when it is constructed.
00067 class SignalTracker {
00068 public:
00069    typedef std::vector<SignalIF*>  SignalPVec;
00070    typedef SignalPVec::iterator    SignalPVecIter;
00071 
00072    SignalTracker() {}
00073    SignalTracker(const SignalTracker &st) {}
00074    SignalTracker &operator=(const SignalTracker &st) {}
00075    ~SignalTracker();
00076    
00077    /// detach a signal 
00078    void detatchSignalIF(SignalIF *sig);
00079    void attachSignalIF(SignalIF *sig)
00080    { _sigs.push_back(sig); }
00081 
00082    void *callee;
00083 protected:
00084    SignalPVec _sigs;   
00085 };
00086 
00087 /////////////////////////////////////////////////////////////////////////
00088 /// if you use slots (functions called by signals) you must have:
00089 /// HAS_SLOTS; 
00090 /// inside the class, example:
00091 ///
00092 /// class myClass {
00093 /// public:
00094 ///    HAS_SLOTS;
00095 /// }
00096 ///
00097 /// Maybe we can all agree that this is better than requiring a 
00098 ///  baseclass just for supporting slots!
00099 /////////////////////////////////////////////////////////////////////////
00100 
00101 #define HAS_SLOTS  gutz::SignalTracker G_SIG_TRACK;
00102 
00103 /////////////////////////////////////////////////////////////////////////
00104 /////////////////////////////////////////////////////////////////////////
00105 /// The rest of this is also NOT FOR GENERAL USE, it is used in the 
00106 ///   signals & slots framework...
00107 /////////////////////////////////////////////////////////////////////////
00108 /////////////////////////////////////////////////////////////////////////
00109 
00110 /////////////////////////////////////////////////////////////////////////
00111 /// the call interface, to get rid of a few irrelevant types imposed by
00112 ///  the (more) concrete version below so that the Signal can keep a 
00113 ///  list/vector of these.  The number of arguments in the "call" classes
00114 ///  should match the number supported by signals.
00115 template<class A1,class A2,class A3,class A4,
00116          class A5,class A6,class A7,class A8>
00117 class _CallIF {
00118 public:
00119    typedef A1 Arg1;
00120 
00121    virtual ~_CallIF() {}
00122    virtual void call(A1,A2,A3,A4,A5,A6,A7,A8) = 0;
00123    virtual void detatch(SignalIF *sig) = 0;
00124    virtual bool isCallee(void const *callee) const = 0;
00125    virtual bool isCall(_CallIF const *) const = 0;
00126    int _p;
00127 protected:
00128    _CallIF(int priority) : _p(priority) {}
00129 
00130 };
00131 
00132 //////////////////////////////////////////////////////////////
00133 /// an intermediate class so that we can speciallize one for the "call" function
00134 ///  based on types.  Needed since we will get compile errors if we declare a 
00135 ///  call() function with the wrong number of parameters, even if it is never
00136 ///  used.  (this is likely only an issue with some compilers but... need to support
00137 ///  at least a few of them :)
00138 template<class CE,class F,class A1,class A2,class A3,class A4,
00139                           class A5,class A6,class A7,class A8>
00140 class _Call : public _CallIF<A1,A2,A3,A4,A5,A6,A7,A8> {
00141 public:
00142    typedef _CallIF<A1,A2,A3,A4,A5,A6,A7,A8> btype;
00143 
00144    _Call(CE *callee, F fptr, int priority, SignalIF *sig) 
00145       : btype(priority), _func(fptr), _callee(callee) 
00146    {
00147       /// if your compilation is dying here, this means
00148       /// that you forgot to add:
00149       /// HAS_SLOTS
00150       /// to a class that is recieving signals, ie has
00151       /// member functions that behave as slots.  The
00152       /// type of template parameter "CE" is the class 
00153       /// that needs HAS_SLOTS in its declaration.
00154       callee->G_SIG_TRACK.attachSignalIF(sig);
00155       /// sucks, but have to set this here since we don't want
00156       /// users bothered with the SignalTrackers constructor,
00157       /// I don't trust those diry users! :P
00158       callee->G_SIG_TRACK.callee = callee;
00159    }
00160    /// this one is just for creating a Call for comparisons
00161    ///  This class, by itself, doesn't implement the necessary
00162    ///  "call" function, the "Call" class below does.
00163    _Call(CE *callee, F fptr)
00164       : btype(0), _func(fptr), _callee(callee)
00165    {}
00166    ~_Call() {}
00167    
00168    /// this should NEVER be called, I implemented it so
00169    /// you can create a dummy _Call for comparisons, needed
00170    /// to delete a call by disconnect() from the Signal level.
00171    /// If you are creating one of these to actually be called,
00172    /// you need to create a "Call" instead!!!
00173    virtual void call(A1,A2,A3,A4,A5,A6,A7,A8) {};
00174 
00175    void detatch(SignalIF *sig)
00176    {
00177       _callee->G_SIG_TRACK.detatchSignalIF(sig);
00178    }
00179    bool isCallee(void const *callee) const
00180    {
00181       return _callee == callee; 
00182    }
00183    bool isCall(_CallIF<A1,A2,A3,A4,A5,A6,A7,A8> const *c) const
00184    {
00185       _Call const *tc = dynamic_cast<_Call<CE,F,A1,A2,A3,A4,A5,A6,A7,A8> const *>(c);
00186       if(!tc)
00187          return false;
00188       return (tc->_callee == _callee) && (tc->_func == _func);
00189    }
00190   
00191 
00192    CE *_callee;
00193    F   _func;
00194 };
00195 
00196 //////////////////////////////////////////////////////////////
00197 //////////////////////////////////////////////////////////////
00198 //// declaration of Call, with implementation for 8 parameters
00199 //////////////////////////////////////////////////////////////
00200 //////////////////////////////////////////////////////////////
00201 template<class CE,class F, 
00202          class A1,class A2,class A3,class A4,
00203          class A5,class A6,class A7,class A8>
00204 class Call : public _Call<CE,F,A1,A2,A3,A4,A5,A6,A7,A8>
00205 {
00206 public:
00207    typedef _Call<CE,F,A1,A2,A3,A4,A5,A6,A7,A8> btype;
00208    Call(CE *callee, F fptr, int priority, SignalIF *sig)
00209       : btype(callee,fptr,priority,sig) 
00210    {}
00211 
00212    void call(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8)
00213    {
00214       (_callee->*_func)(a1,a2,a3,a4,a5,a6,a7,a8);
00215    }
00216 };
00217 
00218 //////////////////////////////////////////////////////////////
00219 /// implement/specialize call with 0 parameters
00220 template<class CE, class F>
00221 class Call<CE,F,NA,NA,NA,NA,NA,NA,NA,NA> 
00222    : public _Call<CE,F,NA,NA,NA,NA,NA,NA,NA,NA>
00223 {
00224 public:
00225    typedef _Call<CE,F,NA,NA,NA,NA,NA,NA,NA,NA> btype;
00226    Call(CE *callee, F fptr, int priority, SignalIF *sig)
00227       : btype(callee,fptr,priority,sig) 
00228    {}
00229 
00230    void call(NA,NA,NA,NA,NA,NA,NA,NA)
00231    {
00232       (_callee->*_func)();
00233    }
00234 };
00235 
00236 //////////////////////////////////////////////////////////////
00237 /// implement/specialize Call with 1 parameter
00238 template<class CE,class F,class A1>
00239 class Call<CE,F,A1,NA,NA,NA,NA,NA,NA,NA> 
00240    : public _Call<CE,F,A1,NA,NA,NA,NA,NA,NA,NA>
00241 {
00242 public:
00243    typedef _Call<CE,F,A1,NA,NA,NA,NA,NA,NA,NA> btype;
00244    Call(CE *callee, F fptr, int priority, SignalIF *sig)
00245       : btype(callee,fptr,priority,sig) 
00246    {}
00247 
00248    void call(A1 a1,NA,NA,NA,NA,NA,NA,NA)
00249    {
00250       (_callee->*_func)(a1);
00251    }
00252 };
00253 
00254 //////////////////////////////////////////////////////////////
00255 /// implement/specialize Call with 2 parameters
00256 template<class CE,class F,class A1,class A2>
00257 class Call<CE,F,A1,A2,NA,NA,NA,NA,NA,NA> 
00258    : public _Call<CE,F,A1,A2,NA,NA,NA,NA,NA,NA>
00259 {
00260 public:
00261    typedef _Call<CE,F,A1,A2,NA,NA,NA,NA,NA,NA> btype;
00262    Call(CE *callee, F fptr, int priority, SignalIF *sig)
00263       : btype(callee,fptr,priority,sig) 
00264    {}
00265 
00266    void call(A1 a1,A2 a2,NA,NA,NA,NA,NA,NA)
00267    {
00268       (_callee->*_func)(a1,a2);
00269    }
00270 };
00271 
00272 //////////////////////////////////////////////////////////////
00273 /// implement/specialize Call with 3 parameters
00274 template<class CE,class F,class A1,class A2,class A3>
00275 class Call<CE,F,A1,A2,A3,NA,NA,NA,NA,NA> 
00276    : public _Call<CE,F,A1,A2,A3,NA,NA,NA,NA,NA>
00277 {
00278 public:
00279    typedef _Call<CE,F,A1,A2,A3,NA,NA,NA,NA,NA> btype;
00280    Call(CE *callee, F fptr, int priority, SignalIF *sig)
00281       : btype(callee,fptr,priority,sig) 
00282    {}
00283 
00284    void call(A1 a1,A2 a2,A3 a3,NA,NA,NA,NA,NA)
00285    {
00286       (_callee->*_func)(a1,a2,a3);
00287    }
00288 };
00289 
00290 //////////////////////////////////////////////////////////////
00291 /// implement/specialize Call with 4 parameters
00292 template<class CE,class F,class A1,class A2,class A3,class A4>
00293 class Call<CE,F,A1,A2,A3,A4,NA,NA,NA,NA> 
00294    : public _Call<CE,F,A1,A2,A3,A4,NA,NA,NA,NA>
00295 {
00296 public:
00297    typedef _Call<CE,F,A1,A2,A3,A4,NA,NA,NA,NA> btype;
00298    Call(CE *callee, F fptr, int priority, SignalIF *sig)
00299       : btype(callee,fptr,priority,sig) 
00300    {}
00301 
00302    void call(A1 a1,A2 a2,A3 a3,A4 a4,NA,NA,NA,NA)
00303    {
00304       (_callee->*_func)(a1,a2,a3,a4);
00305    }
00306 };
00307 
00308 //////////////////////////////////////////////////////////////
00309 /// implement/specialize Call with 5 parameters
00310 template<class CE,class F,class A1,class A2,class A3,class A4,
00311                           class A5>
00312 class Call<CE,F,A1,A2,A3,A4,A5,NA,NA,NA> 
00313    : public _Call<CE,F,A1,A2,A3,A4,A5,NA,NA,NA>
00314 {
00315 public:
00316    typedef _Call<CE,F,A1,A2,A3,A4,A5,NA,NA,NA> btype;
00317    Call(CE *callee, F fptr, int priority, SignalIF *sig)
00318       : btype(callee,fptr,priority,sig) 
00319    {}
00320 
00321    void call(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,NA,NA,NA)
00322    {
00323       (_callee->*_func)(a1,a2,a3,a4,a5);
00324    }
00325 };
00326 
00327 //////////////////////////////////////////////////////////////
00328 /// implement/specialize Call with 6 parameters
00329 template<class CE,class F,class A1,class A2,class A3,class A4,
00330                           class A5,class A6>
00331 class Call<CE,F,A1,A2,A3,A4,A5,A6,NA,NA> 
00332    : public _Call<CE,F,A1,A2,A3,A4,A5,A6,NA,NA>
00333 {
00334 public:
00335    typedef _Call<CE,F,A1,A2,A3,A4,A5,A6,NA,NA> btype;
00336    Call(CE *callee, F fptr, int priority, SignalIF *sig)
00337       : btype(callee,fptr,priority,sig) 
00338    {}
00339 
00340    void call(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,NA,NA)
00341    {
00342       (_callee->*_func)(a1,a2,a3,a4,a5,a6);
00343    }
00344 };
00345 
00346 //////////////////////////////////////////////////////////////
00347 /// implement/specialize Call with 7 parameters
00348 template<class CE,class F,class A1,class A2,class A3,class A4,
00349                           class A5,class A6,class A7>
00350 class Call<CE,F,A1,A2,A3,A4,A5,A6,A7,NA> 
00351    : public _Call<CE,F,A1,A2,A3,A4,A5,A6,A7,NA>
00352 {
00353 public:
00354    typedef _Call<CE,F,A1,A2,A3,A4,A5,A6,A7,NA> btype;
00355    Call(CE *callee, F fptr, int priority, SignalIF *sig)
00356       : btype(callee,fptr,priority,sig) 
00357    {}
00358 
00359    void call(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,NA)
00360    {
00361       (_callee->*_func)(a1,a2,a3,a4,a5,a6,a7);
00362    }
00363 };
00364 
00365 /// 8 parameters already defined in the declaration of Call!
00366 
00367 } //< end namespace gutz
00368 
00369 #endif
00370 
00371 

Send questions, comments, and bug reports to:
jmk