Added 'send_events' boolean argument to the function
[silc.git] / lib / silcutil / silcschedule.c
index bfb72997ad2017d2163c30c90cabac9278477468..97005ca1911e1c75c96b5cd6a209fda56fbfc73f 100644 (file)
@@ -35,7 +35,7 @@ int silc_select(SilcScheduleFd fds, SilcUInt32 fds_count,
    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. */
-void *silc_schedule_internal_init(SilcSchedule schedule);
+void *silc_schedule_internal_init(SilcSchedule schedule, void *context);
 
 /* Uninitializes the platform specific scheduler context. */
 void silc_schedule_internal_uninit(void *context);
@@ -210,6 +210,7 @@ struct SilcTaskQueueStruct {
 
 */
 struct SilcScheduleStruct {
+  void *app_context;           /* Application specific context */
   SilcTaskQueue fd_queue;
   SilcTaskQueue timeout_queue;
   SilcTaskQueue generic_queue;
@@ -227,9 +228,10 @@ struct SilcScheduleStruct {
 /* Initializes the scheduler. This returns the scheduler context that
    is given as arugment usually to all silc_schedule_* functions.
    The `max_tasks' indicates the number of maximum tasks that the
-   scheduler can handle. */
+   scheduler can handle. The `app_context' is application specific
+   context that is delivered to task callbacks. */
 
-SilcSchedule silc_schedule_init(int max_tasks)
+SilcSchedule silc_schedule_init(int max_tasks, void *app_context)
 {
   SilcSchedule schedule;
 
@@ -251,12 +253,13 @@ SilcSchedule silc_schedule_init(int max_tasks)
   schedule->max_fd = max_tasks;
   schedule->timeout = NULL;
   schedule->valid = TRUE;
+  schedule->app_context = app_context;
 
   /* Allocate scheduler lock */
   silc_mutex_alloc(&schedule->lock);
 
   /* Initialize the platform specific scheduler. */
-  schedule->internal = silc_schedule_internal_init(schedule);
+  schedule->internal = silc_schedule_internal_init(schedule, app_context);
 
   return schedule;
 }
@@ -366,7 +369,8 @@ static void silc_schedule_dispatch_nontimeout(SilcSchedule schedule)
       if (task->valid && schedule->fd_list[i].revents & SILC_TASK_READ) {
        silc_mutex_unlock(schedule->fd_queue->lock);
        SILC_SCHEDULE_UNLOCK(schedule);
-       task->callback(schedule, SILC_TASK_READ, task->fd, task->context);
+       task->callback(schedule, schedule->app_context,
+                      SILC_TASK_READ, task->fd, task->context);
        SILC_SCHEDULE_LOCK(schedule);
        silc_mutex_lock(schedule->fd_queue->lock);
       }
@@ -375,7 +379,8 @@ static void silc_schedule_dispatch_nontimeout(SilcSchedule schedule)
       if (task->valid && schedule->fd_list[i].revents & SILC_TASK_WRITE) {
        silc_mutex_unlock(schedule->fd_queue->lock);
        SILC_SCHEDULE_UNLOCK(schedule);
-       task->callback(schedule, SILC_TASK_WRITE, task->fd, task->context);
+       task->callback(schedule, schedule->app_context,
+                      SILC_TASK_WRITE, task->fd, task->context);
        SILC_SCHEDULE_LOCK(schedule);
        silc_mutex_lock(schedule->fd_queue->lock);
       }
@@ -405,7 +410,8 @@ static void silc_schedule_dispatch_nontimeout(SilcSchedule schedule)
        if (task->valid && schedule->fd_list[i].revents & SILC_TASK_READ) {
          silc_mutex_unlock(schedule->generic_queue->lock);
          SILC_SCHEDULE_UNLOCK(schedule);
-         task->callback(schedule, SILC_TASK_READ, fd, task->context);
+         task->callback(schedule, schedule->app_context,
+                        SILC_TASK_READ, fd, task->context);
          SILC_SCHEDULE_LOCK(schedule);
          silc_mutex_lock(schedule->generic_queue->lock);
        }
@@ -414,7 +420,8 @@ static void silc_schedule_dispatch_nontimeout(SilcSchedule schedule)
        if (task->valid && schedule->fd_list[i].revents & SILC_TASK_WRITE) {
          silc_mutex_unlock(schedule->generic_queue->lock);
          SILC_SCHEDULE_UNLOCK(schedule);
-         task->callback(schedule, SILC_TASK_WRITE, fd, task->context);
+         task->callback(schedule, schedule->app_context,
+                        SILC_TASK_WRITE, fd, task->context);
          SILC_SCHEDULE_LOCK(schedule);
          silc_mutex_lock(schedule->generic_queue->lock);
        }
@@ -476,7 +483,8 @@ static void silc_schedule_dispatch_timeout(SilcSchedule schedule,
         if (task->valid) {
          silc_mutex_unlock(queue->lock);
          SILC_SCHEDULE_UNLOCK(schedule);
-         task->callback(schedule, SILC_TASK_EXPIRE, task->fd, task->context);
+         task->callback(schedule, schedule->app_context,
+                        SILC_TASK_EXPIRE, task->fd, task->context);
          SILC_SCHEDULE_LOCK(schedule);
          silc_mutex_lock(queue->lock);
        }
@@ -688,6 +696,16 @@ void silc_schedule_wakeup(SilcSchedule schedule)
 #endif
 }
 
+/* Returns the application specific context that was saved into the
+   scheduler in silc_schedule_init function.  The context is also
+   returned to application in task callback functions, but this function
+   may be used to get it as well if needed. */
+
+void *silc_schedule_get_context(SilcSchedule schedule)
+{
+  return schedule->app_context;
+}
+
 /* Add new task to the scheduler */
 
 SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd,
@@ -724,7 +742,7 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd,
 
          /* Add the fd to be listened, the task found now applies to this
             fd as well. */
-         silc_schedule_set_listen_fd(schedule, fd, SILC_TASK_READ);
+         silc_schedule_set_listen_fd(schedule, fd, SILC_TASK_READ, FALSE);
          return task;
        }
        
@@ -763,7 +781,7 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd,
   /* If the task is non-timeout task we have to tell the scheduler that we
      would like to have these tasks scheduled at some odd distant future. */
   if (type != SILC_TASK_TIMEOUT)
-    silc_schedule_set_listen_fd(schedule, fd, SILC_TASK_READ);
+    silc_schedule_set_listen_fd(schedule, fd, SILC_TASK_READ, FALSE);
 
   silc_mutex_lock(queue->lock);
 
@@ -864,8 +882,8 @@ void silc_schedule_task_del_by_context(SilcSchedule schedule, void *context)
    call this directly if wanted. This can be called multiple times for
    one file descriptor to set different iomasks. */
 
-void silc_schedule_set_listen_fd(SilcSchedule schedule,
-                                SilcUInt32 fd, SilcTaskEvent iomask)
+void silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd,
+                                SilcTaskEvent mask, bool send_events)
 {
   int i;
   bool found = FALSE;
@@ -878,10 +896,14 @@ void silc_schedule_set_listen_fd(SilcSchedule schedule,
   for (i = 0; i < schedule->max_fd; i++)
     if (schedule->fd_list[i].fd == fd) {
       schedule->fd_list[i].fd = fd;
-      schedule->fd_list[i].events = iomask;
+      schedule->fd_list[i].events = mask;
       if (i > schedule->last_fd)
        schedule->last_fd = i;
       found = TRUE;
+      if (send_events) {
+       schedule->fd_list[i].revents = mask;
+       silc_schedule_dispatch_nontimeout(schedule);
+      }
       break;
     }
 
@@ -889,9 +911,13 @@ void silc_schedule_set_listen_fd(SilcSchedule schedule,
     for (i = 0; i < schedule->max_fd; i++)
       if (schedule->fd_list[i].events == 0) {
        schedule->fd_list[i].fd = fd;
-       schedule->fd_list[i].events = iomask;
+       schedule->fd_list[i].events = mask;
        if (i > schedule->last_fd)
          schedule->last_fd = i;
+       if (send_events) {
+         schedule->fd_list[i].revents = mask;
+         silc_schedule_dispatch_nontimeout(schedule);
+       }
        break;
       }