X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcutil%2Fsilcschedule_i.h;h=a88df592c8fb7bad88b4f183e16b50dc7a2d3cc8;hb=e7b6c157b80152bf9fb9266e6bdd93f9fb0db776;hp=4abf530d8ec04e9c12214332d1af01593fb1209f;hpb=6d18348a06478dbb7e7963aa429241b61ebe82fd;p=silc.git diff --git a/lib/silcutil/silcschedule_i.h b/lib/silcutil/silcschedule_i.h index 4abf530d..a88df592 100644 --- a/lib/silcutil/silcschedule_i.h +++ b/lib/silcutil/silcschedule_i.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2001 - 2006 Pekka Riikonen + Copyright (C) 2001 - 2007 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 @@ -27,42 +27,77 @@ #include "silchashtable.h" #include "silclist.h" +/* Task types */ +typedef enum { + /* File descriptor task that performs some event over file descriptors. + These tasks are for example network connections. */ + SILC_TASK_FD = 0, + + /* Timeout tasks are tasks that are executed after the specified + time has elapsed. After the task is executed the task is removed + automatically from the scheduler. It is safe to re-register the + task in task callback. It is also safe to unregister a task in + the task callback. */ + SILC_TASK_TIMEOUT = 1, + + /* Platform specific process signal task. On Unix systems this is one of + the signals described in signal(7). On other platforms this may not + be available at all. Only one callback per signal may be added. */ + SILC_TASK_SIGNAL = 2, + + /* Asynchronous event task. */ + SILC_TASK_EVENT = 3, +} SilcTaskType; + /* Task header */ struct SilcTaskStruct { + struct SilcTaskStruct *next; SilcTaskCallback callback; void *context; - unsigned int type : 1; /* 0 = fd, 1 = timeout */ + unsigned int type : 2; /* SilcTaskType */ unsigned int valid : 1; /* Set if task is valid */ }; /* Timeout task */ typedef struct SilcTaskTimeoutStruct { struct SilcTaskStruct header; - struct SilcTaskTimeoutStruct *next; struct timeval timeout; } *SilcTaskTimeout; /* Fd task */ -typedef struct { +typedef struct SilcTaskFdStruct { struct SilcTaskStruct header; - unsigned int events : 15; - unsigned int revents : 15; + unsigned int scheduled : 1; + unsigned int events : 14; + unsigned int revents : 14; SilcUInt32 fd; } *SilcTaskFd; +/* Event task */ +typedef struct SilcEventTaskStruct { + struct SilcTaskStruct header; + char *event; + SilcList connections; +} *SilcEventTask; + /* Scheduler context */ struct SilcScheduleStruct { + SilcSchedule parent; /* Parent scheduler */ void *internal; void *app_context; /* Application specific context */ + SilcTaskNotifyCb notify; /* Notify callback */ + void *notify_context; /* Notify context */ + SilcStack stack; /* Stack */ + SilcHashTable events; /* Event tasks */ SilcHashTable fd_queue; /* FD task queue */ + SilcList fd_dispatch; /* Dispatched FDs */ SilcList timeout_queue; /* Timeout queue */ SilcList free_tasks; /* Timeout task freelist */ SilcMutex lock; /* Scheduler lock */ struct timeval timeout; /* Current timeout */ - unsigned int max_tasks : 28; /* Max FD tasks */ + unsigned int max_tasks : 29; /* Max FD tasks */ unsigned int has_timeout : 1; /* Set if timeout is set */ unsigned int valid : 1; /* Set if scheduler is valid */ - unsigned int is_locked : 1; /* Set if scheduler is locked */ unsigned int signal_tasks : 1; /* Set if to dispatch signals */ }; @@ -71,13 +106,13 @@ struct SilcScheduleStruct { synchronise signals with SILC Scheduler. */ #define SILC_SCHEDULE_LOCK(schedule) \ do { \ - schedule_ops.signals_block(schedule, schedule->internal); \ silc_mutex_lock(schedule->lock); \ + schedule_ops.signals_block(schedule, schedule->internal); \ } while (0) #define SILC_SCHEDULE_UNLOCK(schedule) \ do { \ - silc_mutex_unlock(schedule->lock); \ schedule_ops.signals_unblock(schedule, schedule->internal); \ + silc_mutex_unlock(schedule->lock); \ } while (0) /* Platform specific scheduler operations */ @@ -85,14 +120,22 @@ typedef struct { /* Initializes the platform specific scheduler. This for example initializes the wakeup mechanism of the scheduler. In multi-threaded environment the scheduler needs to be wakenup when tasks are added or removed from - the task queues. Returns context to the platform specific scheduler. */ + the task queues. Returns context to the platform specific scheduler. + If this returns NULL the scheduler initialization will fail. Do not + add FD tasks inside function. Timeout tasks can be added. */ void *(*init)(SilcSchedule schedule, void *app_context); /* Uninitializes the platform specific scheduler context. */ void (*uninit)(SilcSchedule schedule, void *context); - /* System specific select(). Returns same values as normal select(). */ - int (*select)(SilcSchedule schedule, void *context); + /* System specific waiter. This must fill the schedule->fd_dispatch queue + with valid tasks that has something to dispatch, when this returns. */ + int (*schedule)(SilcSchedule schedule, void *context); + + /* Schedule `task' with events `event_mask'. Zero `event_mask' + unschedules the task. */ + SilcBool (*schedule_fd)(SilcSchedule schedule, void *context, + SilcTaskFd task, SilcTaskEvent event_mask); /* Wakes up the scheduler. This is platform specific routine */ void (*wakeup)(SilcSchedule schedule, void *context); @@ -104,11 +147,7 @@ typedef struct { /* Unregister signal */ void (*signal_unregister)(SilcSchedule schedule, void *context, - SilcUInt32 signal, SilcTaskCallback callback, - void *callback_context); - - /* Mark signal to be called later. */ - void (*signal_call)(SilcSchedule schedule, void *context, SilcUInt32 signal); + SilcUInt32 signal); /* Call all signals */ void (*signals_call)(SilcSchedule schedule, void *context); @@ -120,9 +159,19 @@ typedef struct { void (*signals_unblock)(SilcSchedule schedule, void *context); } SilcScheduleOps; -#if defined(SILC_DEBUG) +/* The generic function to add any type of task to the scheduler. This + used to be exported as is to application, but now they should use the + macro wrappers defined in silcschedule.h. For Fd task the timeout must + be zero, for timeout task the timeout must not be zero, for signal task + the fd argument is the signal. */ +SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd, + SilcTaskCallback callback, void *context, + long seconds, long useconds, + SilcTaskType type); + +#ifdef SILC_DIST_INPLACE /* Print scheduler statistics to stdout. */ void silc_schedule_stats(SilcSchedule schedule); -#endif /* SILC_DEBUG */ +#endif /* SILC_DIST_INPLACE */ #endif /* SILCSCHEDULE_I_H */