Added SILC Thread Queue API
[silc.git] / lib / silcutil / silcfsm_i.h
index 4c27acb8d5c3cbfc02303c197ba84fbe4f3462a0..50475da5ca7c4d5204b2539eecaea5a8c68762d9 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2005 Pekka Riikonen
+  Copyright (C) 2005 - 2006 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
 #error "Do not include this header directly"
 #endif
 
-/* Semaphore structure, holds list of FSM machines that are waiting
-   for this semaphore.  The SilcFSM has *next; pointer that is used
-   with SilcList. */
-struct SilcFSMSemaObject {
+/* FSM state status */
+typedef enum {
+  SILC_FSM_ST_CONTINUE,             /* Continue immediately to next state */
+  SILC_FSM_ST_YIELD,        /* Continue to next state through scheduler */
+  SILC_FSM_ST_WAIT,         /* Wait for some async call or timeout */
+  SILC_FSM_ST_FINISH,       /* Finish state machine and call destructor
+                               through scheduler */
+} SilcFSMStatus;
+
+/* Event structure, holds list of FSM machines that are waiting for this
+   event.  The SilcFSM has *next; pointer that is used with SilcList.
+   Internally events act as semaphore counters. */
+struct SilcFSMEventObject {
   SilcFSM fsm;                         /* Machine */
   SilcList waiters;                    /* List of SilcFSM pointers */
-  SilcUInt32 value;                    /* Current semaphore value */
+  unsigned int value     : 21;         /* Current event semaphore value */
+  unsigned int refcnt    : 10;         /* Reference counter */
+  unsigned int allocated : 1;          /* Set if allocated */
 };
 
 /* FSM and FSM thread context */
@@ -38,52 +49,58 @@ struct SilcFSMObject {
   struct SilcFSMObject *next;
   void *fsm_context;                   /* Caller's context */
   SilcSchedule schedule;               /* Scheduler */
-  SilcFSMSema sema;                    /* Valid if waiting sema timeout */
+  SilcFSMEvent event;                  /* Valid if waiting event timeout */
   SilcFSMStateCallback next_state;     /* Next state in machine */
+  void *state_context;                 /* Extra state specific context */
   SilcFSMDestructor destructor;                /* Destructor */
   void *destructor_context;
   union {
     /* Machine */
     struct {
-      SilcUInt32 threads;              /* Number of threads */
+      SilcAtomic32 threads;            /* Number of threads */
       SilcMutex lock;                  /* Lock, valid if using real threads */
     } m;
 
     /* Thread */
     struct {
       struct SilcFSMObject *fsm;       /* Machine */
-      SilcFSMSema sema;                        /* Semaphore for waiting termination */
+      SilcFSMEvent event;               /* Event for waiting termination */
     } t;
   } u;
   unsigned int thread           : 1;   /* Set if this is thread */
   unsigned int real_thread      : 1;    /* Set if to use real threads */
   unsigned int async_call       : 1;    /* Set if called real async call */
   unsigned int finished         : 1;    /* Set if SILC_FSM_FINISH returned */
-  unsigned int sema_timedout    : 1;    /* Set if waiting sema timedout */
+  unsigned int event_timedout   : 1;    /* Set if waiting event timedout */
   unsigned int synchronous      : 1;    /* Set if silc_fsm_start_sync called */
+  unsigned int next_later       : 1;    /* Set if silc_fsm_next_later called */
+  unsigned int started          : 1;    /* Set when started and not finished */
 };
 
+/* Event signal context */
+typedef struct {
+  SilcFSMEvent event;                  /* Event */
+  SilcFSM fsm;                         /* Signalled FSM */
+} *SilcFSMEventSignal;
+
 /* Used internally by the SILC_FSM_CALL macros to detect whether async
    call is really async or not. */
 static inline
-bool silc_fsm_set_call(struct SilcFSMObject *fsm, bool async_call)
+SilcBool silc_fsm_set_call(struct SilcFSMObject *fsm, SilcBool async_call)
 {
-  bool old = fsm->async_call;
+  SilcBool old = fsm->async_call;
   fsm->async_call = async_call;
   return old;
 }
 
-/* Continues after callback */
-void silc_fsm_continue(void *fsm);
-void silc_fsm_continue_sync(void *fsm);
-
 /* Wait for thread to terminate */
-bool silc_fsm_thread_wait(void *fsm, void *thread);
-
-/* Semaphores */
-SilcUInt32 silc_fsm_sema_wait(SilcFSMSema sema, void *fsm);
-SilcUInt32 silc_fsm_sema_timedwait(SilcFSMSema sema, void *fsm,
-                                  SilcUInt32 seconds, SilcUInt32 useconds);
-void silc_fsm_sema_post(SilcFSMSema sema);
+SilcBool silc_fsm_thread_wait(void *fsm, void *thread);
+
+/* Events */
+SilcUInt32 silc_fsm_event_wait(SilcFSMEvent event, void *fsm);
+SilcUInt32 silc_fsm_event_timedwait(SilcFSMEvent event, void *fsm,
+                                   SilcUInt32 seconds, SilcUInt32 useconds,
+                                   SilcBool *ret_to);
+void silc_fsm_event_signal(SilcFSMEvent event);
 
 #endif /* SILCFSM_I_H */