Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/internal/task_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ extern "C" {
struct task {
uint32_t id; //!< Task identifier.
bool is_orphan; //!< Flag indicating whether the task is orphaned.
bool auto_release; //!< Flag indicating whether the task must be released after its execution.
struct task *next; //!< Next element of the current instance.
struct task *prev; //!< Previous element of the current instance.
void *(*task)(void *); //!< Task callback.
Expand Down
11 changes: 10 additions & 1 deletion include/pool_day.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ uint32_t queued_tasks(pool_day_t pool);
*
* pool = create_pool(size);
* if (pool) {
* task_t t = create_task(id, callback, (void *)param, param_size, NULL, NULL);
* task_t t = create_sync_task(id, callback, (void *)param, param_size);
*
* enqueue_task(pool, t);
*
Expand All @@ -100,6 +100,15 @@ uint32_t queued_tasks(pool_day_t pool);
*/
void *get_task_result(task_t task);

/**
* @brief Wait for the finish of a given task without retrieving its result.
*
* @note This function blocks the current thread.
*
* @param[in] task Task handle.
*/
void wait_task_finish(task_t task);

/**
* @brief Abort the execution of incoming tasks.
*
Expand Down
30 changes: 25 additions & 5 deletions include/task.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#ifndef TASK_H_
#define TASK_H_

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

Expand All @@ -34,23 +35,42 @@ extern "C" {
typedef struct task *task_t; //!< Handle to the task.

/**
* @brief Create a new task.
* @brief Create a new synchronous task.
*
* @note The created task doesn't require a manual release once it's bound to a
* @note The created task requires a manual release once it's bound to a
* pool.
*
* @param[in] id Task identifier.
* @param[in] task Task callback.
* @param[in] param Task parameter.
* @param[in] param_size Size of the task parameter.
*
* @return Handle to the new task.
*/
task_t create_sync_task(uint32_t id, void *(*task)(void *), void *param,
size_t param_size);

/**
* @brief Create a new asynchronous task.
*
* @note When the 'auto_release' parameter is set to false, the created task
* requires a manual release once it's bound to a pool.
*
* @param[in] id Task identifier.
* @param[in] task Task callback.
* @param[in] param Task parameter.
* @param[in] param_size Size of the task parameter.
* @param[in] auto_release Flag indicating whether the task must be released
* after its execution.
* @param[in] start_cb Callback executed when the task starts.
* @param[in] end_cb Callback executed when the task ends.
*
* @return Handle to the new task.
*/
task_t create_task(uint32_t id, void *(*task)(void *), void *param,
size_t param_size, void (*start_cb)(uint32_t, void *),
void (*end_cb)(uint32_t, void *, void *));
task_t create_async_task(uint32_t id, void *(*task)(void *), void *param,
size_t param_size, bool auto_release,
void (*start_cb)(uint32_t, void *),
void (*end_cb)(uint32_t, void *, void *));

/**
* @brief Destroy a task.
Expand Down
4 changes: 2 additions & 2 deletions samples/c/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ int main(void) {
}

char str[] = "foo";
task_t task = create_task(DUMMY_TASK_ID, func, (void *)str,
sizeof(char) * strlen(str) + 1, NULL, NULL);
task_t task = create_sync_task(DUMMY_TASK_ID, func, (void *)str,
sizeof(char) * strlen(str) + 1);

assert(enqueue_task(pool, task) == POOL_DAY_SUCCESS);
char *ret = (char *)get_task_result(task);
Expand Down
10 changes: 4 additions & 6 deletions samples/cpp/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,10 @@ class Foo {
public:
Foo()
: pool_{create_pool(2)},
t1_{create_task(0, Foo::Cb1, (void *)"hello",
sizeof(char) * std::strlen("hello") + 1, nullptr,
nullptr)},
t2_{create_task(1, Foo::Cb2, (void *)"hi",
sizeof(char) * std::strlen("hi") + 1, nullptr,
nullptr)} {
t1_{create_sync_task(0, Foo::Cb1, (void *)"hello",
sizeof(char) * std::strlen("hello") + 1)},
t2_{create_sync_task(1, Foo::Cb2, (void *)"hi",
sizeof(char) * std::strlen("hi") + 1)} {
}

void RunTasks(void) {
Expand Down
54 changes: 32 additions & 22 deletions src/pool_day.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ __static void *thread_func(void *param) {
pool_day_t pool = (pool_day_t)param;

while (!pool->must_stop) {
POOL_DAY_DEBUG("thread '0x%x' waiting...", pthread_self());
sem_wait(&pool->lock);

POOL_DAY_DEBUG("thread '0x%x' woke up", pthread_self());

if (pool->must_stop) {
Expand All @@ -36,30 +36,36 @@ __static void *thread_func(void *param) {
}

task_t entry = dequeue(pool->tasks);
if (entry) {
entry->is_orphan = true;
if (!entry) {
POOL_DAY_DEBUG("thread '0x%x' found no task to execute", pthread_self());
continue;
}

entry->is_orphan = true;

if (entry->on_task_start) {
POOL_DAY_DEBUG("thread '0x%x' executing start callback for task '0x%x'",
pthread_self(), entry->id);
entry->on_task_start(entry->id, entry->param);
}

if (entry->on_task_start) {
entry->on_task_start(entry->id, entry->param);
}
POOL_DAY_DEBUG("thread '0x%x' running the task '0x%x'", pthread_self(),
entry->id);
void *ret = entry->task(entry->param);
POOL_DAY_DEBUG("thread '0x%x' finished the task '0x%x'", pthread_self(),
entry->id);

POOL_DAY_DEBUG("thread '0x%x' running the task '0x%x'", pthread_self(),
entry->id);
void *ret = entry->task(entry->param);
POOL_DAY_DEBUG("thread '0x%x' finished the task '0x%x'", pthread_self(),
entry->id);
if (entry->on_task_end) {
POOL_DAY_DEBUG("thread '0x%x' executing end callback for task '0x%x'",
pthread_self(), entry->id);
entry->on_task_end(entry->id, entry->param, ret);
}

if (!entry->auto_release) {
entry->ret_val = ret;
if (entry->on_task_end) {
POOL_DAY_DEBUG("thread '0x%x' running async teardown for task '0x%x'",
pthread_self(), entry->id);
entry->on_task_end(entry->id, entry->param, entry->ret_val);
destroy_task(entry);
} else {
POOL_DAY_DEBUG("thread '0x%x' running sync teardown for task '0x%x'",
pthread_self(), entry->id);
sem_post(&entry->ready);
}
sem_post(&entry->ready);
} else {
destroy_task(entry);
}
}

Expand Down Expand Up @@ -180,7 +186,6 @@ uint32_t queued_tasks(pool_day_t pool) {
return pool ? queue_size(pool->tasks) : 0;
}

// cppcheck-suppress unusedFunction
void *get_task_result(task_t task) {
if (!task) {
POOL_DAY_ERROR("null task provided");
Expand All @@ -193,3 +198,8 @@ void *get_task_result(task_t task) {

return task->ret_val;
}

// cppcheck-suppress unusedFunction
void wait_task_finish(task_t task) {
(void)get_task_result(task);
}
13 changes: 10 additions & 3 deletions src/task.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@
#include "internal/task_def.h"

// cppcheck-suppress unusedFunction
task_t create_task(uint32_t id, void *(*task)(void *), void *param,
size_t param_size, void (*start_cb)(uint32_t, void *),
void (*end_cb)(uint32_t, void *, void *)) {
task_t create_sync_task(uint32_t id, void *(*task)(void *), void *param,
size_t param_size) {
return create_async_task(id, task, param, param_size, false, NULL, NULL);
}

task_t create_async_task(uint32_t id, void *(*task)(void *), void *param,
size_t param_size, bool auto_release,
void (*start_cb)(uint32_t, void *),
void (*end_cb)(uint32_t, void *, void *)) {
task_t node;

node = (task_t)calloc(1, sizeof(*node));
Expand All @@ -18,6 +24,7 @@ task_t create_task(uint32_t id, void *(*task)(void *), void *param,
node->on_task_start = start_cb;
node->on_task_end = end_cb;
node->is_orphan = true;
node->auto_release = auto_release;

if (param) {
node->param = malloc(param_size);
Expand Down
Loading