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

Generated on Sun Mar 16 01:01:10 2003 for WvStreams by doxygen1.3-rc3