As mentioned briefly in the introduction, the LibCXX Widget Toolkit creates an internal execution thread for the connection with the display server. LibCXX Widget Toolkit takes care of starting and stopping the connection thread. The connection thread gets started when needed, and the connection thread gets stopped when the last top level window, or an explicitly constructed connection object, goes out of scope and gets destroyed.
The connection thread takes care of updating the display, and processing internal display protocol messages. The connection thread also executes application-specified lambdas or other callable objects in response to specific events.
The connection thread resumes its normal duties after the application callback returns. Application callbacks should not get bogged down with long-running tasks, as this will result in the application window appearing to be frozen. Callbacks should be minimal, and consist of little more than sending a message of some kind, or setting a flag.
Typical example: a
main window's on_delete
() method
sets the callback that gets executed in when the window's close
button gets clicked:
main_window->on_delete([close_flag] (ONLY IN_THREAD, const x::w::busy &ignore) { close_flag->close(); });
This is an example of the calling convention LibCXXW uses for
invoking its callbacks by the internal execution thread.
The callback's first parameter is a reference to an internal
object that represents the connection thread itself.
The callback's first parameter gets specified as
“ONLY IN_THREAD
”, this declares a
parameter named IN_THREAD
that carries this
internal reference.
This calling convention serves a dual purpose:
This identifies lambdas that always get invoked by the library's' internal connection thread, as well as object methods that can only be invoked from the connection thread.
A lambda that receives the IN_THREAD
parameter
can call other functions and methods by forwarding to them this
parameter:
lm->remove_item(IN_THREAD, 0);
The only way to receive the IN_THREAD
parameter
is by having a function executed by the internal connection thread.
In this manner only IN_THREAD
code can invoke
other IN_THREAD
code.
The “THREAD_CALLBACK
” designation
is just an alias. for the parameter's type:
main_window->on_delete([close_flag] (THREAD_CALLBACK, const x::w::busy &ignore) { close_flag->close(); });
“ONLY IN_THREAD
” and
“THREAD_CALLBACK
” mean the same
thing. The only difference is that the former declares a named
parameter, called “IN_THREAD”; and the latter is just
a parameter type declaration. This on_delete
()
example does not need to call any other connection thread code, so
it doesn't need to forward its thread parameter anywhere.
Using the THREAD_CALLBACK
designation is a little
but more descriptive.
Some LibCXXW objects provide overloaded versions of the same
method, with and without the ONLY IN_THREAD
designation. Except where noted, LibCXXW makes all changes to
widgets from the internal connection thread.
Application code invoking the non-IN_THREAD
method does not immediately update the widget. What happens
is that a message gets sent to the connection thread, which processes
it at the first available opportunity.
But a callback that gets executed by the connection thread and receives
the IN_THREAD
parameter has the ability to
use the ONLY IN_THREAD
overload, which makes the
change immediately. An
IN_THREAD
code is free to invoke the
non-IN_THREAD
overload also, but this will not
result in any changes until the callback returns, and the connection
thread resumes processing its internal messages.