FairThreads explicitely introduces schedulers, of type
ft_scheduler_t. Before being used, a scheduler must be created
by calling the function
In order to be executed, a scheduler must be started by a call to the
ft_scheduler_start. Note that several schedulers
can be used without problem simultaneously in the same program.
Fair threads are of type
ft_thread_t. The call
ft_thread_create(s,r,c,a) creates a thread in the
s. The thread is automatically started as soon as
it is created. The function
r is executed by the
thread, and the parameter
a is transmitted to it.
c is executed by the thread if it is stopped
ft_scheduler_stop). The parameter
a is also
transmitted to it, if this happens.
Events are of the type
ft_event_t. An event is created by
calling the function
ft_event_create which takes as
parameter the scheduler in charge of it.
Automata are fair threads of the type
with the function
ft_automaton_create. The thread returned by
ft_automaton_create(s,r,c,a) is executed as an automaton by
s. The function
r executed by the
automaton must be defined with the macro
Control of Threads
ft_scheduler_stop(t) gives to the scheduler which
executes the thread
t the order to stop it. The stop will
become actual at the begining of the next instant of the scheduler, in
order to assure that
t is in a stable state when stopped.
ft_scheduler_suspend(t) gives to the scheduler
t the order to suspend
suspension will become actual at the begining of the next instant of
the scheduler. The function
ft_scheduler_resume is used to
resume execution of suspended threads.
Broadcast of Events
ft_scheduler_broadcast(e) gives to the
scheduler of the event
e the order to broadcast it to all
threads running in the scheduler. The event will be actually generated
at the begining of the next instant of the scheduler. The call
ft_scheduler_broadcast_value(e,v) associates the value
v can be read using
ft_thread_cooperate() is the explicit way for the
calling thread to return control to the scheduler running it. The
ft_thread_cooperate_n(i) is equivalent to a sequence of
ft_thread_join(t) suspends the execution of the
calling thread until the thread
t terminates (either
normally or because it is stopped). Note that
t needs not to be
linked or running in the scheduler of the calling thread. With
ft_thread_join_n(t,i) the suspension takes at most
ft_thread_generate(e) generates the event
e in the scheduler which was associated to it, when created. The
v to the list of values associated to
e during the current
instant (these values can be read using
ft_thread_await(e) suspends the execution of the calling thread
until the generation of the event
e. Execution is resumed as soon as the
event is generated. With
ft_thread_await_n(e,i), the waiting takes at most
ft_thread_select(k,array,mask) suspends the execution of the calling thread
until the generation of one element of
array which is an array of
k events. Then,
mask, which is an array of
k boolean values, is set accordingly.
ft_thread_select_n(k,array,mask,i), the waiting takes at most
Getting Events Values
ft_thread_get_value(e,i,r) is an attempt to get the
associated to the event
e during the current instant. If such a
value exists, it is returned in
r and the call immediately terminates. Otherwise,
the value NULL is returned at the next instant. The return code of the call indicates if
the call was sucessful or not.
Link and Unlink
ft_thread_unlink() unlinks the calling thread
t from the scheduler in which it was previously
t will no longer synchronize, instant after
instant, with other threads linked to the scheduler. Actually, after
t behaves as a standard native thread.
ft_thread_link(s) links the calling thread to the
s. The calling thread must be unlinked when
executing the call. The linkage becomes actual at the begining of the
next instant of
In presence of unlinked threads, locks can be needed to protect data
shared between unlinked and linked threads. Standard mutexes are used
for this purpose. The call
p is a mutex, suspends the calling thread until the moment
p can be locked. The lock is released using
ft_thread_mutex_unlock. Locks owned by a thread are automatically
released when the thread terminates definitively or is stopped.
Automata are coded using macros. Here are the macros to define the automaton structure:
The following macros start the state whose number is
AUTOMATON(aut) declares the automaton
DEFINE_AUTOMATON(aut) starts definition of the automaton
BEGIN_AUTOMATON starts the state list.
END_AUTOMATON ends the state list.
Going from state to state is possible with:
STATE(num) introduces a standard state.
STATE_AWAIT_N(num,event,delay) are states
are states to join
STATE_STAY(num,n) is a state which keeps execution in it for
STATE_GET_VALUE(num,event,n,result) is a state to get the
STATE_AWAIT_N to an array of events of length
Finally, the following macros define some special variables:
GOTO(num) blocks execution for the current instant
and sets the state for the next instant to be state
GOTO_NEXT blocks execution for the current instant
and sets the state for the next instant to be the next state.
IMMEDIATE(num) forces execution to jump to state
which is immediately executed.
RETURN immediately terminates the automaton.
SELF is the automaton.
SET_LOCAL(data) sets the local data of the automaton.
LOCAL is the local data of the automaton.
ARGS is the argument that is passed at creation to the automaton.
RETURN_CODE is the error code set by macros run during automaton execution.
The calling thread is returned by
The scheduler of the calling thread is returned by
ft_pthread(t) returns the native pthread which
executes the fair thread
t. This function gives direct
access to the Pthreads implementation of FairThreads. In the rest of the
paper, native thread and pthread will be considered as synonymous.
ft_exit is equivalent to
pthread_exit. The basic use of
ft_exit is to terminate
the pthread which is running the function
exiting from the whole process.