glib_threadable.h

Go to the documentation of this file.
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

Generated on Mon Aug 3 17:35:08 2009 for sigx++ by  doxygen 1.5.9