Re: [GTKMM] Gtkmm thread example
- From: Charles McLachlan <cim20 metropolis-data co uk>
- To: Damon Register <damonregister bellsouth net>
- Cc: gtkmm-list gnome org
- Subject: Re: [GTKMM] Gtkmm thread example
- Date: Fri, 6 Jun 2008 11:02:09 +0100 (BST)
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
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]