Added asynchronous event tasks to SILC Scheduler. Added
[crypto.git] / lib / silcutil / silcfsm.h
index 8a28360b5d3c1cfe8ff4a4322a33875bac22af04..503b8f43eafebff4ad8f81992582c095dca56e66 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2005, 2006 Pekka Riikonen
+  Copyright (C) 2005, 2006, 2007 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
@@ -94,7 +94,7 @@ typedef struct SilcFSMObject SilcFSMStruct;
  ***/
 typedef struct SilcFSMObject *SilcFSMThread;
 
-/****s* silcutil/SilcFSMAPI/SilcFSM
+/****s* silcutil/SilcFSMAPI/SilcFSMThreadStruct
  *
  * NAME
  *
@@ -113,13 +113,12 @@ typedef struct SilcFSMObject SilcFSMThreadStruct;
  *
  * NAME
  *
- *    SILC_FSM_CONTINUE
+ *    #define SILC_FSM_CONTINUE ...
  *
  * DESCRIPTION
  *
- *    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.
+ *    Moves to next state synchronously.  This type is returned from state
+ *    functions to immediately move to next state.
  *
  * EXAMPLE
  *
@@ -129,60 +128,63 @@ typedef struct SilcFSMObject SilcFSMThreadStruct;
  *
  *      // Move to next state now
  *      silc_fsm_next(fsm, silc_foo_next_state);
- *      SILC_FSM_CONTINUE;
+ *      return SILC_FSM_CONTINUE;
  *    }
  *
  ***/
+#if defined(SILC_DEBUG)
 #define SILC_FSM_CONTINUE \
-  return fsm->next_state(fsm, fsm->fsm_context, fsm->state_context);
+  fsm->next_state(fsm, fsm->fsm_context, fsm->state_context);
+#else
+#define SILC_FSM_CONTINUE SILC_FSM_ST_CONTINUE;
+#endif /* SILC_DEBUG */
 
 /****d* silcutil/SilcFSMAPI/SILC_FSM_YIELD
  *
  * NAME
  *
- *    SILC_FSM_YIELD
+ *    #define SILC_FSM_YIELD ...
  *
  * DESCRIPTION
  *
  *    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.
+ *    This type is returned in the state function.
  *
  ***/
-#define SILC_FSM_YIELD return SILC_FSM_ST_YIELD;
+#define SILC_FSM_YIELD SILC_FSM_ST_YIELD;
 
 /****d* silcutil/SilcFSMAPI/SILC_FSM_WAIT
  *
  * NAME
  *
- *    SILC_FSM_WAIT
+ *    #define SILC_FSM_WAIT ...
  *
  * 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.
+ *    that requires waiting.  This type is returned in the state function.
  *
  ***/
-#define SILC_FSM_WAIT return SILC_FSM_ST_WAIT
+#define SILC_FSM_WAIT SILC_FSM_ST_WAIT
 
 /****d* silcutil/SilcFSMAPI/SILC_FSM_FINISH
  *
  * NAME
  *
- *    SILC_FSM_FINISH
+ *    #define 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.
+ *    finishing the machine.  This type is returned in the state function.
  *
  ***/
-#define SILC_FSM_FINISH return SILC_FSM_ST_FINISH
+#define SILC_FSM_FINISH SILC_FSM_ST_FINISH
 
 /****f* silcutil/SilcFSMAPI/SilcFSMDestructor
  *
@@ -195,10 +197,10 @@ typedef struct SilcFSMObject SilcFSMThreadStruct;
  *
  *    The destructor callback that was set in silc_fsm_alloc or in
  *    silc_fsm_init function.  It will be called when a state function
- *    calls SILC_FSM_FINISH.  This function will be called through
+ *    returns 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 `fsm'
- *    may be freed in this function.
+ *    function returns SILC_FSM_FINISH, but will be called later.  The
+ *    `fsm' can be freed in this function.
  *
  ***/
 typedef void (*SilcFSMDestructor)(SilcFSM fsm, void *fsm_context,
@@ -216,9 +218,9 @@ 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
- *    calls SILC_FSM_FINISH.  This function will be called through the
+ *    returns 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
+ *    returns SILC_FSM_FINISH, but will be called later.  The `thread' can
  *    be freed in this function.
  *
  * NOTES
@@ -289,11 +291,11 @@ typedef int (*SilcFSMStateCallback)(struct SilcFSMObject *fsm,
  ***/
 #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))          \
-    SILC_FSM_CONTINUE;                         \
-  SILC_FSM_WAIT;                               \
+    return SILC_FSM_CONTINUE;                  \
+  return SILC_FSM_WAIT;                                \
 } while(0)
 
 /****d* silcutil/SilcFSMAPI/SILC_FSM_CALL_CONTINUE
@@ -362,7 +364,8 @@ do {                                                \
  *
  *    Macro used to wait for the `thread' to terminate.  The machine or
  *    thread will be suspended while it is waiting for the thread to
- *    terminate.
+ *    terminate.  The machine or thread will continue once the waited
+ *    thread has terminated.
  *
  * NOTES
  *
@@ -370,7 +373,7 @@ do {                                                \
  *
  *    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
- *    FSM events to signal from the thread before SILC_FSM_FINISH is called
+ *    FSM events to signal from the thread before SILC_FSM_FINISH is returned
  *    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
@@ -381,7 +384,7 @@ do {                                                \
 #define SILC_FSM_THREAD_WAIT(thread)           \
 do {                                           \
   silc_fsm_thread_wait(fsm, thread);           \
-  SILC_FSM_WAIT;                               \
+  return SILC_FSM_WAIT;                                \
 } while(0)
 
 /****f* silcutil/SilcFSMAPI/silc_fsm_alloc
@@ -400,6 +403,9 @@ do {                                                \
  *    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.
  *
  * EXAMPLE
  *
@@ -445,7 +451,9 @@ SilcFSM silc_fsm_alloc(void *fsm_context,
  *    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
  *
@@ -478,7 +486,8 @@ SilcBool silc_fsm_init(SilcFSM fsm,
  *    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.
  *
  * NOTES
  *
@@ -489,8 +498,11 @@ SilcBool silc_fsm_init(SilcFSM fsm,
  *    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
@@ -632,8 +644,8 @@ void silc_fsm_start_sync(void *fsm, SilcFSMStateCallback start_state);
  * DESCRIPTION
  *
  *    Set the next state to be executed.  If the state function that
- *    call this function calls SILC_FSM_CONTINUE, the `next_state'
- *    will be executed immediately.  If it calls SILC_FSM_YIELD it
+ *    call this function returns SILC_FSM_CONTINUE, the `next_state'
+ *    will be executed immediately.  If it returns 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
@@ -643,7 +655,7 @@ void silc_fsm_start_sync(void *fsm, SilcFSMStateCallback start_state);
  *
  *    // Move to next state
  *    silc_fsm_next(fsm, next_state);
- *    SILC_FSM_CONTINUE;
+ *    return SILC_FSM_CONTINUE;
  *
  ***/
 void silc_fsm_next(void *fsm, SilcFSMStateCallback next_state);
@@ -658,7 +670,7 @@ 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 called in the state function if this
+ *    The SILC_FSM_WAIT must be returned 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
@@ -667,7 +679,7 @@ void silc_fsm_next(void *fsm, SilcFSMStateCallback next_state);
  * NOTES
  *
  *    If both `seconds' and `useconds' are 0, the effect is same as calling
- *    silc_fsm_next function, and SILC_FSM_CONTINUE must be called.
+ *    silc_fsm_next function, and SILC_FSM_CONTINUE must be returned.
  *
  *    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
@@ -677,7 +689,7 @@ void silc_fsm_next(void *fsm, SilcFSMStateCallback next_state);
  *
  *    // Move to next state after 10 seconds
  *    silc_fsm_next_later(fsm, next_state, 10, 0);
- *    SILC_FSM_WAIT;
+ *    return SILC_FSM_WAIT;
  *
  ***/
 void silc_fsm_next_later(void *fsm, SilcFSMStateCallback next_state,
@@ -729,7 +741,7 @@ void silc_fsm_continue_sync(void *fsm);
  *
  *    Finishes the `fsm'.  This function may be used in case the FSM
  *    needs to be finished outside FSM states.  Usually FSM is finished
- *    by calling SILC_FSM_FINISH from the state, but if this is not
+ *    by returning 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.
  *
@@ -902,7 +914,8 @@ typedef struct SilcFSMEventObject SilcFSMEventStruct;
  *    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
@@ -921,7 +934,8 @@ SilcFSMEvent silc_fsm_event_alloc(SilcFSM fsm);
  *
  *    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);
@@ -976,7 +990,7 @@ void silc_fsm_event_free(SilcFSMEvent event);
 #define SILC_FSM_EVENT_WAIT(event)             \
 do {                                           \
   if (silc_fsm_event_wait(event, fsm) == 0)    \
-    SILC_FSM_WAIT;                             \
+    return SILC_FSM_WAIT;                      \
 } while(0)
 
 /****d* silcutil/SilcFSMAPI/SILC_FSM_EVENT_TIMEDWAIT
@@ -1021,7 +1035,7 @@ do {                                              \
 #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;                                                     \
+    return SILC_FSM_WAIT;                                              \
 } while(0)
 
 /****f* silcutil/SilcFSMAPI/SILC_FSM_EVENT_SIGNAL