3 #include "silcincludes.h"
6 typedef void (*Callback)(void *context);
8 #define NUM_THREADS 200
10 typedef struct FooStruct *Foo;
13 SilcFSMThreadStruct thread;
14 SilcFSMSemaStruct sema;
23 SilcFSMThreadStruct thread;
25 SilcFSMSemaStruct sema;
26 SilcSchedule schedule;
29 T threads[NUM_THREADS];
30 T threads2[NUM_THREADS];
33 SILC_FSM_STATE(test_st_start);
34 SILC_FSM_STATE(test_st_second);
35 SILC_FSM_STATE(test_st_third);
36 SILC_FSM_STATE(test_st_fourth);
37 SILC_FSM_STATE(test_st_fifth);
38 SILC_FSM_STATE(test_st_sixth);
39 SILC_FSM_STATE(test_st_seventh);
40 SILC_FSM_STATE(test_st_eighth);
41 SILC_FSM_STATE(test_st_ninth);
42 SILC_FSM_STATE(test_st_tenth);
43 SILC_FSM_STATE(test_st_finish);
45 SILC_FSM_STATE(test_thread_st_start);
46 SILC_FSM_STATE(test_thread_st_finish);
47 SILC_FSM_STATE(test_thread2_st_start);
48 SILC_FSM_STATE(test_thread2_st_finish);
49 SILC_FSM_STATE(test_thread3_st_start);
50 SILC_FSM_STATE(test_thread4_st_start);
52 SILC_TASK_CALLBACK(async_call_timeout)
55 SILC_LOG_DEBUG(("Async call cb, continuing FSM"));
59 static void async_call(Callback cb, void *context)
63 f->cb_context = context;
64 SILC_LOG_DEBUG(("Async call"));
65 silc_schedule_task_add(f->schedule, 0, async_call_timeout, f, 0, 200000,
69 SILC_FSM_STATE(test_st_start)
71 SILC_LOG_DEBUG(("test_st_start"));
73 /** Move to second state */
74 SILC_LOG_DEBUG(("Move to next state"));
75 silc_fsm_next(fsm, test_st_second);
76 return SILC_FSM_CONTINUE;
79 SILC_FSM_STATE(test_st_second)
81 SILC_LOG_DEBUG(("test_st_second"));
83 /** Move to third state, timeout */
84 SILC_LOG_DEBUG(("Move to next state with 2 second timeout"));
85 silc_fsm_next_later(fsm, test_st_third, 2, 0);
89 static void async_call_cb(void *context)
92 SILC_LOG_DEBUG(("Callback, continue to next state"));
93 SILC_FSM_CALL_CONTINUE(f->fsm);
96 SILC_FSM_STATE(test_st_third)
100 SILC_LOG_DEBUG(("test_st_third"));
104 /** Wait async callback*/
105 SILC_LOG_DEBUG(("Call async call"));
106 silc_fsm_next(fsm, test_st_fourth);
107 SILC_FSM_CALL(async_call(async_call_cb, f));
110 SILC_FSM_STATE(test_st_fourth)
114 SILC_LOG_DEBUG(("test_st_fourth"));
118 SILC_LOG_DEBUG(("Creating FSM thread"));
119 if (!silc_fsm_thread_init(&f->thread, fsm, f, NULL, NULL, FALSE)) {
120 /** Error creating thread */
121 SILC_LOG_DEBUG(("Error creating thread"));
123 silc_fsm_next(fsm, test_st_finish);
124 return SILC_FSM_CONTINUE;
126 SILC_LOG_DEBUG(("Starting thread"));
127 silc_fsm_start(&f->thread, test_thread_st_start);
129 /** Waiting thread to terminate */
130 SILC_LOG_DEBUG(("Waiting for thread to terminate"));
131 silc_fsm_next(fsm, test_st_fifth);
132 SILC_FSM_THREAD_WAIT(&f->thread);
135 SILC_FSM_STATE(test_thread_st_start)
139 SILC_LOG_DEBUG(("test_thread_st_start"));
141 /** Move to final state, timeout */
142 SILC_LOG_DEBUG(("Move to final state with %d second timeout", f->timeout));
143 silc_fsm_next_later(fsm, test_thread_st_finish, f->timeout, 0);
144 return SILC_FSM_WAIT;
147 SILC_FSM_STATE(test_thread_st_finish)
149 SILC_LOG_DEBUG(("test_thread_st_finish"));
151 SILC_LOG_DEBUG(("Finishing the thread"));
152 return SILC_FSM_FINISH;
155 SILC_FSM_STATE(test_st_fifth)
158 SILC_LOG_DEBUG(("test_st_fifth"));
160 SILC_LOG_DEBUG(("Thread terminated, start new real thread"));
164 SILC_LOG_DEBUG(("Creating FSM semaphore"));
165 silc_fsm_sema_init(&f->sema, fsm, 0);
167 SILC_LOG_DEBUG(("Creating FSM thread"));
168 if (!silc_fsm_thread_init(&f->thread, fsm, f, NULL, NULL, TRUE)) {
169 /** Error creating real thread */
170 SILC_LOG_DEBUG(("Error creating thread"));
172 silc_fsm_next(fsm, test_st_finish);
173 return SILC_FSM_CONTINUE;
175 SILC_LOG_DEBUG(("Starting thread"));
176 silc_fsm_start(&f->thread, test_thread2_st_start);
178 /** Waiting thread to terminate, timeout */
179 SILC_LOG_DEBUG(("Waiting for thread to terminate for 5 seconds"));
180 silc_fsm_next(fsm, test_st_sixth);
181 SILC_FSM_SEMA_TIMEDWAIT(&f->sema, 5, 0);
182 return SILC_FSM_CONTINUE;
185 SILC_FSM_STATE(test_thread2_st_start)
189 SILC_LOG_DEBUG(("test_thread2_st_start"));
191 /** Move to final state, timeout */
192 SILC_LOG_DEBUG(("Move to final state with %d second timeout", f->timeout));
193 silc_fsm_next_later(fsm, test_thread2_st_finish, f->timeout, 0);
194 return SILC_FSM_WAIT;
197 SILC_FSM_STATE(test_thread2_st_finish)
200 SILC_LOG_DEBUG(("test_thread2_st_finish"));
202 SILC_LOG_DEBUG(("Post semaphore"));
203 SILC_FSM_SEMA_POST(&f->sema);
205 SILC_LOG_DEBUG(("Finishing the thread"));
206 return SILC_FSM_FINISH;
209 SILC_FSM_STATE(test_st_sixth)
211 SILC_LOG_DEBUG(("test_st_sixth"));
213 SILC_LOG_DEBUG(("Thread wait timedout, OK"));
215 /** Move to next state, timeout */
216 SILC_LOG_DEBUG(("Continue to next state with 4 second timeout"));
217 silc_fsm_next_later(fsm, test_st_seventh, 4, 0);
218 return SILC_FSM_WAIT;
221 SILC_FSM_STATE(test_thread3_st_start)
225 if (t->rounds == 0) {
226 SILC_FSM_SEMA_POST(&t->sema);
227 return SILC_FSM_FINISH;
232 /** Call in recursive */
233 silc_fsm_next(fsm, test_thread3_st_start);
234 return SILC_FSM_CONTINUE;
237 SILC_FSM_STATE(test_st_seventh)
242 SILC_LOG_DEBUG(("test_st_seventh"));
245 SILC_LOG_DEBUG(("Creating %d FSM threads", NUM_THREADS));
246 for (i = 0; i < NUM_THREADS; i++) {
247 f->threads[i].rounds = 10;
249 silc_fsm_sema_init(&f->threads[i].sema, fsm, 0);
250 if (!silc_fsm_thread_init(&f->threads[i].thread, fsm,
251 &f->threads[i], NULL, NULL, FALSE)) {
252 /** Error creating thread */
253 SILC_LOG_DEBUG(("Error creating thread"));
255 silc_fsm_next(fsm, test_st_finish);
256 return SILC_FSM_CONTINUE;
259 silc_fsm_start(&f->threads[i].thread, test_thread3_st_start);
262 /** Move to wait threads */
263 silc_fsm_next(fsm, test_st_eighth);
264 return SILC_FSM_CONTINUE;
267 SILC_FSM_STATE(test_st_eighth)
272 for (i = 0; i < NUM_THREADS; i++) {
273 if (f->threads[i].finished == FALSE) {
274 SILC_FSM_SEMA_WAIT(&f->threads[i].sema);
275 f->threads[i].finished = TRUE;
279 for (i = 0; i < NUM_THREADS; i++)
280 silc_fsm_uninit(&f->threads[i].thread);
282 SILC_LOG_DEBUG(("All %d threads terminated", NUM_THREADS));
284 /** Move to next thread */
285 silc_fsm_next(fsm, test_st_ninth);
286 return SILC_FSM_CONTINUE;
289 SILC_FSM_STATE(test_thread4_st_start)
293 if (t->rounds == 0) {
294 SILC_FSM_SEMA_POST(&t->sema);
295 return SILC_FSM_FINISH;
300 /** Call in recursive */
301 silc_fsm_next(fsm, test_thread4_st_start);
302 return SILC_FSM_CONTINUE;
305 SILC_FSM_STATE(test_st_ninth)
310 SILC_LOG_DEBUG(("test_st_ninth"));
312 SILC_LOG_DEBUG(("Creating FSM semaphore"));
313 silc_fsm_sema_init(&f->sema, fsm, NUM_THREADS + 1);
315 SILC_LOG_DEBUG(("Creating %d real FSM threads", NUM_THREADS));
316 for (i = 0; i < NUM_THREADS; i++) {
317 f->threads2[i].rounds = 10;
318 f->threads2[i].f = f;
319 silc_fsm_sema_init(&f->threads2[i].sema, fsm, 0);
320 if (!silc_fsm_thread_init(&f->threads2[i].thread, fsm,
321 &f->threads2[i], NULL, NULL, TRUE)) {
322 /** Error creating real thread */
323 SILC_LOG_DEBUG(("Error creating real thread"));
325 silc_fsm_next(fsm, test_st_finish);
326 return SILC_FSM_CONTINUE;
329 silc_fsm_start(&f->threads2[i].thread, test_thread4_st_start);
332 /** Move to wait threads */
333 silc_fsm_next(fsm, test_st_tenth);
334 return SILC_FSM_CONTINUE;
337 SILC_FSM_STATE(test_st_tenth)
342 for (i = 0; i < NUM_THREADS; i++)
343 if (f->threads2[i].finished == FALSE) {
344 SILC_FSM_SEMA_WAIT(&f->threads2[i].sema);
345 f->threads2[i].finished = TRUE;
348 for (i = 0; i < NUM_THREADS; i++)
349 silc_fsm_uninit(&f->threads2[i].thread);
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 bool 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 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");