00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef BACKGROUND_THREAD_H
00023 #define BAKCGROUND_THREAD_H
00024
00025 #include "claraty/share.h"
00026 #include <ace/Thread_Manager.h>
00027 #include <assert.h>
00028
00029 #include "claraty/functor.h"
00030
00031 #include <memory>
00032
00033 namespace claraty {
00034
00035 class BG_Task {
00036 public:
00037 BG_Task() { }
00038 virtual ~BG_Task() { }
00039 virtual void wait() { }
00040 };
00041
00042 template <class Op, class ret>
00043 class bg_helper {
00044 Op fn;
00045 ACE_thread_t& thread_id;
00046 ret& return_value;
00047
00048 explicit bg_helper(const bg_helper& rhs);
00049
00050 static ACE_THR_FUNC_RETURN dispatch(void *arg) {
00051 bg_helper *mgr = static_cast<bg_helper*>(arg);
00052 mgr->return_value = mgr->fn();
00053 delete mgr;
00054 return 0;
00055 }
00056
00057 public:
00058 bg_helper(Op op, ret& return_var, ACE_thread_t& tid, bool detach = false)
00059 : fn(op), thread_id(tid), return_value(return_var)
00060 {
00061 ACE_Thread_Manager *tm = ACE_Thread_Manager::instance();
00062 long flags = THR_NEW_LWP;
00063 if (!detach)
00064 flags |= THR_JOINABLE;
00065 tm->spawn(dispatch, this, flags, &thread_id);
00066 }
00067
00068 ~bg_helper() { }
00069 };
00070
00071 template <class Op>
00072 class bg_void_helper {
00073 Op fn;
00074 ACE_thread_t& thread_id;
00075
00076 explicit bg_void_helper(const bg_void_helper& rhs);
00077
00078 static ACE_THR_FUNC_RETURN dispatch(void *arg) {
00079 bg_void_helper *mgr = static_cast<bg_void_helper*>(arg);
00080 mgr->fn();
00081 delete mgr;
00082 return 0;
00083 }
00084
00085 public:
00086 bg_void_helper(Op op, ACE_thread_t& tid, bool detach = false)
00087 : fn(op), thread_id(tid)
00088 {
00089 ACE_Thread_Manager *tm = ACE_Thread_Manager::instance();
00090 long flags = THR_NEW_LWP;
00091 if (!detach)
00092 flags |= THR_JOINABLE;
00093 tm->spawn(dispatch, this, flags, &thread_id);
00094 }
00095
00096 ~bg_void_helper() { }
00097 };
00098
00099
00100 template <class result_type>
00101 class bg : public BG_Task {
00102 ACE_thread_t thread_id;
00103 result_type& return_value;
00104
00105 explicit bg(const bg& rhs);
00106
00107 protected:
00108 bool detached;
00109 public:
00110 template <class Op>
00111 bg(Op op, result_type& return_var, bool detach = false)
00112 : BG_Task(),
00113
00114
00115 thread_id (0),
00116 return_value(return_var), detached(detach)
00117 {
00118 new bg_helper<Op, result_type>(op, return_var, thread_id, detach);
00119 }
00120
00121 virtual ~bg() {
00122 if (!detached)
00123 wait();
00124 }
00125
00126 virtual void wait() {
00127 assert(!detached);
00128 ACE_Thread_Manager *tm = ACE_Thread_Manager::instance();
00129 tm->join(thread_id);
00130 detached = true;
00131 }
00132 };
00133
00134 template<> class bg<void> : public BG_Task {
00135 ACE_thread_t thread_id;
00136
00137 explicit bg(const bg& rhs);
00138
00139 protected:
00140 bool detached;
00141 public:
00142 template <class Op>
00143 bg(Op op, bool detach = false)
00144 : BG_Task(),
00145
00146
00147 thread_id (0),
00148 detached(detach)
00149 {
00150 new bg_void_helper<Op>(op, thread_id, detach);
00151 }
00152
00153 virtual ~bg() {
00154 if (!detached)
00155 wait();
00156 }
00157
00158 virtual void wait() {
00159 assert(!detached);
00160 ACE_Thread_Manager *tm = ACE_Thread_Manager::instance();
00161 tm->join(thread_id);
00162 detached = true;
00163 }
00164 };
00165
00166 template <class ret_type>
00167 class auto_bg : public bg<ret_type>, public VFunctor0_const<bool> {
00168 bool time_to_quit;
00169
00170 template <class Op>
00171 struct quittable_functor {
00172 const auto_bg<ret_type>& quit_functor;
00173 Op op;
00174 quittable_functor(Op& o, const auto_bg<ret_type>& func)
00175 : quit_functor(func), op(o) { }
00176
00177 ret_type operator()() { return op(quit_functor); }
00178 };
00179
00180 public:
00181 template <class Op>
00182 auto_bg(Op op, ret_type& return_var, bool detach = false)
00183 : bg<ret_type>(quittable_functor<Op>(op, *this), return_var, detach),
00184 time_to_quit(false)
00185 { }
00186
00187 virtual ~auto_bg() {
00188 if (!this->detached)
00189 wait();
00190 }
00191
00192 virtual void wait() {
00193 time_to_quit = true;
00194 bg<ret_type>::wait();
00195 }
00196
00197 virtual bool operator()() const { return time_to_quit; }
00198 };
00199
00200 template<> class auto_bg<void> : public bg<void>, public VFunctor0_const<bool> {
00201 bool time_to_quit;
00202
00203 template <class Op>
00204 struct quittable_functor {
00205 const auto_bg<void>& quit_functor;
00206 Op op;
00207 quittable_functor(Op& o, const auto_bg<void>& func)
00208 : quit_functor(func), op(o) { }
00209
00210 void operator()() { op(quit_functor); }
00211 };
00212
00213 public:
00214 template <class Op>
00215 auto_bg(Op op, bool detach = false)
00216 : bg<void>(quittable_functor<Op>(op, *this), detach), time_to_quit(false)
00217 { }
00218
00219 virtual ~auto_bg() {
00220 if (!detached)
00221 wait();
00222 }
00223
00224 virtual void wait() {
00225 time_to_quit = true;
00226 bg<void>::wait();
00227 }
00228
00229 virtual bool operator()() const { return time_to_quit; }
00230 };
00231
00232 template <class Op, class res_type>
00233 std::auto_ptr<BG_Task> background(Op op, res_type& retval,
00234 bool detach = false) {
00235 return std::auto_ptr<BG_Task>(new bg<res_type>(op, retval, detach));
00236 }
00237
00238 template <class Op>
00239 std::auto_ptr<BG_Task> background(Op op, bool detach = false) {
00240 return std::auto_ptr<BG_Task>(new bg<void>(op, detach));
00241 }
00242
00243
00244
00245
00246
00247
00248 template <class T, class R, class A, class B, class C, class D, class E, class F, class G, class H>
00249 struct big_8 {
00250 A _a;
00251 B _b;
00252 C _c;
00253 D _d;
00254 E _e;
00255 F _f;
00256 G _g;
00257 H _h;
00258
00259 T *const object;
00260 R (T::*fn)(A, B, C, D, E, F, G, H);
00261
00262 typedef R result_type;
00263
00264 big_8(T *const obj, R (T::*func)(A, B, C, D, E, F, G, H),
00265 A a, B b, C c, D d, E e, F f, G g, H h)
00266 : _a(a), _b(b), _c(c), _d(d), _e(e), _f(f), _g(g), _h(h), object(obj),
00267 fn(func)
00268 { }
00269
00270 R operator()() {
00271 return (object->*fn)(_a, _b, _c, _d, _e, _f, _g, _h);
00272 }
00273 };
00274
00275 template <class T, class R, class A, class B, class C, class D, class E, class F, class G, class H>
00276 big_8<T, R, A, B, C, D, E, F, G, H>
00277 compos8(T *const obj, R (T::*func)(A, B, C, D, E, F, G, H),
00278 A a, B b, C c, D d, E e, F f, G g, H h)
00279 {
00280 return big_8<T, R, A, B, C, D, E, F, G, H>
00281 (obj, func, a, b, c, d, e, f, g, h);
00282 }
00283
00284 }
00285
00286 #endif