Added SILC Thread Queue API
[silc.git] / lib / silcutil / silcschedule_i.h
1 /*
2
3   silcschedule_i.h.
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2001 - 2007 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19
20 #ifndef SILCSCHEDULE_I_H
21 #define SILCSCHEDULE_I_H
22
23 #ifndef SILCSCHEDULE_H
24 #error "Do not include this header directly"
25 #endif
26
27 #include "silchashtable.h"
28 #include "silclist.h"
29
30 /* Task types */
31 typedef enum {
32   /* File descriptor task that performs some event over file descriptors.
33      These tasks are for example network connections. */
34   SILC_TASK_FD           = 0,
35
36   /* Timeout tasks are tasks that are executed after the specified
37      time has elapsed. After the task is executed the task is removed
38      automatically from the scheduler. It is safe to re-register the
39      task in task callback. It is also safe to unregister a task in
40      the task callback. */
41   SILC_TASK_TIMEOUT      = 1,
42
43   /* Platform specific process signal task.  On Unix systems this is one of
44      the signals described in signal(7).  On other platforms this may not
45      be available at all.  Only one callback per signal may be added. */
46   SILC_TASK_SIGNAL       = 2,
47
48   /* Asynchronous event task. */
49   SILC_TASK_EVENT        = 3,
50 } SilcTaskType;
51
52 /* Task header */
53 struct SilcTaskStruct {
54   struct SilcTaskStruct *next;
55   SilcTaskCallback callback;
56   void *context;
57   unsigned int type    : 2;     /* SilcTaskType */
58   unsigned int valid   : 1;     /* Set if task is valid */
59 };
60
61 /* Timeout task */
62 typedef struct SilcTaskTimeoutStruct {
63   struct SilcTaskStruct header;
64   struct timeval timeout;
65 } *SilcTaskTimeout;
66
67 /* Fd task */
68 typedef struct SilcTaskFdStruct {
69   struct SilcTaskStruct header;
70   unsigned int scheduled  : 1;
71   unsigned int events     : 14;
72   unsigned int revents    : 14;
73   SilcUInt32 fd;
74 } *SilcTaskFd;
75
76 /* Event task */
77 typedef struct SilcEventTaskStruct {
78   struct SilcTaskStruct header;
79   char *event;
80   SilcList connections;
81 } *SilcEventTask;
82
83 /* Scheduler context */
84 struct SilcScheduleStruct {
85   SilcSchedule parent;             /* Parent scheduler */
86   void *internal;
87   void *app_context;               /* Application specific context */
88   SilcTaskNotifyCb notify;         /* Notify callback */
89   void *notify_context;            /* Notify context */
90   SilcStack stack;                 /* Stack */
91   SilcHashTable events;            /* Event tasks */
92   SilcHashTable fd_queue;          /* FD task queue */
93   SilcList fd_dispatch;            /* Dispatched FDs */
94   SilcList timeout_queue;          /* Timeout queue */
95   SilcList free_tasks;             /* Timeout task freelist */
96   SilcMutex lock;                  /* Scheduler lock */
97   struct timeval timeout;          /* Current timeout */
98   unsigned int max_tasks     : 29; /* Max FD tasks */
99   unsigned int has_timeout   : 1;  /* Set if timeout is set */
100   unsigned int valid         : 1;  /* Set if scheduler is valid */
101   unsigned int signal_tasks  : 1;  /* Set if to dispatch signals */
102 };
103
104 /* Locks. These also blocks signals that we care about and thus guarantee
105    that while we are in scheduler no signals can happen.  This way we can
106    synchronise signals with SILC Scheduler. */
107 #define SILC_SCHEDULE_LOCK(schedule)                            \
108 do {                                                            \
109   silc_mutex_lock(schedule->lock);                              \
110   schedule_ops.signals_block(schedule, schedule->internal);     \
111 } while (0)
112 #define SILC_SCHEDULE_UNLOCK(schedule)                          \
113 do {                                                            \
114   schedule_ops.signals_unblock(schedule, schedule->internal);   \
115   silc_mutex_unlock(schedule->lock);                            \
116 } while (0)
117
118 /* Platform specific scheduler operations */
119 typedef struct {
120   /* Initializes the platform specific scheduler.  This for example initializes
121      the wakeup mechanism of the scheduler.  In multi-threaded environment
122      the scheduler needs to be wakenup when tasks are added or removed from
123      the task queues.  Returns context to the platform specific scheduler.
124      If this returns NULL the scheduler initialization will fail.  Do not
125      add FD tasks inside function.  Timeout tasks can be added. */
126   void *(*init)(SilcSchedule schedule, void *app_context);
127
128   /* Uninitializes the platform specific scheduler context. */
129   void (*uninit)(SilcSchedule schedule, void *context);
130
131   /* System specific waiter. This must fill the schedule->fd_dispatch queue
132      with valid tasks that has something to dispatch, when this returns. */
133   int (*schedule)(SilcSchedule schedule, void *context);
134
135   /* Schedule `task' with events `event_mask'. Zero `event_mask'
136      unschedules the task. */
137   SilcBool (*schedule_fd)(SilcSchedule schedule, void *context,
138                           SilcTaskFd task, SilcTaskEvent event_mask);
139
140   /* Wakes up the scheduler. This is platform specific routine */
141   void (*wakeup)(SilcSchedule schedule, void *context);
142
143   /* Register signal */
144   void (*signal_register)(SilcSchedule schedule, void *context,
145                           SilcUInt32 signal, SilcTaskCallback callback,
146                           void *callback_context);
147
148   /* Unregister signal */
149   void (*signal_unregister)(SilcSchedule schedule, void *context,
150                             SilcUInt32 signal);
151
152   /* Call all signals */
153   void (*signals_call)(SilcSchedule schedule, void *context);
154
155   /* Block registered signals in scheduler. */
156   void (*signals_block)(SilcSchedule schedule, void *context);
157
158   /* Unblock registered signals in schedule. */
159   void (*signals_unblock)(SilcSchedule schedule, void *context);
160 } SilcScheduleOps;
161
162 /* The generic function to add any type of task to the scheduler.  This
163    used to be exported as is to application, but now they should use the
164    macro wrappers defined in silcschedule.h.  For Fd task the timeout must
165    be zero, for timeout task the timeout must not be zero, for signal task
166    the fd argument is the signal. */
167 SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd,
168                                 SilcTaskCallback callback, void *context,
169                                 long seconds, long useconds,
170                                 SilcTaskType type);
171
172 #ifdef SILC_DIST_INPLACE
173 /* Print scheduler statistics to stdout. */
174 void silc_schedule_stats(SilcSchedule schedule);
175 #endif /* SILC_DIST_INPLACE */
176
177 #endif /* SILCSCHEDULE_I_H */