00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #if !defined(INCLUDED_GENERIC_CLOSURE_H)
00028 #define INCLUDED_GENERIC_CLOSURE_H
00029
00030 #include <cstddef>
00031 #include "functional.h"
00032 #include "callbackfwd.h"
00033
00034 template<typename Type>
00035 inline void* convertToOpaque (Type* t)
00036 {
00037 return t;
00038 }
00039 template<typename Type>
00040 inline void* convertToOpaque (const Type* t)
00041 {
00042 return const_cast<Type*> (t);
00043 }
00044 template<typename Type>
00045 inline void* convertToOpaque (Type& t)
00046 {
00047 return &t;
00048 }
00049 template<typename Type>
00050 inline void* convertToOpaque (const Type& t)
00051 {
00052 return const_cast<Type*> (&t);
00053 }
00054
00055 template<typename Type>
00056 class ConvertFromOpaque
00057 {
00058 };
00059
00060 template<typename Type>
00061 class ConvertFromOpaque<Type&>
00062 {
00063 public:
00064 static Type& apply (void* p)
00065 {
00066 return *static_cast<Type*> (p);
00067 }
00068 };
00069
00070 template<typename Type>
00071 class ConvertFromOpaque<const Type&>
00072 {
00073 public:
00074 static const Type& apply (void* p)
00075 {
00076 return *static_cast<Type*> (p);
00077 }
00078 };
00079
00080 template<typename Type>
00081 class ConvertFromOpaque<Type*>
00082 {
00083 public:
00084 static Type* apply (void* p)
00085 {
00086 return static_cast<Type*> (p);
00087 }
00088 };
00089
00090 template<typename Type>
00091 class ConvertFromOpaque<const Type*>
00092 {
00093 public:
00094 static const Type* apply (void* p)
00095 {
00096 return static_cast<Type*> (p);
00097 }
00098 };
00099
00100 template<typename Caller>
00101 class BindFirstOpaque
00102 {
00103 typedef typename Caller::first_argument_type FirstBound;
00104 FirstBound firstBound;
00105 public:
00106 typedef typename Caller::result_type result_type;
00107 explicit BindFirstOpaque (FirstBound firstBound) :
00108 firstBound(firstBound)
00109 {
00110 }
00111 result_type operator() () const
00112 {
00113 return Caller::call(firstBound);
00114 }
00115 FirstBound getBound () const
00116 {
00117 return firstBound;
00118 }
00119 static result_type thunk (void* environment)
00120 {
00121 return Caller::call(ConvertFromOpaque<FirstBound>::apply(environment));
00122 }
00123 void* getEnvironment () const
00124 {
00125 return convertToOpaque(firstBound);
00126 }
00127 };
00128
00129 template<typename Caller>
00130 class BindFirstOpaque1
00131 {
00132 typedef typename Caller::first_argument_type FirstBound;
00133 FirstBound firstBound;
00134 public:
00135 typedef typename Caller::second_argument_type first_argument_type;
00136 typedef typename Caller::result_type result_type;
00137 explicit BindFirstOpaque1 (FirstBound firstBound) :
00138 firstBound(firstBound)
00139 {
00140 }
00141 result_type operator() (first_argument_type a1) const
00142 {
00143 return Caller::call(firstBound, a1);
00144 }
00145 FirstBound getBound () const
00146 {
00147 return firstBound;
00148 }
00149 static result_type thunk (void* environment, first_argument_type a1)
00150 {
00151 return Caller::call(ConvertFromOpaque<FirstBound>::apply(environment), a1);
00152 }
00153 void* getEnvironment () const
00154 {
00155 return convertToOpaque(firstBound);
00156 }
00157 };
00158
00159 template<typename Caller>
00160 class BindFirstOpaque2
00161 {
00162 typedef typename Caller::first_argument_type FirstBound;
00163 FirstBound firstBound;
00164 public:
00165 typedef typename Caller::second_argument_type first_argument_type;
00166 typedef typename Caller::third_argument_type second_argument_type;
00167 typedef typename Caller::result_type result_type;
00168 explicit BindFirstOpaque2 (FirstBound firstBound) :
00169 firstBound(firstBound)
00170 {
00171 }
00172 result_type operator() (first_argument_type a1, second_argument_type a2) const
00173 {
00174 return Caller::call(firstBound, a1, a2);
00175 }
00176 FirstBound getBound () const
00177 {
00178 return firstBound;
00179 }
00180 static result_type thunk (void* environment, first_argument_type a1, second_argument_type a2)
00181 {
00182 return Caller::call(ConvertFromOpaque<FirstBound>::apply(environment), a1, a2);
00183 }
00184 void* getEnvironment () const
00185 {
00186 return convertToOpaque(firstBound);
00187 }
00188 };
00189
00190 template<typename Caller>
00191 class BindFirstOpaque3
00192 {
00193 typedef typename Caller::first_argument_type FirstBound;
00194 FirstBound firstBound;
00195 public:
00196 typedef typename Caller::second_argument_type first_argument_type;
00197 typedef typename Caller::third_argument_type second_argument_type;
00198 typedef typename Caller::fourth_argument_type third_argument_type;
00199 typedef typename Caller::result_type result_type;
00200 explicit BindFirstOpaque3 (FirstBound firstBound) :
00201 firstBound(firstBound)
00202 {
00203 }
00204 result_type operator() (first_argument_type a1, second_argument_type a2, third_argument_type a3) const
00205 {
00206 return Caller::call(firstBound, a1, a2, a3);
00207 }
00208 FirstBound getBound () const
00209 {
00210 return firstBound;
00211 }
00212 static result_type thunk (void* environment, first_argument_type a1, second_argument_type a2,
00213 third_argument_type a3)
00214 {
00215 return Caller::call(ConvertFromOpaque<FirstBound>::apply(environment), a1, a2, a3);
00216 }
00217 void* getEnvironment () const
00218 {
00219 return convertToOpaque(firstBound);
00220 }
00221 };
00222
00223 template<typename Thunk_>
00224 class CallbackBase
00225 {
00226 void* m_environment;
00227 Thunk_ m_thunk;
00228 public:
00229 typedef Thunk_ Thunk;
00230 CallbackBase (void* environment, Thunk function) :
00231 m_environment(environment), m_thunk(function)
00232 {
00233 }
00234 void* getEnvironment () const
00235 {
00236 return m_environment;
00237 }
00238 Thunk getThunk () const
00239 {
00240 return m_thunk;
00241 }
00242 };
00243
00244 template<typename Thunk>
00245 inline bool operator== (const CallbackBase<Thunk>& self, const CallbackBase<Thunk>& other)
00246 {
00247 return self.getEnvironment() == other.getEnvironment() && self.getThunk() == other.getThunk();
00248 }
00249 template<typename Thunk>
00250 inline bool operator!= (const CallbackBase<Thunk>& self, const CallbackBase<Thunk>& other)
00251 {
00252 return !(self == other);
00253 }
00254 template<typename Thunk>
00255 inline bool operator< (const CallbackBase<Thunk>& self, const CallbackBase<Thunk>& other)
00256 {
00257 return self.getEnvironment() < other.getEnvironment() || (!(other.getEnvironment() < self.getEnvironment())
00258 && self.getThunk() < other.getThunk());
00259 }
00260
00265 template<typename Result>
00266 class Callback0: public CallbackBase<Result(*) (void*)>
00267 {
00268 typedef CallbackBase<Result(*) (void*)> Base;
00269 static Result nullThunk (void*)
00270 {
00271 }
00272
00273 public:
00274 typedef Result result_type;
00275
00276 Callback0 () :
00277 Base(0, nullThunk)
00278 {
00279 }
00280 template<typename Caller>
00281 Callback0 (const BindFirstOpaque<Caller>& caller) :
00282 Base(caller.getEnvironment(), BindFirstOpaque<Caller>::thunk)
00283 {
00284 }
00285 Callback0 (void* environment, typename Base::Thunk function) :
00286 Base(environment, function)
00287 {
00288 }
00289 result_type operator() () const
00290 {
00291 return Base::getThunk()(Base::getEnvironment());
00292 }
00293 };
00294
00295 template<typename Caller>
00296 inline Callback0<typename Caller::result_type> makeCallback0 (const Caller& caller,
00297 typename Caller::first_argument_type callee)
00298 {
00299 return Callback0<typename Caller::result_type> (BindFirstOpaque<Caller> (callee));
00300 }
00301 template<typename Caller>
00302 inline Callback0<typename Caller::result_type> makeStatelessCallback0 (const Caller& caller)
00303 {
00304 return makeCallback0(Caller0To1<Caller> (), 0);
00305 }
00306
00307 typedef Callback0<void> Callback;
00308
00313 template<typename FirstArgument, typename Result>
00314 class Callback1: public CallbackBase<Result(*) (void*, FirstArgument)>
00315 {
00316 typedef CallbackBase<Result(*) (void*, FirstArgument)> Base;
00317 static Result nullThunk (void*, FirstArgument)
00318 {
00319 }
00320
00321 public:
00322 typedef FirstArgument first_argument_type;
00323 typedef Result result_type;
00324
00325 Callback1 () :
00326 Base(0, nullThunk)
00327 {
00328 }
00329 template<typename Caller>
00330 Callback1 (const BindFirstOpaque1<Caller>& caller) :
00331 Base(caller.getEnvironment(), BindFirstOpaque1<Caller>::thunk)
00332 {
00333 }
00334 Callback1 (void* environment, typename Base::Thunk function) :
00335 Base(environment, function)
00336 {
00337 }
00338 result_type operator() (FirstArgument firstArgument) const
00339 {
00340 return Base::getThunk()(Base::getEnvironment(), firstArgument);
00341 }
00342 };
00343
00344 template<typename Caller>
00345 inline Callback1<typename Caller::second_argument_type, typename Caller::result_type> makeCallback1 (
00346 const Caller& caller, typename Caller::first_argument_type callee)
00347 {
00348 return Callback1<typename Caller::second_argument_type, typename Caller::result_type> (BindFirstOpaque1<Caller> (
00349 callee));
00350 }
00351 template<typename Caller>
00352 inline Callback1<typename Caller::second_argument_type, typename Caller::result_type> makeStatelessCallback1 (
00353 const Caller& caller)
00354 {
00355 return makeCallback1(Caller1To2<Caller> (), 0);
00356 }
00357
00361 template<typename FirstArgument, typename SecondArgument, typename Result>
00362 class Callback2: public CallbackBase<Result(*) (void*, FirstArgument, SecondArgument)>
00363 {
00364 typedef CallbackBase<Result(*) (void*, FirstArgument, SecondArgument)> Base;
00365 static Result nullThunk (void*, FirstArgument, SecondArgument)
00366 {
00367 }
00368
00369 public:
00370 typedef FirstArgument first_argument_type;
00371 typedef SecondArgument second_argument_type;
00372 typedef Result result_type;
00373
00374 Callback2 () :
00375 Base(0, nullThunk)
00376 {
00377 }
00378 template<typename Caller>
00379 Callback2 (const BindFirstOpaque2<Caller>& caller) :
00380 Base(caller.getEnvironment(), BindFirstOpaque2<Caller>::thunk)
00381 {
00382 }
00383 Callback2 (void* environment, typename Base::Thunk function) :
00384 Base(environment, function)
00385 {
00386 }
00387 result_type operator() (FirstArgument firstArgument, SecondArgument secondArgument) const
00388 {
00389 return Base::getThunk()(Base::getEnvironment(), firstArgument, secondArgument);
00390 }
00391 };
00392
00393 template<typename Caller>
00394 inline Callback2<typename Caller::second_argument_type, typename Caller::third_argument_type,
00395 typename Caller::result_type> makeCallback2 (const Caller& caller, typename Caller::first_argument_type callee)
00396 {
00397 return Callback2<typename Caller::second_argument_type, typename Caller::third_argument_type,
00398 typename Caller::result_type> (BindFirstOpaque2<Caller> (callee));
00399 }
00400 template<typename Caller>
00401 inline Callback2<typename Caller::first_argument_type, typename Caller::second_argument_type,
00402 typename Caller::result_type> makeStatelessCallback2 (const Caller& caller)
00403 {
00404 return makeCallback2(Caller2To3<Caller> (), 0);
00405 }
00406
00410 template<typename FirstArgument, typename SecondArgument, typename ThirdArgument, typename Result>
00411 class Callback3: public CallbackBase<Result(*) (void*, FirstArgument, SecondArgument, ThirdArgument)>
00412 {
00413 typedef CallbackBase<Result(*) (void*, FirstArgument, SecondArgument, ThirdArgument)> Base;
00414 static Result nullThunk (void*, FirstArgument, SecondArgument, ThirdArgument)
00415 {
00416 }
00417
00418 public:
00419 typedef FirstArgument first_argument_type;
00420 typedef SecondArgument second_argument_type;
00421 typedef ThirdArgument third_argument_type;
00422 typedef Result result_type;
00423
00424 Callback3 () :
00425 Base(0, nullThunk)
00426 {
00427 }
00428 template<typename Caller>
00429 Callback3 (const BindFirstOpaque3<Caller>& caller) :
00430 Base(caller.getEnvironment(), BindFirstOpaque3<Caller>::thunk)
00431 {
00432 }
00433 Callback3 (void* environment, typename Base::Thunk function) :
00434 Base(environment, function)
00435 {
00436 }
00437 result_type operator() (FirstArgument firstArgument, SecondArgument secondArgument, ThirdArgument thirdArgument) const
00438 {
00439 return Base::getThunk()(Base::getEnvironment(), firstArgument, secondArgument, thirdArgument);
00440 }
00441 };
00442
00443 template<typename Caller>
00444 inline Callback3<typename Caller::second_argument_type, typename Caller::third_argument_type,
00445 typename Caller::fourth_argument_type, typename Caller::result_type> makeCallback3 (const Caller& caller,
00446 typename Caller::first_argument_type callee)
00447 {
00448 return Callback3<typename Caller::second_argument_type, typename Caller::third_argument_type,
00449 typename Caller::fourth_argument_type, typename Caller::result_type> (BindFirstOpaque3<Caller> (callee));
00450 }
00451 template<typename Caller>
00452 inline Callback3<typename Caller::first_argument_type, typename Caller::second_argument_type,
00453 typename Caller::third_argument_type, typename Caller::result_type> makeStatelessCallback3 (
00454 const Caller& caller)
00455 {
00456 return makeCallback3(Caller3To4<Caller> (), 0);
00457 }
00458
00464 template<typename Environment, void(Environment::*member) ()>
00465 class MemberCaller: public BindFirstOpaque<Member<Environment, void, member> >
00466 {
00467 public:
00468 MemberCaller (Environment& environment) :
00469 BindFirstOpaque<Member<Environment, void, member> > (environment)
00470 {
00471 }
00472 };
00473
00479 template<typename Environment, void(Environment::*member) () const>
00480 class ConstMemberCaller: public BindFirstOpaque<ConstMember<Environment, void, member> >
00481 {
00482 public:
00483 ConstMemberCaller (const Environment& environment) :
00484 BindFirstOpaque<ConstMember<Environment, void, member> > (environment)
00485 {
00486 }
00487 };
00488
00492 template<typename Environment, typename FirstArgument, void(Environment::*member) (FirstArgument)>
00493 class MemberCaller1: public BindFirstOpaque1<Member1<Environment, FirstArgument, void, member> >
00494 {
00495 public:
00496 MemberCaller1 (Environment& environment) :
00497 BindFirstOpaque1<Member1<Environment, FirstArgument, void, member> > (environment)
00498 {
00499 }
00500 };
00501
00505 template<typename Environment, typename FirstArgument, void(Environment::*member) (FirstArgument) const>
00506 class ConstMemberCaller1: public BindFirstOpaque1<ConstMember1<Environment, FirstArgument, void, member> >
00507 {
00508 public:
00509 ConstMemberCaller1 (const Environment& environment) :
00510 BindFirstOpaque1<ConstMember1<Environment, FirstArgument, void, member> > (environment)
00511 {
00512 }
00513 };
00514
00520 template<typename Environment, void(*func) (Environment&)>
00521 class ReferenceCaller: public BindFirstOpaque<Function1<Environment&, void, func> >
00522 {
00523 public:
00524 ReferenceCaller (Environment& environment) :
00525 BindFirstOpaque<Function1<Environment&, void, func> > (environment)
00526 {
00527 }
00528 };
00529
00535 template<typename Environment, void(*func) (const Environment&)>
00536 class ConstReferenceCaller: public BindFirstOpaque<Function1<const Environment&, void, func> >
00537 {
00538 public:
00539 ConstReferenceCaller (const Environment& environment) :
00540 BindFirstOpaque<Function1<const Environment&, void, func> > (environment)
00541 {
00542 }
00543 };
00544
00548 template<typename Environment, typename FirstArgument, void(*func) (Environment&, FirstArgument)>
00549 class ReferenceCaller1: public BindFirstOpaque1<Function2<Environment&, FirstArgument, void, func> >
00550 {
00551 public:
00552 ReferenceCaller1 (Environment& environment) :
00553 BindFirstOpaque1<Function2<Environment&, FirstArgument, void, func> > (environment)
00554 {
00555 }
00556 };
00557
00561 template<typename Environment, typename FirstArgument, void(*func) (const Environment&, FirstArgument)>
00562 class ConstReferenceCaller1: public BindFirstOpaque1<Function2<const Environment&, FirstArgument, void, func> >
00563 {
00564 public:
00565 ConstReferenceCaller1 (const Environment& environment) :
00566 BindFirstOpaque1<Function2<const Environment&, FirstArgument, void, func> > (environment)
00567 {
00568 }
00569 };
00570
00574 template<typename Environment, void(*func) (const Environment*)>
00575 class ConstPointerCaller: public BindFirstOpaque<Function1<const Environment*, void, func> >
00576 {
00577 public:
00578 ConstPointerCaller (const Environment* environment) :
00579 BindFirstOpaque<Function1<const Environment*, void, func> > (environment)
00580 {
00581 }
00582 };
00583
00587 template<typename Environment, typename FirstArgument, void(*func) (const Environment*, FirstArgument)>
00588 class ConstPointerCaller1: public BindFirstOpaque1<Function2<const Environment*, FirstArgument, void, func> >
00589 {
00590 public:
00591 ConstPointerCaller1 (const Environment* environment) :
00592 BindFirstOpaque1<Function2<const Environment*, FirstArgument, void, func> > (environment)
00593 {
00594 }
00595 };
00596
00600 template<void(*func) ()>
00601 class FreeCaller: public BindFirstOpaque<Caller0To1<Function0<void, func> > >
00602 {
00603 public:
00604 FreeCaller () :
00605 BindFirstOpaque<Caller0To1<Function0<void, func> > > (0)
00606 {
00607 }
00608 };
00609
00613 template<typename FirstArgument, void(*func) (FirstArgument)>
00614 class FreeCaller1: public BindFirstOpaque1<Caller1To2<Function1<FirstArgument, void, func> > >
00615 {
00616 public:
00617 FreeCaller1 () :
00618 BindFirstOpaque1<Caller1To2<Function1<FirstArgument, void, func> > > (0)
00619 {
00620 }
00621 };
00622
00627 template<typename Functor>
00628 inline Callback makeCallback (Functor& functor)
00629 {
00630 return Callback(MemberCaller<Functor, &Functor::operator()> (functor));
00631 }
00632
00637 template<typename Functor>
00638 inline Callback makeCallback (const Functor& functor)
00639 {
00640 return Callback(ConstMemberCaller<Functor, &Functor::operator()> (functor));
00641 }
00642
00647 template<typename Functor>
00648 inline Callback1<typename Functor::first_argument_type> makeCallback1 (Functor& functor)
00649 {
00650 typedef typename Functor::first_argument_type FirstArgument;
00651 return Callback1<FirstArgument> (MemberCaller1<Functor, FirstArgument, &Functor::operator()> (functor));
00652 }
00653
00658 template<typename Functor>
00659 inline Callback1<typename Functor::first_argument_type> makeCallback1 (const Functor& functor)
00660 {
00661 typedef typename Functor::first_argument_type FirstArgument;
00662 return Callback1<FirstArgument> (ConstMemberCaller1<Functor, FirstArgument, &Functor::operator()> (functor));
00663 }
00664
00665 typedef Callback1<bool> BoolImportCallback;
00666 typedef Callback1<const BoolImportCallback&> BoolExportCallback;
00667
00668 typedef Callback1<int> IntImportCallback;
00669 typedef Callback1<const IntImportCallback&> IntExportCallback;
00670
00671 typedef Callback1<float> FloatImportCallback;
00672 typedef Callback1<const FloatImportCallback&> FloatExportCallback;
00673
00674 typedef Callback1<const char*> StringImportCallback;
00675 typedef Callback1<const StringImportCallback&> StringExportCallback;
00676
00677 typedef Callback1<std::size_t> SizeImportCallback;
00678 typedef Callback1<const SizeImportCallback&> SizeExportCallback;
00679
00680 template<bool(*BoolFunction) ()>
00681 class BoolFunctionExport
00682 {
00683 public:
00684 static void apply (const BoolImportCallback& importCallback)
00685 {
00686 importCallback(BoolFunction());
00687 }
00688 };
00689
00690 #endif