Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2005, 2006, 2007 Pekka Riikonen
+ Copyright (C) 2005 - 2008 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
*/
-/****h* silcutil/SILC Finite State Machine
+/****h* silcutil/Finite State Machine
*
* DESCRIPTION
*
#ifndef SILCFSM_H
#define SILCFSM_H
-/****s* silcutil/SilcFSMAPI/SilcFSM
+/****s* silcutil/SilcFSM
*
* NAME
*
***/
typedef struct SilcFSMObject *SilcFSM;
-/****s* silcutil/SilcFSMAPI/SilcFSMStruct
+/****s* silcutil/SilcFSMStruct
*
* NAME
*
***/
typedef struct SilcFSMObject SilcFSMStruct;
-/****s* silcutil/SilcFSMAPI/SilcFSMThread
+/****s* silcutil/SilcFSMThread
*
* NAME
*
***/
typedef struct SilcFSMObject *SilcFSMThread;
-/****s* silcutil/SilcFSMAPI/SilcFSMThreadStruct
+/****s* silcutil/SilcFSMThreadStruct
*
* NAME
*
***/
typedef struct SilcFSMObject SilcFSMThreadStruct;
-/****d* silcutil/SilcFSMAPI/SILC_FSM_CONTINUE
+/****d* silcutil/SILC_FSM_CONTINUE
*
* NAME
*
*
* DESCRIPTION
*
- * Moves to next state synchronously. This type is used is returned
- * from state functions to immediately move to next state.
+ * Moves to next state synchronously. This type is returned from state
+ * functions to immediately move to next state.
*
* EXAMPLE
*
#define SILC_FSM_CONTINUE SILC_FSM_ST_CONTINUE;
#endif /* SILC_DEBUG */
-/****d* silcutil/SilcFSMAPI/SILC_FSM_YIELD
+/****d* silcutil/SILC_FSM_YIELD
*
* NAME
*
***/
#define SILC_FSM_YIELD SILC_FSM_ST_YIELD;
-/****d* silcutil/SilcFSMAPI/SILC_FSM_WAIT
+/****d* silcutil/SILC_FSM_WAIT
*
* NAME
*
***/
#define SILC_FSM_WAIT SILC_FSM_ST_WAIT
-/****d* silcutil/SilcFSMAPI/SILC_FSM_FINISH
+/****d* silcutil/SILC_FSM_FINISH
*
* NAME
*
***/
#define SILC_FSM_FINISH SILC_FSM_ST_FINISH
-/****f* silcutil/SilcFSMAPI/SilcFSMDestructor
+/****f* silcutil/SilcFSMDestructor
*
* SYNOPSIS
*
typedef void (*SilcFSMDestructor)(SilcFSM fsm, void *fsm_context,
void *destructor_context);
-/****f* silcutil/SilcFSMAPI/SilcFSMThreadDestructor
+/****f* silcutil/SilcFSMThreadDestructor
*
* SYNOPSIS
*
void *thread_context,
void *destructor_context);
-/****d* silcutil/SilcFSMAPI/SILC_FSM_STATE
+/****d* silcutil/SILC_FSM_STATE
*
* NAME
*
void *fsm_context,
void *state_context);
-/****d* silcutil/SilcFSMAPI/SILC_FSM_CALL
+/****d* silcutil/SILC_FSM_CALL
*
* NAME
*
***/
#define SILC_FSM_CALL(function) \
do { \
- assert(!silc_fsm_set_call(fsm, TRUE)); \
+ SILC_VERIFY(!silc_fsm_set_call(fsm, TRUE)); \
function; \
if (!silc_fsm_set_call(fsm, FALSE)) \
return SILC_FSM_CONTINUE; \
return SILC_FSM_WAIT; \
} while(0)
-/****d* silcutil/SilcFSMAPI/SILC_FSM_CALL_CONTINUE
+/****d* silcutil/SILC_FSM_CALL_CONTINUE
*
* NAME
*
silc_fsm_continue(fsm); \
} while(0)
-/****d* silcutil/SilcFSMAPI/SILC_FSM_CALL_CONTINUE_SYNC
+/****d* silcutil/SILC_FSM_CALL_CONTINUE_SYNC
*
* NAME
*
silc_fsm_continue_sync(fsm); \
} while(0)
-/****d* silcutil/SilcFSMAPI/SILC_FSM_THREAD_WAIT
+/****d* silcutil/SILC_FSM_THREAD_WAIT
*
* NAME
*
return SILC_FSM_WAIT; \
} while(0)
-/****f* silcutil/SilcFSMAPI/silc_fsm_alloc
+/****f* silcutil/silc_fsm_alloc
*
* SYNOPSIS
*
* caller must free the returned context with silc_fsm_free. The
* `fsm_context' is delivered to every FSM state function. The `schedule'
* is the caller's scheduler and the FSM will be run in the scheduler.
+ * If `schedule' is NULL this will call silc_schedule_get_global to try
+ * get global scheduler. Returns NULL on error or if system is out of
+ * memory and sets silc_errno.
*
* EXAMPLE
*
void *destructor_context,
SilcSchedule schedule);
-/****f* silcutil/SilcFSMAPI/silc_fsm_init
+/****f* silcutil/silc_fsm_init
*
* SYNOPSIS
*
* as argument. The silc_fsm_free must not be called if this was called.
* Returns TRUE if the initialization is Ok or FALSE if error occurred.
* This function does not allocate any memory. The `schedule' is the
- * caller's scheduler and the FSM will be run in the scheduler.
+ * caller's scheduler and the FSM will be run in the scheduler. If
+ * `schedule' is NULL this will call silc_schedule_get_global to try to
+ * get global scheduler.
*
* EXAMPLE
*
void *destructor_context,
SilcSchedule schedule);
-/****f* silcutil/SilcFSMAPI/silc_fsm_thread_alloc
+/****f* silcutil/silc_fsm_thread_alloc
*
* SYNOPSIS
*
* thread context with silc_fsm_free. If the 'real_thread' is TRUE
* then the thread will actually be executed in real thread, if platform
* supports them. The `thread_context' is delivered to every state
- * function in the thread.
+ * function in the thread. Returns NULL on error or if the system is out
+ * of memory and sets silc_errno.
*
* NOTES
*
* 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.
+ * using silc_fsm_get_schedule function. The new scheduler is a child
+ * scheduler of the original scheduler used with `fsm'. Note that, the
+ * allocated SilcSchedule will become invalid after the thread finishes.
+ * Note also that the scheduler is automatically set as global scheduler
+ * in that thread by calling silc_schedule_set_global.
*
* If `real_thread' is FALSE the silc_fsm_get_schedule will return
* the SilcSchedule that was originally given to silc_fsm_alloc or
void *destructor_context,
SilcBool real_thread);
-/****f* silcutil/SilcFSMAPI/silc_fsm_thread_init
+/****f* silcutil/silc_fsm_thread_init
*
* SYNOPSIS
*
void *destructor_context,
SilcBool real_thread);
-/****f* silcutil/SilcFSMAPI/silc_fsm_free
+/****f* silcutil/silc_fsm_free
*
* SYNOPSIS
*
***/
void silc_fsm_free(void *fsm);
-/****f* silcutil/SilcFSMAPI/silc_fsm_start
+/****f* silcutil/silc_fsm_start
*
* SYNOPSIS
*
***/
void silc_fsm_start(void *fsm, SilcFSMStateCallback start_state);
-/****f* silcutil/SilcFSMAPI/silc_fsm_start_sync
+/****f* silcutil/silc_fsm_start_sync
*
* SYNOPSIS
*
***/
void silc_fsm_start_sync(void *fsm, SilcFSMStateCallback start_state);
-/****f* silcutil/SilcFSMAPI/silc_fsm_next
+/****f* silcutil/silc_fsm_next
*
* SYNOPSIS
*
***/
void silc_fsm_next(void *fsm, SilcFSMStateCallback next_state);
-/****f* silcutil/SilcFSMAPI/silc_fsm_next_later
+/****f* silcutil/silc_fsm_next_later
*
* SYNOPSIS
*
void silc_fsm_next_later(void *fsm, SilcFSMStateCallback next_state,
SilcUInt32 seconds, SilcUInt32 useconds);
-/****f* silcutil/SilcFSMAPI/silc_fsm_continue
+/****f* silcutil/silc_fsm_continue
*
* SYNOPSIS
*
***/
void silc_fsm_continue(void *fsm);
-/****f* silcutil/SilcFSMAPI/silc_fsm_continue_sync
+/****f* silcutil/silc_fsm_continue_sync
*
* SYNOPSIS
*
***/
void silc_fsm_continue_sync(void *fsm);
-/****f* silcutil/SilcFSMAPI/silc_fsm_finish
+/****f* silcutil/silc_fsm_finish
*
* SYNOPSIS
*
***/
void silc_fsm_finish(void *fsm);
-/****f* silcutil/SilcFSMAPI/silc_fsm_set_context
+/****f* silcutil/silc_fsm_set_context
*
* SYNOPSIS
*
***/
void silc_fsm_set_context(void *fsm, void *fsm_context);
-/****f* silcutil/SilcFSMAPI/silc_fsm_get_context
+/****f* silcutil/silc_fsm_get_context
*
* SYNOPSIS
*
***/
void *silc_fsm_get_context(void *fsm);
-/****f* silcutil/SilcFSMAPI/silc_fsm_set_state_context
+/****f* silcutil/silc_fsm_set_state_context
*
* SYNOPSIS
*
***/
void silc_fsm_set_state_context(void *fsm, void *state_context);
-/****f* silcutil/SilcFSMAPI/silc_fsm_get_state_context
+/****f* silcutil/silc_fsm_get_state_context
*
* SYNOPSIS
*
***/
void *silc_fsm_get_state_context(void *fsm);
-/****f* silcutil/SilcFSMAPI/silc_fsm_get_schedule
+/****f* silcutil/silc_fsm_get_schedule
*
* SYNOPSIS
*
***/
SilcSchedule silc_fsm_get_schedule(void *fsm);
-/****f* silcutil/SilcFSMAPI/silc_fsm_get_machine
+/****f* silcutil/silc_fsm_get_machine
*
* SYNOPSIS
*
***/
SilcFSM silc_fsm_get_machine(SilcFSMThread thread);
-/****f* silcutil/SilcFSMAPI/silc_fsm_is_started
+/****f* silcutil/silc_fsm_is_started
*
* SYNOPSIS
*
/* FSM Events */
-/****s* silcutil/SilcFSMAPI/SilcFSMEvent
+/****s* silcutil/SilcFSMEvent
*
* NAME
*
***/
typedef struct SilcFSMEventObject *SilcFSMEvent;
-/****s* silcutil/SilcFSMAPI/SilcFSMEventStruct
+/****s* silcutil/SilcFSMEventStruct
*
* NAME
*
***/
typedef struct SilcFSMEventObject SilcFSMEventStruct;
-/****f* silcutil/SilcFSMAPI/silc_fsm_event_alloc
+/****f* silcutil/silc_fsm_event_alloc
*
* SYNOPSIS
*
* 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.
+ * threads. The `fsm' must be the machine, not a thread. Returns NULL
+ * if system is out of memory or `fsm' is not FSM machine.
*
* 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
***/
SilcFSMEvent silc_fsm_event_alloc(SilcFSM fsm);
-/****f* silcutil/SilcFSMAPI/silc_fsm_event_init
+/****f* silcutil/silc_fsm_event_init
*
* SYNOPSIS
*
*
* 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.
+ * context. This fuction does not allocate any memory. The `fsm'
+ * must be the machine, not a thread.
*
***/
void silc_fsm_event_init(SilcFSMEvent event, SilcFSM fsm);
-/****f* silcutil/SilcFSMAPI/silc_fsm_event_free
+/****f* silcutil/silc_fsm_event_free
*
* SYNOPSIS
*
***/
void silc_fsm_event_free(SilcFSMEvent event);
-/****d* silcutil/SilcFSMAPI/SILC_FSM_EVENT_WAIT
+/****d* silcutil/SILC_FSM_EVENT_WAIT
*
* NAME
*
return SILC_FSM_WAIT; \
} while(0)
-/****d* silcutil/SilcFSMAPI/SILC_FSM_EVENT_TIMEDWAIT
+/****d* silcutil/SILC_FSM_EVENT_TIMEDWAIT
*
* NAME
*
return SILC_FSM_WAIT; \
} while(0)
-/****f* silcutil/SilcFSMAPI/SILC_FSM_EVENT_SIGNAL
+/****f* silcutil/SILC_FSM_EVENT_SIGNAL
*
* SYNOPSIS
*