Project directory structure

Dirk Hohndel dirk at hohndel.org
Wed Apr 3 12:13:40 PDT 2013


Thiago Macieira <thiago at macieira.org> writes:

> On quarta-feira, 3 de abril de 2013 11.29.35, Dirk Hohndel wrote:
>> > The hardest thing, since we are not sharing the GLib mainloop, is
>> > sharing events. This can be done using C callbacks, which can be
>> > registered to the core-lib when it's initialized (think of how Linux
>> > kernel modules register their methods) or when a specific object is
>> > initialized.
>> 
>> I don't know which events you mean.
>> 
>> We have "events" which are things that happen during a dive that we
>> handle (for example, "diver changed tanks" or "diver violated deco
>> ceiling"). But I think the only asynchronous callbacks that we have in
>> our code are for the divecomputer download (where we want to update the
>> UI while a different thread talks to the divecomputer) and things that
>> are triggered from the UI (so those would be signals/slots).
>> 
>> Am I missing something?
>
> Alberto was talking about notifications / callbacks.
>
> Something I'll have to add to the HACKING file, but here it goes. In Qt 
> "speak", an event is a class of notifications that are delivered by sending a 
> QEvent object to a specific target object, even though some UI events "bubble 
> up" to other objects. Events are usually raw, in the sense that they usually 
> don't contain semantic meaning. They are also usually spontaneous, coming from 
> the "outside world". Mouse clicks, touchscreen touches, keyboard input and all 
> sort of information coming from the windowing system are events (paint events, 
> focus events, drag-and-drop events, etc.)
>
> Compare that to "signals", which are semantic notifications that something 
> happened, which is why they're named after verbs in the simple past tense. 
> Signals are not directed: they are an N:M callback mechanism. Usually, the 
> sender of a signal does not even care if anything is receiving the signal (the 
> sender of an event could check if it was handled).
>
> Usually, signals are emitted in reaction to events. For example, a QPushButton 
> can emit the clicked() signal as a result of the user doing a mouse click on 
> the button, but also when the user hits the space bar while the button was 
> focused -- if there's such a thing as focus on this device / style. It's also 
> emitted as a result of someone calling the click() function.

So these are the callbacks that we have. Things in our logic code that
are called based on something that happens in the UI. User clicked on a
button. Focus left an entry field and we want to live-update the
display. Etc.

> For Subsurface, the notification that the download from the divecomputer 
> finished would be a signal. Since that code is in C, we'd simply do with a 
> regular callback that in turn emits the signal. The UI will react soon. 
> Similarly for a progress bar, if any: the callback from the download routine 
> with the update emits a signal.

So how would this be handled from C code? Right now (because of
limitations with the way Gtk does things) the main thread does something
like this:

	while (!import_thread_done) {
		if (!import_thread_cancelled) {
			int result;
			g_timeout_add(100, timeout_func, dialog);
			update_progressbar(&data->progress, progress_bar_fraction);
			update_progressbar_text(&data->progress, progress_bar_text);
			result = gtk_dialog_run(dialog);
			switch (result) {
			case GTK_RESPONSE_CANCEL:
				import_thread_cancelled = TRUE;
				progress_bar_text = _("Cancelled...");
				break;
			default:
				/* nothing */
				break;
			}
		} else {
			update_progressbar(&data->progress, progress_bar_fraction);
			update_progressbar_text(&data->progress, progress_bar_text);
			usleep(100000);
		}
	}

And we use the global variables import_thread_cancelled,
import_thread_done progress_bar_text and progress_bar_fraction to
communicate from the download thread to the UI thread.
The stupid timeout mechanism is working around Gtk's inability to do the
updates from a separate thread (I understand the same is true for Qt).

> However, Dirk mentioned threading, so I'd actually recommend a little 
> refactoring here: use QThread, which abstracts away the Win32 threads. The 
> download function is a simple, blocking function. The completion of the 
> download is simply the fact that the function returned. (I haven't 
> investigated whether such a function exists in libdivecomputer and whether 
> there are mutexes involved, which would complicate the situation a little)

We use pthreads right now:

	pthread_create(&pthread, NULL, pthread_wrapper, data);

and then

	if (pthread_join(pthread, &retval) < 0)
		retval = _("Odd pthread error return");

/D


More information about the subsurface mailing list