blob: 8108f849050cb5ce74a0755dd243b13f5202f4b3 [file]
/*
* BRLTTY - A background process providing access to the console screen (when in
* text mode) for a blind person using a refreshable braille display.
*
* Copyright (C) 1995-2023 by The BRLTTY Developers.
*
* BRLTTY comes with ABSOLUTELY NO WARRANTY.
*
* This is free software, placed under the terms of the
* GNU Lesser General Public License, as published by the Free Software
* Foundation; either version 2.1 of the License, or (at your option) any
* later version. Please see the file LICENSE-LGPL for details.
*
* Web Page: http://brltty.app/
*
* This software is maintained by Dave Mielke <dave@mielke.cc>.
*/
#include "prologue.h"
#include <string.h>
#include "log.h"
#include "async_task.h"
#include "async_internal.h"
#include "async_event.h"
typedef struct {
AsyncTaskCallback *callback;
void *data;
} TaskDefinition;
struct AsyncTaskDataStruct {
Queue *taskQueue;
};
void
asyncDeallocateTaskData (AsyncTaskData *td) {
if (td) {
if (td->taskQueue) deallocateQueue(td->taskQueue);
free(td);
}
}
static AsyncTaskData *
getTaskData (void) {
AsyncThreadSpecificData *tsd = asyncGetThreadSpecificData();
if (!tsd) return NULL;
if (!tsd->taskData) {
AsyncTaskData *td;
if (!(td = malloc(sizeof(*td)))) {
logMallocError();
return NULL;
}
memset(td, 0, sizeof(*td));
td->taskQueue = NULL;
tsd->taskData = td;
}
return tsd->taskData;
}
static void
deallocateTaskDefinition (void *item, void *data) {
TaskDefinition *task = item;
free(task);
}
static Queue *
getTaskQueue (int create) {
AsyncTaskData *td = getTaskData();
if (!td) return NULL;
if (!td->taskQueue && create) {
td->taskQueue = newQueue(deallocateTaskDefinition, NULL);
}
return td->taskQueue;
}
static int
addTask (TaskDefinition *task) {
Queue *queue = getTaskQueue(1);
if (queue) {
if (enqueueItem(queue, task)) {
logSymbol(LOG_CATEGORY(ASYNC_EVENTS), task->callback, "task added");
return 1;
}
}
return 0;
}
int
asyncAddTask (AsyncEvent *event, AsyncTaskCallback *callback, void *data) {
TaskDefinition *task;
if ((task = malloc(sizeof(*task)))) {
memset(task, 0, sizeof(*task));
task->callback = callback;
task->data = data;
if (event) {
if (asyncSignalEvent(event, task)) return 1;
} else if (addTask(task)) {
return 1;
}
free(task);
} else {
logMallocError();
}
return 0;
}
ASYNC_EVENT_CALLBACK(asyncHandleAddTaskEvent) {
addTask(parameters->signalData);
}
AsyncEvent *
asyncNewAddTaskEvent (void) {
return asyncNewEvent(asyncHandleAddTaskEvent, NULL);
}
int
asyncExecuteTaskCallback (AsyncTaskData *td) {
if (td) {
Queue *queue = td->taskQueue;
if (queue) {
TaskDefinition *task = dequeueItem(queue);
if (task) {
AsyncTaskCallback *callback = task->callback;
logSymbol(LOG_CATEGORY(ASYNC_EVENTS), callback, "task starting");
if (callback) callback(task->data);
free(task);
return 1;
}
}
}
return 0;
}