Follow this link to skip to the main content

background_thread.h

Go to the documentation of this file.
00001 // -*-c++-*-
00002 //----------------------------< /-/ CLARAty /-/ >------------------------------
00003 /**
00004  * @file  background_thread.h
00005  *
00006  * Helper classes for background thread
00007  * 
00008  * <br>@b Designer(s):  Clayton Kunz
00009  * <br>@b Author(s):    Clayton Kunz
00010  * <br>@b Date:         February 2, 2004
00011  *
00012  * <b>Software License:</b><br>
00013  * <code> http://claraty.jpl.nasa.gov/license/open_src/  or 
00014  *        file: license/open_src.txt </code>
00015  * 
00016  * &copy; 2006, Jet Propulsion Laboratory, California Institute of Technology
00017  * 
00018  * $Revision: 1.1 $
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       // ACE_thread_t must be initialized to 0 for VxWorks 
00114       // (undocumented in ACE)
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       // ACE_thread_t must be initialized to 0 for VxWorks 
00146       // (undocumented in ACE)
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    Silly helper class + function for spawning a member function taking
00245    8 arguments and returning a value. This was written specifically
00246    with the ARC disparity correlator function call in mind, to do
00247    forward and backward correlation simultaneously. */
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 } // namespace claraty
00285 
00286 #endif