Implement task priorities and message queues
This commit is contained in:
280
task.h
280
task.h
@@ -1,26 +1,57 @@
|
||||
/*---------------------------------------------------------------------------
|
||||
T A S K
|
||||
|
||||
This is a portable task switching module. Tasks are maintained in a
|
||||
T A S K
|
||||
|
||||
This is a portable task switching module. Tasks are maintained in a
|
||||
circular list and switched in between. Waiting for some task to end,
|
||||
a yield and a primitive form of inter task communication is implemented.
|
||||
|
||||
|
||||
Mark Koennecke, September 1997
|
||||
|
||||
extended to suuport task groups
|
||||
extended to support task groups
|
||||
Mark Koennecke, December 2012
|
||||
|
||||
|
||||
copyright: see implementation file
|
||||
-----------------------------------------------------------------------------*/
|
||||
#ifndef TASKOMAT
|
||||
#define TASKOMAT
|
||||
|
||||
typedef long TaskTaskID;
|
||||
typedef long TaskGroupID;
|
||||
extern TaskTaskID TaskUnknownTaskID, TaskBadTaskID;
|
||||
extern TaskGroupID TaskUnknownGroupID, TaskBadGroupID;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
typedef enum eTaskLogLevel {
|
||||
eTaskLogNone = 0,
|
||||
eTaskLogDebug = 1,
|
||||
eTaskLogInfo = 2,
|
||||
eTaskLogWarning = 3,
|
||||
eTaskLogError = 4,
|
||||
eTaskLogFatal = 5
|
||||
} eTaskLogLevel;
|
||||
typedef void (*TaskLogFunc) (eTaskLogLevel, const char *buf);
|
||||
/*
|
||||
A TaskLogFunc can be registered for logging activity within the task module.
|
||||
*/
|
||||
/*
|
||||
* Use these values for the Task Priority
|
||||
*/
|
||||
#define TASK_PRIO_LOW 10
|
||||
#define TASK_PRIO_MED 30
|
||||
#define TASK_PRIO_HIGH 50
|
||||
/*--------------------------------------------------------------------------*/
|
||||
typedef struct __TaskHead *pTaskHead;
|
||||
typedef struct __TaskMan *pTaskMan;
|
||||
typedef struct __TaskQueue *pTaskQueue;
|
||||
typedef struct __TaskMessage *pTaskMessage;
|
||||
/*
|
||||
two data structure used internally and defined in task.c
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
typedef int (*TaskFunc) (void *pData);
|
||||
|
||||
/*
|
||||
/*
|
||||
a task function must be implemented by each task. This function will be
|
||||
called when it is the tasks turn to execute. This function obtains a
|
||||
called when it is the tasks turn to execute. This function obtains a
|
||||
pointer to a user defined data structure as parameter. If the task is going
|
||||
to end, it has to return 0. It's data structure will be removed by a
|
||||
KillFunction of the type defined below. If the task is
|
||||
@@ -28,9 +59,15 @@ typedef int (*TaskFunc) (void *pData);
|
||||
1.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
typedef int (*TaskMsgFunc) (void *pData, pTaskMessage pMsg);
|
||||
|
||||
/*
|
||||
* Like the TaskFunc but with a message extracted from the task queue
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
typedef void (*TaskKillFunc) (void *pData);
|
||||
/*
|
||||
Each task using private data structures must define this functions. It's
|
||||
Each task using private data structures must define this functions. It's
|
||||
task is to clear the private data structure of the task and free all memory
|
||||
associated with it. This function will be called automatically by the
|
||||
Tasker when a task finishes or when the whole Tasker is shut down.
|
||||
@@ -41,23 +78,17 @@ typedef void (*SignalFunc) (void *pUser, int iSignal, void *pSigData);
|
||||
/*
|
||||
A SignalFunction can be implemented by each task. It is the means of
|
||||
inter task communication. The first parameter is a pointer to the
|
||||
tasks private datastructure. Further parameters are an integer signal ID
|
||||
and a pointer to a datastructure for this signal. The meaning of signal
|
||||
tasks private datastructure. Further parameters are an integer signal ID
|
||||
and a pointer to a datastructure for this signal. The meaning of signal
|
||||
ID's and signal data structures is up to the client of this code.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
typedef struct __TaskHead *pTaskHead;
|
||||
typedef struct __TaskMan *pTaskMan;
|
||||
/*
|
||||
two data structure used internally and defined in task.c
|
||||
*/
|
||||
/*===========================================================================
|
||||
ALL FUNTIONS RETURN 0 on FAILURE, 1 ON SUCCESS WHEN NOT MENTIONED
|
||||
OTHERWISE
|
||||
============================================================================*/
|
||||
int TaskerInit(pTaskMan * self);
|
||||
/*
|
||||
Initalises a Task Manager.
|
||||
Initalises a Task Manager.
|
||||
*/
|
||||
int TaskerDelete(pTaskMan * self);
|
||||
/*
|
||||
@@ -65,7 +96,7 @@ int TaskerDelete(pTaskMan * self);
|
||||
tasks and the TaskManager.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
long TaskRegister(pTaskMan self, TaskFunc pTaskRun,
|
||||
TaskTaskID TaskRegister(pTaskMan self, TaskFunc pTaskRun,
|
||||
SignalFunc pSignalFunc,
|
||||
TaskKillFunc pKillFunc, void *pData, int iPriority);
|
||||
/*
|
||||
@@ -75,16 +106,16 @@ long TaskRegister(pTaskMan self, TaskFunc pTaskRun,
|
||||
a SignalFunction [Optional, can be NULL]
|
||||
a KillFunction for task private data.
|
||||
[Optional, can be NULL]
|
||||
a pointer to task private data
|
||||
a pointer to task private data
|
||||
[Optional, can be NULL]
|
||||
a priority for this task. This is currently unused.
|
||||
a priority for this task. This is currently unused.
|
||||
On Success a positive value denoting the ID of the task is returned.
|
||||
On error a negative value is returned.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
long TaskRegisterN(pTaskMan self, char *name, TaskFunc pTaskRun,
|
||||
SignalFunc pSignalFunc,
|
||||
TaskKillFunc pKillFunc, void *pData, int iPriority);
|
||||
TaskTaskID TaskRegisterN(pTaskMan self, char *name, TaskFunc pTaskRun,
|
||||
SignalFunc pSignalFunc, TaskKillFunc pKillFunc,
|
||||
void *pData, int iPriority);
|
||||
/*
|
||||
This call enter a new task into the system. The caller has to
|
||||
specify:
|
||||
@@ -92,12 +123,37 @@ long TaskRegisterN(pTaskMan self, char *name, TaskFunc pTaskRun,
|
||||
a SignalFunction [Optional, can be NULL]
|
||||
a KillFunction for task private data.
|
||||
[Optional, can be NULL]
|
||||
a pointer to task private data
|
||||
a pointer to task private data
|
||||
[Optional, can be NULL]
|
||||
a priority for this task. This is currently unused.
|
||||
a priority for this task. This is currently unused.
|
||||
On Success a positive value denoting the ID of the task is returned.
|
||||
On error a negative value is returned.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
TaskTaskID TaskRegisterD(pTaskMan self, char *name, TaskFunc pTaskRun,
|
||||
SignalFunc pSignalFunc, TaskKillFunc pKillFunc,
|
||||
void *pData, int iPriority, double delay);
|
||||
/*
|
||||
This call enters a new task into the system.
|
||||
The task will start running after the given delay in seconds.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
TaskTaskID TaskRegisterP(pTaskMan self, char *name, TaskFunc pTaskRun,
|
||||
SignalFunc pSignalFunc, TaskKillFunc pKillFunc,
|
||||
void *pData, int iPriority, double delay, double period);
|
||||
/*
|
||||
This call enters a new task into the system.
|
||||
The task will run after delay seconds and then every period seconds.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
TaskTaskID TaskRegisterQ(pTaskMan self, char *name, TaskMsgFunc pTaskRun,
|
||||
SignalFunc pSignalFunc, TaskKillFunc pKillFunc,
|
||||
void *pData, int iPriority);
|
||||
/*
|
||||
This call enters a new task with queue into the system.
|
||||
As for TaskRegisterN except the task function signature has
|
||||
a message pointer.
|
||||
*/
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int TaskSchedule(pTaskMan self);
|
||||
/*
|
||||
@@ -110,27 +166,27 @@ int TaskStop(pTaskMan self);
|
||||
*/
|
||||
/*------------------------------------------------------------------------*/
|
||||
int TaskContinue(pTaskMan self);
|
||||
/*
|
||||
/*
|
||||
Continues an task switching session interrupted by TaskStop. After this
|
||||
the apopriate TaskYield, TaskSchedule or wahtever has to be called.
|
||||
*/
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int TaskWait(pTaskMan self, long lID);
|
||||
int TaskWait(pTaskMan self, TaskTaskID taskID);
|
||||
/*
|
||||
Waits until the task specified by lID has finished. lID is obtained from
|
||||
a call to TaskRegister.
|
||||
Waits until the task specified by taskID has finished. taskID is obtained
|
||||
from a call to TaskRegister.
|
||||
*/
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int TaskYield(pTaskMan self);
|
||||
/*
|
||||
does one cycle of the task loop and returns to the caller.This call allows
|
||||
other tasks to execute while a task executes a lengthy calculation.
|
||||
other tasks to execute while a task executes a lengthy calculation.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int TaskSignal(pTaskMan self, int iSignal, void *pSigData);
|
||||
/*
|
||||
Invokes each Task's signal function with parameters iSignal and
|
||||
pSigData.
|
||||
pSigData.
|
||||
*/
|
||||
/*-------------------------------------------------------------------------*/
|
||||
void TaskRemove(pTaskMan self, TaskFunc pTaskRun, void *pData);
|
||||
@@ -148,7 +204,7 @@ int TaskSignal(pTaskMan self, int iSignal, void *pSigData);
|
||||
returns 1 when task name is running, 0 else
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int isTaskIDRunning(pTaskMan self, long lID);
|
||||
int isTaskIDRunning(pTaskMan self, TaskTaskID taskID);
|
||||
/*
|
||||
returns 1 when task name is running, 0 else
|
||||
*/
|
||||
@@ -160,13 +216,13 @@ char *des;
|
||||
|
||||
for(it = TaskIteratorStart(self); it != NULL; it = TaskIteratorNext(it)){
|
||||
des = TaskDescription(it);
|
||||
}
|
||||
}
|
||||
|
||||
There are two limitations of the implementation here:
|
||||
|
||||
- Never, ever delete the Iterator it
|
||||
- Do your iteration in one go or abandon it mid iteration. If another task
|
||||
gets in between and registers new tasks or removes one, then the whole
|
||||
- Do your iteration in one go or abandon it mid iteration. If another task
|
||||
gets in between and registers new tasks or removes one, then the whole
|
||||
iterator may be messed up.
|
||||
=============================================================================*/
|
||||
|
||||
@@ -179,17 +235,30 @@ pTaskHead TaskIteratorNext(pTaskHead it);
|
||||
Steps to the next element in the task list. Returns NULL when node.
|
||||
Do NOT delete the returned pointer!
|
||||
*/
|
||||
pTaskHead TaskIteratorCurrent(pTaskMan self);
|
||||
pTaskHead TaskIteratorByName(pTaskMan self, const char* name);
|
||||
pTaskHead TaskIteratorByID(pTaskMan self, TaskTaskID taskID);
|
||||
/*
|
||||
Gets the task iterator for either the current, named or numbered task
|
||||
Do NOT delete the returned pointer!
|
||||
*/
|
||||
|
||||
char *TaskDescription(pTaskHead it);
|
||||
/*
|
||||
get a description of the task at the current iterator
|
||||
You are responsible for deleting the returned character array.
|
||||
*/
|
||||
long GetTaskID(pTaskHead it);
|
||||
|
||||
char *TaskDetail(pTaskHead it);
|
||||
/*
|
||||
get a detailed description of the task at the current iterator
|
||||
You are responsible for deleting the returned character array.
|
||||
*/
|
||||
TaskTaskID GetTaskID(pTaskHead it);
|
||||
/*
|
||||
get the ID of the current task
|
||||
*/
|
||||
long GetGroupID(pTaskHead it);
|
||||
TaskGroupID GetGroupID(pTaskHead it);
|
||||
/*
|
||||
get the group ID of the current task
|
||||
*/
|
||||
@@ -202,36 +271,147 @@ const void *GetTaskData(pTaskHead it);
|
||||
Get the user data for the current task. Do not free the returned pointer!
|
||||
*/
|
||||
/*=============================================================================
|
||||
Task Groups. The implementation has the limit that any given task can
|
||||
Task Groups. The implementation has the limit that any given task can
|
||||
only be member of one task group
|
||||
===============================================================================*/
|
||||
long GetTaskGroupID(pTaskMan self);
|
||||
TaskGroupID GetTaskGroupID(pTaskMan self);
|
||||
/*
|
||||
get the ID for a task group
|
||||
*/
|
||||
void AddTaskToGroup(pTaskMan self, long taskID, long groupID);
|
||||
void AddTaskToGroup(pTaskMan self, TaskTaskID taskID, TaskGroupID groupID);
|
||||
/*
|
||||
Add taskID to the task group groupID
|
||||
*/
|
||||
int isTaskGroupRunning(pTaskMan self, long groupID);
|
||||
int isTaskGroupRunning(pTaskMan self, TaskGroupID groupID);
|
||||
/*
|
||||
Returns 1 when the task group is still running, 0 else
|
||||
*/
|
||||
|
||||
typedef struct{
|
||||
pTaskMan tasker;
|
||||
long groupID;
|
||||
} TaskGroupData, *pTaskGroupData;
|
||||
|
||||
int TaskGroupTask(void *data);
|
||||
/*
|
||||
This is a task function which implements the common task of waiting
|
||||
This is a task function which implements the common task of waiting
|
||||
for a group of tasks to finish. It expects as data a TaskGroupData
|
||||
structure.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int TaskSignalGroup(pTaskMan self, int iSignal, void *pSigData, long groupID);
|
||||
int TaskSignalGroup(pTaskMan self, int iSignal, void *pSigData, TaskGroupID groupID);
|
||||
/*
|
||||
signal only tasks in the group groupID
|
||||
*/
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void TaskSetLogFunc(TaskLogFunc);
|
||||
TaskLogFunc TaskGetLogFunc(void);
|
||||
eTaskLogLevel TaskSetLogLevel(eTaskLogLevel thresh);
|
||||
eTaskLogLevel TaskGetLogLevel(void);
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int TaskGetStack(pTaskMan self, pTaskHead it[]);
|
||||
/*
|
||||
* Returns the current stack depth of tasks and, if provided, fills the array
|
||||
* of iterators. The iterators start at it[0] and can be used to get
|
||||
* information about each task.
|
||||
*/
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void TaskRunMeAfter(pTaskMan self, double delay);
|
||||
/*
|
||||
* Run this task once in <delay> seconds
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void TaskRunMeEvery(pTaskMan self, double delay);
|
||||
/*
|
||||
* Run this task every <delay> seconds from now on
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
double TaskRunMyPeriod(pTaskMan self);
|
||||
/*
|
||||
* Return this task run period in seconds
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
pTaskQueue TaskQueueAlloc(void);
|
||||
/*
|
||||
* Task Queue constructor
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int TaskQueueFree(pTaskQueue);
|
||||
/*
|
||||
* Task Queue destructor
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int TaskQueueCount(pTaskQueue);
|
||||
/*
|
||||
* Returns the message count on the Task Queue
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int TaskQueueSend(pTaskQueue, pTaskMessage);
|
||||
/*
|
||||
* Pushes a Task Message onto the tail of the Task Queue
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int TaskQueueSendID(pTaskMan self, TaskTaskID taskID, pTaskMessage);
|
||||
/*
|
||||
* Pushes a Task Message onto the tail of the Task Queue
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
pTaskMessage TaskQueueRecv(pTaskQueue);
|
||||
/*
|
||||
* Pops a Task Message off the head of the given Task Queue
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
pTaskMessage TaskQueueRecvMine(pTaskMan self);
|
||||
/*
|
||||
* Pops a Task Message off the head of the owner's Task Queue
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int TaskQueueSet(pTaskMan self, TaskTaskID taskID, pTaskQueue);
|
||||
/*
|
||||
* Sets the Task Queue of the task
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int TaskQueueRem(pTaskMan self, TaskTaskID taskID);
|
||||
/*
|
||||
* Clears the Task Queue of the task
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
pTaskQueue TaskQueueGet(pTaskMan self, TaskTaskID taskID);
|
||||
/*
|
||||
* Gets the Task Queue of the specified task
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
pTaskQueue TaskQueueGetMine(pTaskMan self);
|
||||
/*
|
||||
* Gets the Task Queue of the current task
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
pTaskMessage TaskMessageAlloc(size_t mSize, int mType);
|
||||
/*
|
||||
* Constructor for a Task Message of the requested size and type
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int TaskMessageFree(pTaskMessage);
|
||||
/*
|
||||
* Destructor for the Task Message
|
||||
* returne 0=success, -1=fail
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int TaskMessageGetType(pTaskMessage self);
|
||||
/*
|
||||
* Get the type of the Task Message
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void TaskMessageSetType(pTaskMessage self, int mType);
|
||||
/*
|
||||
* Set the type of the Task Message
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void * TaskMessageGetData(pTaskMessage self);
|
||||
/*
|
||||
* Get the data pointer from the message
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void TaskMessageSetData(pTaskMessage self, void *mData);
|
||||
/*
|
||||
* Set the data pointer in the message
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user