Added SILC Thread Queue API
[silc.git] / lib / silcutil / tests / test_silcfsm.c
index 5432d418c9fc5e6179060515668c0a0083a99ec3..782165f65c7ea09298259afa8ee40ca9e96487f1 100644 (file)
@@ -23,12 +23,15 @@ struct FooStruct {
   SilcFSMThreadStruct thread;
   int timeout;
   SilcFSMEventStruct sema;
+  SilcFSMEventStruct wait2;
   SilcSchedule schedule;
   Callback cb;
   void *cb_context;
   T threads[NUM_THREADS];
   T threads2[NUM_THREADS];
   int c;
+  int got_wait1 : 1;
+  int got_wait2 : 1;
 };
 
 SILC_FSM_STATE(test_st_start);
@@ -44,6 +47,11 @@ SILC_FSM_STATE(test_st_ninth);
 SILC_FSM_STATE(test_st_tenth);
 SILC_FSM_STATE(test_st_finish);
 
+SILC_FSM_STATE(test_st_wait1);
+SILC_FSM_STATE(test_st_wait2);
+SILC_FSM_STATE(test_st_signal1);
+SILC_FSM_STATE(test_st_signal1_check);
+
 SILC_FSM_STATE(test_thread_st_start);
 SILC_FSM_STATE(test_thread_st_finish);
 SILC_FSM_STATE(test_thread2_st_start);
@@ -51,6 +59,12 @@ SILC_FSM_STATE(test_thread2_st_finish);
 SILC_FSM_STATE(test_thread3_st_start);
 SILC_FSM_STATE(test_thread4_st_start);
 
+static void test_fsm_destr(SilcFSMThread thread, void *thread_context,
+                          void *user_context)
+{
+  silc_fsm_free(thread);
+}
+
 SILC_TASK_CALLBACK(async_call_timeout)
 {
   Foo f = context;
@@ -75,7 +89,7 @@ SILC_FSM_STATE(test_st_start)
   /** Move to second state */
   SILC_LOG_DEBUG(("Move to next state"));
   silc_fsm_next(fsm, test_st_second);
-  SILC_FSM_CONTINUE;
+  return SILC_FSM_CONTINUE;
 }
 
 SILC_FSM_STATE(test_st_second)
@@ -85,7 +99,7 @@ SILC_FSM_STATE(test_st_second)
   /** Move to second timeout state, timeout */
   SILC_LOG_DEBUG(("Move to next state with 2 second timeout"));
   silc_fsm_next_later(fsm, test_st_second_timeout, 2, 0);
-  SILC_FSM_WAIT;
+  return SILC_FSM_WAIT;
 }
 
 SILC_TASK_CALLBACK(test_second_timeout)
@@ -111,7 +125,7 @@ SILC_FSM_STATE(test_st_second_timeout)
   silc_fsm_next_later(fsm, test_st_third, 3, 0);
   silc_schedule_task_add_timeout(silc_fsm_get_schedule(fsm),
                                 test_second_timeout, f, 2, 500000);
-  SILC_FSM_WAIT;
+  return SILC_FSM_WAIT;
 }
 
 static void async_call_cb(void *context)
@@ -141,6 +155,7 @@ SILC_FSM_STATE(test_st_third)
 SILC_FSM_STATE(test_st_fourth)
 {
   Foo f = fsm_context;
+  SilcFSMThread t;
 
   SILC_LOG_DEBUG(("test_st_fourth"));
 
@@ -152,12 +167,64 @@ SILC_FSM_STATE(test_st_fourth)
   /*** Start thread */
   silc_fsm_start(&f->thread, test_thread_st_start);
 
+  SILC_LOG_DEBUG(("Creating two waiting threads"));
+  silc_fsm_event_init(&f->wait2, fsm);
+  t = silc_fsm_thread_alloc(fsm, f, test_fsm_destr, NULL, FALSE);
+  silc_fsm_start(t, test_st_wait1);
+  t = silc_fsm_thread_alloc(fsm, f, test_fsm_destr, NULL, FALSE);
+  silc_fsm_start(t, test_st_wait2);
+
+  SILC_LOG_DEBUG(("Create signaller thread"));
+  t = silc_fsm_thread_alloc(fsm, f, test_fsm_destr, NULL, FALSE);
+  silc_fsm_start(t, test_st_signal1);
+
   /** Waiting thread to terminate */
   SILC_LOG_DEBUG(("Waiting for thread to terminate"));
   silc_fsm_next(fsm, test_st_fifth);
   SILC_FSM_THREAD_WAIT(&f->thread);
 }
 
+SILC_FSM_STATE(test_st_wait1)
+{
+  Foo f = fsm_context;
+
+  SILC_LOG_DEBUG(("Waiter 1"));
+  SILC_FSM_EVENT_WAIT(&f->wait2);
+  SILC_LOG_DEBUG(("Waiter 1 signalled"));
+  f->got_wait1 = 1;
+  return SILC_FSM_FINISH;
+}
+
+SILC_FSM_STATE(test_st_wait2)
+{
+  Foo f = fsm_context;
+
+  SILC_LOG_DEBUG(("Waiter 2"));
+  SILC_FSM_EVENT_WAIT(&f->wait2);
+  SILC_LOG_DEBUG(("Waiter 2 signalled"));
+  f->got_wait2 = 1;
+  return SILC_FSM_FINISH;
+}
+
+SILC_FSM_STATE(test_st_signal1)
+{
+  Foo f = fsm_context;
+
+  SILC_LOG_DEBUG(("Signaller 1"));
+  SILC_FSM_EVENT_SIGNAL(&f->wait2);
+  silc_fsm_next_later(fsm, test_st_signal1_check, 0, 500000);
+  return SILC_FSM_WAIT;;
+}
+
+SILC_FSM_STATE(test_st_signal1_check)
+{
+  Foo f = fsm_context;
+
+  SILC_LOG_DEBUG(("Signal check"));
+  assert(f->got_wait1 && f->got_wait2);
+  return SILC_FSM_FINISH;
+}
+
 SILC_FSM_STATE(test_thread_st_start)
 {
   Foo f = fsm_context;
@@ -167,7 +234,7 @@ SILC_FSM_STATE(test_thread_st_start)
   /** Move to final state, timeout */
   SILC_LOG_DEBUG(("Move to final state with %d second timeout", f->timeout));
   silc_fsm_next_later(fsm, test_thread_st_finish, f->timeout, 0);
-  SILC_FSM_WAIT;
+  return SILC_FSM_WAIT;
 }
 
 SILC_FSM_STATE(test_thread_st_finish)
@@ -175,7 +242,7 @@ SILC_FSM_STATE(test_thread_st_finish)
   SILC_LOG_DEBUG(("test_thread_st_finish"));
 
   SILC_LOG_DEBUG(("Finishing the thread"));
-  SILC_FSM_FINISH;
+  return SILC_FSM_FINISH;
 }
 
 SILC_FSM_STATE(test_st_fifth)
@@ -199,7 +266,7 @@ SILC_FSM_STATE(test_st_fifth)
   SILC_LOG_DEBUG(("Waiting for thread to terminate for 5 seconds"));
   silc_fsm_next(fsm, test_st_sixth);
   SILC_FSM_EVENT_TIMEDWAIT(&f->sema, 5, 0, NULL);
-  SILC_FSM_CONTINUE;
+  return SILC_FSM_CONTINUE;
 }
 
 SILC_FSM_STATE(test_thread2_st_start)
@@ -211,7 +278,7 @@ SILC_FSM_STATE(test_thread2_st_start)
   /** Move to final state, timeout */
   SILC_LOG_DEBUG(("Move to final state with %d second timeout", f->timeout));
   silc_fsm_next_later(fsm, test_thread2_st_finish, f->timeout, 0);
-  SILC_FSM_WAIT;
+  return SILC_FSM_WAIT;
 }
 
 SILC_FSM_STATE(test_thread2_st_finish)
@@ -223,7 +290,7 @@ SILC_FSM_STATE(test_thread2_st_finish)
   SILC_FSM_EVENT_SIGNAL(&f->sema);
 
   SILC_LOG_DEBUG(("Finishing the thread"));
-  SILC_FSM_FINISH;
+  return SILC_FSM_FINISH;
 }
 
 SILC_FSM_STATE(test_st_sixth)
@@ -235,7 +302,7 @@ SILC_FSM_STATE(test_st_sixth)
   /** Move to next state, timeout */
   SILC_LOG_DEBUG(("Continue to next state with 4 second timeout"));
   silc_fsm_next_later(fsm, test_st_seventh, 4, 0);
-  SILC_FSM_WAIT;
+  return SILC_FSM_WAIT;
 }
 
 SILC_FSM_STATE(test_thread3_st_start)
@@ -244,14 +311,14 @@ SILC_FSM_STATE(test_thread3_st_start)
 
   if (t->rounds == 0) {
     SILC_FSM_EVENT_SIGNAL(&t->sema);
-    SILC_FSM_FINISH;
+    return SILC_FSM_FINISH;
   }
 
   t->rounds--;
 
   /** Call in recursive */
   silc_fsm_next(fsm, test_thread3_st_start);
-  SILC_FSM_CONTINUE;
+  return SILC_FSM_CONTINUE;
 }
 
 SILC_FSM_STATE(test_st_seventh)
@@ -274,7 +341,7 @@ SILC_FSM_STATE(test_st_seventh)
 
   /** Move to wait threads */
   silc_fsm_next(fsm, test_st_eighth);
-  SILC_FSM_CONTINUE;
+  return SILC_FSM_CONTINUE;
 }
 
 SILC_FSM_STATE(test_st_eighth)
@@ -293,7 +360,7 @@ SILC_FSM_STATE(test_st_eighth)
 
   /** Move to next thread */
   silc_fsm_next(fsm, test_st_ninth);
-  SILC_FSM_CONTINUE;
+  return SILC_FSM_CONTINUE;
 }
 
 SILC_FSM_STATE(test_thread4_st_start)
@@ -302,14 +369,14 @@ SILC_FSM_STATE(test_thread4_st_start)
 
   if (t->rounds == 0) {
     SILC_FSM_EVENT_SIGNAL(&t->sema);
-    SILC_FSM_FINISH;
+    return SILC_FSM_FINISH;
   }
 
   t->rounds--;
 
   /** Call in recursive */
   silc_fsm_next(fsm, test_thread4_st_start);
-  SILC_FSM_CONTINUE;
+  return SILC_FSM_CONTINUE;
 }
 
 SILC_FSM_STATE(test_st_ninth)
@@ -334,7 +401,7 @@ SILC_FSM_STATE(test_st_ninth)
 
   /** Move to wait threads */
   silc_fsm_next(fsm, test_st_tenth);
-  SILC_FSM_CONTINUE;
+  return SILC_FSM_CONTINUE;
 }
 
 SILC_FSM_STATE(test_st_tenth)
@@ -352,7 +419,7 @@ SILC_FSM_STATE(test_st_tenth)
 
   /** Finished successfully */
   silc_fsm_next_later(fsm, test_st_finish, 2, 0);
-  SILC_FSM_WAIT;
+  return SILC_FSM_WAIT;
 }
 
 SILC_FSM_STATE(test_st_finish)
@@ -360,7 +427,7 @@ SILC_FSM_STATE(test_st_finish)
   SILC_LOG_DEBUG(("test_st_finish"));
 
   SILC_LOG_DEBUG(("Finish machine"));
-  SILC_FSM_FINISH;
+  return SILC_FSM_FINISH;
 }
 
 static void destructor(SilcFSM fsm, void *fsm_context,
@@ -383,11 +450,11 @@ int main(int argc, char **argv)
     silc_log_debug(TRUE);
     silc_log_debug_hexdump(TRUE);
     silc_log_quick(TRUE);
-    silc_log_set_debug_string("*fsm*,*async*");
+    silc_log_set_debug_string("*fsm*,*async*,*errno*");
   }
 
   SILC_LOG_DEBUG(("Allocating scheduler"));
-  schedule = silc_schedule_init(0, NULL);
+  schedule = silc_schedule_init(0, NULL, NULL);
 
   f = silc_calloc(1, sizeof(*f));
   if (!f)