Move callback_job_t to libhydra.
authorTobias Brunner <tobias@strongswan.org>
Mon, 5 Jul 2010 13:32:54 +0000 (15:32 +0200)
committerTobias Brunner <tobias@strongswan.org>
Thu, 2 Sep 2010 17:01:22 +0000 (19:01 +0200)
src/libcharon/Android.mk
src/libcharon/Makefile.am
src/libcharon/processing/jobs/callback_job.c [deleted file]
src/libcharon/processing/jobs/callback_job.h [deleted file]
src/libhydra/Android.mk
src/libhydra/Makefile.am
src/libhydra/processing/jobs/callback_job.c [new file with mode: 0644]
src/libhydra/processing/jobs/callback_job.h [new file with mode: 0644]

index df1b0df..cd2f7a6 100644 (file)
@@ -48,7 +48,6 @@ network/receiver.c network/receiver.h \
 network/sender.c network/sender.h \
 network/socket_manager.c network/socket_manager.h network/socket.h \
 processing/jobs/acquire_job.c processing/jobs/acquire_job.h \
-processing/jobs/callback_job.c processing/jobs/callback_job.h \
 processing/jobs/delete_child_sa_job.c processing/jobs/delete_child_sa_job.h \
 processing/jobs/delete_ike_sa_job.c processing/jobs/delete_ike_sa_job.h \
 processing/jobs/migrate_job.c processing/jobs/migrate_job.h \
index 9fafaec..ba2485c 100644 (file)
@@ -46,7 +46,6 @@ network/receiver.c network/receiver.h \
 network/sender.c network/sender.h \
 network/socket_manager.c network/socket_manager.h network/socket.h \
 processing/jobs/acquire_job.c processing/jobs/acquire_job.h \
-processing/jobs/callback_job.c processing/jobs/callback_job.h \
 processing/jobs/delete_child_sa_job.c processing/jobs/delete_child_sa_job.h \
 processing/jobs/delete_ike_sa_job.c processing/jobs/delete_ike_sa_job.h \
 processing/jobs/migrate_job.c processing/jobs/migrate_job.h \
diff --git a/src/libcharon/processing/jobs/callback_job.c b/src/libcharon/processing/jobs/callback_job.c
deleted file mode 100644 (file)
index 4c9a7fd..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Copyright (C) 2009 Tobias Brunner
- * Copyright (C) 2007 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * 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 the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-#include "callback_job.h"
-
-#include <semaphore.h>
-
-#include <hydra.h>
-#include <threading/thread.h>
-#include <threading/condvar.h>
-#include <threading/mutex.h>
-#include <utils/linked_list.h>
-
-typedef struct private_callback_job_t private_callback_job_t;
-
-/**
- * Private data of an callback_job_t Object.
- */
-struct private_callback_job_t {
-       /**
-        * Public callback_job_t interface.
-        */
-       callback_job_t public;
-
-       /**
-        * Callback to call on execution
-        */
-       callback_job_cb_t callback;
-
-       /**
-        * parameter to supply to callback
-        */
-       void *data;
-
-       /**
-        * cleanup function for data
-        */
-       callback_job_cleanup_t cleanup;
-
-       /**
-        * thread of the job, if running
-        */
-       thread_t *thread;
-
-       /**
-        * mutex to access jobs interna
-        */
-       mutex_t *mutex;
-
-       /**
-        * list of asociated child jobs
-        */
-       linked_list_t *children;
-
-       /**
-        * parent of this job, or NULL
-        */
-       private_callback_job_t *parent;
-
-       /**
-        * TRUE if the job got cancelled
-        */
-       bool cancelled;
-
-       /**
-        * condvar to synchronize the cancellation/destruction of the job
-        */
-       condvar_t *destroyable;
-
-       /**
-        * semaphore to synchronize the termination of the assigned thread.
-        *
-        * separately allocated during cancellation, so that we can wait on it
-        * without risking that it gets freed too early during destruction.
-        */
-       sem_t *terminated;
-};
-
-/**
- * unregister a child from its parent, if any.
- * note: this->mutex has to be locked
- */
-static void unregister(private_callback_job_t *this)
-{
-       if (this->parent)
-       {
-               this->parent->mutex->lock(this->parent->mutex);
-               if (this->parent->cancelled && !this->cancelled)
-               {
-                       /* if the parent has been cancelled but we have not yet, we do not
-                        * unregister until we got cancelled by the parent. */
-                       this->parent->mutex->unlock(this->parent->mutex);
-                       this->destroyable->wait(this->destroyable, this->mutex);
-                       this->parent->mutex->lock(this->parent->mutex);
-               }
-               this->parent->children->remove(this->parent->children, this, NULL);
-               this->parent->mutex->unlock(this->parent->mutex);
-               this->parent = NULL;
-       }
-}
-
-/**
- * Implements job_t.destroy.
- */
-static void destroy(private_callback_job_t *this)
-{
-       this->mutex->lock(this->mutex);
-       unregister(this);
-       if (this->cleanup)
-       {
-               this->cleanup(this->data);
-       }
-       if (this->terminated)
-       {
-               sem_post(this->terminated);
-       }
-       this->children->destroy(this->children);
-       this->destroyable->destroy(this->destroyable);
-       this->mutex->unlock(this->mutex);
-       this->mutex->destroy(this->mutex);
-       free(this);
-}
-
-/**
- * Implementation of callback_job_t.cancel.
- */
-static void cancel(private_callback_job_t *this)
-{
-       callback_job_t *child;
-       sem_t *terminated = NULL;
-
-       this->mutex->lock(this->mutex);
-       this->cancelled = TRUE;
-       /* terminate children */
-       while (this->children->get_first(this->children, (void**)&child) == SUCCESS)
-       {
-               this->mutex->unlock(this->mutex);
-               child->cancel(child);
-               this->mutex->lock(this->mutex);
-       }
-       if (this->thread)
-       {
-               /* terminate the thread, if there is currently one executing the job.
-                * we wait for its termination using a semaphore */
-               this->thread->cancel(this->thread);
-               terminated = this->terminated = malloc_thing(sem_t);
-               sem_init(terminated, 0, 0);
-       }
-       else
-       {
-               /* if the job is currently queued, it gets terminated later.
-                * we can't wait, because it might not get executed at all.
-                * we also unregister the queued job manually from its parent (the
-                * others get unregistered during destruction) */
-               unregister(this);
-       }
-       this->destroyable->signal(this->destroyable);
-       this->mutex->unlock(this->mutex);
-
-       if (terminated)
-       {
-               sem_wait(terminated);
-               sem_destroy(terminated);
-               free(terminated);
-       }
-}
-
-/**
- * Implementation of job_t.execute.
- */
-static void execute(private_callback_job_t *this)
-{
-       bool cleanup = FALSE, requeue = FALSE;
-
-       thread_cleanup_push((thread_cleanup_t)destroy, this);
-
-       this->mutex->lock(this->mutex);
-       this->thread = thread_current();
-       this->mutex->unlock(this->mutex);
-
-       while (TRUE)
-       {
-               this->mutex->lock(this->mutex);
-               if (this->cancelled)
-               {
-                       this->mutex->unlock(this->mutex);
-                       cleanup = TRUE;
-                       break;
-               }
-               this->mutex->unlock(this->mutex);
-               switch (this->callback(this->data))
-               {
-                       case JOB_REQUEUE_DIRECT:
-                               continue;
-                       case JOB_REQUEUE_FAIR:
-                       {
-                               requeue = TRUE;
-                               break;
-                       }
-                       case JOB_REQUEUE_NONE:
-                       default:
-                       {
-                               cleanup = TRUE;
-                               break;
-                       }
-               }
-               break;
-       }
-       this->mutex->lock(this->mutex);
-       this->thread = NULL;
-       this->mutex->unlock(this->mutex);
-       /* manually create a cancellation point to avoid that a cancelled thread
-        * goes back into the thread pool */
-       thread_cancellation_point();
-       if (requeue)
-       {
-               hydra->processor->queue_job(hydra->processor,
-                                                                        &this->public.job_interface);
-       }
-       thread_cleanup_pop(cleanup);
-}
-
-/*
- * Described in header.
- */
-callback_job_t *callback_job_create(callback_job_cb_t cb, void *data,
-                                                                       callback_job_cleanup_t cleanup,
-                                                                       callback_job_t *parent)
-{
-       private_callback_job_t *this = malloc_thing(private_callback_job_t);
-
-       /* interface functions */
-       this->public.job_interface.execute = (void (*) (job_t *)) execute;
-       this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
-       this->public.cancel = (void(*)(callback_job_t*))cancel;
-
-       /* private variables */
-       this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
-       this->callback = cb;
-       this->data = data;
-       this->cleanup = cleanup;
-       this->thread = 0;
-       this->children = linked_list_create();
-       this->parent = (private_callback_job_t*)parent;
-       this->cancelled = FALSE;
-       this->destroyable = condvar_create(CONDVAR_TYPE_DEFAULT);
-       this->terminated = NULL;
-
-       /* register us at parent */
-       if (parent)
-       {
-               this->parent->mutex->lock(this->parent->mutex);
-               this->parent->children->insert_last(this->parent->children, this);
-               this->parent->mutex->unlock(this->parent->mutex);
-       }
-
-       return &this->public;
-}
-
diff --git a/src/libcharon/processing/jobs/callback_job.h b/src/libcharon/processing/jobs/callback_job.h
deleted file mode 100644 (file)
index 92bd764..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2007 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * 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 the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup callback_job callback_job
- * @{ @ingroup cjobs
- */
-
-#ifndef CALLBACK_JOB_H_
-#define CALLBACK_JOB_H_
-
-typedef struct callback_job_t callback_job_t;
-
-#include <library.h>
-#include <processing/jobs/job.h>
-
-
-typedef enum job_requeue_t job_requeue_t;
-
-/**
- * Job requeueing policy
- *
- * The job requeueing policy defines how a job is handled when the callback
- * function returns.
- */
-enum job_requeue_t {
-
-       /**
-        * Do not requeue job, destroy it
-        */
-       JOB_REQUEUE_NONE,
-
-       /**
-        * Reque the job fairly, meaning it has to requeue as any other job
-        */
-       JOB_REQUEUE_FAIR,
-
-       /**
-        * Reexecute the job directly, without the need of requeueing it
-        */
-       JOB_REQUEUE_DIRECT,
-};
-
-/**
- * The callback function to use for the callback job.
- *
- * This is the function to use as callback for a callback job. It receives
- * a parameter supplied to the callback jobs constructor.
- *
- * @param data                 param supplied to job
- * @return                             requeing policy how to requeue the job
- */
-typedef job_requeue_t (*callback_job_cb_t)(void *data);
-
-/**
- * Cleanup function to use for data cleanup.
- *
- * The callback has an optional user argument which receives data. However,
- * this data may be cleaned up if it is allocated. This is the function
- * to supply to the constructor.
- *
- * @param data                 param supplied to job
- * @return                             requeing policy how to requeue the job
- */
-typedef void (*callback_job_cleanup_t)(void *data);
-
-/**
- * Class representing an callback Job.
- *
- * This is a special job which allows a simple callback function to
- * be executed by a thread of the thread pool. This allows simple execution
- * of asynchronous methods, without to manage threads.
- */
-struct callback_job_t {
-       /**
-        * The job_t interface.
-        */
-       job_t job_interface;
-
-       /**
-        * Cancel the job's thread and wait for its termination. This only works
-        * reliably for jobs that always use JOB_REQUEUE_FAIR or JOB_REQUEUE_DIRECT,
-        * otherwise the job may already be destroyed when cancel is called. */
-       void (*cancel)(callback_job_t *this);
-};
-
-/**
- * Creates a callback job.
- *
- * The cleanup function is called when the job gets destroyed to destroy
- * the associated data.
- * If parent is not NULL, the specified job gets an association. Whenever
- * the parent gets cancelled (or runs out), all of its children are cancelled,
- * too.
- *
- * @param cb                           callback to call from the processor
- * @param data                         user data to supply to callback
- * @param cleanup                      destructor for data on destruction, or NULL
- * @param parent                       parent of this job
- * @return                                     callback_job_t object
- */
-callback_job_t *callback_job_create(callback_job_cb_t cb, void *data,
-                                                                       callback_job_cleanup_t cleanup,
-                                                                       callback_job_t *parent);
-
-#endif /** CALLBACK_JOB_H_ @}*/
index abbec9e..b94fc7f 100644 (file)
@@ -9,6 +9,7 @@ attributes/attribute_provider.h attributes/attribute_handler.h \
 attributes/attribute_manager.c attributes/attribute_manager.h \
 attributes/mem_pool.c attributes/mem_pool.h \
 processing/jobs/job.h \
+processing/jobs/callback_job.c processing/jobs/callback_job.h \
 processing/processor.c processing/processor.h
 
 # adding the plugin source files
index 78e12e0..1d32a12 100644 (file)
@@ -7,6 +7,7 @@ attributes/attribute_provider.h attributes/attribute_handler.h \
 attributes/attribute_manager.c attributes/attribute_manager.h \
 attributes/mem_pool.c attributes/mem_pool.h \
 processing/jobs/job.h \
+processing/jobs/callback_job.c processing/jobs/callback_job.h \
 processing/processor.c processing/processor.h
 
 libhydra_la_LIBADD =
diff --git a/src/libhydra/processing/jobs/callback_job.c b/src/libhydra/processing/jobs/callback_job.c
new file mode 100644 (file)
index 0000000..4c9a7fd
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2009 Tobias Brunner
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "callback_job.h"
+
+#include <semaphore.h>
+
+#include <hydra.h>
+#include <threading/thread.h>
+#include <threading/condvar.h>
+#include <threading/mutex.h>
+#include <utils/linked_list.h>
+
+typedef struct private_callback_job_t private_callback_job_t;
+
+/**
+ * Private data of an callback_job_t Object.
+ */
+struct private_callback_job_t {
+       /**
+        * Public callback_job_t interface.
+        */
+       callback_job_t public;
+
+       /**
+        * Callback to call on execution
+        */
+       callback_job_cb_t callback;
+
+       /**
+        * parameter to supply to callback
+        */
+       void *data;
+
+       /**
+        * cleanup function for data
+        */
+       callback_job_cleanup_t cleanup;
+
+       /**
+        * thread of the job, if running
+        */
+       thread_t *thread;
+
+       /**
+        * mutex to access jobs interna
+        */
+       mutex_t *mutex;
+
+       /**
+        * list of asociated child jobs
+        */
+       linked_list_t *children;
+
+       /**
+        * parent of this job, or NULL
+        */
+       private_callback_job_t *parent;
+
+       /**
+        * TRUE if the job got cancelled
+        */
+       bool cancelled;
+
+       /**
+        * condvar to synchronize the cancellation/destruction of the job
+        */
+       condvar_t *destroyable;
+
+       /**
+        * semaphore to synchronize the termination of the assigned thread.
+        *
+        * separately allocated during cancellation, so that we can wait on it
+        * without risking that it gets freed too early during destruction.
+        */
+       sem_t *terminated;
+};
+
+/**
+ * unregister a child from its parent, if any.
+ * note: this->mutex has to be locked
+ */
+static void unregister(private_callback_job_t *this)
+{
+       if (this->parent)
+       {
+               this->parent->mutex->lock(this->parent->mutex);
+               if (this->parent->cancelled && !this->cancelled)
+               {
+                       /* if the parent has been cancelled but we have not yet, we do not
+                        * unregister until we got cancelled by the parent. */
+                       this->parent->mutex->unlock(this->parent->mutex);
+                       this->destroyable->wait(this->destroyable, this->mutex);
+                       this->parent->mutex->lock(this->parent->mutex);
+               }
+               this->parent->children->remove(this->parent->children, this, NULL);
+               this->parent->mutex->unlock(this->parent->mutex);
+               this->parent = NULL;
+       }
+}
+
+/**
+ * Implements job_t.destroy.
+ */
+static void destroy(private_callback_job_t *this)
+{
+       this->mutex->lock(this->mutex);
+       unregister(this);
+       if (this->cleanup)
+       {
+               this->cleanup(this->data);
+       }
+       if (this->terminated)
+       {
+               sem_post(this->terminated);
+       }
+       this->children->destroy(this->children);
+       this->destroyable->destroy(this->destroyable);
+       this->mutex->unlock(this->mutex);
+       this->mutex->destroy(this->mutex);
+       free(this);
+}
+
+/**
+ * Implementation of callback_job_t.cancel.
+ */
+static void cancel(private_callback_job_t *this)
+{
+       callback_job_t *child;
+       sem_t *terminated = NULL;
+
+       this->mutex->lock(this->mutex);
+       this->cancelled = TRUE;
+       /* terminate children */
+       while (this->children->get_first(this->children, (void**)&child) == SUCCESS)
+       {
+               this->mutex->unlock(this->mutex);
+               child->cancel(child);
+               this->mutex->lock(this->mutex);
+       }
+       if (this->thread)
+       {
+               /* terminate the thread, if there is currently one executing the job.
+                * we wait for its termination using a semaphore */
+               this->thread->cancel(this->thread);
+               terminated = this->terminated = malloc_thing(sem_t);
+               sem_init(terminated, 0, 0);
+       }
+       else
+       {
+               /* if the job is currently queued, it gets terminated later.
+                * we can't wait, because it might not get executed at all.
+                * we also unregister the queued job manually from its parent (the
+                * others get unregistered during destruction) */
+               unregister(this);
+       }
+       this->destroyable->signal(this->destroyable);
+       this->mutex->unlock(this->mutex);
+
+       if (terminated)
+       {
+               sem_wait(terminated);
+               sem_destroy(terminated);
+               free(terminated);
+       }
+}
+
+/**
+ * Implementation of job_t.execute.
+ */
+static void execute(private_callback_job_t *this)
+{
+       bool cleanup = FALSE, requeue = FALSE;
+
+       thread_cleanup_push((thread_cleanup_t)destroy, this);
+
+       this->mutex->lock(this->mutex);
+       this->thread = thread_current();
+       this->mutex->unlock(this->mutex);
+
+       while (TRUE)
+       {
+               this->mutex->lock(this->mutex);
+               if (this->cancelled)
+               {
+                       this->mutex->unlock(this->mutex);
+                       cleanup = TRUE;
+                       break;
+               }
+               this->mutex->unlock(this->mutex);
+               switch (this->callback(this->data))
+               {
+                       case JOB_REQUEUE_DIRECT:
+                               continue;
+                       case JOB_REQUEUE_FAIR:
+                       {
+                               requeue = TRUE;
+                               break;
+                       }
+                       case JOB_REQUEUE_NONE:
+                       default:
+                       {
+                               cleanup = TRUE;
+                               break;
+                       }
+               }
+               break;
+       }
+       this->mutex->lock(this->mutex);
+       this->thread = NULL;
+       this->mutex->unlock(this->mutex);
+       /* manually create a cancellation point to avoid that a cancelled thread
+        * goes back into the thread pool */
+       thread_cancellation_point();
+       if (requeue)
+       {
+               hydra->processor->queue_job(hydra->processor,
+                                                                        &this->public.job_interface);
+       }
+       thread_cleanup_pop(cleanup);
+}
+
+/*
+ * Described in header.
+ */
+callback_job_t *callback_job_create(callback_job_cb_t cb, void *data,
+                                                                       callback_job_cleanup_t cleanup,
+                                                                       callback_job_t *parent)
+{
+       private_callback_job_t *this = malloc_thing(private_callback_job_t);
+
+       /* interface functions */
+       this->public.job_interface.execute = (void (*) (job_t *)) execute;
+       this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
+       this->public.cancel = (void(*)(callback_job_t*))cancel;
+
+       /* private variables */
+       this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
+       this->callback = cb;
+       this->data = data;
+       this->cleanup = cleanup;
+       this->thread = 0;
+       this->children = linked_list_create();
+       this->parent = (private_callback_job_t*)parent;
+       this->cancelled = FALSE;
+       this->destroyable = condvar_create(CONDVAR_TYPE_DEFAULT);
+       this->terminated = NULL;
+
+       /* register us at parent */
+       if (parent)
+       {
+               this->parent->mutex->lock(this->parent->mutex);
+               this->parent->children->insert_last(this->parent->children, this);
+               this->parent->mutex->unlock(this->parent->mutex);
+       }
+
+       return &this->public;
+}
+
diff --git a/src/libhydra/processing/jobs/callback_job.h b/src/libhydra/processing/jobs/callback_job.h
new file mode 100644 (file)
index 0000000..722fa52
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup callback_job callback_job
+ * @{ @ingroup hjobs
+ */
+
+#ifndef CALLBACK_JOB_H_
+#define CALLBACK_JOB_H_
+
+typedef struct callback_job_t callback_job_t;
+
+#include <library.h>
+#include <processing/jobs/job.h>
+
+
+typedef enum job_requeue_t job_requeue_t;
+
+/**
+ * Job requeueing policy
+ *
+ * The job requeueing policy defines how a job is handled when the callback
+ * function returns.
+ */
+enum job_requeue_t {
+
+       /**
+        * Do not requeue job, destroy it
+        */
+       JOB_REQUEUE_NONE,
+
+       /**
+        * Reque the job fairly, meaning it has to requeue as any other job
+        */
+       JOB_REQUEUE_FAIR,
+
+       /**
+        * Reexecute the job directly, without the need of requeueing it
+        */
+       JOB_REQUEUE_DIRECT,
+};
+
+/**
+ * The callback function to use for the callback job.
+ *
+ * This is the function to use as callback for a callback job. It receives
+ * a parameter supplied to the callback jobs constructor.
+ *
+ * @param data                 param supplied to job
+ * @return                             requeing policy how to requeue the job
+ */
+typedef job_requeue_t (*callback_job_cb_t)(void *data);
+
+/**
+ * Cleanup function to use for data cleanup.
+ *
+ * The callback has an optional user argument which receives data. However,
+ * this data may be cleaned up if it is allocated. This is the function
+ * to supply to the constructor.
+ *
+ * @param data                 param supplied to job
+ * @return                             requeing policy how to requeue the job
+ */
+typedef void (*callback_job_cleanup_t)(void *data);
+
+/**
+ * Class representing an callback Job.
+ *
+ * This is a special job which allows a simple callback function to
+ * be executed by a thread of the thread pool. This allows simple execution
+ * of asynchronous methods, without to manage threads.
+ */
+struct callback_job_t {
+       /**
+        * The job_t interface.
+        */
+       job_t job_interface;
+
+       /**
+        * Cancel the job's thread and wait for its termination. This only works
+        * reliably for jobs that always use JOB_REQUEUE_FAIR or JOB_REQUEUE_DIRECT,
+        * otherwise the job may already be destroyed when cancel is called. */
+       void (*cancel)(callback_job_t *this);
+};
+
+/**
+ * Creates a callback job.
+ *
+ * The cleanup function is called when the job gets destroyed to destroy
+ * the associated data.
+ * If parent is not NULL, the specified job gets an association. Whenever
+ * the parent gets cancelled (or runs out), all of its children are cancelled,
+ * too.
+ *
+ * @param cb                           callback to call from the processor
+ * @param data                         user data to supply to callback
+ * @param cleanup                      destructor for data on destruction, or NULL
+ * @param parent                       parent of this job
+ * @return                                     callback_job_t object
+ */
+callback_job_t *callback_job_create(callback_job_cb_t cb, void *data,
+                                                                       callback_job_cleanup_t cleanup,
+                                                                       callback_job_t *parent);
+
+#endif /** CALLBACK_JOB_H_ @}*/