Re: [GTKMM] Gtkmm thread example



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]