view src/pthread/ThreadManager.cbc @ 14:5f65da34f4f3

add runnable pthread mode.
author kent <kent@cr.ie.u-ryukyu.ac.jp>
date Sat, 09 Jan 2010 18:13:49 +0900
parents f06fb0370caf
children e89acebd97b1
line wrap: on
line source

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
// 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;

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);
	}
}