1. 什么是JobQueue
SylixOS中为了减少线程的创建或者让中断服务程序做更少的事情,引入了JobQueue机制。
JobQueue(工作队列)我们可以看成是一种将工作推后由同一个工作线程去执行多个工作的一种异步机制,尤为重要的是这个线程可以设置等待的超时时间。
2. 数据结构
这是从SylixOS源码中截取的一个图,从图中我们可以看到工作队列管理的消息(JOBQ_pjobmsgQueue)就是我们自己的函数地址及其参数(这里参数默认是由6个元素的数组来管理)。
通过下面一个队列图我们来看各成员的含义:
- JOBQ_uiIn是队列的入队计数;
- JOBQ_uiOut是队列的出队计数;
- JOBQ_uiCnt是队列中当前消息的数量;
- JOBQ_stSize是队列总的大小;
- JOBQ_stLost是队列丢失信息数量。
其他两个成员是队列操作的同步锁(关于SylixOS同步锁在以后的文章中会呈现,敬请关注)
我们来分析一下这个队列操作的过程:
向队列中添加一个消息的时候JOBQ_uiIn就会加1同时队列消息数量JOBQ_uiCnt也会相应加1,当队列满后JOBQ_uiIn会自动置0;出队列的过程和入队类似,从队列中拿走一个消息后JOBQ_uiOut就会加1同时队列消息数量JOBQ_uiCnt会减去一个,当JOBQ_uiOut加到满之后将会被自动置0。有一种情况当JOBQ_uiCnt等于JOBQ_stSize的时候又要添加一个新的信息,那么这个信息就会丢失同时JOBQ_stLost计数将加1。3. SylixOS JobQueue函数
PLW_JOB_QUEUE _jobQueueCreate(UINT uiQueueSize, BOOL bNonBlock);
VOID _jobQueueDelete(PLW_JOB_QUEUE pjobq);
ULONG _jobQueueInit(PLW_JOB_QUEUE pjobq, PLW_JOB_MSG pjobmsg,
UINT uiQueueSize, BOOL bNonBlock);
VOID _jobQueueFinit(PLW_JOB_QUEUE pjobq);
ULONG _jobQueueAdd(PLW_JOB_QUEUE pjobq,
VOIDFUNCPTR pfunc,
PVOID pvArg0,
PVOID pvArg1,
PVOID pvArg2,
PVOID pvArg3,
PVOID pvArg4,
PVOID pvArg5);
VOID _jobQueueDel(PLW_JOB_QUEUE pjobq,
UINT uiMatchArgNum,
VOIDFUNCPTR pfunc,
PVOID pvArg0,
PVOID pvArg1,
PVOID pvArg2,
PVOID pvArg3,
PVOID pvArg4,
PVOID pvArg5);
size_t _jobQueueLost(PLW_JOB_QUEUE pjobq);
ULONG _jobQueueExec(PLW_JOB_QUEUE pjobq, ULONG ulTimeout);
4. 创建JobQueue
SylixOS中创建一个JobQueue有两种方法,一种是动态创建,一种是静态创建。
- 动态创建(及其对应销毁函数)我们可以通过下面的函数:
PLW_JOB_QUEUE _jobQueueCreate(UINT uiQueueSize, BOOL bNonBlock);
VOID _jobQueueDelete(PLW_JOB_QUEUE pjobq);
- 静态创建(及其对应销毁函数)我们可以通过下面的函数:
ULONG _jobQueueInit(PLW_JOB_QUEUE pjobq, PLW_JOB_MSG pjobmsg, UINT uiQueueSize, BOOL bNonBlock);
VOID _jobQueueFinit(PLW_JOB_QUEUE pjobq);
从两者的函数来看,静态创建我们需要提前定义好一个自己的工作队列变量,然后通过_jobQueueInit来进行初始化(一般建议使用静态的方式)。
创建好JobQueue之后我们需要一个线程来使队列工作,通常我们会以下面的形式来创建这个线程:
VOID testJobQueue (VOID)
{
For (;;) {
_jobQueueExec(&myJobQueue,LW_OPTION_WAIT_INFINITE);
}
}
当需要向JobQueue中添加消息的时候,只需简单的调用_jobQueueAdd即可。
如果想要获得丢失的消息数量可调用函数_jobQueueLost来获得。
(本节完)