task-manager: Add method to remove a task from a queue
authorTobias Brunner <tobias@strongswan.org>
Wed, 28 Nov 2018 13:50:09 +0000 (14:50 +0100)
committerTobias Brunner <tobias@strongswan.org>
Fri, 7 Dec 2018 09:32:12 +0000 (10:32 +0100)
src/libcharon/sa/ikev1/task_manager_v1.c
src/libcharon/sa/ikev2/task_manager_v2.c
src/libcharon/sa/task_manager.h

index b1a8702..90d623b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2016 Tobias Brunner
+ * Copyright (C) 2007-2018 Tobias Brunner
  * Copyright (C) 2007-2011 Martin Willi
  * HSR Hochschule fuer Technik Rapperswil
  *
@@ -1984,19 +1984,86 @@ METHOD(task_manager_t, reset, void,
        }
 }
 
+/**
+ * Data for a task queue enumerator
+ */
+typedef struct {
+       enumerator_t public;
+       task_queue_t queue;
+       enumerator_t *inner;
+} task_enumerator_t;
+
+METHOD(enumerator_t, task_enumerator_destroy, void,
+       task_enumerator_t *this)
+{
+       this->inner->destroy(this->inner);
+       free(this);
+}
+
+METHOD(enumerator_t, task_enumerator_enumerate, bool,
+       task_enumerator_t *this, va_list args)
+{
+       task_t **task;
+
+       VA_ARGS_VGET(args, task);
+       return this->inner->enumerate(this->inner, task);
+}
+
 METHOD(task_manager_t, create_task_enumerator, enumerator_t*,
        private_task_manager_t *this, task_queue_t queue)
 {
+       task_enumerator_t *enumerator;
+
+       INIT(enumerator,
+               .public = {
+                       .enumerate = enumerator_enumerate_default,
+                       .venumerate = _task_enumerator_enumerate,
+                       .destroy = _task_enumerator_destroy,
+               },
+               .queue = queue,
+       );
        switch (queue)
        {
                case TASK_QUEUE_ACTIVE:
-                       return this->active_tasks->create_enumerator(this->active_tasks);
+                       enumerator->inner = this->active_tasks->create_enumerator(
+                                                                                                               this->active_tasks);
+                       break;
+               case TASK_QUEUE_PASSIVE:
+                       enumerator->inner = this->passive_tasks->create_enumerator(
+                                                                                                               this->passive_tasks);
+                       break;
+               case TASK_QUEUE_QUEUED:
+                       enumerator->inner = this->queued_tasks->create_enumerator(
+                                                                                                               this->queued_tasks);
+                       break;
+               default:
+                       enumerator->inner = enumerator_create_empty();
+                       break;
+       }
+       return &enumerator->public;
+}
+
+METHOD(task_manager_t, remove_task, void,
+       private_task_manager_t *this, enumerator_t *enumerator_public)
+{
+       task_enumerator_t *enumerator = (task_enumerator_t*)enumerator_public;
+
+       switch (enumerator->queue)
+       {
+               case TASK_QUEUE_ACTIVE:
+                       this->active_tasks->remove_at(this->active_tasks,
+                                                                                 enumerator->inner);
+                       break;
                case TASK_QUEUE_PASSIVE:
-                       return this->passive_tasks->create_enumerator(this->passive_tasks);
+                       this->passive_tasks->remove_at(this->passive_tasks,
+                                                                                  enumerator->inner);
+                       break;
                case TASK_QUEUE_QUEUED:
-                       return this->queued_tasks->create_enumerator(this->queued_tasks);
+                       this->queued_tasks->remove_at(this->queued_tasks,
+                                                                                 enumerator->inner);
+                       break;
                default:
-                       return enumerator_create_empty();
+                       break;
        }
 }
 
@@ -2050,6 +2117,7 @@ task_manager_v1_t *task_manager_v1_create(ike_sa_t *ike_sa)
                                .adopt_child_tasks = _adopt_child_tasks,
                                .busy = _busy,
                                .create_task_enumerator = _create_task_enumerator,
+                               .remove_task = _remove_task,
                                .flush = _flush,
                                .flush_queue = _flush_queue,
                                .destroy = _destroy,
index 09447b7..a050be6 100644 (file)
@@ -2186,17 +2186,39 @@ METHOD(task_manager_t, reset, void,
        this->reset = TRUE;
 }
 
-CALLBACK(filter_queued, bool,
-       void *unused, enumerator_t *orig, va_list args)
-{
+/**
+ * Data for a task queue enumerator
+ */
+typedef struct {
+       enumerator_t public;
+       task_queue_t queue;
+       enumerator_t *inner;
        queued_task_t *queued;
+} task_enumerator_t;
+
+METHOD(enumerator_t, task_enumerator_destroy, void,
+       task_enumerator_t *this)
+{
+       this->inner->destroy(this->inner);
+       free(this);
+}
+
+METHOD(enumerator_t, task_enumerator_enumerate, bool,
+       task_enumerator_t *this, va_list args)
+{
        task_t **task;
 
        VA_ARGS_VGET(args, task);
-
-       if (orig->enumerate(orig, &queued))
+       if (this->queue == TASK_QUEUE_QUEUED)
+       {
+               if (this->inner->enumerate(this->inner, &this->queued))
+               {
+                       *task = this->queued->task;
+                       return TRUE;
+               }
+       }
+       else if (this->inner->enumerate(this->inner, task))
        {
-               *task = queued->task;
                return TRUE;
        }
        return FALSE;
@@ -2205,18 +2227,54 @@ CALLBACK(filter_queued, bool,
 METHOD(task_manager_t, create_task_enumerator, enumerator_t*,
        private_task_manager_t *this, task_queue_t queue)
 {
+       task_enumerator_t *enumerator;
+
+       INIT(enumerator,
+               .public = {
+                       .enumerate = enumerator_enumerate_default,
+                       .venumerate = _task_enumerator_enumerate,
+                       .destroy = _task_enumerator_destroy,
+               },
+               .queue = queue,
+       );
        switch (queue)
        {
                case TASK_QUEUE_ACTIVE:
-                       return array_create_enumerator(this->active_tasks);
+                       enumerator->inner = array_create_enumerator(this->active_tasks);
+                       break;
+               case TASK_QUEUE_PASSIVE:
+                       enumerator->inner = array_create_enumerator(this->passive_tasks);
+                       break;
+               case TASK_QUEUE_QUEUED:
+                       enumerator->inner = array_create_enumerator(this->queued_tasks);
+                       break;
+               default:
+                       enumerator->inner = enumerator_create_empty();
+                       break;
+       }
+       return &enumerator->public;
+}
+
+METHOD(task_manager_t, remove_task, void,
+       private_task_manager_t *this, enumerator_t *enumerator_public)
+{
+       task_enumerator_t *enumerator = (task_enumerator_t*)enumerator_public;
+
+       switch (enumerator->queue)
+       {
+               case TASK_QUEUE_ACTIVE:
+                       array_remove_at(this->active_tasks, enumerator->inner);
+                       break;
                case TASK_QUEUE_PASSIVE:
-                       return array_create_enumerator(this->passive_tasks);
+                       array_remove_at(this->passive_tasks, enumerator->inner);
+                       break;
                case TASK_QUEUE_QUEUED:
-                       return enumerator_create_filter(
-                                                                       array_create_enumerator(this->queued_tasks),
-                                                                       filter_queued, NULL, NULL);
+                       array_remove_at(this->queued_tasks, enumerator->inner);
+                       free(enumerator->queued);
+                       enumerator->queued = NULL;
+                       break;
                default:
-                       return enumerator_create_empty();
+                       break;
        }
 }
 
@@ -2269,6 +2327,7 @@ task_manager_v2_t *task_manager_v2_create(ike_sa_t *ike_sa)
                                .adopt_child_tasks = _adopt_child_tasks,
                                .busy = _busy,
                                .create_task_enumerator = _create_task_enumerator,
+                               .remove_task = _remove_task,
                                .flush = _flush,
                                .flush_queue = _flush_queue,
                                .destroy = _destroy,
index 9545da4..442eaa6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2016 Tobias Brunner
+ * Copyright (C) 2013-2018 Tobias Brunner
  * Copyright (C) 2006 Martin Willi
  * HSR Hochschule fuer Technik Rapperswil
  *
@@ -285,6 +285,16 @@ struct task_manager_t {
                                                                                        task_queue_t queue);
 
        /**
+        * Remove the task the given enumerator points to.
+        *
+        * @note This should be used with caution, in partciular, for tasks in the
+        * active and passive queues.
+        *
+        * @param enumerator    enumerator created with the method above
+        */
+       void (*remove_task)(task_manager_t *this, enumerator_t *enumerator);
+
+       /**
         * Flush all tasks, regardless of the queue.
         */
        void (*flush)(task_manager_t *this);