Schedulers
Jancy implements the concept of function pointer scheduling. When passing a function pointers as a callback of some sort (completion routine, event handler etc) you are free to assign it a user-defined “scheduler”. The purpose of this scheduler is to ensure the execution of your callback in the correct environment (i.e. a specific worker thread, from within a Windows Message handler, under lock/mutex, and so on).
The scheduler is a built-in interface of the Jancy compiler:
namespace jnc {
class Scheduler {
abstract schedule(function* f ());
}
} // namespace jnc {
Note that even the schedule
method accepts a pointer to a function with no arguments, and you can schedule functions with arbitrary argument list, as arguments will be captured in the closure object.
To assign a scheduler you use @ operator (at):
class WorkerThread: jnc.Scheduler {
override schedule(function* f()) {
// enqueue f and signal worker thread event
}
void workerThread() {
for (;;) {
// wait for worker thread event
function* f() = getNextRequest ();
f();
}
}
}
void foo(int x);
void bar() {
WorkerThread workerThread;
function* f(int) = foo @ workerThread; // create a scheduled pointer
(foo @ workerThread)(100); // or schedule now
// ...
f(200); // call through a scheduled pointer
}
Below is a real-life example (from our IO Ninja software) of assigning a socket event handler (which gets fired from within the socket IO thread) and scheduling it to be called from the main UI thread:
TcpListenerSession.construct(doc.PluginHost* pluginHost) {
// ...
m_listenerSocket = new io.Socket();
m_listenerSocket.m_onSocketEvent +=
onListenerSocketEvent @ pluginHost.m_mainThreadScheduler;
// ...
}