Re: [GTKMM] Gtkmm thread example



Just a a hint: for a stop-condition g_atomic_int_(get|set) can be used; it achieves the same effect, atomic reads/writes to a condition variable, but is much cheaper (on x86 is implemented with a single assembler instruction).

2008/6/6 Charles McLachlan <cim20 metropolis-data co uk>:
On Thu, 5 Jun 2008, Damon Register wrote:

> I am attempting to write a relatively simple gtkmm applicaton that gets and
> displays data from a hardware device.  The hardware part is easy because I
> have several console example apps for that.  I have learned some basic gtkmm
> to allow me to create a simple application.  I think I could even figure
> out how to use a timer to periodically poll the hardware for data.
>
> What I really want to do (I think) is have the main gtkmm app and a separate
> thread that reads the hardware and signals the main app when there is data.
> I have been searching for info and examples.  Perhaps I have found something
> quite close to what I need.
> http://www.gtkmm.org/docs/glibmm-2.4/docs/reference/html/group__Threads.html
> shows a link to this dispatcher example.
> http://www.gtkmm.org/docs/glibmm-2.4/docs/reference/html/thread_2dispatcher_8cc-example.html#a17
>
>
> This might be just what I need but the example is glibmm and I don't know how
> to adapt to a gtkmm.  Is there a relatively simple gtkmm thread dispatcher
> example, or can someone here suggest how to modify the glibmm dispatcher
> example to be a gtkmm example?

Here's my particular simplest possible useful thread test that I wrote
when learning gthread. It's certainly not perfect, but hopefully
illustrates a few useful features.

// g++ testthread.cc -o testthread `pkg-config --libs --cflags gtkmm-2.4 gthread-2.0`

#include <iostream>
#include <gtkmm.h>

// an object that lives in a subthread (mostly)
class pinger
{
       public:
               pinger() : thread(0), value(0), threadMustStop(false) {
                       // deferr creation of the thread until main loop has some time
                       // It is not entirely clear why this is needed, but the documentation says so
                       Glib::signal_idle().connect(sigc::bind_return(sigc::mem_fun(*this, &pinger::start), false));
               }

               // called by main thread to create subthread
               void start() {
                       std::cerr << __PRETTY_FUNCTION__ << " called by " << Glib::Thread::self() << "\n";
                       thread = Glib::Thread::create(sigc::mem_fun(*this, &pinger::threadfunc), true);
               }

               // main subthread function - called on the stack of the subthread (obviously)
               void threadfunc()
               {
                       std::cerr << __PRETTY_FUNCTION__ << " called by " << Glib::Thread::self() << "\n";

                       for(;;)
                       {
                               Glib::usleep(50000);

                               {
                               Glib::Mutex::Lock lock (mutex);
                               value++;
                               value = value % 100;
                               }

                               std::cerr << "signal_increment called by " << Glib::Thread::self() << "\n";
                               signal_increment();

                               // less than ideal: thread only stops when it notices flag has changed
                               {
                               Glib::Mutex::Lock lock (mutex);
                               if (threadMustStop) break;
                               }
                       }
                       std::cerr << "Subthread stop\n";
               }

               // called by main thread to interogate state of subthread
               int get_value()
               {
                       std::cerr << __PRETTY_FUNCTION__ << " called by " << Glib::Thread::self() << "\n";
                       int ret = 0;

                       {
                       Glib::Mutex::Lock lock (mutex);
                       ret = value;
                       }
                       return ret;
               }

               // main thread tells substread to stop
               ~pinger()
               {
                       {
                       Glib::Mutex::Lock lock (mutex);
                       threadMustStop = true;
                       }

                       if (thread)
                               thread->join();
                       std::cerr << "Subthread joined\n";
               }

       Glib::Dispatcher    signal_increment;
       Glib::Thread*       thread;
       Glib::Mutex     mutex; // protects both the following variables
       int value;
       bool threadMustStop;
};

// a progress bar that lives in the main thread
class pbar
{
       public:
               pbar()
               {
                       win.add(pb);
                       pb.show();
                       win.show();

                       pb.set_fraction(0.0);
                       ping.signal_increment.connect(sigc::mem_fun(*this, &pbar::pong));
               }

               // invoked on stack of *main thread* by signal from subthread (magic)
               // so *can* call normal gtkmm GUI functions (like set_fraction)
               void pong()
               {
                       int val = ping.get_value();
                       std::cerr << __PRETTY_FUNCTION__ << " called by " << Glib::Thread::self() << " value = " << val << "\n";
                       pb.set_fraction(float(val) / float(100.0));
                       if (val >= 99) Gtk::Main::quit();
               }

       pinger ping;
       Gtk::Window win;
       Gtk::ProgressBar pb;
};

int main(int argc, char *argv[])
{
       if(!Glib::thread_supported()) Glib::thread_init();

       Gtk::Main app(argc, argv);

       pbar pb;

       app.run();
       std::cerr << "application ended\n";
}

Charlie - Metropolis Data Consultants - 07976 028167 - 01223 763758

_______________________________________________
gtkmm-list mailing list
gtkmm-list gnome org
http://mail.gnome.org/mailman/listinfo/gtkmm-list



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]