00001
00002
00003
00004
00005
00006
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 }
00292
00293
00294 #endif