/*	
 *	clipidle.h
 *
 *	アイドルスレッド
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2009 Naoyuki Sawa
 *
 *	* Fri Jun 19 01:44:03 JST 2009 Naoyuki Sawa
 *	- 1st リリース。
 *	* Sun Oct 11 21:57:48 JST 2009 Naoyuki Sawa
 *	- idle_stat()関数を追加しました。
 *	* Mon Oct 12 05:55:33 JST 2009 Naoyuki Sawa
 *	- idle_exit()関数を追加しました。
 */
#ifndef __CLIP_IDLE_H__
#define __CLIP_IDLE_H__

/*****************************************************************************
 *	グローバル関数
 *****************************************************************************/

/* アイドル関数を登録します。
 * [in]
 *	fn		アイドル関数。NULLを指定すると、アイドル処理を実行しません。
 *	param		アイドル関数への、任意のパラメータ。
 * [note]
 *	- 本関数は、アイドル関数を登録するだけで、まだ、アイドル関数を起動しません。
 *	  実際に起動するのは、次回にidle_yield()、または、idle_wait()を呼んだときです。
 *	- 既にアイドル関数が起動していて、処理途中である場合に、本関数を呼び出すと、
 *	  処理途中のアイドル関数は、強制終了します。
 *	  アイドル関数が、アトミックでない処理を処理している途中にプリエンプトされ、
 *	  メインスレッドに戻った後、本関数で強制終了すると、不安定な状態になったり、
 *	  リソースリークが発生する可能性があるので、注意してください。
 * [使用例]
 *	- ユーザーにロード時間を意識させないよう、タイトル画面の裏でロード処理や圧縮展開処理を行う例です。
 *
 *		void schedule() {
 *			...
 *			idle_yield(); // 通常のyield()の代わりに、idle_yield()を使う
 *			...
 *		}
 *
 *		int load_data(int param) {
 *			... // 時間がかかる、ロード処理や、圧縮展開処理など。プリエンプトされるので要注意!
 *			return exit_code;
 *		}
 *
 *		void app_main() {
 *			idle_init(load_data, data_number); // タイトル画面の裏で、ロード処理を行うよう登録
 *			for(;;) {
 *				schedule();
 *				... // タイトル画面処理
 *			}
 *			exit_code = idle_wait(); // ロードしたデータを使う前に、確実にロード処理を完了する
 *			for(;;) {
 *				schedule();
 *				... // ゲーム画面処理
 *			}
 *		}
 */
void idle_init(int (*fn)(int param), int param);

/* 残りタイムスライスでアイドル処理を実行した後、システム処理を実行します。
 * [note]
 *	- アイドル関数が登録されていない場合や、既に終了していた場合は、
 *	  アイドル処理を実行せずにシステム処理を実行し、残り時間をhaltします。
 *	- タイムスライスが残っていない場合は、アイドル処理を実行しません。
 *	  ユーザー処理が、常にフレーム時間を超過しているようなプログラムでは、
 *	  アイドル処理が全く実行されない場合が有り得るので、注意してください。
 */
void idle_yield();

/* アイドル処理をすべて実行し、終了コードを返します。
 * [out]
 *	戻り値		アイドル関数の戻り値。
 * [note]
 *	- アイドル関数が既に終了している場合は、すぐに終了コードを返します。
 *	  アイドル関数が登録されていない場合も、すぐに処理を返しますが、戻り値は未定義です。
 *	- アイドル関数が処理を終了しない、無限ループである場合は、本関数も処理を返しません。
 *	  アプリケーションは、ハングアップしてしまうので、注意してください。
 */
int idle_wait();

/* アイドル処理の実行状態を取得します。
 * [out]
 *	戻り値		アイドル処理の実行状態。
 *			アイドル関数がまだ終了していない場合は、0以外の値を返します。
 *			アイドル関数が登録されていない場合や、既に終了していた場合は、0を返します。
 * [note]
 *	- アプリケーションから、以下の例のように利用することを想定して、この関数を用意しました。
 *	  アプリケーションのメインループで、アイドル処理が終了するまで、別の処理を行う利用法です。
 *
 *		void app_main() {
 *			int exit_code;
 *			idle_init(load_data, data_number); // 時間のかかるロード処理を、アイドル処理で実行する
 *			while(idle_stat()) { // アイドル処理が終了するまで…
 *				schedule() ; // この中で、アイドル処理を実行
 *				// ここで、Now Loading...アニメーション等を表示する //
 *			}
 *			//exit_code = idle_wait(); // 終了コードが必要なければ、idle_wait()を呼ばなくても構いません
 *			for(;;) {
 *				schedule();
 *				// ロードしたデータを使って、メインループを実行する //
 *			}
 *		}
 */
int idle_stat();

/* アイドル処理を終了します。
 * [in]
 *	exit_code	終了コード。
 * [note]
 *	- アイドル関数からreturnするのと同じ効果を持ちます。
 *	  アイドル関数から呼び出された関数の中から、直接、アイドル処理を終了させるために用意しました。
 *	- 本関数は、アイドルスレッドのコンテキストからのみ、呼び出し可能です。
 *	  通常のコンテキストから呼び出すと、異常動作となります。
 * [使用例]
 *	int idle_proc(int param) { // アイドル関数
 *		idle_proc_sub1();
 *	}
 *	void idle_proc_sub1() {
 *		idle_proc_sub2();
 *	}
 *	void idle_proc_sub2() {
 *		idle_exit(123); // exit_code = 123
 *	}
 */
void idle_exit(int exit_code) __attribute__((noreturn));

#endif /*__CLIP_IDLE_H__*/

