pthreadpool: add pthreadpool_cancel_job()
authorStefan Metzmacher <metze@samba.org>
Fri, 20 Apr 2018 13:00:31 +0000 (15:00 +0200)
committerStefan Metzmacher <metze@samba.org>
Thu, 12 Jul 2018 12:25:19 +0000 (14:25 +0200)
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
lib/pthreadpool/pthreadpool.c
lib/pthreadpool/pthreadpool.h
lib/pthreadpool/pthreadpool_sync.c

index 6c51bc5272b391559a8cbf6b78c5197c8c2c7d71..55ea36ed0234cce231cd9908ff6482f67460e17e 100644 (file)
@@ -750,3 +750,49 @@ int pthreadpool_add_job(struct pthreadpool *pool, int job_id,
 
        return res;
 }
+
+size_t pthreadpool_cancel_job(struct pthreadpool *pool, int job_id,
+                             void (*fn)(void *private_data), void *private_data)
+{
+       int res;
+       size_t i, j;
+       size_t num = 0;
+
+       res = pthread_mutex_lock(&pool->mutex);
+       if (res != 0) {
+               return res;
+       }
+
+       for (i = 0, j = 0; i < pool->num_jobs; i++) {
+               size_t idx = (pool->head + i) % pool->jobs_array_len;
+               size_t new_idx = (pool->head + j) % pool->jobs_array_len;
+               struct pthreadpool_job *job = &pool->jobs[idx];
+
+               if ((job->private_data == private_data) &&
+                   (job->id == job_id) &&
+                   (job->fn == fn))
+               {
+                       /*
+                        * Just skip the entry.
+                        */
+                       num++;
+                       continue;
+               }
+
+               /*
+                * If we already removed one or more jobs (so j will be smaller
+                * then i), we need to fill possible gaps in the logical list.
+                */
+               if (j < i) {
+                       pool->jobs[new_idx] = *job;
+               }
+               j++;
+       }
+
+       pool->num_jobs -= num;
+
+       res = pthread_mutex_unlock(&pool->mutex);
+       assert(res == 0);
+
+       return num;
+}
index cb8baffebb1825f78cc226fe3a3f19d5e61b1547..dd1f9718b2364ff20dcafe6babf71766fc9f6d32 100644 (file)
@@ -103,4 +103,30 @@ int pthreadpool_destroy(struct pthreadpool *pool);
 int pthreadpool_add_job(struct pthreadpool *pool, int job_id,
                        void (*fn)(void *private_data), void *private_data);
 
+/**
+ * @brief Try to cancel a job in a pthreadpool
+ *
+ * This tries to cancel a job in a pthreadpool. The same
+ * arguments, which were given to pthreadpool_add_job()
+ * needs to be passed.
+ *
+ * The combination of id, fn, private_data might not be unique.
+ * So the function tries to cancel as much matching jobs as possible.
+ * Note once a job is scheduled in a thread it's to late to
+ * cancel it.
+ *
+ * Canceled jobs that weren't started yet won't be reported via a
+ * pool's signal_fn.
+ *
+ * @param[in]  pool            The pool to run the job on
+ * @param[in]  job_id          A custom identifier
+ * @param[in]  fn              The function to run asynchronously
+ * @param[in]  private_data    Pointer passed to fn
+ * @return                     The number of canceled jobs
+ *
+ * @see pthreadpool_add_job()
+ */
+size_t pthreadpool_cancel_job(struct pthreadpool *pool, int job_id,
+                             void (*fn)(void *private_data), void *private_data);
+
 #endif
index a7dce580951b8f5a92cf26948a7027d4427144cc..837abac54d7c1ddcd1506e85f570b7ff48846676 100644 (file)
@@ -71,6 +71,12 @@ int pthreadpool_add_job(struct pthreadpool *pool, int job_id,
                               pool->signal_fn_private_data);
 }
 
+size_t pthreadpool_cancel_job(struct pthreadpool *pool, int job_id,
+                             void (*fn)(void *private_data), void *private_data)
+{
+       return 0;
+}
+
 int pthreadpool_destroy(struct pthreadpool *pool)
 {
        free(pool);