#include #include #include // TODO: malloc #include "Debug.h" #include "Fifo/SchedTask.h" #include "ThreadManager.h" typedef __code (*Scheduler)(struct _UserManager*,Taskrun,void*,void*); typedef struct _UserManager { Scheduler scheduler; struct _ThreadManager *threadmanager; /* * ユーザ側からは次のように見えるのが望ましい? * struct UserManager { * Scheduler scheduler; * } */ } UserManager; __code threadloop(ThreadManager *manager); __code exitThread(ThreadManager *manager); __code checkNewTask(ThreadManager *manager); __code waitNewTask(ThreadManager *manager); static __code schedEntry(UserManager *user, Taskrun nextcode, void *rbuff, void *wbuff); static __code selectCode(ThreadManager *manager); void * threadbase(void *args) { ThreadManager *manager = args; UserManager *umanager; umanager = malloc(sizeof(UserManager)); umanager->scheduler = schedEntry; umanager->threadmanager = manager; manager->user = umanager; fprintf(stderr, "test\n"); fflush(stderr); __DEBUG("ThreadManager:%d started.\n",manager->thread_id); fflush(stderr); goto threadloop(manager); } __code threadloop(ThreadManager *manager) { if (manager->finishFlag) goto exitThread(manager); else if (!manager->schedTasks) goto waitNewTask(manager); else goto checkNewTask(manager); } __code exitThread(ThreadManager *manager) { __DEBUG("thread whose id is %d finished!\n", manager->thread_id); free(manager->user); pthread_exit(0); } __code checkNewTask(ThreadManager *manager) { Task *task; SchedTask *stask; __DEBUG("thread:%d.\n",manager->thread_id); task = queuePoll(manager->newtaskQ); if (task) { stask = malloc(sizeof(SchedTask)); stask->task = task; stask->nextcode = tasktypes[task->typeid].code; stask->rbuff = task->rbuff; stask->wbuff = task->wbuff; manager->schedTasks = _listAddFirst(manager->schedTasks, stask); } goto selectCode(manager); } __code waitNewTask(ThreadManager *manager) { Task *task; SchedTask *stask; __DEBUG("thread:%d.\n",manager->thread_id); task = queueTake(manager->newtaskQ); stask = malloc(sizeof(SchedTask)); stask->task = task; stask->nextcode = tasktypes[task->typeid].code; stask->rbuff = task->rbuff; stask->wbuff = task->wbuff; manager->schedTasks = _listAddFirst(manager->schedTasks, stask); goto selectCode(manager); } /* * Scheduler * copied from Fifo/TaskManager.cbc. * it may should be organized to common codes. */ static __code selectCode(ThreadManager *manager) { SchedTask *task; if (manager->schedTasks) { task = (SchedTask*)_listGetLastData(manager->schedTasks); manager->running = task; /* goto user-defined task. */ goto task->nextcode(manager->user, task->task->rbuff, task->task->wbuff); } else { /* no task we have. */ //goto checkNewCode(); goto threadloop(manager); } } static __code schedEntry(UserManager *user, Taskrun nextcode, void *rbuff, void *wbuff) { ThreadManager *manager = user->threadmanager; /* schedulerd */ if ( nextcode==NULL ) { /* the task finished. */ Task *task; task = manager->running->task; manager->schedTasks = _listRemove(manager->schedTasks, manager->running); free(manager->running); manager->running = NULL; queueOffer(manager->finishtaskQ, task); //goto selectCode(manager); goto threadloop(manager); } else { /* save the next code segment for the task. */ manager->running->nextcode = nextcode; manager->running->rbuff = rbuff; manager->running->wbuff = wbuff; /* move last task to first to be fair. */ manager->schedTasks = _listMoveLasttoFirst(manager->schedTasks); goto selectCode(manager); } }