SILC_TASK_CALLBACK(silc_fsm_run);
SILC_TASK_CALLBACK(silc_fsm_finish_fsm);
-SILC_TASK_CALLBACK(silc_fsm_sema_timedout);
+SILC_TASK_CALLBACK(silc_fsm_event_timedout);
SILC_TASK_CALLBACK(silc_fsm_start_real_thread);
-static void silc_fsm_thread_termination_post(SilcFSMSema sema);
-static void silc_fsm_sema_ref(SilcFSMSema sema);
-static void silc_fsm_sema_unref(SilcFSMSema sema);
+static void silc_fsm_thread_termination_signal(SilcFSMEvent event);
+static void silc_fsm_event_ref(SilcFSMEvent event);
+static void silc_fsm_event_unref(SilcFSMEvent event);
void *silc_fsm_thread(void *context);
/* Allocate FSM */
if (!f->thread && f->u.m.lock)
silc_mutex_free(f->u.m.lock);
- if (f->thread && f->u.t.sema)
- silc_fsm_sema_free(f->u.t.sema);
+ if (f->thread && f->u.t.event)
+ silc_fsm_event_free(f->u.t.event);
silc_free(f);
}
SILC_ASSERT(t->thread);
- t->u.t.sema = silc_fsm_sema_alloc(t->u.t.fsm, 0);
- if (!t->u.t.sema)
+ t->u.t.event = silc_fsm_event_alloc(t->u.t.fsm);
+ if (!t->u.t.event)
return FALSE;
SILC_LOG_DEBUG(("Waiting for thread %p to terminate", thread));
- silc_fsm_sema_wait(t->u.t.sema, fsm);
+ silc_fsm_event_wait(t->u.t.event, fsm);
return TRUE;
}
SILC_LOG_DEBUG(("Running %s %p", fsm->thread ? "thread" : "FSM", fsm));
/* Run the states */
- do
+// do
status = fsm->next_state(fsm, fsm->fsm_context, fsm->state_context);
- while (status == SILC_FSM_CONTINUE);
+// while (status == SILC_FSM_CONTINUE);
switch (status) {
- case SILC_FSM_YIELD:
+ case SILC_FSM_ST_YIELD:
/* Continue through scheduler */
silc_fsm_continue(fsm);
break;
- case SILC_FSM_WAIT:
+ case SILC_FSM_ST_WAIT:
/* The machine is in hold */
SILC_LOG_DEBUG(("State wait %p", fsm));
fsm->synchronous = FALSE;
break;
- case SILC_FSM_FINISH:
+ case SILC_FSM_ST_FINISH:
/* Finish the state machine */
SILC_LOG_DEBUG(("State finish %p", fsm));
silc_fsm_finish(fsm);
if (fsm->thread) {
/* This is thread, send signal */
- if (fsm->u.t.sema) {
- silc_fsm_thread_termination_post(fsm->u.t.sema);
- silc_fsm_sema_free(fsm->u.t.sema);
- fsm->u.t.sema = NULL;
+ if (fsm->u.t.event) {
+ silc_fsm_thread_termination_signal(fsm->u.t.event);
+ silc_fsm_event_free(fsm->u.t.event);
+ fsm->u.t.event = NULL;
}
/* Remove the thread from machine */
}
}
-/* Allocate FSM semaphore */
+/* Allocate FSM event */
-SilcFSMSema silc_fsm_sema_alloc(SilcFSM fsm, SilcUInt32 value)
+SilcFSMEvent silc_fsm_event_alloc(SilcFSM fsm)
{
- SilcFSMSema sema;
+ SilcFSMEvent event;
- sema = silc_calloc(1, sizeof(*sema));
- if (silc_unlikely(!sema))
+ event = silc_calloc(1, sizeof(*event));
+ if (silc_unlikely(!event))
return NULL;
- silc_fsm_sema_init(sema, fsm, value);
- sema->allocated = TRUE;
+ silc_fsm_event_init(event, fsm);
+ event->allocated = TRUE;
- return sema;
+ return event;
}
-/* Initializes FSM semaphore */
+/* Initializes FSM event */
-void silc_fsm_sema_init(SilcFSMSema sema, SilcFSM fsm, SilcUInt32 value)
+void silc_fsm_event_init(SilcFSMEvent event, SilcFSM fsm)
{
- SILC_LOG_DEBUG(("Initializing semaphore %p", sema));
+ SILC_LOG_DEBUG(("Initializing event %p", event));
SILC_ASSERT(!fsm->thread);
- memset(sema, 0, sizeof(*sema));
- sema->fsm = fsm;
- sema->refcnt = 0;
- silc_list_init(sema->waiters, struct SilcFSMObject, next);
- sema->value = value;
+ memset(event, 0, sizeof(*event));
+ event->fsm = fsm;
+ event->refcnt = 0;
+ silc_list_init(event->waiters, struct SilcFSMObject, next);
}
-/* Free semaphore */
+/* Free event */
-void silc_fsm_sema_free(SilcFSMSema sema)
+void silc_fsm_event_free(SilcFSMEvent event)
{
- if (sema->refcnt > 0)
+ if (event->refcnt > 0)
return;
- if (silc_list_count(sema->waiters) > 0)
+ if (silc_list_count(event->waiters) > 0)
return;
- silc_free(sema);
+ silc_free(event);
}
-/* Reference semaphore */
+/* Reference event */
-static void silc_fsm_sema_ref(SilcFSMSema sema)
+static void silc_fsm_event_ref(SilcFSMEvent event)
{
- sema->refcnt++;
+ event->refcnt++;
}
-/* Unreference semaphore */
+/* Unreference event */
-static void silc_fsm_sema_unref(SilcFSMSema sema)
+static void silc_fsm_event_unref(SilcFSMEvent event)
{
- sema->refcnt--;
- if (sema->refcnt == 0 && sema->allocated)
- silc_fsm_sema_free(sema);
+ event->refcnt--;
+ if (event->refcnt == 0 && event->allocated)
+ silc_fsm_event_free(event);
}
-/* Wait until semaphore is non-zero. */
+/* Wait until event is non-zero. */
-SilcUInt32 silc_fsm_sema_wait(SilcFSMSema sema, void *fsm)
+SilcUInt32 silc_fsm_event_wait(SilcFSMEvent event, void *fsm)
{
- SilcMutex lock = sema->fsm->u.m.lock;
+ SilcMutex lock = event->fsm->u.m.lock;
silc_mutex_lock(lock);
- if (!sema->value) {
+ if (!event->value) {
#if defined(SILC_DEBUG)
SilcFSM entry;
- silc_list_start(sema->waiters);
- while ((entry = silc_list_get(sema->waiters)) != SILC_LIST_END)
+ silc_list_start(event->waiters);
+ while ((entry = silc_list_get(event->waiters)))
SILC_ASSERT(entry != fsm);
#endif /* SILC_DEBUG */
- SILC_LOG_DEBUG(("Waiting for semaphore %p", sema));
+ SILC_LOG_DEBUG(("Waiting for event %p", event));
/* Add the FSM to waiter list */
- silc_list_add(sema->waiters, fsm);
+ silc_list_add(event->waiters, fsm);
silc_mutex_unlock(lock);
return 0;
}
- SILC_LOG_DEBUG(("Acquired semaphore %p", sema));
+ SILC_LOG_DEBUG(("Received event %p", event));
/* It is possible that this FSM is in the list so remove it */
- silc_list_del(sema->waiters, fsm);
- sema->value--;
+ silc_list_del(event->waiters, fsm);
+ event->value--;
silc_mutex_unlock(lock);
return 1;
}
-/* Wait util semaphore is non-zero, or timeout occurs. */
+/* Wait util event is non-zero, or timeout occurs. */
-SilcUInt32 silc_fsm_sema_timedwait(SilcFSMSema sema, void *fsm,
- SilcUInt32 seconds, SilcUInt32 useconds,
- SilcBool *ret_to)
+SilcUInt32 silc_fsm_event_timedwait(SilcFSMEvent event, void *fsm,
+ SilcUInt32 seconds, SilcUInt32 useconds,
+ SilcBool *ret_to)
{
- SilcMutex lock = sema->fsm->u.m.lock;
+ SilcMutex lock = event->fsm->u.m.lock;
SilcFSM f = fsm;
SilcUInt32 value;
silc_mutex_lock(lock);
- if (f->sema_timedout) {
- SILC_LOG_DEBUG(("Semaphore was timedout"));
- f->sema_timedout = FALSE;
+ if (f->event_timedout) {
+ SILC_LOG_DEBUG(("Event waiting timedout"));
+ f->event_timedout = FALSE;
if (ret_to)
*ret_to = TRUE;
silc_mutex_unlock(lock);
silc_mutex_unlock(lock);
- value = silc_fsm_sema_wait(sema, fsm);
+ value = silc_fsm_event_wait(event, fsm);
if (!value) {
- silc_schedule_task_add_timeout(f->schedule, silc_fsm_sema_timedout,
+ silc_schedule_task_add_timeout(f->schedule, silc_fsm_event_timedout,
f, seconds, useconds);
- f->sema = sema;
+ f->event = event;
}
if (ret_to)
return value;
}
-/* Semaphore timedout */
+/* Event timedout */
-SILC_TASK_CALLBACK(silc_fsm_sema_timedout)
+SILC_TASK_CALLBACK(silc_fsm_event_timedout)
{
SilcFSM fsm = context;
- SilcMutex lock = fsm->sema->fsm->u.m.lock;
+ SilcMutex lock = fsm->event->fsm->u.m.lock;
- SILC_LOG_DEBUG(("Semaphore %p timedout", fsm->sema));
+ SILC_LOG_DEBUG(("Event %p timedout", fsm->event));
- /* Remove the waiter from the semaphore */
+ /* Remove the waiter from the event waiters list */
silc_mutex_lock(lock);
- silc_list_del(fsm->sema->waiters, fsm);
+ silc_list_del(fsm->event->waiters, fsm);
/* Continue */
- if (fsm->sema) {
+ if (fsm->event) {
silc_fsm_continue(fsm);
- fsm->sema_timedout = TRUE;
- fsm->sema = NULL;
+ fsm->event_timedout = TRUE;
+ fsm->event = NULL;
}
silc_mutex_unlock(lock);
}
-/* Signalled, semaphore */
+/* Signalled, event */
SILC_TASK_CALLBACK(silc_fsm_signal)
{
- SilcFSMSemaPost p = context;
- SilcMutex lock = p->sema->fsm->u.m.lock;
+ SilcFSMEventSignal p = context;
+ SilcMutex lock = p->event->fsm->u.m.lock;
- /* If the semaphore value has went to zero while we've been waiting this
- callback, sempahore has been been signalled already. It can happen
- when using real threads because the FSM may not be waiting state when
- the sempahore is posted. */
+ /* If the event value has went to zero while we've been waiting this
+ callback, the event has been been signalled already. It can happen
+ when using real threads because the FSM may not be in waiting state
+ when the sempahore is posted. */
silc_mutex_lock(lock);
- if (!p->sema->value) {
+ if (!p->event->value) {
silc_mutex_unlock(lock);
- silc_fsm_sema_unref(p->sema);
+ silc_fsm_event_unref(p->event);
silc_free(p);
return;
}
/* Signal */
silc_fsm_continue_sync(p->fsm);
- silc_fsm_sema_unref(p->sema);
+ silc_fsm_event_unref(p->event);
silc_free(p);
}
-/* Increase semaphore */
+/* Signal event */
-void silc_fsm_sema_post(SilcFSMSema sema)
+void silc_fsm_event_signal(SilcFSMEvent event)
{
SilcFSM fsm;
- SilcFSMSemaPost p;
- SilcMutex lock = sema->fsm->u.m.lock;
+ SilcFSMEventSignal p;
+ SilcMutex lock = event->fsm->u.m.lock;
- SILC_LOG_DEBUG(("Posting semaphore %p", sema));
+ SILC_LOG_DEBUG(("Signal event %p", event));
silc_mutex_lock(lock);
- sema->value++;
- silc_list_start(sema->waiters);
- while ((fsm = silc_list_get(sema->waiters)) != SILC_LIST_END) {
- if (fsm->sema) {
- silc_schedule_task_del_by_all(fsm->schedule, 0, silc_fsm_sema_timedout,
+ event->value++;
+ silc_list_start(event->waiters);
+ while ((fsm = silc_list_get(event->waiters)) != SILC_LIST_END) {
+ if (fsm->event) {
+ silc_schedule_task_del_by_all(fsm->schedule, 0, silc_fsm_event_timedout,
fsm);
- fsm->sema = NULL;
+ fsm->event = NULL;
}
p = silc_calloc(1, sizeof(*p));
if (silc_unlikely(!p))
continue;
- p->sema = sema;
+ p->event = event;
p->fsm = fsm;
- silc_fsm_sema_ref(sema);
+ silc_fsm_event_ref(event);
/* Signal through scheduler. Wake up destination scheduler in case
caller is a real thread. */
silc_mutex_unlock(lock);
}
-/* Post thread termination semaphore. Special function used only to
+/* Post thread termination event. Special function used only to
signal thread termination when SILC_FSM_THREAD_WAIT was used. */
-static void silc_fsm_thread_termination_post(SilcFSMSema sema)
+static void silc_fsm_thread_termination_signal(SilcFSMEvent event)
{
SilcFSM fsm;
- SilcMutex lock = sema->fsm->u.m.lock;
+ SilcMutex lock = event->fsm->u.m.lock;
- SILC_LOG_DEBUG(("Post thread terminate semaphore %p", sema));
+ SILC_LOG_DEBUG(("Post thread terminate event %p", event));
silc_mutex_lock(lock);
- silc_list_start(sema->waiters);
- while ((fsm = silc_list_get(sema->waiters)) != SILC_LIST_END) {
+ silc_list_start(event->waiters);
+ while ((fsm = silc_list_get(event->waiters)) != SILC_LIST_END) {
/* Signal on thread termination. Wake up destination scheduler in case
caller is a real thread. */
- silc_list_del(sema->waiters, fsm);
+ silc_list_del(event->waiters, fsm);
silc_fsm_continue(fsm);
silc_schedule_wakeup(fsm->schedule);
}
*
* SILC FSM Interface implements a finite state machine. The FSM can be
* used to implement all kinds of machines and protocols. The FSM supports
- * also threads and can be synchronized by using FSM semaphores. The FSM
+ * also threads and can be synchronized by using mutex locks. The FSM
* also supports real system threads. It is possible to create new FSM
* thread and then execute in real system thread, if platform supports
* threads.
*
- * The FSM provides semaphores because of their versatility. The FSM
- * semaphores can be used as mutual exclusion locks to protect critical
- * sections, and as conditional variables and signallers. The FSM
- * semaphores can safely be used to synchronize also FSM threads that are
- * executed in real system threads. This makes SILC FSM very effective
- * tool to implement complex machines whether they are executed in single
- * thread or in multiple threads.
+ * The FSM provides also asynchronous events that can be used to wait for
+ * some events or states to occur. The FSM events may be used as condition
+ * variables and signallers. The FSM events can safely be used in FSM
+ * threads that are executed in real system threads.
+ *
+ * To synchronize machines that use FSM threads that are executed in real
+ * system threads the SILC Mutex API (silcmutex.h) may be used. Normal
+ * multi-threaded coding conventions apply when programming with real FSM
+ * threads. If the FSM threads are not real system threads, synchronization
+ * is not required.
*
***/
***/
typedef struct SilcFSMObject SilcFSMThreadStruct;
-/****d* silcutil/SilcFSMAPI/SilcFSMStatus
+/****d* silcutil/SilcFSMAPI/SILC_FSM_CONTINUE
*
* NAME
*
- * typedef enum { ... } SilcFSMStatus;
+ * SILC_FSM_CONTINUE
*
* DESCRIPTION
*
- * Status values that the FSM state functions return. They dicatate
- * how the machine will behave after returning from the state function.
+ * Moves to next state synchronously. This macro is used in state
+ * functions to immediately move to next state. The state function
+ * returns in this macro. The macro has no arguments.
+ *
+ * EXAMPLE
+ *
+ * SILC_FSM_STATE(silc_foo_state)
+ * {
+ * ...
+ *
+ * // Move to next state now
+ * silc_fsm_next(fsm, silc_foo_next_state);
+ * SILC_FSM_CONTINUE;
+ * }
+ *
+ ***/
+#define SILC_FSM_CONTINUE \
+ return fsm->next_state(fsm, fsm->fsm_context, fsm->state_context);
+
+/****d* silcutil/SilcFSMAPI/SILC_FSM_YIELD
+ *
+ * NAME
+ *
+ * SILC_FSM_YIELD
*
- * The SILC_FSM_CONTINUE always moves to the next state synchronously.
+ * DESCRIPTION
*
- * The SILC_FSM_YIELD always moves to the next state through the
- * scheduler. Other threads will get running time with SILC_FSM_YIELD.
+ * Moves to next state through the machine scheduler. Other threads
+ * running in the machine will get running time with SILC_FSM_YIELD.
* When using real threads, using SILC_FSM_YIELD is usually unnecessary.
+ * The state function returns in this macro. The macro has no arguments.
+ *
+ ***/
+#define SILC_FSM_YIELD return SILC_FSM_ST_YIELD;
+
+/****d* silcutil/SilcFSMAPI/SILC_FSM_WAIT
*
- * The SILC_FSM_WAIT will suspend the machine until it is awaken.
+ * NAME
*
- * The SILC_FSM_FINISH finished the machine or thread and calls its
- * destructor, if defined. If the machine is finished when it has
- * running threads the machine will fatally fail. User must always
- * finish the threads before finishing the machine.
+ * SILC_FSM_WAIT
*
- * SOURCE
- */
-typedef enum {
- SILC_FSM_CONTINUE, /* Continue immediately to next state */
- SILC_FSM_YIELD, /* Continue to next state through scheduler */
- SILC_FSM_WAIT, /* Wait for some async call or timeout */
- SILC_FSM_FINISH, /* Finish state machine and call destructor
- through scheduler */
-} SilcFSMStatus;
-/***/
+ * DESCRIPTION
+ *
+ * Suspends the machine or thread until it is awaken. This is used
+ * when asynchronous call is made or timer is set, or something else
+ * that requires waiting. The state function returns in this macro.
+ * The macro has no arguments.
+ *
+ ***/
+#define SILC_FSM_WAIT return SILC_FSM_ST_WAIT
+
+/****d* silcutil/SilcFSMAPI/SILC_FSM_FINISH
+ *
+ * NAME
+ *
+ * SILC_FSM_FINISH
+ *
+ * DESCRIPTION
+ *
+ * Finishes the machine or thread and calls its destructor, if defined.
+ * If the machine is finished when it has running threads the machine
+ * will fatally fail. User must always finish the threads before
+ * finishing the machine. The macro has no arguments.
+ *
+ ***/
+#define SILC_FSM_FINISH return SILC_FSM_ST_FINISH
/****f* silcutil/SilcFSMAPI/SilcFSMDestructor
*
*
* The destructor callback that was set in silc_fsm_alloc or in
* silc_fsm_init function. It will be called when a state function
- * returns SILC_FSM_FINISH. This function will be called through
+ * calls SILC_FSM_FINISH. This function will be called through
* the scheduler; it will not be called immediately after the state
- * function returns SILC_FSM_FINISH, but will be called later.
- * The `fsm' may be freed in this function.
+ * function calls SILC_FSM_FINISH, but will be called later. The `fsm'
+ * may be freed in this function.
*
***/
typedef void (*SilcFSMDestructor)(SilcFSM fsm, void *fsm_context,
*
* The destructor callback that was set in silc_fsm_thread_alloc or in
* silc_fsm_thread_init function. It will be called when a state function
- * returns SILC_FSM_FINISH. This function will be called through
- * the scheduler; it will not be called immediately after the state
- * function returns SILC_FSM_FINISH, but will be called later. The
- * `thread' may be freed in this function.
+ * calls SILC_FSM_FINISH. This function will be called through the
+ * scheduler; it will not be called immediately after the state function
+ * calls SILC_FSM_FINISH, but will be called later. The `thread' may
+ * be freed in this function.
*
* NOTES
*
*
* DESCRIPTION
*
- * This macro is used to declare a FSM state function. The `fsm' is
+ * This macro is used to declare an FSM state function. The `fsm' is
* the SilcFSM or SilcFSMThread context, the `fsm_context' is the context
* given as argument to silc_fsm_alloc, silc_fsm_init, silc_fsm_thread_init,
* or silc_fsm_thread_alloc function. The `state_context' is the optional
* SOURCE
*/
#define SILC_FSM_STATE(name) \
-SilcFSMStatus name(struct SilcFSMObject *fsm, void *fsm_context, \
- void *state_context)
+int name(struct SilcFSMObject *fsm, void *fsm_context, void *state_context)
/***/
/* State function callback */
-typedef SilcFSMStatus (*SilcFSMStateCallback)(struct SilcFSMObject *fsm,
- void *fsm_context,
- void *state_context);
+typedef int (*SilcFSMStateCallback)(struct SilcFSMObject *fsm,
+ void *fsm_context,
+ void *state_context);
/****d* silcutil/SilcFSMAPI/SILC_FSM_CALL
*
assert(!silc_fsm_set_call(fsm, TRUE)); \
function; \
if (!silc_fsm_set_call(fsm, FALSE)) \
- return SILC_FSM_CONTINUE; \
- return SILC_FSM_WAIT; \
+ SILC_FSM_CONTINUE; \
+ SILC_FSM_WAIT; \
} while(0)
/****d* silcutil/SilcFSMAPI/SILC_FSM_CALL_CONTINUE
*
* This macro is the only way to safely make sure that the thread has
* terminated by the time FSM continues from the waiting state. Using
- * semaphores to signal from the thread before SILC_FSM_FINISH is returned
+ * FSM events to signal from the thread before SILC_FSM_FINISH is called
* works with normal FSM threads, but especially with real system threads
* it does not guarantee that the FSM won't continue before the thread has
* actually terminated. Usually this is not a problem, but it can be a
#define SILC_FSM_THREAD_WAIT(thread) \
do { \
silc_fsm_thread_wait(fsm, thread); \
- return SILC_FSM_WAIT; \
+ SILC_FSM_WAIT; \
} while(0)
/****f* silcutil/SilcFSMAPI/silc_fsm_alloc
*
* NOTES
*
- * Note the limitations on using `real_thread' boolean to indicate running
- * the FSM thread in a real system thread:
- *
* If the system does not support threads, then this function will revert
* back to normal FSM threads.
*
* If the `real_thread' is TRUE then FSM will allocate new SilcSchedule
- * for the FSM thread. This is done because the SilcSchedule that the
- * `fsm' use cannot be used in the thread. This is limitation in the
- * SilcSchedule implementation. If you need scheduler in the real thread
- * it is strongly recommended that you use the SilcSchedule that is
- * allocated for the thread. You can retrieve the SilcSchedule from the
- * thread using silc_fsm_get_schedule function. Note that, the allocated
+ * for the FSM thread. If you need scheduler in the real thread it is
+ * strongly recommended that you use the SilcSchedule that is allocated
+ * for the thread. You can retrieve the SilcSchedule from the thread
+ * using silc_fsm_get_schedule function. Note that, the allocated
* SilcSchedule will become invalid after the thread finishes.
*
- * You may still however use the original SilcSchedule if you wish. In
- * this case note its limitation: you may only add and/or remove tasks,
- * tasks cannot be executed in the thread. You will need to deliver the
- * original SilcSchedule to the thread in the `thread_context' if you wish
- * to use it.
- *
- * If `real_thread' is FALSE then no limitations on what can be run in
- * the thread exist. In this case silc_fsm_get_schedule will return
+ * If `real_thread' is FALSE the silc_fsm_get_schedule will return
* the SilcSchedule that was originally given to silc_fsm_alloc or
* silc_fsm_init.
*
* DESCRIPTION
*
* Set the next state to be executed. If the state function that
- * call this function returns SILC_FSM_CONTINUE, the `next_state'
- * will be executed immediately. If it returns SILC_FSM_YIELD it
+ * call this function calls SILC_FSM_CONTINUE, the `next_state'
+ * will be executed immediately. If it calls SILC_FSM_YIELD it
* yields the thread and the `next_state' will be run after other
* threads have run first. This function must always be used to set
* the next state in the machine or thread. This function is used
*
* // Move to next state
* silc_fsm_next(fsm, next_state);
- * return SILC_FSM_CONTINUE;
+ * SILC_FSM_CONTINUE;
*
***/
void silc_fsm_next(void *fsm, SilcFSMStateCallback next_state);
* DESCRIPTION
*
* Set the next state to be executed later, at the specified time.
- * The SILC_FSM_WAIT must be returned in the state function if this
+ * The SILC_FSM_WAIT must be called in the state function if this
* function is called. If any other state is returned machine operation
* is undefined. The machine or thread will move to `next_state' after
* the specified timeout. This function is used with both SilcFSM and
* NOTES
*
* If both `seconds' and `useconds' are 0, the effect is same as calling
- * silc_fsm_next function, and SILC_FSM_CONTINUE must be returned.
+ * silc_fsm_next function, and SILC_FSM_CONTINUE must be called.
*
* If silc_fsm_continue or silc_fsm_continue_sync is called while the
* machine or thread is in SILC_FSM_WAIT state the timeout is automatically
*
* // Move to next state after 10 seconds
* silc_fsm_next_later(fsm, next_state, 10, 0);
- * return SILC_FSM_WAIT;
+ * SILC_FSM_WAIT;
*
***/
void silc_fsm_next_later(void *fsm, SilcFSMStateCallback next_state,
*
* Finishes the `fsm'. This function may be used in case the FSM
* needs to be finished outside FSM states. Usually FSM is finished
- * by returning SILC_FSM_FINISH from the state, but if this is not
+ * by calling SILC_FSM_FINISH from the state, but if this is not
* possible this function may be called. This function is used with
* both SilcFSM and SilcFSMThread contexts.
*
***/
SilcBool silc_fsm_is_started(void *fsm);
-/* FSM Semaphores */
+/* FSM Events */
-/****s* silcutil/SilcFSMAPI/SilcFSMSema
+/****s* silcutil/SilcFSMAPI/SilcFSMEvent
*
* NAME
*
- * typedef struct SilcFSMSemaObject *SilcFSMSema;
+ * typedef struct SilcFSMEventObject *SilcFSMEvent;
*
* DESCRIPTION
*
- * The FSM semaphore context allocated with silc_fsm_sema_alloc. The
- * caller must free it with silc_fsm_sema_free. It is also possible
- * to use pre-allocated SilcFSMSemaStruct instead of SilcFSMSema context.
+ * The FSM event context allocated with silc_fsm_event_alloc. The
+ * caller must free it with silc_fsm_event_free. It is also possible
+ * to use pre-allocated SilcFSMEventStruct instead of SilcFSMEvent context.
*
***/
-typedef struct SilcFSMSemaObject *SilcFSMSema;
+typedef struct SilcFSMEventObject *SilcFSMEvent;
-/****s* silcutil/SilcFSMAPI/SilcFSMSemaStruct
+/****s* silcutil/SilcFSMAPI/SilcFSMEventStruct
*
* NAME
*
- * typedef struct SilcFSMSemaObject SilcFSMSemaStruct;
+ * typedef struct SilcFSMEventObject SilcFSMEventStruct;
*
* DESCRIPTION
*
- * The FSM semaphore context that can be used as pre-allocated context.
- * It is initialized with silc_fsm_sema_init. It need not be
+ * The FSM event context that can be used as pre-allocated context.
+ * It is initialized with silc_fsm_event_init. It need not be
* uninitialized.
*
***/
-typedef struct SilcFSMSemaObject SilcFSMSemaStruct;
+typedef struct SilcFSMEventObject SilcFSMEventStruct;
-/****f* silcutil/SilcFSMAPI/silc_fsm_sema_alloc
+/****f* silcutil/SilcFSMAPI/silc_fsm_event_alloc
*
* SYNOPSIS
*
- * SilcFSMSema silc_fsm_sema_alloc(SilcFSM fsm, SilcUInt32 value);
+ * SilcFSMEvent silc_fsm_event_alloc(SilcFSM fsm);
*
* DESCRIPTION
*
- * Allocates FSM semaphore with initial value of `value'. Semaphores are
- * counters for resources shared between machine and threads. Semaphores
- * can be waited until the semaphore value is non-zero. The FSM will be
- * suspended when waiting for semaphore. When the semaphore is incremented
- * all that are waiting for the semaphore will be signalled and awaken.
+ * Allocates asynchronous FSM event. FSM events are asynchronous events
+ * that can be waited and signalled. They can be used as condition
+ * variables and signallers. They can be used for example to wait that
+ * some event happens, some thread moves to a specific state or similar.
+ * The FSM Events may also be used in FSM threads that are executed in
+ * real system threads. It is safe to wait and signal the event from
+ * threads.
*
- * Semaphores can be used to wait for example when thread terminates, or
- * when thread moves into a specific state, or to protect critical
- * sections. The FSM semaphores can be used also in FSM threads that are
- * executed in real system threads.
- *
- * Use the macros SILC_FSM_SEMA_WAIT and SILC_FSM_SEMA_TIMEDWAIT to wait
- * for semaphore. Use the SILC_FSM_SEMA_POST macro to increment the
- * counter and wake up all waiters.
+ * Use the macros SILC_FSM_EVENT_WAIT and SILC_FSM_EVENT_TIMEDWAIT to wait
+ * for the event. Use the SILC_FSM_EVENT_SIGNAL macro to signal all the
+ * waiters.
*
***/
-SilcFSMSema silc_fsm_sema_alloc(SilcFSM fsm, SilcUInt32 value);
+SilcFSMEvent silc_fsm_event_alloc(SilcFSM fsm);
-/****f* silcutil/SilcFSMAPI/silc_fsm_sema_init
+/****f* silcutil/SilcFSMAPI/silc_fsm_event_init
*
* SYNOPSIS
*
- * void silc_fsm_sema_init(SilcFSMSema sema, SilcFSM fsm, SilcUInt32 value);
+ * void silc_fsm_event_init(SilcFSMEvent event, SilcFSM fsm);
*
* DESCRIPTION
*
- * Initializes a pre-allocates semaphore context. This call is
- * equivalent to silc_fsm_sema_alloc except this use the pre-allocated
+ * Initializes a pre-allocates FSM event context. This call is
+ * equivalent to silc_fsm_event_alloc except this use the pre-allocated
* context. This fuction does not allocate any memory.
*
***/
-void silc_fsm_sema_init(SilcFSMSema sema, SilcFSM fsm, SilcUInt32 value);
+void silc_fsm_event_init(SilcFSMEvent event, SilcFSM fsm);
-/****f* silcutil/SilcFSMAPI/silc_fsm_sema_free
+/****f* silcutil/SilcFSMAPI/silc_fsm_event_free
*
* SYNOPSIS
*
- * void silc_fsm_sema_free(SilcFSMSema sema);
+ * void silc_fsm_event_free(SilcFSMEvent event);
*
* DESCRIPTION
*
- * Free the semaphore allocated by silc_fsm_sema_alloc function.
+ * Free the event allocated by silc_fsm_event_alloc function.
*
***/
-void silc_fsm_sema_free(SilcFSMSema sema);
+void silc_fsm_event_free(SilcFSMEvent event);
-/****d* silcutil/SilcFSMAPI/SILC_FSM_SEMA_WAIT
+/****d* silcutil/SilcFSMAPI/SILC_FSM_EVENT_WAIT
*
* NAME
*
- * SILC_FSM_SEMA_WAIT(semaphore)
+ * SILC_FSM_EVENT_WAIT(event)
*
* DESCRIPTION
*
- * Macro used to wait for the `semaphore' to become non-zero. The
- * machine will be suspended while it is waiting for the semaphore.
+ * Macro used to wait for the `event' to be signalled. The machine
+ * or thread will be suspended while it is waiting for the event.
* This macro can only be used in FSM state functions. When the
- * semaphore is signalled the FSM will re-enter the current state (or
+ * event is signalled the FSM will re-enter the current state (or
* state that was set with silc_fsm_next before waiting).
*
* EXAMPLE
*
* // Signalling example
- * ctx->async_sema = silc_fsm_sema_alloc(fsm, 0);
+ * ctx->async_event = silc_fsm_event_alloc(fsm);
* ...
*
* SILC_FSM_STATE(silc_foo_state)
* ...
*
* // Wait here for async call to complete
- * SILC_FSM_SEMA_WAIT(ctx->async_sema);
+ * SILC_FSM_EVENT_WAIT(ctx->async_event);
*
* // Async call completed
* if (ctx->async_success == FALSE)
* ...
* }
*
- * // Mutual exclusion example
- * ctx->lock = silc_fsm_sema_alloc(fsm, 1);
- * ...
- *
- * SILC_FSM_STATE(silc_foo_state)
- * {
- * ...
- * SILC_FSM_SEMA_WAIT(ctx->lock);
- * very critical stuff...
- * SILC_FSM_SEMA_POST(ctx->lock);
- * ...
- * }
- *
***/
-#define SILC_FSM_SEMA_WAIT(sema) \
+#define SILC_FSM_EVENT_WAIT(event) \
do { \
- if (silc_fsm_sema_wait(sema, fsm) == 0) \
- return SILC_FSM_WAIT; \
+ if (silc_fsm_event_wait(event, fsm) == 0) \
+ SILC_FSM_WAIT; \
} while(0)
-/****d* silcutil/SilcFSMAPI/SILC_FSM_SEMA_TIMEDWAIT
+/****d* silcutil/SilcFSMAPI/SILC_FSM_EVENT_TIMEDWAIT
*
* NAME
*
- * SILC_FSM_SEMA_TIMEDWAIT(semaphore, seconds, useconds, timedout)
+ * SILC_FSM_EVENT_TIMEDWAIT(event, seconds, useconds, timedout)
*
* DESCRIPTION
*
- * Macro used to wait for the `semaphore' to become non-zero, or until
+ * Macro used to wait for the `event' to be signalled, or until
* the timeout specified by `seconds' and `useconds' has elapsed. If
- * the timeout occurs before the semaphore becomes non-zero, the machine
+ * the timeout occurs before the event is signalled, the machine
* will wakeup. The `timedout' is SilcBool pointer and if it is
* non-NULL indication of whether timeout occurred or not is saved to
* the pointer. This macro can only be used in FSM state functions.
- * When the semaphore is signalled or timedout the FSM will re-enter
+ * When the event is signalled or timedout the FSM will re-enter
* the current state (or state that was set with silc_fsm_next before
* waiting).
*
* ...
*
* // Wait here for async call to complete, or 10 seconds for timeout
- * SILC_FSM_SEMA_TIMEDWAIT(ctx->async_sema, 10, 0, &timedout);
+ * SILC_FSM_EVENT_TIMEDWAIT(ctx->async_event, 10, 0, &timedout);
*
* // See if timeout occurred
* if (timedout == TRUE)
* }
*
***/
-#define SILC_FSM_SEMA_TIMEDWAIT(sema, seconds, useconds, ret_to) \
-do { \
- if (silc_fsm_sema_timedwait(sema, fsm, seconds, useconds, ret_to) == 0) \
- return SILC_FSM_WAIT; \
+#define SILC_FSM_EVENT_TIMEDWAIT(event, seconds, useconds, ret_to) \
+do { \
+ if (silc_fsm_event_timedwait(event, fsm, seconds, useconds, ret_to) == 0) \
+ SILC_FSM_WAIT; \
} while(0)
-/****f* silcutil/SilcFSMAPI/SILC_FSM_SEMA_POST
+/****f* silcutil/SilcFSMAPI/SILC_FSM_EVENT_SIGNAL
*
* SYNOPSIS
*
- * SILC_FSM_SEMA_POST(semaphore)
+ * SILC_FSM_EVENT_SIGNAL(event)
*
* DESCRIPTION
*
- * Increases the semaphore counter and awakens everybody that are
- * waiting for this semaphore. This macro never blocks. It can be
- * safely called at any place in state function and in asynchronous
- * callbacks or other functions.
+ * Signals the `event' and awakens everybody that are waiting for this
+ * event. This macro never blocks. It can be safely called at any place
+ * in state function and in asynchronous callbacks or other functions.
*
* EXAMPLE
*
*
* // Notify all waiters
* ctx->async_success = TRUE;
- * SILC_FSM_SEMA_POST(ctx->async_sema);
+ * SILC_FSM_EVENT_SIGNAL(ctx->async_event);
* ...
* }
*
***/
-#define SILC_FSM_SEMA_POST(sema) \
+#define SILC_FSM_EVENT_SIGNAL(event) \
do { \
- silc_fsm_sema_post(sema); \
+ silc_fsm_event_signal(event); \
} while(0)
#include "silcfsm_i.h"