6 typedef void (*Callback)(void *context);
8 #define NUM_THREADS 200
10 typedef struct FooStruct *Foo;
13 SilcFSMThreadStruct thread;
14 SilcFSMEventStruct sema;
23 SilcFSMThreadStruct thread;
25 SilcFSMEventStruct sema;
26 SilcSchedule schedule;
29 T threads[NUM_THREADS];
30 T threads2[NUM_THREADS];
34 SILC_FSM_STATE(test_st_start);
35 SILC_FSM_STATE(test_st_second);
36 SILC_FSM_STATE(test_st_second_timeout);
37 SILC_FSM_STATE(test_st_third);
38 SILC_FSM_STATE(test_st_fourth);
39 SILC_FSM_STATE(test_st_fifth);
40 SILC_FSM_STATE(test_st_sixth);
41 SILC_FSM_STATE(test_st_seventh);
42 SILC_FSM_STATE(test_st_eighth);
43 SILC_FSM_STATE(test_st_ninth);
44 SILC_FSM_STATE(test_st_tenth);
45 SILC_FSM_STATE(test_st_finish);
47 SILC_FSM_STATE(test_thread_st_start);
48 SILC_FSM_STATE(test_thread_st_finish);
49 SILC_FSM_STATE(test_thread2_st_start);
50 SILC_FSM_STATE(test_thread2_st_finish);
51 SILC_FSM_STATE(test_thread3_st_start);
52 SILC_FSM_STATE(test_thread4_st_start);
54 SILC_TASK_CALLBACK(async_call_timeout)
57 SILC_LOG_DEBUG(("Async call cb, continuing FSM"));
61 static void async_call(Callback cb, void *context)
65 f->cb_context = context;
66 SILC_LOG_DEBUG(("Async call"));
67 silc_schedule_task_add(f->schedule, 0, async_call_timeout, f, 0, 200000,
71 SILC_FSM_STATE(test_st_start)
73 SILC_LOG_DEBUG(("test_st_start"));
75 /** Move to second state */
76 SILC_LOG_DEBUG(("Move to next state"));
77 silc_fsm_next(fsm, test_st_second);
78 return SILC_FSM_CONTINUE;
81 SILC_FSM_STATE(test_st_second)
83 SILC_LOG_DEBUG(("test_st_second"));
85 /** Move to second timeout state, timeout */
86 SILC_LOG_DEBUG(("Move to next state with 2 second timeout"));
87 silc_fsm_next_later(fsm, test_st_second_timeout, 2, 0);
91 SILC_TASK_CALLBACK(test_second_timeout)
94 SILC_LOG_DEBUG(("test_second_timeout"));
96 SILC_LOG_DEBUG(("Interrupt 3 second wait and continue immediately"));
98 silc_fsm_next(f->fsm, test_st_third);
99 silc_fsm_continue(f->fsm);
102 SILC_FSM_STATE(test_st_second_timeout)
106 SILC_LOG_DEBUG(("test_st_second_timeout"));
108 /** Move to third state, timeout */
109 SILC_LOG_DEBUG(("Move to next state with 3 second timeout"));
110 SILC_LOG_DEBUG(("The timeout will be interrupted with silc_fsm_continue"));
111 silc_fsm_next_later(fsm, test_st_third, 3, 0);
112 silc_schedule_task_add_timeout(silc_fsm_get_schedule(fsm),
113 test_second_timeout, f, 2, 500000);
114 return SILC_FSM_WAIT;
117 static void async_call_cb(void *context)
120 SILC_LOG_DEBUG(("Callback, continue to next state"));
121 SILC_FSM_CALL_CONTINUE(f->fsm);
124 SILC_FSM_STATE(test_st_third)
128 SILC_LOG_DEBUG(("test_st_third"));
135 /** Wait async callback*/
136 SILC_LOG_DEBUG(("Call async call"));
137 silc_fsm_next(fsm, test_st_fourth);
138 SILC_FSM_CALL(async_call(async_call_cb, f));
141 SILC_FSM_STATE(test_st_fourth)
145 SILC_LOG_DEBUG(("test_st_fourth"));
149 SILC_LOG_DEBUG(("Creating FSM thread"));
150 silc_fsm_thread_init(&f->thread, fsm, f, NULL, NULL, FALSE);
151 SILC_LOG_DEBUG(("Starting thread"));
153 silc_fsm_start(&f->thread, test_thread_st_start);
155 /** Waiting thread to terminate */
156 SILC_LOG_DEBUG(("Waiting for thread to terminate"));
157 silc_fsm_next(fsm, test_st_fifth);
158 SILC_FSM_THREAD_WAIT(&f->thread);
161 SILC_FSM_STATE(test_thread_st_start)
165 SILC_LOG_DEBUG(("test_thread_st_start"));
167 /** Move to final state, timeout */
168 SILC_LOG_DEBUG(("Move to final state with %d second timeout", f->timeout));
169 silc_fsm_next_later(fsm, test_thread_st_finish, f->timeout, 0);
170 return SILC_FSM_WAIT;
173 SILC_FSM_STATE(test_thread_st_finish)
175 SILC_LOG_DEBUG(("test_thread_st_finish"));
177 SILC_LOG_DEBUG(("Finishing the thread"));
178 return SILC_FSM_FINISH;
181 SILC_FSM_STATE(test_st_fifth)
184 SILC_LOG_DEBUG(("test_st_fifth"));
186 SILC_LOG_DEBUG(("Thread terminated, start new real thread"));
190 SILC_LOG_DEBUG(("Creating FSM event"));
191 silc_fsm_event_init(&f->sema, fsm);
193 SILC_LOG_DEBUG(("Creating FSM thread"));
194 silc_fsm_thread_init(&f->thread, fsm, f, NULL, NULL, TRUE);
195 SILC_LOG_DEBUG(("Starting thread"));
196 silc_fsm_start(&f->thread, test_thread2_st_start);
198 /** Waiting thread to terminate, timeout */
199 SILC_LOG_DEBUG(("Waiting for thread to terminate for 5 seconds"));
200 silc_fsm_next(fsm, test_st_sixth);
201 SILC_FSM_EVENT_TIMEDWAIT(&f->sema, 5, 0, NULL);
202 return SILC_FSM_CONTINUE;
205 SILC_FSM_STATE(test_thread2_st_start)
209 SILC_LOG_DEBUG(("test_thread2_st_start"));
211 /** Move to final state, timeout */
212 SILC_LOG_DEBUG(("Move to final state with %d second timeout", f->timeout));
213 silc_fsm_next_later(fsm, test_thread2_st_finish, f->timeout, 0);
214 return SILC_FSM_WAIT;
217 SILC_FSM_STATE(test_thread2_st_finish)
220 SILC_LOG_DEBUG(("test_thread2_st_finish"));
222 SILC_LOG_DEBUG(("Post semaphore"));
223 SILC_FSM_EVENT_SIGNAL(&f->sema);
225 SILC_LOG_DEBUG(("Finishing the thread"));
226 return SILC_FSM_FINISH;
229 SILC_FSM_STATE(test_st_sixth)
231 SILC_LOG_DEBUG(("test_st_sixth"));
233 SILC_LOG_DEBUG(("Thread wait timedout, OK"));
235 /** Move to next state, timeout */
236 SILC_LOG_DEBUG(("Continue to next state with 4 second timeout"));
237 silc_fsm_next_later(fsm, test_st_seventh, 4, 0);
238 return SILC_FSM_WAIT;
241 SILC_FSM_STATE(test_thread3_st_start)
245 if (t->rounds == 0) {
246 SILC_FSM_EVENT_SIGNAL(&t->sema);
247 return SILC_FSM_FINISH;
252 /** Call in recursive */
253 silc_fsm_next(fsm, test_thread3_st_start);
254 return SILC_FSM_CONTINUE;
257 SILC_FSM_STATE(test_st_seventh)
262 SILC_LOG_DEBUG(("test_st_seventh"));
265 SILC_LOG_DEBUG(("Creating %d FSM threads", NUM_THREADS));
266 for (i = 0; i < NUM_THREADS; i++) {
267 f->threads[i].rounds = 10;
269 silc_fsm_event_init(&f->threads[i].sema, fsm);
270 silc_fsm_thread_init(&f->threads[i].thread, fsm,
271 &f->threads[i], NULL, NULL, FALSE);
272 silc_fsm_start(&f->threads[i].thread, test_thread3_st_start);
275 /** Move to wait threads */
276 silc_fsm_next(fsm, test_st_eighth);
277 return SILC_FSM_CONTINUE;
280 SILC_FSM_STATE(test_st_eighth)
285 for (i = 0; i < NUM_THREADS; i++) {
286 if (f->threads[i].finished == FALSE) {
287 SILC_FSM_EVENT_WAIT(&f->threads[i].sema);
288 f->threads[i].finished = TRUE;
292 SILC_LOG_DEBUG(("All %d threads terminated", NUM_THREADS));
294 /** Move to next thread */
295 silc_fsm_next(fsm, test_st_ninth);
296 return SILC_FSM_CONTINUE;
299 SILC_FSM_STATE(test_thread4_st_start)
303 if (t->rounds == 0) {
304 SILC_FSM_EVENT_SIGNAL(&t->sema);
305 return SILC_FSM_FINISH;
310 /** Call in recursive */
311 silc_fsm_next(fsm, test_thread4_st_start);
312 return SILC_FSM_CONTINUE;
315 SILC_FSM_STATE(test_st_ninth)
320 SILC_LOG_DEBUG(("test_st_ninth"));
322 SILC_LOG_DEBUG(("Creating FSM event"));
323 silc_fsm_event_init(&f->sema, fsm);
325 SILC_LOG_DEBUG(("Creating %d real FSM threads", NUM_THREADS));
326 for (i = 0; i < NUM_THREADS; i++) {
327 f->threads2[i].rounds = 10;
328 f->threads2[i].f = f;
329 silc_fsm_event_init(&f->threads2[i].sema, fsm);
330 silc_fsm_thread_init(&f->threads2[i].thread, fsm,
331 &f->threads2[i], NULL, NULL, TRUE);
332 silc_fsm_start(&f->threads2[i].thread, test_thread4_st_start);
335 /** Move to wait threads */
336 silc_fsm_next(fsm, test_st_tenth);
337 return SILC_FSM_CONTINUE;
340 SILC_FSM_STATE(test_st_tenth)
345 for (i = 0; i < NUM_THREADS; i++)
346 if (f->threads2[i].finished == FALSE) {
347 SILC_FSM_EVENT_WAIT(&f->threads2[i].sema);
348 f->threads2[i].finished = TRUE;
351 SILC_LOG_DEBUG(("All %d real threads terminated", NUM_THREADS));
353 /** Finished successfully */
354 silc_fsm_next_later(fsm, test_st_finish, 2, 0);
355 return SILC_FSM_WAIT;
358 SILC_FSM_STATE(test_st_finish)
360 SILC_LOG_DEBUG(("test_st_finish"));
362 SILC_LOG_DEBUG(("Finish machine"));
363 return SILC_FSM_FINISH;
366 static void destructor(SilcFSM fsm, void *fsm_context,
367 void *destructor_context)
369 Foo f = destructor_context;
370 SILC_LOG_DEBUG(("FSM destructor, stopping scheduler"));
372 silc_schedule_stop(f->schedule);
375 int main(int argc, char **argv)
377 SilcBool success = FALSE;
378 SilcSchedule schedule;
382 if (argc > 1 && !strcmp(argv[1], "-d")) {
383 silc_log_debug(TRUE);
384 silc_log_debug_hexdump(TRUE);
385 silc_log_quick(TRUE);
386 silc_log_set_debug_string("*fsm*,*async*");
389 SILC_LOG_DEBUG(("Allocating scheduler"));
390 schedule = silc_schedule_init(0, NULL);
392 f = silc_calloc(1, sizeof(*f));
395 f->schedule = schedule;
397 SILC_LOG_DEBUG(("Allocating FSM context"));
398 f->fsm = fsm = silc_fsm_alloc(f, destructor, f, schedule);
401 silc_fsm_start(fsm, test_st_start);
403 SILC_LOG_DEBUG(("Running scheduler"));
404 silc_schedule(schedule);
409 silc_schedule_uninit(schedule);
415 SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE"));
416 fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE");