/*	
 *	cliptask.c
 *
 *	タスク制御 (ガーベージコレクター必須!!)
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2004 Naoyuki Sawa
 *
 *	* Mon Jul 05 05:31:56 JST 2004 Naoyuki Sawa
 *	- 作成開始。
 *	  GCを使わないタスク制御は、keepフォルダに保存しました。
 */
#include "clip.h"

/*****************************************************************************
 *	
 *****************************************************************************/

void*
task_start(TASK** task_list, TASKEVENTHANDLER* event_handler, int data_size)
{
	TASK* task;
	TASK* pos;

	/* 共通タスクヘッダとタスクデータ領域のためのメモリを確保します。 */
	task = (TASK*)calloc(1, sizeof(TASK) + data_size);
	if(!task) DIE();

	/* イベント処理関数へのポインタを格納します。 */
	task->event_handler = event_handler;
	/* calloc()でメモリ確保したので、next_taskは既にNULLです。 */

	/* タスクリストに追加します。 */
	if(!*task_list) {
		/* 空のタスクリストへの追加: 新しいタスクがタスクリストの先頭になります。 */
		*task_list = task;
	} else {
		/* 既存タスクリストへの追加: 既存タスクリストの先頭タスクは変化しません。 */
		pos = *task_list;
		while(pos->next_task) {
			pos = pos->next_task;
		}
		pos->next_task = task;
	}

	/* タスクデータ領域へのポインタを返します。 */
	return task + 1;
}

void
task_stop(void* data)
{
	TASK* task;

	/* タスク停止をマークします。 */
	task = (TASK*)data - 1;
	task->event_handler = NULL;
}

void
task_event(TASK** task_list, int code, void* param)
{
	/* タスクリスト末尾に達するまで... */
	while(*task_list) {

		/* 動作中のタスクならば... */
		if((*task_list)->event_handler) {
			/* イベント処理関数を呼び出します。 */
			(*task_list)->event_handler((*task_list) + 1, code, param);
			// ↑イベント処理関数の中でtask_new()を呼び出して新規タスクを生成した場合、
			// │(*task_list)->next_task がNULL値→非NULL値へ変化する可能性があります。
			// ↓その場合も、この処理手順で安全です。
			/* 走査位置を次へ進めます。 */
			task_list = &(*task_list)->next_task;

		/* 停止中のタスクならば... */
		} else {
			/* タスクリストから除外します。 */
			*task_list = (*task_list)->next_task;
		}
	}
}
