Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

wvcallback.h

Go to the documentation of this file.
00001 /*
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
00004  */
00005 #ifndef __WVCALLBACK_H
00006 #define __WVCALLBACK_H
00007 
00008 // the templated base class for WvCallback.  All the other callback classes
00009 // come from this somehow.
00010 template <class RET>
00011 class WvCallbackBase
00012 {
00013 protected:
00014 public:
00015     // Fake is a boring object type that we use for calling our "generic"
00016     // member function pointers.  Strangely, it crashes if Fake doesn't
00017     // have a virtual table, so we have an empty virtual function to make it
00018     // happy.  (This is all a bit evil, but only because C++ sucks.  When
00019     // they pass me a callback, they _know_ which function I want to call; I
00020     // don't need to resolve it at runtime...)
00021     struct Fake { virtual void silly() {} };
00022     
00023     // FakeFunc is a completely generic member-function pointer.  Actually the
00024     // functions we _really_ call aren't part of the Fake class and probably
00025     // have different parameters, but some hideous typecasts should fix that
00026     // right up.
00027     typedef RET (Fake::*FakeFunc)();
00028     typedef RET (*FakeGlobalFunc)();
00029     
00030     Fake *obj;
00031     
00032     union {
00033         FakeFunc func;
00034         FakeGlobalFunc globalfunc;
00035     };
00036     
00037     WvCallbackBase::WvCallbackBase(void *_obj, FakeFunc _func)
00038         : obj((Fake *)_obj), func(_func)
00039         { }
00040     
00041     WvCallbackBase::WvCallbackBase(FakeGlobalFunc _func)
00042         : obj(0), globalfunc(_func)
00043         { }
00044     
00045     bool operator== (const WvCallbackBase &cb) const
00046         { if (obj)
00047             return obj==cb.obj && func==cb.func;
00048           else
00049             return !cb.obj && globalfunc == cb.globalfunc;
00050         }
00051     
00052     operator bool () const
00053         { return obj || globalfunc; }
00054 };
00055 
00056 
00057 // Declare WvCallback#, an object derived from WvCallbackBase that takes
00058 // n parameters.  This macro is mainly for use later in this header
00059 // file, to avoid duplicated code.  It's supposed to be part of a template
00060 // declaration - be careful!
00061 #define __MakeWvCallback(n, decls, parms) \
00062     class WvCallback##n : public WvCallbackBase<RET> \
00063     { \
00064     protected: \
00065     public: \
00066         typedef RET (Fake::*Func) decls; \
00067         typedef RET (*GlobalFunc) decls; \
00068         WvCallback##n(Fake *_obj, Func _func) \
00069             : WvCallbackBase<RET>(_obj, (FakeFunc)_func) { } \
00070         WvCallback##n(GlobalFunc _func) \
00071             : WvCallbackBase<RET>((FakeGlobalFunc)_func) { } \
00072     public: \
00073         RET operator() decls  \
00074             { \
00075               if (obj) \
00076                 return ((*obj).*(Func)func) parms; \
00077               else \
00078                 return ((GlobalFunc)globalfunc) parms; \
00079             } \
00080     }
00081 
00082 // Derive WvCallback#_bound, an actual instance of WvCallback# that has a
00083 // particular object type.  This macro is mainly for use later in this header
00084 // file, to avoid duplicated code.
00085 // 
00086 // Note: normally I don't like the silly C++ casting operators, but
00087 // changing a normal typecast to reinterpret_cast<Func> below makes a _huge_
00088 // improvement in code size.  (g++ 2.95.4)
00089 #define __MakeWvBoundCallback(n, decls, basetype...) \
00090     class WvCallback##n##_bound : public basetype \
00091     { \
00092     public: \
00093         typedef RET (T::*BoundFunc) decls; \
00094         WvCallback##n##_bound(T &_obj, BoundFunc _func) \
00095             : basetype((Fake *)&_obj, reinterpret_cast<Func>(_func)) { } \
00096     }
00097 
00098 
00099 // declare WvCallback# and WvCallback#_bound classes for 0 through 6
00100 // parameters (we can add more parameters later, if necessary, by adding
00101 // more declarations below)
00102 
00103 template <class RET>
00104     __MakeWvCallback(0, (), ());
00105 template <class RET, class T>
00106     __MakeWvBoundCallback(0, (), WvCallback0<RET>);
00107 
00108 template <class RET, class P1>
00109     __MakeWvCallback(1, (P1 p1), (p1));
00110 template <class RET, class T, class P1>
00111     __MakeWvBoundCallback(1, (P1 p1), WvCallback1<RET, P1>);
00112 
00113 template <class RET, class P1, class P2>
00114     __MakeWvCallback(2, (P1 p1, P2 p2), (p1, p2));
00115 template <class RET, class T, class P1, class P2>
00116     __MakeWvBoundCallback(2, (P1 p1, P2 p2), WvCallback2<RET, P1, P2>);
00117 
00118 template <class RET, class P1, class P2, class P3>
00119     __MakeWvCallback(3, (P1 p1, P2 p2, P3 p3), (p1, p2, p3));
00120 template <class RET, class T, class P1, class P2, class P3>
00121     __MakeWvBoundCallback(3, (P1 p1, P2 p2, P3 p3),
00122                           WvCallback3<RET, P1, P2, P3>);
00123 
00124 template <class RET, class P1, class P2, class P3, class P4>
00125     __MakeWvCallback(4, (P1 p1, P2 p2, P3 p3, P4 p4), (p1, p2, p3, p4));
00126 template <class RET, class T, class P1, class P2, class P3, class P4>
00127     __MakeWvBoundCallback(4, (P1 p1, P2 p2, P3 p3, P4 p4),
00128                           WvCallback4<RET, P1, P2, P3, P4>);
00129 
00130 template <class RET, class P1, class P2, class P3, class P4, class P5>
00131     __MakeWvCallback(5, (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5),
00132                      (p1, p2, p3, p4, p5));
00133 template <class RET, class T, class P1, class P2, class P3, class P4, class P5>
00134     __MakeWvBoundCallback(5, (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5),
00135                           WvCallback5<RET, P1, P2, P3, P4, P5>);
00136 
00137 template <class RET, class P1, class P2, class P3, class P4, class P5, class P6>
00138     __MakeWvCallback(6, (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6),
00139                      (p1, p2, p3, p4, p5, p6));
00140 template <class RET, class T, class P1, class P2, class P3, class P4, class P5,
00141                 class P6>
00142     __MakeWvBoundCallback(6, (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6),
00143                           WvCallback6<RET, P1, P2, P3, P4, P5, P6>);
00144 
00145 
00146 // DeclareWvCallback is how you create a new type of callback.  The options
00147 // are:
00148 //    n - the number of parameters the callback takes (only 0..4 are allowed)
00149 //    ret - the return value of the callback
00150 //    type - the name of the callback type
00151 //    parms... - the types of the parameters.  There are 'n' of these.
00152 // 
00153 // Example:
00154 //     DeclareWvCallback(3, void, TriCallback, Object*, Blob&, bool);
00155 //     
00156 // NOTE!!
00157 // 
00158 // For some reason, running this inside a class definition causes an internal
00159 // compiler error (g++ 2.95.4).  So you'll have to declare your callbacks
00160 // at the top level, rather than inside your class where it might seem to
00161 // make more sense.  Oh well, at least it's less typing that way...
00162 // 
00163 #define DeclareWvCallback(n, ret, type, parms...) \
00164     typedef WvCallback##n<ret , ## parms> type; \
00165     \
00166     template <class T> \
00167         class type##_bound : public WvCallback##n##_bound<ret,T , ## parms> \
00168         { \
00169         public: \
00170             type##_bound(T &_obj, BoundFunc _func) \
00171                 : WvCallback##n##_bound<ret,T , ## parms>(_obj, _func) {} \
00172         }
00173 
00174 // Use wvcallback() to actually generate a new callback object, given the
00175 // callback type, object type, and member function.  The callback type needs
00176 // to have been declared earlier with DeclareWvCallback.
00177 // 
00178 // Example:
00179 //     CallBackType cb = wvcallback(CallbackType, myobject, MyObject::Func);
00180 //     
00181 // You can pass the result of this call to anything that's expecting a
00182 // callback of the appropriate type; you don't need to actually create the
00183 // object first.
00184 // 
00185 #define wvcallback(cbname, instance, func) \
00186     cbname##_bound<typeof(instance)>(instance, &func)
00187 
00188 
00189 // Some types of callbacks are so common we'll just declare them here.
00190 
00191 DeclareWvCallback(0, void, VoidCallback);
00192 
00193 
00194 #endif // __WVCALLBACK_H

Generated on Sat Aug 24 21:09:33 2002 for WvStreams by doxygen1.2.15