sigx++ 2.0.1
|
00001 #ifndef _SIGX_GLIB_THREADABLE_HPP_ 00002 #define _SIGX_GLIB_THREADABLE_HPP_ 00003 00004 /* 00005 * Copyright 2006 Klaus Triendl 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Library General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Library General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Library General Public 00018 * License along with this library; if not, write to the Free 00019 * Software Foundation, 51 Franklin Street, Fifth Floor, 00020 * Boston, MA 02110-1301, USA. 00021 */ 00022 00023 #include <sigc++/functors/slot.h> 00024 #include <glibmm/refptr.h> 00025 #include <glibmm/thread.h> 00026 #include <glibmm/main.h> 00027 #include <sigxconfig.h> 00028 #include <sigx/threadable.h> 00029 #include <sigx/tunnel_functor.h> 00030 #include <sigx/lockable.h> 00031 #include <sigx/volatile_trait.h> 00032 #include <sigx/signal_f.h> 00033 00034 00035 00036 namespace sigx 00037 { 00038 00130 class SIGX_API glib_threadable: public threadable 00131 { 00132 public: 00136 glib_threadable(); 00137 00141 virtual ~glib_threadable(); 00142 00176 template<typename T_functor> 00177 void run(const T_functor& func_on_thread_ready); 00178 00190 void run(); 00191 00209 void finish(); 00210 00211 00212 private: 00215 void create_thread(const sigc::slot<void>& slot_on_thread_ready); 00216 00224 void on_run(const sigc::slot<void>& slot_on_thread_ready); 00225 00229 void on_idle_and_ready(Glib::Mutex& mtx, Glib::Cond& cond); 00230 00231 protected: 00234 Glib::RefPtr<Glib::MainContext> maincontext(); 00235 00238 Glib::RefPtr<Glib::MainLoop> mainloop(); 00239 00242 signal_f<Glib::SignalIdle> make_idle_signal_f() 00243 { 00244 return signal_f<Glib::SignalIdle>( 00245 // the dispatchable 00246 *this, 00247 // the signal source is a functor executing 00248 // this->maincontext()->signal_idle() 00249 sigc::compose( 00250 // setter 00251 sigc::mem_fun(&Glib::MainContext::signal_idle), 00252 // getter 00253 sigc::compose( 00254 // setter 00255 sigc::mem_fun(&Glib::RefPtr<Glib::MainContext>::operator ->), 00256 // getter 00257 sigc::mem_fun(this, &glib_threadable::maincontext) 00258 ) 00259 ) 00260 ); 00261 } 00262 00265 signal_f<Glib::SignalTimeout> make_timeout_signal_f() 00266 { 00267 return signal_f<Glib::SignalTimeout>( 00268 // the dispatchable 00269 *this, 00270 // the signal source is a functor executing 00271 // this->maincontext()->signal_timeout() 00272 sigc::compose( 00273 // setter 00274 sigc::mem_fun(&Glib::MainContext::signal_timeout), 00275 // getter 00276 sigc::compose( 00277 // setter 00278 sigc::mem_fun(&Glib::RefPtr<Glib::MainContext>::operator ->), 00279 // getter 00280 sigc::mem_fun(this, &glib_threadable::maincontext) 00281 ) 00282 ) 00283 ); 00284 } 00285 00288 signal_f<Glib::SignalIO> make_io_signal_f() 00289 { 00290 return signal_f<Glib::SignalIO>( 00291 // the dispatchable 00292 *this, 00293 // the signal source is a functor executing 00294 // this->maincontext()->signal_io() 00295 sigc::compose( 00296 // setter 00297 sigc::mem_fun(&Glib::MainContext::signal_io), 00298 // getter 00299 sigc::compose( 00300 // setter 00301 sigc::mem_fun(&Glib::RefPtr<Glib::MainContext>::operator ->), 00302 // getter 00303 sigc::mem_fun(this, &glib_threadable::maincontext) 00304 ) 00305 ) 00306 ); 00307 } 00308 00311 signal_f<Glib::SignalChildWatch> make_childwatch_signal_f() 00312 { 00313 return signal_f<Glib::SignalChildWatch>( 00314 // the dispatchable 00315 *this, 00316 // the signal source is a functor executing 00317 // this->maincontext()->signal_childwatch() 00318 sigc::compose( 00319 // setter 00320 sigc::mem_fun(&Glib::MainContext::signal_child_watch), 00321 // getter 00322 sigc::compose( 00323 // setter 00324 sigc::mem_fun(&Glib::RefPtr<Glib::MainContext>::operator ->), 00325 // getter 00326 sigc::mem_fun(this, &glib_threadable::maincontext) 00327 ) 00328 ) 00329 ); 00330 } 00331 00332 00333 private: 00334 struct threaddata; 00335 Glib::Private<threaddata> m_threaddata; 00336 typedef mutex_lockable<Glib::Thread*> mutex_lockable_thread; 00337 mutex_lockable_thread m_thread; 00338 }; 00339 00340 00364 } // namespace sigx 00365 00366 00367 00368 00369 #include <sigx/auto_tunneler.h> 00370 #include <sigx/static_assert.h> 00371 00372 00373 namespace sigx 00374 { 00375 00376 template<typename T_functor> 00377 void glib_threadable::run(const T_functor& func_on_thread_ready) 00378 { 00379 typedef internal::auto_tunneler<T_functor> auto_tunneler_t; 00380 00381 // passed in functor must not be a slot or adapt a slot; 00382 // we have to apply this restriction because slots might have bound 00383 // trackables that can cause non-threadsafe access to the passed in slot 00384 // which will live in the context of the server thread 00385 SIGX_STATIC_ASSERT((sigx::internal::is_or_adapts_slot<T_functor>::value == false)); 00386 00387 // toplevel functor must be a tunnel functor 00388 SIGX_STATIC_ASSERT((sigc::is_base_and_derived<tunnel_base, typename auto_tunneler_t::functor_type>::value == true)); 00389 00390 const typename auto_tunneler_t::functor_type& functor2callback = 00391 auto_tunneler_t::auto_open_tunnel(func_on_thread_ready); 00392 00393 // a sigc::slot is created out of the functor func_on_thread_ready and bound 00394 // to another functor suitable for Glib::Thread::create. 00395 // this still happens in the context of the calling thread and is therefore 00396 // threadsafe 00397 create_thread(sigc::slot<void>(functor2callback)); 00398 } 00399 00400 00401 } // namespace sigx 00402 00403 00404 #endif // end file guard