#include "ort_prive.h"
#include <stdlib.h>
#include <stdio.h>
ort_task_node_t* ort_task_alloc(void* (*func)(void *), void *arg)
{
if(arg != NULL)//任务函数参数非空,那么就返回此参数所在的任务节点
return *((ort_task_node_t **)PP(arg));
if(func != NULL)
{//此时任务函数参数为空,但是任务函数存在,获取一个没有参数的任务节点
arg = ort_taskenv_alloc(0, func);
return (*((ort_task_node_t **)PP(arg)));//返回此任务节点
}
return ort_task_empty_node_alloc();//当任务函数不存在,任务函数参数不存在,就创建一个空的任务节点
}
void ort_task_free(ort_eecb_t *thr, ort_task_node_t* node)
{//此函数用于将指定节点放到指定eecb的回收站中去
ort_task_node_pool_t *task_node_pool;
int my_max_mates = thr->tasking.max_mates;
/* if node was allocated form a node pool */
if(node->occupied == 1)//待回收的节点是节点池中的节点,修改它的使用情况即可
node->occupied = 0;
else /* else store node in my recycle bin */
{//待回收的节点是从回收站分配的节点
task_node_pool = thr->tasking.task_node_pool;
while(task_node_pool != NULL)
{//从任务节点池队列中搜索该task-func属于那个节点池
if(task_node_pool->task_func == node->func)
{//找到了对应的任务节点池
node->next = task_node_pool->recycler;
task_node_pool->recycler = node;//将此任务节点重新链接到回收站
return;
}
task_node_pool = task_node_pool->next;//搜寻下一个任务节点池
}
//我没有为这个task-func分配一个任务节点池,那么分配一个
task_node_pool = (ort_task_node_pool_t *) ort_calloc_aligned(sizeof(ort_task_node_pool_t), NULL);
task_node_pool->task_func = node->func;//指定新建的任务节点池的任务函数
node->next = NULL;//将待回收的任务节点链接到新建的任务节点池的回收站中
task_node_pool->recycler = node;
//创建多个任务节点
task_node_pool->sub_pool = (ort_task_node_t*) ort_calloc(TASKPOOLSIZE(my_max_mates)*sizeof(ort_task_node_t));
//将此新建的任务节点池放到链表中去
task_node_pool->next = thr->tasking.task_node_pool;
thr->tasking.task_node_pool = task_node_pool;
}
}
void task_pools_init(ort_eecb_t *t)
{
ort_tasking_t *td = &(t->tasking);
ort_task_node_pool_t *tnp;
int i, teamsize = t->num_siblings;
if(td->task_node_pool == NULL)
{
td->max_mates = teamsize;
return;
}
else if(td->max_mates >= teamsize)
return;
//非空并且当前任务节点池的数量不足teamsize
tnp = td->task_node_pool;
while(tnp != NULL)
{
for (i = 0; i< TASKPOOLSIZE(td->max_mates); i++)
{//将任务节点池中各个任务节点的任务参数置为空
if((tnp->sub_pool[i]).funcarg != NULL)
free((tnp->sub_pool[i]).funcarg);
}
//realloc任务节点数组的大小
tnp->sub_pool = (ort_task_node_t*)
ort_realloc(tnp->sub_pool, TASKPOOLSIZE(teamsize)*sizeof(ort_task_node_t));
for (i=0; i< TASKPOOLSIZE(teamsize); i++)
{//初始化任务节点池中任务节点数组中各个节点的参数
(tnp->sub_pool[i]).next = NULL;
(tnp->sub_pool[i]).func = NULL;
(tnp->sub_pool[i]).occupied = 0;//表示未被使用
(tnp->sub_pool[i]).funcarg = NULL;
}
tnp = tnp->next;//搜寻下一个任务节点池
}
td->max_mates = teamsize;//设置任务节点池中节点数组的容量
}
void *ort_taskenv_alloc(int size, void *(*task_func)(void *))
{//返回一个任务函数的参数节点,size为任务参数结构体的大小(即sizeof(struct __taskenv__)),另一个参数是任务函数的地址
ort_eecb_t *me = __MYCB;
ort_task_node_pool_t *task_node_pool;
ort_task_node_t *new_node;
int i;
int my_max_mates = me->tasking.max_mates;//存储的是任务节点池的大小,即一个任务节点池中有多少任务节点(有3个任务节点不包含)
task_node_pool = me->tasking.task_node_pool;//获取任务节点池的头指针
while(task_node_pool != NULL)
{//遍历链表
if(task_node_pool->task_func == task_func)
{//找到对应的节点池
//遍历此线程池,找到第一个空的节点
for(i=0; i<(TASKPOOLSIZE(my_max_mates)); i++)
if (task_node_pool->sub_pool[i].occupied == 0)
{//找到一个空的节点
if(task_node_pool->sub_pool[i].funcarg == NULL)//当前任务节点的任务函数参数为空
ALLOCATE_ENV(task_node_pool->sub_pool[i], size);//新建一个任务函数参数存储空间,在首位存储任务节点的地址,然后才是真正的参数存储空间
task_node_pool->sub_pool[i].occupied = 1;//修改该任务节点的使用标志
return NP(task_node_pool->sub_pool[i].funcarg);//返回指向struct __taskenv__结构体的指针,调用者此时可以向里面填充任务函数的参数值
}
/* Pool is full, allocate a task node and return it */
new_node = task_node_pool->recycler;//获取回收站的第一个任务节点
if(new_node == NULL)
{//表明回收站是空的,那么新建一个任务节点
new_node = (ort_task_node_t *)ort_calloc_aligned(sizeof(ort_task_node_t), NULL);
new_node->next = NULL;//将新建的任务节点的next设置为空
ALLOCATE_PENV(new_node, size);//给新建的任务节点分配参数存储空间
new_node->occupied = 2;//设置任务节点的使用标志
}
else
task_node_pool->recycler = task_node_pool->recycler->next;//回收站非空,指向下一个任务节点
return NP(new_node->funcarg);//返回指向任务参数存储空间的地址
}
task_node_pool = task_node_pool->next;//此任务节点池不属于此任务函数,搜寻下一个
}
//此时我并没有在任务节点池链表中找到属于task-func的任务节点池,所以需分配一个属于自己的任务节点池
task_node_pool = (ort_task_node_pool_t *)ort_calloc_aligned(sizeof(ort_task_node_pool_t), NULL);
task_node_pool->task_func = task_func;//设置该任务节点池属于那个任务函数
task_node_pool->recycler = NULL;//设置初始回收站指向为空,表示回收站中没有任务节点
//新建多个任务节点
task_node_pool->sub_pool = (ort_task_node_t*) ort_calloc(TASKPOOLSIZE(my_max_mates)*sizeof(ort_task_node_t));
//将此任务节点池链接到任务节点池链表中
task_node_pool->next = me->tasking.task_node_pool;
me->tasking.task_node_pool = task_node_pool;
ALLOCATE_ENV(task_node_pool->sub_pool[0], size);//分配一个任务函数参数的存储空间
task_node_pool->sub_pool[0].occupied = 1;//设置第一个任务节点的使用标志
return NP(task_node_pool->sub_pool[0].funcarg);//返回任务函数参数的地址,调用者使用具体值来填充此地址
}
ort_task_node_t* ort_task_empty_node_alloc(void)
{
ort_eecb_t *me = __MYCB;
ort_task_node_pool_t *task_node_pool;
ort_task_node_t *new_node;
int i;
int my_max_mates = me->tasking.max_mates;
task_node_pool = me->tasking.task_node_pool;
while(task_node_pool != NULL)
{//搜索本eecb的任务节点池链表,看是否有空的任务节点池,若有则返回此节点池中一个没有使用的任务节点
if(task_node_pool->task_func == NULL)
{
//搜索这个空的任务节点池
for(i=0; i<(TASKPOOLSIZE(my_max_mates)); i++)
if (task_node_pool->sub_pool[i].occupied == 0)
{//找到一个没有使用的任务节点
task_node_pool->sub_pool[i].funcarg = NULL;
task_node_pool->sub_pool[i].occupied = 1;//设置使用标志
return &(task_node_pool->sub_pool[i]);//返回这个空的任务节点的地址
}
//这个任务节点池中的节点都已被占用,那么从回收站中获取一个任务节点
new_node = task_node_pool->recycler;
if(new_node == NULL)
{//回收站中没有节点,新建一个任务节点
new_node = (ort_task_node_t *)ort_calloc_aligned(sizeof(ort_task_node_t), NULL);
new_node->next = NULL;
new_node->occupied = 2;//此标志表明该任务节点最终会被回收到回收站中
}
else//回收站中有任务节点
task_node_pool->recycler = task_node_pool->recycler->next;//修改回收站的起始位置
return new_node;//返回回收站中的此任务节点
}
task_node_pool = task_node_pool->next;//搜寻下一个任务节点池
}
//没有找到空的任务节点池,那么新建一个任务节点池
task_node_pool = (ort_task_node_pool_t *)ort_calloc_aligned(sizeof(ort_task_node_pool_t), NULL);
task_node_pool->task_func = NULL;//没有确定该任务节点池属于哪个任务函数
task_node_pool->recycler = NULL;//设置回收站中当前节点为空
//给该任务节点池创建多个任务节点,这是一个节点数组,此中节点的回收方式为1.
task_node_pool->sub_pool = (ort_task_node_t*)ort_calloc(TASKPOOLSIZE(my_max_mates)*sizeof(ort_task_node_t));
//将此任务节点池放入链表中
task_node_pool->next = me->tasking.task_node_pool;
me->tasking.task_node_pool = task_node_pool;
//从任务节点数组中取出第一个节点,设置其任务函数参数为空,并设置此节点的回收方式
task_node_pool->sub_pool[0].funcarg = NULL;
task_node_pool->sub_pool[0].occupied = 1;//设置此标志为1表示回收时只需要将此标志修改为0即可
return &(task_node_pool->sub_pool[0]);//返回这个节点的地址
}
void ort_taskenv_free(void *ptr, void *(*task_func)(void *))
{
}