![]() |
License / Documentation home / Help and feedback | ![]() |
In order to control the execution of events, MIT provides a timing loop which it uses in both the Hub and servers. We document this loop here. As of 3.0, the functions Gal_AddTimedTask, etc. are no longer recommended; use Gal_AddTask, etc. instead.
It is now possible to use a version of the timed task API to produce threads instead.
In the normal case, this task will be started as soon as it's created.
In the threaded case, this is exceptionally important, because if you need
to store the task away anywhere, or do anything with it before it starts,
you must create the task and start it later. You can do this by passing -1
as the value of num_millisecs and using Gal_StartTask.
The Gal_TaskPkg * structure argument to the task provides five things:
Gal_TaskPkg *Gal_AddTaskWithSocketIO(void
(*task)(Gal_TaskPkg *), void *refcon, long num_millisecs,
int read_blocking_available, GAL_SOCKET *read_socket, GAL_SOCKET
*write_socket, void (*cleanup_fn)(void *))
Gal_TaskPkg *Gal_AddTaskWithFileIO(void
(*task)(Gal_TaskPkg *), void *refcon, long num_millisecs,
int read_blocking_available, FILE *read_file, FILE *write_file,
void (*cleanup_fn)(void *))
Adds the task with sensitivity to I/O on sockets and file descriptors, respectively.
Otherwise, identical to Gal_AddTask(). Note that file I/O polling is not available
on Win32.
typedef int (*Gal_TaskConditionFn)(void *caller_data);
Gal_TaskPkg *Gal_AddTaskExtended(void
(*task)(Gal_TaskPkg *), void *caller_data, long num_millisecs,
int read_blocking_available, GAL_SOCKET *read_socket, GAL_SOCKET
*write_socket, GAL_SOCKET *err_socket, FILE *read_file,
FILE *write_file, FILE*err_file, Gal_TaskConditionFn condition,
void (*cleanup_fn)(void *))
Adds the task with sensitivity to the entire range of elements, including
I/O on sockets and file descriptors, the additional possibility of error streams
and task conditions. Task conditions are passed the caller_data, and
if the task condition returns nonzero, the task will be executed in advance
of its normal time expiration. Otherwise, identical to Gal_AddTask(). Note
that file I/O polling is not available on Win32.
int Gal_StartTask(Gal_TaskPkg
*pkg, int num_millisecs)
Starts the task. If the polling interval in the task pkg is -1, and
num_millisecs is > -1, take the appropriate action to start the
task (i.e., insert it into the task array in non-threaded mode, or create
and start a thread for it in threaded mode). This function can be used to
start a task after it's been created.
void Gal_ReAddTask(Gal_TaskPkg
*p, void *refcon, long num_millisecs, int read_blocking_available,
void (*cleanup_fn)(void *))
This function is identical to Gal_AddTask(), except it is to be used when
tasks are supposed to be refired, as described in Gal_AddTask().
In the non-threaded case, it just adds the Gal_TaskPkg * structure back to
the list of timed tasks; in the threaded case, the thread is continued. This
function is intended to be called from inside the task which p was
passed to. If the task is not refired, the task package is freed; the programmer
is responsible for managing the memory associated with refcon.
void Gal_ReAddTaskWithSocketIO(Gal_TaskPkg
*p, void *refcon, long num_millisecs, int read_blocking_available,
GAL_SOCKET *read_socket, GAL_SOCKET *write_socket, void (*cleanup_fn)(void
*))
void Gal_ReAddTaskWithFileIO(Gal_TaskPkg
*p, void *refcon, long num_millisecs, int read_blocking_available,
FILE *read_file, FILE *write_file, void (*cleanup_fn)(void
*))
Re-adds the task with sensitivity to I/O on sockets and file descriptors,
respectively. Otherwise, identical to Gal_ReAddTask(). Note that file I/O
polling is not available on Win32.
void Gal_ReAddTaskExtended(Gal_TaskPkg
*p, void *caller_data, long num_millisecs, int read_blocking_available,
GAL_SOCKET *read_socket, GAL_SOCKET *write_socket, GAL_SOCKET
*err_socket, FILE *read_file, FILE *write_file, FILE
*err_file, Gal_TaskConditionFn condition, void (*cleanup_fn)(void
*))
Re-adds the task with sensitivity sensitivity to the entire range of elements,
including I/O on sockets and file descriptors, the additional possibility
of error streams and task conditions. Otherwise, identical to Gal_ReAddTask().
Note that file I/O polling is not available on Win32.
int Gal_TaskPkgRunReasons(Gal_TaskPkg
*pkg)
Returns the logical OR of the reasons the package was run. Possible reasons
are:
value | description |
GAL_SOCKET_READABLE | The task was fired because a read socket had data |
GAL_SOCKET_WRITABLE | The task was fired because a write socket had data |
GAL_SOCKET_ERR_READABLE | The task was fired because an error socket had data |
GAL_FILE_READABLE | The task was fired because a read file pointer had data |
GAL_FILE_WRITABLE | The task was fired because a write file pointer had data |
GAL_FILE_ERR_READABLE | The task was fired because an error file pointer had data |
GAL_TIMER_EXPIRED | The task was fired because it had slept for the required number of milliseconds |
GAL_CONDITION_SATISFIED | The task was fired because its task condition function returned nonzero |
GAL_THREAD_READABLE | The task was fired because a blocking read had data in the threaded case |
So you can check, for instance, to see if your task fired because of a readable file as follows:
if (Gal_TaskPkgRunReasons(pkg) & GAL_FILE_READABLE) {
...
}
voidGal_RemoveTask(Gal_TaskPkg
*task_id)
Removes the task task_id.
int Gal_TaskPkgBlocking(Gal_TaskPkg
*pkg)
If 1, the task should set its read file descriptors to blocking mode; if
0, non-blocking.
void *Gal_TaskPkgData(Gal_TaskPkg
*pkg)
Returns the data associated with the package. This is the same as the value
of the refcon argument to Gal_AddTask and
Gal_ReAddTask.
void Gal_TimedTasksLoop(void)
This function initiates the timed task loop. It loops until Gal_TimedTasksLoopExit
is called.
void Gal_TimedTasksLoopExit(void)
This function halts the timed tasks loop. All tasks in the queue are completed,
but no other tasks are queued.
typedef void (*Gal_IdleFunction)(void *client_data);
int Gal_AddIdleFunction(Gal_IdleFunction
func, void *client_data)
Adds a function to the list of functions which the timed task loop will
execute when there are no tasks to fire. The client_data argument
is passed to func when it's called. Unlike tasks, which are removed
after they're fired, idle functions remain installed until they're removed
with Gal_RemoveIdleFunction().
void Gal_RemoveIdleFunction(Gal_IdleFunction
func)
Removes func from the list of functions which the timed task loop
executes when there are no tasks to fire.
void Gal_RunIdleFunctions()
Runs the idle functions. Called by the timed task loop, but can also be
called explicitly.
If you want to use the timed task loop in a threaded context, it should work (we haven't tested it extensively). In particular, you can only run the timed task loop from one thread at a time, and you can only shut down the loop from that thread. However, be warned that if you use the -thread argument, the timed task loop will not be started automatically; you will have to start it yourself.
void Gal_EnableTimedTaskThreads()
This function controls whether tasks added via Gal_AddTask() and Gal_ReAddTask()
are handled via timed tasks or via threads. Once timed task threads are enabled,
they can only disabled by Gal_EndTasks(). Gal_EnableTimedTaskThreads() is
the function which is invoked when you provide the -thread argument
to servers when threads are enabled. If the user is writing his/her own main()
and wants to avoid the timed task loop for server, connection and broker
handling but would like threads to handle these facilities, the user can enable
this facility with this function.
int Gal_TimedTaskThreadsEnabled()
Returns 1 if timed tasks threads have enabled via Gal_EnableTimedTaskThreads(),
0 otherwise. The user should never need to call this function.
void Gal_TimedTaskLoopThreadWaiter(void)
Waits until all the tasks are completed. This function is the threaded equivalent
of Gal_TimedTasksLoop. The main server loop
uses it in the threaded case to delay the actions of the main thread so that
GalSS_RunServer
only returns when the server is finished.
void Gal_EndTasks(int
immediate)
This is a more general version of Gal_TimedTasksLoopExit.
It causes one of two types of exits: immediate and deferred. An immediate
exit will cancel tasks at the most immediate possible exit point, while
a deferred exit will cancel tasks which are already "scheduled" to happen.
If immediate is non-zero, this call causes an immediate exit,
otherwise a deferred exit. This function halts both threads (if running)
and the timed task loop (if running).
void Gal_MaybeEndTask(int
immediate, int deferred)
This function introduces an exit point into a long-running task. For instance,
if your (threaded) task is looping forever and doing blocking reads, you might
choose to call Gal_MaybeEndTask() to check to see if another thread has scheduled
an exit via Gal_EndTasks. If it finds an immediate scheduled exit and immediate
is nonzero, or if it finds a deferred scheduled exit and deferred
is nonzero, the thread will terminate.
int Gal_AddTimedTask(void
*task, void *refcon, long num_millisecs)
Use this function to add a timed task. The task is a function which
takes refcon as its argument and returns void. The num_millisecs
is how long in milliseconds after the task is added (or, if the loop hasn't
been started, how long after the loop is started) the task should be executed.
Once the task is executed, it is removed from the list of timed tasks; so
typically the last thing the task will do is call Gal_AddTimedTask
again. This function is implemented in terms of the internal function Gal_AddTask.
int Gal_AddTimedTaskWithFileIO(void
*task, void *refcon, long num_millisecs, FILE *read_file,
FILE *write_file)
Use this function to add a timed task which is sensitive to input and output
on file descriptors. If any of the elements in either of the file descriptor
sets is ready for reading and writing before num_milliseconds has elapsed,
the task will nonetheless be executed. Note that file I/O polling is not
available on Win32.
int Gal_AddTimedTaskWithSocketIO(void
*task, void *refcon, long num_millisecs, GAL_SOCKET
*read_socket, GAL_SOCKET *write_socket)
Use this function to add a timed task which is sensitive to input and output
on sockets. If any of the elements in either of the file descriptor sets is
ready for reading and writing before num_milliseconds has elapsed,
the task will nonetheless be executed.
int Gal_RemoveTimedTask(void
*task, void *refcon)
Removes the given timed task. Note that tasks are distinguished by task
and refcon, so it's not a good idea to define multiple timed tasks
with the same task and refcon.
![]() |
License / Documentation home / Help and feedback | ![]() |