CppCMS
booster/callback.h
00001 //
00002 //  Copyright (C) 2009-2012 Artyom Beilis (Tonkikh)
00003 //
00004 //  Distributed under the Boost Software License, Version 1.0. (See
00005 //  accompanying file LICENSE_1_0.txt or copy at
00006 //  http://www.boost.org/LICENSE_1_0.txt)
00007 //
00008 #ifndef BOOSTER_CALLBACK_H
00009 #define BOOSTER_CALLBACK_H
00010 
00011 #include <booster/backtrace.h>
00012 #include <memory>
00013 #include <booster/intrusive_ptr.h>
00014 #include <booster/refcounted.h>
00015 
00016 namespace booster {
00017         template<typename Type>
00018         class callback;
00019 
00020         template<typename Type>
00021         struct callable;
00022 
00027         class bad_callback_call : public booster::runtime_error {
00028         public:
00029                 bad_callback_call() : 
00030                         booster::runtime_error("bad_callback_call")
00031                 {
00032                 }
00033         };
00034 
00035 
00036         #ifdef BOOSTER_DOXYGEN_DOCS
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054         template<typename Result,typename ...Params>                    
00055         class callback<Result(Params...)>                               
00056         {                                                                       
00057         public:                                                                 
00061                 typedef Result result_type;             
00065                 callback();
00070                 template<typename F>                                            
00071                 callback(F func);
00072                 
00076                 callback(callback const &other);
00077 
00082                 template<typename F>                                            
00083                 callback const &operator=(F func);
00084 
00088                 callback const &operator=(callback const &other);
00089 
00093                 result_type operator()(Params... params) const;
00097                 bool empty() const;
00101                 operator bool() const;
00102 
00106                 void swap(callback &other);
00107         };                      
00108 
00109         #else
00110 
00111         #define BOOSTER_CALLBACK                                                \
00112         template<typename Result BOOSTER_TEMPLATE_PARAMS >                      \
00113         struct callable<Result(BOOSTER_TEMPLATE_TYPE_PARAMS)> :public refcounted\
00114         {                                                                       \
00115                 virtual Result operator()(BOOSTER_TYPE_PARAMS) = 0;             \
00116                 virtual ~callable(){}                                           \
00117         };                                                                      \
00118                                                                                 \
00119         template<typename Result BOOSTER_TEMPLATE_PARAMS >                      \
00120         class callback<Result(BOOSTER_TEMPLATE_TYPE_PARAMS)>                    \
00121         {                                                                       \
00122         public:                                                                 \
00123                 typedef Result result_type;                                     \
00124                                                                                 \
00125                 typedef callable<Result(BOOSTER_TEMPLATE_TYPE_PARAMS)>          \
00126                         callable_type;                                          \
00127                                                                                 \
00128                 template<typename R,typename F>                                 \
00129                 struct callable_impl : public callable_type {                   \
00130                         F func;                                                 \
00131                         callable_impl(F f) : func(f){}                          \
00132                         virtual R operator()(BOOSTER_TYPE_PARAMS)               \
00133                         {  return func(BOOSTER_CALL_PARAMS); }                  \
00134                 };                                                              \
00135                                                                                 \
00136                 template<typename F>                                            \
00137                 struct callable_impl<void,F> : public callable_type {           \
00138                         F func;                                                 \
00139                         callable_impl(F f) : func(f){}                          \
00140                         virtual void operator()(BOOSTER_TYPE_PARAMS)            \
00141                         {  func(BOOSTER_CALL_PARAMS); }                         \
00142                 };                                                              \
00143                                                                                 \
00144                 callback(){}                                                    \
00145                                                                                 \
00146                 template<typename Call>                                         \
00147                 callback(intrusive_ptr<Call> c) : call_ptr(c)                   \
00148                 {}                                                              \
00149                                                                                 \
00150                 template<typename Call>                                         \
00151                 callback(std::auto_ptr<Call> ptr) : call_ptr(ptr.release())     \
00152                 {}                                                              \
00153                                                                                 \
00154                 template<typename Call>                                         \
00155                 callback const &operator=(intrusive_ptr<Call> c)                \
00156                 { call_ptr = c; return *this; }                                 \
00157                                                                                 \
00158                 template<typename Call>                                         \
00159                 callback const &operator=(std::auto_ptr<Call> c)                \
00160                 { call_ptr = 0; call_ptr = c.release(); return *this; }         \
00161                                                                                 \
00162                 template<typename F>                                            \
00163                 callback(F func) : call_ptr(new callable_impl<Result,F>(func))  \
00164                 {}                                                              \
00165                                                                                 \
00166                 callback(callback const &other) : call_ptr(other.call_ptr) {}   \
00167                                                                                 \
00168                 template<typename F>                                            \
00169                 callback const &operator=(F func)                               \
00170                 {                                                               \
00171                         call_ptr = new callable_impl<Result,F>(func);           \
00172                         return *this;                                           \
00173                 }                                                               \
00174                                                                                 \
00175                 callback const &operator=(callback const &other)                \
00176                 {                                                               \
00177                         if(this != &other) { call_ptr=other.call_ptr; }         \
00178                         return *this;                                           \
00179                 }                                                               \
00180                                                                                 \
00181                 Result operator()(BOOSTER_TYPE_PARAMS) const                    \
00182                 {                                                               \
00183                         if(!call_ptr.get()) throw bad_callback_call();          \
00184                         return (*call_ptr)(BOOSTER_CALL_PARAMS);                \
00185                 }                                                               \
00186                                                                                 \
00187                 bool empty() const { return call_ptr.get()==0; }                \
00188                                                                                 \
00189                 operator bool() const { return !empty(); }                      \
00190                                                                                 \
00191                 void swap(callback &other) { call_ptr.swap(other.call_ptr); }   \
00192                                                                                 \
00193         private:                                                                \
00194                 intrusive_ptr<callable_type> call_ptr;                          \
00195         };                                                                      \
00196 
00197         #define BOOSTER_TEMPLATE_PARAMS
00198         #define BOOSTER_TEMPLATE_TYPE_PARAMS
00199         #define BOOSTER_TYPE_PARAMS
00200         #define BOOSTER_CALL_PARAMS
00201         BOOSTER_CALLBACK
00202         #undef BOOSTER_TEMPLATE_PARAMS
00203         #undef BOOSTER_TEMPLATE_TYPE_PARAMS
00204         #undef BOOSTER_TYPE_PARAMS
00205         #undef BOOSTER_CALL_PARAMS
00206 
00207         #define BOOSTER_TEMPLATE_PARAMS ,typename P1
00208         #define BOOSTER_TEMPLATE_TYPE_PARAMS  P1
00209         #define BOOSTER_TYPE_PARAMS  P1 a1
00210         #define BOOSTER_CALL_PARAMS a1
00211         BOOSTER_CALLBACK
00212         #undef BOOSTER_TEMPLATE_PARAMS
00213         #undef BOOSTER_TEMPLATE_TYPE_PARAMS
00214         #undef BOOSTER_TYPE_PARAMS
00215         #undef BOOSTER_CALL_PARAMS
00216 
00217         #define BOOSTER_TEMPLATE_PARAMS ,typename P1,typename P2
00218         #define BOOSTER_TEMPLATE_TYPE_PARAMS  P1, P2
00219         #define BOOSTER_TYPE_PARAMS  P1 a1,P2 a2
00220         #define BOOSTER_CALL_PARAMS a1,a2
00221         BOOSTER_CALLBACK
00222         #undef BOOSTER_TEMPLATE_PARAMS
00223         #undef BOOSTER_TEMPLATE_TYPE_PARAMS
00224         #undef BOOSTER_TYPE_PARAMS
00225         #undef BOOSTER_CALL_PARAMS
00226                         
00227         #define BOOSTER_TEMPLATE_PARAMS ,typename P1,typename P2,typename P3
00228         #define BOOSTER_TEMPLATE_TYPE_PARAMS  P1, P2, P3
00229         #define BOOSTER_TYPE_PARAMS  P1 a1,P2 a2,P3 a3
00230         #define BOOSTER_CALL_PARAMS a1,a2,a3
00231         BOOSTER_CALLBACK
00232         #undef BOOSTER_TEMPLATE_PARAMS
00233         #undef BOOSTER_TEMPLATE_TYPE_PARAMS
00234         #undef BOOSTER_TYPE_PARAMS
00235         #undef BOOSTER_CALL_PARAMS
00236         
00237         #define BOOSTER_TEMPLATE_PARAMS ,typename P1,typename P2,typename P3,typename P4
00238         #define BOOSTER_TEMPLATE_TYPE_PARAMS  P1, P2, P3, P4
00239         #define BOOSTER_TYPE_PARAMS  P1 a1,P2 a2,P3 a3,P4 a4
00240         #define BOOSTER_CALL_PARAMS a1,a2,a3,a4
00241         BOOSTER_CALLBACK
00242         #undef BOOSTER_TEMPLATE_PARAMS
00243         #undef BOOSTER_TEMPLATE_TYPE_PARAMS
00244         #undef BOOSTER_TYPE_PARAMS
00245         #undef BOOSTER_CALL_PARAMS
00246 
00247         #define BOOSTER_TEMPLATE_PARAMS ,typename P1,typename P2,typename P3,typename P4,typename P5
00248         #define BOOSTER_TEMPLATE_TYPE_PARAMS  P1, P2, P3, P4, P5
00249         #define BOOSTER_TYPE_PARAMS  P1 a1,P2 a2,P3 a3,P4 a4,P5 a5
00250         #define BOOSTER_CALL_PARAMS a1,a2,a3,a4,a5
00251         BOOSTER_CALLBACK
00252         #undef BOOSTER_TEMPLATE_PARAMS
00253         #undef BOOSTER_TEMPLATE_TYPE_PARAMS
00254         #undef BOOSTER_TYPE_PARAMS
00255         #undef BOOSTER_CALL_PARAMS
00256 
00257         #define BOOSTER_TEMPLATE_PARAMS ,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6
00258         #define BOOSTER_TEMPLATE_TYPE_PARAMS  P1, P2, P3, P4, P5, P6
00259         #define BOOSTER_TYPE_PARAMS  P1 a1,P2 a2,P3 a3,P4 a4,P5 a5,P6 a6
00260         #define BOOSTER_CALL_PARAMS a1,a2,a3,a4,a5,a6
00261         BOOSTER_CALLBACK
00262         #undef BOOSTER_TEMPLATE_PARAMS
00263         #undef BOOSTER_TEMPLATE_TYPE_PARAMS
00264         #undef BOOSTER_TYPE_PARAMS
00265         #undef BOOSTER_CALL_PARAMS
00266         
00267         #define BOOSTER_TEMPLATE_PARAMS ,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7
00268         #define BOOSTER_TEMPLATE_TYPE_PARAMS  P1, P2, P3, P4, P5, P6, P7
00269         #define BOOSTER_TYPE_PARAMS  P1 a1,P2 a2,P3 a3,P4 a4,P5 a5,P6 a6,P7 a7
00270         #define BOOSTER_CALL_PARAMS a1,a2,a3,a4,a5,a6,a7
00271         BOOSTER_CALLBACK
00272         #undef BOOSTER_TEMPLATE_PARAMS
00273         #undef BOOSTER_TEMPLATE_TYPE_PARAMS
00274         #undef BOOSTER_TYPE_PARAMS
00275         #undef BOOSTER_CALL_PARAMS
00276         
00277         #define BOOSTER_TEMPLATE_PARAMS ,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7,typename P8
00278         #define BOOSTER_TEMPLATE_TYPE_PARAMS  P1, P2, P3, P4, P5, P6, P7, P8
00279         #define BOOSTER_TYPE_PARAMS  P1 a1,P2 a2,P3 a3,P4 a4,P5 a5,P6 a6,P7 a7,P8 a8
00280         #define BOOSTER_CALL_PARAMS a1,a2,a3,a4,a5,a6,a7,a8
00281         BOOSTER_CALLBACK
00282         #undef BOOSTER_TEMPLATE_PARAMS
00283         #undef BOOSTER_TEMPLATE_TYPE_PARAMS
00284         #undef BOOSTER_TYPE_PARAMS
00285         #undef BOOSTER_CALL_PARAMS
00286 
00287         #undef BOOSTER_CALLBACK
00288 
00289         #endif // DOC
00290 
00291 } // booster
00292 
00293 
00294 #endif