sigx::glib_threadable Class Reference
[Threading]

A useful and convenient thread wrapper for Glib threads. More...

#include <glib_threadable.h>

Inheritance diagram for sigx::glib_threadable:

sigx::threadable sigx::manual_dispatchable sigx::dispatchable sigx::noncopyable

Public Member Functions

 glib_threadable ()
 Constructs the threadable object.
virtual ~glib_threadable ()
 dtor.
template<typename T_functor >
void run (const T_functor &func_on_thread_ready)
 Creates a joinable thread.
void run ()
 Creates a joinable thread.
void finish ()
 Ends the thread, joins it and frees all its resources.

Protected Member Functions

Glib::RefPtr< Glib::MainContext > maincontext ()
 access the thread's maincontext
Glib::RefPtr< Glib::MainLoop > mainloop ()
 access the thread's mainloop
signal_f< Glib::SignalIdle > make_idle_signal_f ()
 Make a signal functor that returns the glib idle signal.
signal_f< Glib::SignalTimeout > make_timeout_signal_f ()
 Make a signal functor that returns the glib timeout signal.
signal_f< Glib::SignalIO > make_io_signal_f ()
 Make a signal functor that returns the glib IO signal.
signal_f< Glib::SignalChildWatch > make_childwatch_signal_f ()
 Make a signal functor that returns the glib childwatch signal.

Detailed Description

A useful and convenient thread wrapper for Glib threads.

A glib_threadable is used as a baseclass handling the major part of dealing with Glib threads in a threadsafe manner. It encapsulates starting and ending the thread, setting and cleaning up a Glib::MainContext and Glib::MainLoop for the thread and a sigx::dispatcher.

Derived classes just need a request interface and a signal interface other threads can connect to. The request interface consists of methods instructing the thread to do something by tunneling a message with sigx::open_tunnel() to a thread private request handler method that gets called when the message gets dispatched.

The thread in turn emits a signal that it has successfully (or not) completed the task. All thread's connected to that signal then know of the thread's attempt to execute the request.

A glib_threadable uses a sigx::glib_dispatcher (that in turn uses a Glib::Dispatcher) to dispatch requests in a threadsafe manner.

See the following code example to get an idea how to derive from glib_threadable and its usage.

    class MyThread: public sigx::glib_threadable
    {
    protected:
        typedef sigc::signal<void, bool> signal_did_something_t;
    
    private:
        struct ThreadPrivate
        {
            signal_did_something_t m_sigDidSomething;
        };
    
    
    private:
        Glib::Private<ThreadPrivate> m_threadpriv;
    
    public:
        MyThread();
    
        // request interface
        sigx::request_f<> do_something;
        
        // signal interface;
        // return a sigx::signal_wrapper for threadsafe access to the signal did_something
        sigx::signal_f<signal_did_something_t> signal_did_something;
    
    protected:
        // virtuals from threadable
        virtual void on_startup();
        
        // dispatcher methods, get called when requests of the request interface
        // get dispatched
        void on_do_something();
    };
    
    
    MyThread::MyThread(): 
        m_threadpriv(), 
        // initialize request interface
        do_something(sigc::mem_fun(this, &MyThread::on_do_something)), 
        // initialize signal interface
        signal_did_something(this, m_threadpriv, &ThreadPrivate::m_sigDidSomething)
    {}
    
    void MyThread::on_startup()
    {
        m_threadpriv.set(new ThreadPrivate);
    }
    
    void MyThread::on_do_something()
    {
        // do something
        // ...
        
        // broadcast that I have done something
        const success = true;
        ThreadPrivate* privdata = m_threadpriv.get();
        privdata->m_sigDidSomething.emit(success);
    }

When a glib_threadable is instantiated the thread does not immediately start its execution. You have to start it explicitly by calling run().

Note:
The thread must have finished before the destructor is called.

Constructor & Destructor Documentation

sigx::glib_threadable::glib_threadable (  ) 

Constructs the threadable object.

Note:
The thread must be started explicitly by calling run().

sigx::glib_threadable::~glib_threadable (  )  [virtual]

dtor.

Attention:
Thread must have finished before dtor is called.

References sigx::safe_lockable< T_type, T_mutex >::access_nonvolatile().


Member Function Documentation

void sigx::glib_threadable::finish (  ) 

Ends the thread, joins it and frees all its resources.

Waits for the main loop to quit and joins the thread and in the process deleting all the thread private data associated with this thread and all the internal resources. You MUST call finish() before deleting a class derived from glib_threadable.

Calling finish() from multiple threads is thread safe;

Note:
Ends the thread's mainloop immediately (as soon as the message gets dispatched). If your thread still must complete things before actually quitting the mainloop then you have to create another request in your derived class like "stop_working()" that signals the thread to stop its work. "stop_working()" could then send back the answer that the thread has completed its work and is ready to get the "finish" signal.

References mainloop(), and sigx::open_tunnel_with().

Glib::RefPtr< Glib::MainContext > sigx::glib_threadable::maincontext (  )  [protected]

access the thread's maincontext

Referenced by make_childwatch_signal_f(), make_idle_signal_f(), make_io_signal_f(), and make_timeout_signal_f().

Glib::RefPtr< Glib::MainLoop > sigx::glib_threadable::mainloop (  )  [protected]

access the thread's mainloop

Referenced by finish().

signal_f<Glib::SignalChildWatch> sigx::glib_threadable::make_childwatch_signal_f (  )  [inline, protected]

Make a signal functor that returns the glib childwatch signal.

References maincontext().

signal_f<Glib::SignalIdle> sigx::glib_threadable::make_idle_signal_f (  )  [inline, protected]

Make a signal functor that returns the glib idle signal.

References maincontext().

signal_f<Glib::SignalIO> sigx::glib_threadable::make_io_signal_f (  )  [inline, protected]

Make a signal functor that returns the glib IO signal.

References maincontext().

signal_f<Glib::SignalTimeout> sigx::glib_threadable::make_timeout_signal_f (  )  [inline, protected]

Make a signal functor that returns the glib timeout signal.

References maincontext().

void sigx::glib_threadable::run (  ) 

Creates a joinable thread.

Start the main loop of the thread, this will block until the thread has been created and is in a running state.

Attention:
Multiple calls from multiple threads are not threadsafe; Call run() only once from one thread, otherwise there are unpredictable results.
Afterwards you can connect to the thread's signals.

References sigx::ref().

template<typename T_functor >
void sigx::glib_threadable::run ( const T_functor &  func_on_thread_ready  )  [inline]

Creates a joinable thread.

Start the main loop of the thread. The function returns as soon as the thread is created which does not mean that it is already in a running state. To get notified that it is running you pass in a functor (func_on_thread_ready) that gets called as soon as the thread is in a running state.

Attention:
Multiple calls from multiple threads are not threadsafe; Call run() only once from one thread, otherwise there are unpredictable results.
Parameters:
func_on_thread_ready a functor that gets called as soon as the thread is idle and ready. The passed in functor is tunneled automatically if not yet a tunnel_functor. Must be convertible to a sigc::slot<void>.
Note:
In your on_thread_ready handler you can connect to the thread's signals.
    MyThread mythread;
    mythread.run(sigc::mem_fun(this, &TheGui::on_mythread_ready));
    
    void TheGUI::on_mythread_ready()
    {
        // now, the thread if fully set up, idle and ready
        mythread.signal_did_something().connect(
            sigc::mem_fun(this, &TheGUI::on_mythread_did_something)
        );
    }

References SIGX_STATIC_ASSERT.


The documentation for this class was generated from the following files:

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