RobotStateMachine |
---|
class RobotStateMachine { static final int forward = 1; static final int pivotLeft = 2; static final int pivotRight = 3; int state = forward ; public void nextState ( int state ) { this.state = state; } public void execute () { switch ( state ) { case forward: moveForward (); if ( obstacleToLeft ()) nextState ( pivotRight ); else if ( obstacleToRight ()) nextState ( pivotLeft ); break ; case pivotLeft: pivotLeft (); if ( obstacleToRight ()) nextState ( pivotRight ); else if ( ! obstacleToLeft ()) nextState ( forward ); break ; case pivotRight: pivotRight (); if ( obstacleToLeft ()) nextState ( pivotRight ); else if ( ! obstacleToRight ()) nextState ( forward ); break; } return state; } // 検出と動きに対する他のメソッドがここから始まる。 } |
ラウンドロビン |
---|
一つの資源を順番に利用する手法。 ネットワークの負荷分散の場合、同様の構成にした系を複数用意して処理要求を順番に割り振ることをいう。ホスト名とIPアドレスの対応関係を利用して複数のサーバで負荷分散を行なう「DNSラウンドロビン」が有名。 コンピュータの並列処理の場合、各プロセスを一定時間ずつ順番に実行することをいう。「巡回的並列処理」とも呼ばれる。持ち時間を使い果たしたプロセスは一旦中断され、待ち行列の最後に回される。各プロセスに割り当てられるCPU時間の断片をタイムクォンタム(time quantum)もしくはタイムスライス(time slice)という。ラウンドロビン方式ではすべてのプロセスが平等に扱われる。 |
Event | ||||
Semaphore | ||||
Task | ||||
InterruptTask | ||||
TimerTask | ||||
TaskToneGenerator | ||||
CallableTask | ||||
WatchHeapTask | ||||
ShowStatus | ||||
TaskStatus | ||||
SemaphoreStatus |
semaphore セマフォ |
---|
複数のプロセス(プログラム)が同時実行されるマルチタスクOSにおいて、複数プログラム間での同期をとるためのしくみ。セマフォは一種の共有フラグで、同期をとるプログラム同士がこのフラグに注目し、フラグの変化に応じて処理を行なうようにすることで、同期を実現する。 |
協調的マルチタスク状態遷移マシンオペレーティングシステム |
---|
/* * 協調的マルチタスク状態遷移マシンオペレーティングシステム * タスクはEventのサブクラスでタスクはEventによって再開される */ package stamp.util.os; import stamp.util.*; import stamp.core.*; /** * イベントが生じたことを示すためのインターフェース */ public class Event { static final public Event nullEvent = new Event () ; /** * null eventを作る。Event.nullEventを用いること。 */ protected Event () { } /** * イベント参照がnullかどうかチェックする。 * * event: チェックするevent * * returns: もしnullだったらnullEventを返し、それ以外はeventを返す。 */ static public Event checkEvent ( Event event ) { return ( event == null ) ? nullEvent : event ; } /** * イベントを生じさせる。 */ public void notify() { notify(null); } /** * イベントを生じさせる。 */ public void notify( Object object ) { } /** * イベントの名前を得る。 * * return: イベント名("Event") */ public String name () { return "Event" ; } } |
multi-thread |
---|
「thread」は「糸」という意味で、コンピュータ関連では、 プログラムの実行単位を表わす言葉として利用される。 一般に複数のプログラムが同時に実行可能なマルチタスクシステムでは、 それらの各プログラムに見掛け上、独立したメモリ空間やI/O空間などを 割り当てることで、それぞれのプログラムに対し、あたかもそれだけが 動いているように見せ掛ける。これにより各プログラムは、同時に実行 される他のプログラムとの相互作用を意識しなくてすむ。 マルチタスクシステムでは、このように、メモリ資源やディスク資源などを 独立して所有するプログラムの実行単位をプロセス(process。 「過程」の意)と呼んでいる。 しかしマルチタスクシステムが、あるプロセスから別のプロセスに実行を 切り替えるには、現在のCPUレジスタの内容をすべて保存し、これから制御を 切り替えるプロセスのためのレジスタ値をロードするなど、負荷が非常に 大きい(こうした処理により、プロセスの独立性が保証される)。 このような負荷の大きなプロセスの切り替え処理を必要とせず、同一 プロセス内でのマルチタスク処理を可能にしたものがマルチスレッド・ システムであり、この場合のタスクの実行の単位をスレッドと呼ぶ。 同一プロセス内のスレッド間では、処理の切り替えにかかる負荷が 小さく、またメモリやI/O資源などを共有するため、負荷の大きな プロセス間通信を伴わずに、スレッド間での通信が行なえるという メリットがある。 一般にマルチスレッドシステムでは、実行単位はすべてスレッドで 管理される。このためプロセスが生成されると、最低でも1つのスレッドが 同時に生成される。このようにプロセスを代表するスレッドを、 プライマリスレッド(primary thread)と呼んでいる。 |
協調的マルチタスク状態遷移マシンオペレーティングシステム |
---|
/* * 協調的マルチタスク状態遷移マシンオペレーティングシステム * これはラウンドロビンタスクスケジューリングを用いた非常に * 基本的なOSです。 * タスクリストは効率性の理由から循環的にリンクしています。 * * 注意: もしTaskStatusクラスが用いないで、数バイトを付け加えれば * コンストラクタの参照でtaskStatusListとnextTaskStatus * を削除可能になる。 */ package stamp.util.os; import stamp.util.*; import stamp.core.*; /** * フリーサイクルのときはいつでもタスクが走ります。 * 注意: 外部タスクを終了させる良い方法はtaskToAbort.nextState(abort) * を用いることです。代替手段はtaskToAbort.stop()ですが、これはメモリ * の掃除をしません。 */ public abstract class Task extends Event { /** * taskState() result */ final public static int taskRunning = 0 ; /** * taskState() result */ final public static int taskSuspended = 1 ; /** * taskState() result */ final public static int taskSemaphoreWait = 2 ; /** * Initial value of state in execute() */ final public static int initialState = 0 ; final public static int checkTimer = -1 ; // sleep()のサポート用 final public static int interrupt = -2 ; // InterruptTaskを見よ final public static int terminate = -3 ; final public static int stopped = -4 ; /** * sleep()要求によるタスクを扱うためのTimerオブジェクト */ public Timer timer = new Timer () ; /** * 次のアクティブタスクは循環リストの中 */ protected static Task taskStatusList = null ; /** * taskStatusListに対するリンクされたリスト */ protected Task nextTaskStatus = null ; /** * taskState()によって戻される値 */ protected int taskStatus ; /** * 循環リスト上の次のアクティブリスト */ protected Task nextTask = null ; /** * execute()の中で用いられる状態変数 */ protected int state = initialState ; /** * タイムアウトが起こった後の次の状態 */ protected int sleepState = checkTimer ; /** * Timout値 */ protected int hi, lo ; /** * タスクのセットアップ(設定)と開始 */ public Task() { addTask ( this ) ; // タスクをステータスリストに加える nextTaskStatus = taskStatusList ; taskStatusList = this ; } /** * タスク名を得る。 * * 戻り: String の"Task" */ public String name () { return "Task" ; } /** * タスクのステータスを得る * * 戻り: タスクのステータス * (taskRunning, taskSuspended, taskSemaphoreWait) */ public int taskStatus() { return taskStatus; } /** * 現在のタスクの状態を得る * * 戻り: int タスクの状態 */ public int getState () { return state ; } /** * もし、タスクが実行中ならばタスクマネージャーのタスクリスト * からタスクを削除する。 * 任意のタスクから呼ぶことが出来る。 * * 戻り: boolean タスクがリストから削除されたときにtrue */ public boolean suspend () { if ( taskStatus == taskRunning ) { // 注意: nextTaskがnullでなかったらマネージャーはnull // であってはいけない taskStatus = taskSuspended ; return removeTask ( this ) ; } return false ; } /** * 停止するためにタスクを削除しstopの状態に設定する * 戻り: boolean 停止に成功したらtrue */ public boolean stop() { if ( suspend ()) { state = stopped ; return true ; } return false ; } /** * もしタスクが実行していなかったならば、タスクマネージャーの * リストにタスクを戻して加える。 * 任意のタスクから呼ぶことができるが、そのタスクはマネージャーを * 持っていなければならない * */ public boolean resume () { if ( taskStatus == taskSuspended ) { // 注意: マネージャーはnextTaskがnullでなかったならばnullで // であってはいけない addTask ( this ) ; return true; } return false ; } /** * resume()と同じ */ public boolean start() { return resume () ; } /** * resume()と同じ */ public void notify( Object object ) { resume () ; } /** * 次のexecute()呼び出しに対して状態を設定する * */ public void nextState(int state) { this.state = state ; } /** * 次のexecute()呼び出しに対して状態を設定する * タスクをSuspendする。他のタスクによってresumeされる */ public void sleep(int state) { this.state = state ; suspend(); } /** * poll timerを仕掛けて設定単位時間を経過後に次の状態を続ける * * 入力: int nextState タイムアウトが起こったときに入る状態 * 入力: int hi タイムアウト値。詳細はTimer.timeout(hi,lo)を見よ * 入力: int lo タイムアウト値 */ public void sleep ( int nextState, int hi, int lo ) { this.hi = hi ; this.lo = lo ; timer.mark () ; sleepState = nextState ; state = checkTimer ; } /** * poll timerを仕掛けて設定単位時間を経過後に次の状態を続ける * 入力: int nextState タイムアウトが起こったときに入る状態 * 入力: int msec ミリ秒単位でのタイムアウト値 */ public void sleep ( int nextState, int timeMS ) { sleep ( nextState, timeMS/569, (timeMS%569)*119) ; } /** * poll timerを仕掛けて設定単位時間を経過後に次の状態を続ける * 入力: int nextState タイムアウトが起こったときに入る状態 * 入力: int timeS 秒単位でのタイムアウト値 */ public void sleepSec ( int nextState, int timeS ) { sleep ( nextState, (timeS*18)/10, 0); } /** * 1期間タスクを実行する。全てのサブクラスはこのメソッドで * 実装されなければいけない * GUIがアイドルのときはいつでもアイドルタスクが実行される。 * execute()の実装はインターフェースが応答可能にするために * 100ms以上かかってはいけない。 */ protected abstract void execute() ; // タスクマネージャーサポート /** * クラス変数: タスクリストの現在のタスク */ static protected Task taskList = null; /** * 現在のアクティブタスク */ static protected Task currentTask = null ; /** * 現在実行しているタスクオブジェクトを得る * * 戻り:Task 現在実行しているタスク */ static public Task getCurrentTask () { return currentTask ; } /** * タスクリストにタスクを加える * * 入力:Task aNewTask: タスクリストに加えるタスク */ public static void addTask(Task aNewTask) { if ( taskList == null ) { aNewTask.nextTask = aNewTask ; } else { aNewTask.nextTask = taskList.nextTask ; taskList.nextTask = aNewTask ; } aNewTask.taskStatus = taskRunning ; taskList = aNewTask ; } /** * タスクリストからタスクを削除する * * 入力:aTaskToRemove:タスクリストから削除するタスク * * 戻り:boolean リストからタスクが削除できたらtrue */ public static boolean removeTask(Task aTaskToRemove) { // 空のリストを始めに処理する if ( taskList != null ) { // 現在のタスクからリストを走査し見つかったらそれを削除する Task scanTask = taskList ; do { if ( scanTask.nextTask == aTaskToRemove ) { // 削除するタスクが見つかった if ( scanTask == aTaskToRemove ) { // リストの中の一つだけのタスクを削除する taskList = null ; } else { // 現在のタスクが削除されたかどうかチェックする if ( taskList == aTaskToRemove ) { taskList = aTaskToRemove.nextTask ; } scanTask.nextTask = aTaskToRemove.nextTask ; } aTaskToRemove.nextTask = null ; return true ; } // リストの中の次のタスクをチェックする scanTask = scanTask.nextTask ; } while ( scanTask != taskList ); //全てのリストが走査されたら脱出 } return false ; } /** * ラウンドロビン法でタスクリストの中の各々のタスクを * 永久に実行する。実行するタスクが無くなった時に戻る */ public static void TaskManager() { while ( taskList != null ) { // execute()がremoveTaskを通して変えることができるように // taskListを変える currentTask = taskList ; taskList = taskList.nextTask ; if (currentTask.state == checkTimer) { // タスクがタイムアウトを待機している if (currentTask.timer.timeout(currentTask.hi,currentTask.lo)) { // タイムアウトが起こったら、次の状態を設定する currentTask.state = currentTask.sleepState ; // もし、次の状態が不適切に設定されていたらば抜け出す if ( currentTask.state == checkTimer ) { currentTask.state = terminate ; } } } else { // 次の状態を呼び出す currentTask.execute () ; } } } } |
protected |
---|
protectedが付与されたメンバ変数、メソッドは同一クラス、 同一パッケージ、サブクラスから参照することができます。 注意点はサブクラスからアクセスできるのはサブクラスの オブジェクトを通してのみということです。サブクラスから スーパークラスのオブジェクトを通して参照することはできません。 |
class task1 extends Task { static final int newState = 1 ; static final int anotherState = 2 ; public void execute () { switch ( state ) { case initialState: // この状態で行うことを記述 break; case newState: // この状態で行うことを記述 break; case anotherState: // この状態で行うことを記述 break; default: stop (); break; } } }変数の前についているstatic final intは整数型の定数を表しています。状態の数字はユニークである必要があります。それには連番が簡単ですが、そのようにしなければならないことはありません。定数値が使われると実際の値は無関係です。同様に状態定数は正の数値にすべきです。 ゼロとマイナスの数値は内部のTaskManagerの使用のために確保されています。
最初のマルチタスクのプログラム |
---|
import stamp.core.*; import stamp.util.os.*; /** * Multitasking Test 1 */ public class MutlitaskingTest1 extends Task { // execute()の状態 final static int state1 = 1 ; final static int state2 = 2 ; String name ; MutlitaskingTest1 ( String name ) { this.name = name ; } /** * タスク名を得る */ public String name () { return name ; } public void show ( String text ) { System.out.print ( name ) ; System.out.print ( ": " ) ; System.out.println ( text ) ; } protected void execute () { switch ( state ) { case initialState: show ( "Initial state" ) ; nextState ( state1 ) ; break ; case state1: show ( "State 1" ) ; nextState ( state2 ) ; break ; case state2: show ( "State 2" ) ; stop () ; break ; default: // 異常な状態を捕獲し停止するためにdefaultにする stop () ; break; } } public static void main() { new MutlitaskingTest1 ( "Task 1" ) ; new MutlitaskingTest1 ( "Task 2" ) ; new MutlitaskingTest1 ( "Task 3" ) ; Task.TaskManager () ; System.out.println ( "All done" ) ; } } |
InterruptTaskタスク |
---|
/** * このタイプのタスクはInterrupt()メソッドを用いて割り込まれる * ことができます。 * タスクの状態をInterruptに変えて、現在の状態を保存します。 * タスクはlastStateを用いて再開(resume)することができます。 * * public void execute (int state) { * switch ( state ) { * case interrupt: * // do something here with interruptValue * * nextState ( lastState ) ; * break ; */ package stamp.util.os; import stamp.util.*; public abstract class InterruptTask extends Task { public int interruptState = terminate ; public int interruptValue = 0 ; /** * タスクの割り込みに用いる。割り込み状態に入る前に * 多重割り込みが起こった場合、最初の割り込みのみが認識されます。 * 他の全ては無視されます。 * * 入力:int interruptValue: * 割り込み原因を決めるためにタスクに与えられる値 * * 戻り:boolean 割り込みが処理されたならばtrue */ public boolean interrupt ( int interruptValue ) { if ( state != interrupt ) { this.interruptValue = interruptValue ; interruptState = state ; state = interrupt ; return true ; } else return false ; } /** * 割り込みの前の状態で再開する。 * これは割り込み状態からのみ呼ばれるべきであるResume state prior to */ public void resumeInterrupt () { state = interruptState ; } /** * タスクの割り込みに用いる。割り込み状態に入る前に * 多重割り込みが起こった場合、最初の割り込みのみが認識されます。 * 他の全ては無視されます。 */ public boolean interrupt () { return interrupt(0); } } |
MutlitaskingTest2 |
---|
import stamp.core.*; import stamp.util.os.*; /** * Multitasking Test 2 */ public class MutlitaskingTest2 extends InterruptTask { // execute()の状態 final static int state1 = 1 ; final static int state2 = 2 ; String name ; InterruptTask taskToInterrupt ; MutlitaskingTest2 ( String name, InterruptTask taskToInterrupt ) { this.name = name ; this.taskToInterrupt = taskToInterrupt ; } public void show ( String text ) { System.out.print ( name ) ; System.out.print ( ": " ) ; System.out.println ( text ) ; } protected void execute () { switch ( state ) { case initialState: show ( "Initial state" ) ; nextState ( state1 ) ; break ; case state1: show ( "State 1" ) ; nextState ( state2 ) ; if ( taskToInterrupt != null ) if ( taskToInterrupt.interrupt ()) show ( "Task interrupted" ) ; else show ( "Task already interrupted" ) ; break ; case state2: show ( "State 2" ) ; stop () ; break ; case interrupt: show ( "Interrupted" ) ; resumeInterrupt () ; break ; default: // 異常な状態を捕獲し停止するためにdefaultにする stop () ; break; } } public static void main() { MutlitaskingTest2 task1 = new MutlitaskingTest2 ( "Task 1", null ) ; new MutlitaskingTest2 ( "Task 2", task1 ) ; new MutlitaskingTest2 ( "Task 3", task1 ) ; Task.TaskManager () ; System.out.println ( "All done" ) ; } } |
TimerTask -- タイマーを用いた単純化な方法 |
---|
/** * 単純なタイマーを基本として運用するタスク * タイマーが開始されたときにタスクが開始するように設計されている。 * handleTimeoutメソッドがタイムアウトが起こった * 時によばれる。 * タイマーは再開(restart)されることができ、あるいは * タスクは終了することができる。 * * 典型的な使用法はTaskManager用いた音発生である。 * これはタイマーが走っている間に他のタスクが実行できる。 * handleTimeoutメソッドは同様に定義される。 * デフォールトでinterruptメソッドを呼ぶことは * タイマーを止めます。 */ package stamp.util.os; public abstract class TimerTask extends InterruptTask { final static int timeout = 1 ; /** * 割り込みが起動されたときに呼ばれる * もしサブクラスがこの状態を処理するならば、再定義される。 * * 戻り:boolean false */ public boolean handleInterrupt ( int interruptValue ) { return false ; } /** * タイムアウトが起こったときに呼ばれる。 * もしサブクラスがこの状態を処理するならば、再定義される。 * * 戻り:boolean true: resumeだったら * false: terminateだったら */ public abstract boolean handleTimeout () ; /** * タイマーが走っているかどうかをチェックする。 * * 戻り:boolean true: タイマーが入っていれば */ public boolean timerRunning () { return state == checkTimer ; } /** * TaskManagerに呼ばれるタスク実行ルーチン */ public void execute () { switch ( state ) { case interrupt: if ( handleInterrupt ( interruptValue )) resumeInterrupt () ; else nextState ( terminate ) ; break ; case timeout: if ( handleTimeout ()) break ; // タイムアウトが処理されたら続ける // でなければ、タスクをstop()するように下に落ちる // case initialState: // case terminate: default: stop () ; break ; } } /** * Start timer and call on timeout. * タイムアウト時にタイマーを開始し、handleTimeout()を呼ぶ。??? * 入力:int hi タイムアウト値、詳しくはTimer.timeout(hi,lo)を見よ * 入力:int lo タイムアウト値 */ public void sleep ( int hi, int lo ) { sleep ( timeout, hi, lo ) ; resume () ; } /** * タイムアウト時にタイマーを開始し、handleTimeout()を呼ぶ。??? * * 入力:int timeMS: ミリ秒単位のタイムアウト値 */ public void sleep ( int timeMS ) { // スーパークラスを用いる super.sleep ( timeout, timeMS ) ; resume () ; } /** * タイムアウト時にタイマーを開始し、handleTimeout()を呼ぶ。??? * * 入力:int timeS: 秒単位のタイムアウト値 */ public void sleepSec ( int timeS ) { sleepSec ( timeout, timeS ); resume () ; } } |
TaskToneGenerator -- TaskManagerを用いて音を発生させる |
---|
/** * TaskManagerを用いた音発生器 * * TaskTimerサポートを用いて指定された期間音を発生させる。 * FreqoutがしていたようにCPU.delayは用いていない。 */ package stamp.util.os; import stamp.core.*; public class TaskToneGenerator extends TimerTask { protected PWM pwm ; protected int pin ; protected int tones[] ; protected int tonesIndex ; protected boolean pwmRunning = false ; final static int endTone = 1 ; // 終了時の状態 final static int noMoreTones = -1 ; /** * 音発生出力を設定する * * 入力: int pin: CPU.pin10のように出力ピンを設定する */ public TaskToneGenerator ( int pin ) { this.pin = pin ; pwm = new PWM ( pin ) ; } /** * タスク名を得る * * 戻り:String タスク名 */ public String name () { return "TaskToneGenerator" ; } /** * 出力周波数を設定する * * 入力:int frequency 10ヘルツ単位の周波数(0 - 11k) */ protected void setFrequency ( int frequency ) { if ( frequency == 0 ) frequency = 1 ; int halfCycleTime = 5761 / frequency ; pwm.update ( halfCycleTime, halfCycleTime ) ; } /** * 固定時間だけ音を発生する * * 入力:int frequency 10ヘルツ単位の周波数(0 - 11k) * 入力:int time ミリ秒単位の持続時間 */ public void playTone (int frequency, int time) { tonesIndex = noMoreTones ; playToneNow ( frequency, time ) ; } /** * 音の組を発生する。配列は偶数個の要素が含まれる。 * 要素の始めの値は周波数 * 二番目は持続時間 * 配列に少なくとも二つないと何もしない。 * * 入力:int[] tones: 音の配列(frequency, duration)の対 */ public void playTones ( int tones[] ) { if ( tones.length >= 2 ) { this.tones = tones ; tonesIndex = 0 ; startNextTone () ; } } /* Internal routine */ protected void playToneNow ( int frequency, int time ) { // PWMを設定する setFrequency ( frequency ) ; // PWMとタスクがすでに入っているかどうかチェックする if ( ! pwmRunning ) { pwmRunning = true ; pwm.start () ; // PWMを開始する } /* 指定した時間Sleepする * 後でtimerRunningのstatusを設定するからtimerRunning * のチェックをした後に実行しなければならない */ sleep(time) ; } /* 内部ルーチン */ protected void startNextTone () { // tonesIndexはいつも正しい対を参照する playToneNow ( tones[tonesIndex], tones[tonesIndex+1] ) ; tonesIndex += 2 ; // リストの中の最後の音かどうかtonesIndexを調整する if (( tonesIndex + 2 ) > tones.length ) { tonesIndex = noMoreTones ; } } /** * 音が出ていれば音の発生を切る */ public void stopTone () { interrupt ( 0 ) ; } /** * 音が出ていれば音の発生を切る * * 入力:int interruptValue: 無視される * * 戻り:タスクが停止したときfalse */ public boolean handleInterrupt ( int interruptValue ) { if ( pwmRunning ) { tonesIndex = noMoreTones ; //次のタイムアウトでdisableにする handleTimeout () ; //タイムアウトさせる } return false ; } /** * TaskManagerで呼ばれるタスク実行ルーチン * * 戻り:boolean: 終了したときfalse、残りがあるときtrue */ public boolean handleTimeout () { if ( tonesIndex == noMoreTones ) { // 残りの音がないときPWMを切る pwmRunning = false ; pwm.stop () ; // 音を切る CPU.readPin (pin); return false ; // タスクを停止 } else { // Get next tone startNextTone () ; // タイマーと次の音を開始 return true ; // タスクを続ける } } /** * */ public boolean running() { if( pwmRunning ) return true; return false; } } |
MutlitaskingTest3 |
---|
import stamp.core.*; import stamp.util.os.*; /** * Multitasking Test 3 - Tone generation */ public class MutlitaskingTest3 extends InterruptTask { final static int waitForToneDone = 1 ; final static int waitForTonesDone = 2 ; // 音リストは周波数と持続時間(msec)の対の組である final static int toneList [] = { 120, 50, 240, 50, 360, 50 } ; TaskToneGenerator toneGenerator = new TaskToneGenerator ( CPU.pin10 ) ; protected void execute () { switch ( state ) { case initialState: System.out.println ( "Initial state" ) ; toneGenerator.playTone ( 200, 1000 ) ; nextState ( waitForToneDone ) ; break ; case waitForToneDone: if ( toneGenerator.running ()) { System.out.println ( "Waiting for tone to end" ) ; } else { toneGenerator.playTones ( toneList ) ; nextState ( waitForTonesDone ) ; } break ; case waitForTonesDone: if ( toneGenerator.running ()) { System.out.println ( "Waiting for tone list to end" ) ; } else { stop () ; } break ; default: // 異常な状態を捕獲し停止するためにdefaultにする stop () ; break; } } public static void main() { new MutlitaskingTest3 () ; Task.TaskManager () ; System.out.println ( "All done" ) ; } } |
CallableTask |
---|
/** * この型のタスクは呼び出し規約の基本的な状態をサポートする。 * * タスクは他の状態を呼ぶことよって状態を変えることができる * これらの状態は呼び出し状態に戻ることができる。パラメータはまだ * 実装されていないがサブクラスは簡単にできる */ package stamp.util.os; import stamp.util.*; public abstract class CallableTask extends InterruptTask { // スタックはタスクに対して排他的である protected CallStackEntry stack = null ; /** * 現在のパラメータを得る * 戻り:直近のcallStateで渡されたパラメータを戻す */ public Object getParameter () { return ( stack == null ) ? null : stack.parameter ; } /** * 状態を呼ぶ * * 入力:int callState: 入る次の状態 * 入力:Object parameter: 呼び出しパラメータ * 入力:int returnState: returnState()が呼ばれたときに入る状態 */ public void callState ( int callState, Object parameter, int returnState ) { // 新しいスタックエントリーを加える stack = CallStackEntry.getEntry ( returnState, stack, parameter ) ; // 新しい状態を設定する nextState ( callState ) ; } /** * 状態を呼ぶ * * 入力:int callState: 入る次の状態 * 入力:int returnState: returnState()が呼ばれたときに入る状態 */ public void callState ( int callState, int returnState ) { callState ( callState, null, returnState ) ; } /** * 一番最近のcallStateで指定された前の状態に戻る * もし前の呼び出し無しで実行されたらばタスクが終了する */ public void returnState () { CallStackEntry oldEntry ; if ( stack == null ) { state = terminate ; } else { // Setup return state state = stack.returnState ; // スタックをPopする oldEntry = stack ; stack = oldEntry.nextEntry ; // Free entry oldEntry.free () ; // 注意: ガーベージコレクションがサポートされているならば // 次を付け加えるべきである // stackEntry.parameter = null } } } |
CallStackEntry |
---|
/** * CallableTaskスタックを実装するのに用いる */ package stamp.util.os; import stamp.util.*; public class CallStackEntry { protected CallStackEntry nextEntry ; protected int returnState ; protected Object parameter ; protected static CallStackEntry freeList = null ; protected CallStackEntry () { } /** * freeリストのエントリーを戻す */ void free () { nextEntry = freeList ; freeList = this ; } /** * 用いていないスタックエントリーを返す * フリーリストが空ならば新しいエントリーが作られる * * 入力:int returnState: 新しいエントリーに保存される * 入力:CallStackEntry nextEntry:新しいエントリーに保存される * 入力:Object parameter:新しいエントリーに保存される */ static CallStackEntry getEntry ( int returnState , CallStackEntry nextEntry , Object parameter) { CallStackEntry result ; if ( freeList == null ) { result = new CallStackEntry () ; } else { result = freeList ; freeList = result.nextEntry ; } // スタックリストにエントリーを加える result.returnState = returnState ; result.nextEntry = nextEntry ; result.parameter = parameter ; return result ; } } |
garbage collection |
---|
OSのメモリ管理機能の一つ。プログラムが使用しなくなったメモリ領域や、プログラム間の隙間のメモリ領域を集めて、連続した利用可能なメモリ領域を増やす技術。これが不完全なOSは次第に利用可能なメモリが減ってゆくため、一定期間ごとに再起動を強いられることになる。Java言語の実行環境(JVM)は自身がガーベジコレクション機能を持っており、Javaプログラマがメモリ管理に気を使わなくてもいいようにしている。 「garbage」は「ごみ、がらくた」という意味。 |
aCallStateParameter |
---|
class aCallStateParameter extends Object { public int bufferSize; public byte buffer[20]; public boolean success; } |
Multitasking Test 4 |
---|
import stamp.core.*; import stamp.util.os.*; /** * Multitasking Test 4 - Callable Task test */ public class MutlitaskingTest4 extends CallableTask { final static int state1 = 1 ; final static int state2 = 2 ; final static int call1 = 10 ; final static int call2 = 20 ; final static int call2a = 21 ; protected void execute () { switch ( state ) { case initialState: System.out.println ( "Starting" ) ; callState ( call1, "test base", state1 ) ; break ; case state1: System.out.println ( "State 1" ) ; callState ( call2, state2 ); break ; case state2: System.out.println ( "State 2" ) ; nextState ( terminate ) ; break ; // --- Call 1 ----- case call1: System.out.println ( "Enter call 1" ) ; System.out.println ( (String) getParameter ()) ; System.out.println ( "Exit call 1" ) ; returnState () ; break ; // --- Call 2 ----- case call2: System.out.println ( "Entering call 2" ) ; callState ( call1, "test 2", call2a ) ; break ; case call2a: System.out.println ( "Done with call 2" ) ; returnState () ; break ; // ---- End of program --- default: // 異常の状態を検知した場合終了する case terminate: System.out.println ( "All done" ) ; stop () ; break; } } public static void main() { new MutlitaskingTest4 () ; Task.TaskManager () ; System.out.println ( "No more tasks running" ) ; } } |
タスク内通信 |
---|
Javaのスレッドでは、JavaはJavelinではサポートされていない自分自身のタスク内通信サービスを持っています。Semaphoreクラスは標準のJavaでは実装することはできますが、他のメソッドは普通使いません。 |
Semaphoreクラス |
---|
/* * Semaphore class * * 資源をコントロールするタスクによって用いられる。 * 一度に一つのタスクによって取得することができる。 * 続いて起こるタスクは中断されセマフォリストに加えられる */ package stamp.util.os; import stamp.util.*; /** * タスクオブジェクトに対しての標準的なセマフォサポート * ready状態から開始する */ public class Semaphore extends Event { protected static Semaphore semaphoreList ; protected Semaphore nextSemaphore ; protected Task acquiredTask ; protected Task waitingTaskList ; /** * セマフォオブジェクトを作る */ public Semaphore () { nextSemaphore = semaphoreList ; semaphoreList = this ; acquiredTask = null ; waitingTaskList = null ; } /** * セマフォがreadyかどうかを調べる * * 戻り:取得されるセマフォがreadyならばtrue */ public boolean ready () { return ( acquiredTask == null ) ; } /** * セマフォを取得する。タスクの次の状態を設定する * * この作用を実現するにはタスクはexecute()を抜けなければならない * もしそのタスクがセマフォを条件付で取得しなければならないならば * ready()を用いる。 * もしセマフォがreadyでなかったならば、task.suspend()を実行せよ * もしセマフォが取得できたら実行が続けられる。 * これはもし可能ならばあるアクションを実行した後でセマフォをすぐに * タスクが解放することを許します。適切にnextStateを設定する。 * release()に一つ以上一致することはないことを念頭に入れよ。 * 例: * case 9: // これはいつもコントロールを与える * semaphore.acquire(11); * break; * case 10: // もし取得されなかったらなばコントロールを与える * if ( semaphore.acquire(11)) * break; * case 11: * // 何かをする * semaphore.relese() ; * nextState(12); * break ; * * 戻り:もしセマフォが取得されたならばfalse * もし中断(suspend)だったらtrue */ public boolean acquire ( int nextState ) { Task currentTask = Task.currentTask ; // static protected // 次の状態に行かせる currentTask.nextState ( nextState ) ; if ( ready ()) { acquiredTask = Task.currentTask ; return false ; } // 実行リスト()からタスクを削除する if ( ! currentTask.suspend ()) { return true ; // タスクがすでにsuspendしていた。 } // タスクはセマフォ待ちと表す。 currentTask.taskStatus = Task.taskSemaphoreWait ; // final int // 待ちリストにタスクを加える if ( waitingTaskList == null ) { // リストが空だった waitingTaskList = Task.currentTask ; } else { // リストの最後に付け加える // 注意: task.nextTask はnullであるべき Task lastTask = waitingTaskList ; // リストの最後に移動 while ( lastTask.nextTask != null ) lastTask = lastTask.nextTask ; // リストの最後にタスクを追加する lastTask.nextTask = Task.currentTask ; // static protected Task.currentTask.nextTask = null ; // 丁度この場合 } return true ; } /** * セマフォの解放。一つが待っていれば次のタスクを開始する * 解放するタスクはそれをする事が許可されていると仮定する */ public void release () { if ( waitingTaskList == null ) { acquiredTask = null ; } else { // nextStateセット(集合)でタスクがsuspendしている // 最初の待機タスクをResumeする acquiredTask = waitingTaskList ; waitingTaskList = waitingTaskList.nextTask ; acquiredTask.nextTask = null ; // 仕事をresumeするにはtaskStatusがtaskSuspendedでなければならない acquiredTask.taskStatus = Task.taskSuspended ; // final static acquiredTask.resume () ; } } /** * イベントが起こったときにセマフォを解放する * Semaphoreクラスはnotifyメソッドのみを持っている * イベントクラスに基づいている */ public void notify (Object object) { release () ; } /** * 名前を得る * * 戻り:セマフォの名前を返す */ public String name () { return "Semaphore" ; } } |
割り込みの場合 |
---|
そのタスクがInterruptTaskで割り込みが起こった場合、タスクのexecuteメソッドの次の状態値が割り込みの状態になります。セマフォのacquireメソッド呼び出しで示された状態は次のexecute呼び出しになります。同様に、割り込みの状態はセマフォが取得されるまで入りません。 |
Maltitasking Test 5 - セマフォのデモ |
---|
import stamp.core.*; import stamp.util.os.*; /** * Multitasking Test 5 - セマフォのデモ */ public class MutlitaskingTest5 extends Task { static public Semaphore semaphore = new Semaphore () ; String name ; MutlitaskingTest5 ( String name ) { this.name = name ; } public void show ( String text ) { System.out.print ( name ) ; System.out.print ( ": " ) ; System.out.println ( text ) ; } // execute()の状態 final static int state1 = 1 ; final static int state2 = 2 ; final static int state3 = 3 ; protected void execute () { switch ( state ) { case initialState: show ( "Initial state - acquire semaphore" ) ; semaphore.acquire ( state1 ) ; break ; case state1: show ( "State 1 - semaphore acquired" ) ; sleep(state2,1000) ; // 待機(wait)して状態2に行く break ; case state2: show ( "State 2 - done sleeping" ) ; show ( "Releasing semaphore" ) ; semaphore.release () ; stop () ; break ; default: // 異常の状態を検知した場合終了する stop () ; break; } } public static void main() { new MutlitaskingTest5 ( "Task 1" ) ; new MutlitaskingTest5 ( "Task 2" ) ; new MutlitaskingTest5 ( "Task 3" ) ; // 各々のタスクはセマフォを取得を試みる // タスクは少しの期間待機する // そして、セマフォを解放し終了する。 Task.TaskManager () ; System.out.println ( "All done" ) ; } } |
MultitaskingJBotクラス |
---|
package JBot ; import stamp.core.*; import stamp.util.os.*; /** * MultitaskingJBot クラス * * マルチタスクシステムを用いてJ-Botを走らせるプログラム */ public class MultitaskingJBot extends Task { protected JBotInterface jbot ; static final int checkMovement = 1 ; /** * J-Botオブジェクトを監視するためにセットアップする */ public void notify ( Object jbotInterface ) { jbot = (JBotInterface) jbotInterface ; nextState(checkMovement); resume () ; } /** * タスクを実行するメソッド */ protected void execute () { switch ( state ) { case checkMovement: if (jbot.movementDone()) { // 動作が終了したためタスクを停止する stop () ; } break; case initialState: default: // defaultは異常な状態を捕獲する stop () ; break; } } } |
MultitaskingJBotクラスをテストする |
---|
import stamp.core.*; import stamp.util.os.* ; import JBot.* ; /** * MultitaskingJBotクラスをテストする * * BasicMultitaskingJBotのクラスメソッドを用いてJ-Botを * 走らせるプログラム */ public class MultitaskingJBotTest1 extends Task { JBotInterface jbot = new RampingJBot ( new MultitaskingJBot ()) ; protected void execute () { switch ( state ) { case initialState: jbot.move ( 2 ) ; nextState ( 1 ) ; // 完了のためpollすることが必要 break; case 1: if ( jbot.movementDone ()) { // Non-polled version. // 動作が終わるまでタスクはsuspendになる jbot.pivot ( -2 ) ; jbot.wait ( 2 ) ; // 終わるまでこのタスクはsuspendする } break; case 2: jbot.turn ( 1 ) ; // 短い回転をさせる jbot.wait ( 3 ) ; // 終わるまでこのタスクはsuspendする break; case 3: jbot.stop(); // 待機しないでバックグラウンド // タスクが走る default: // 異常な状態を捕獲 stop () ; break; } } public static void main () { new MultitaskingJBotTest1 () ; Task.TaskManager () ; System.out.println ( "All done" ) ; } } |
基本的なアブストラクト型のsensorクラス |
---|
package JBot; import stamp.util.os.* ; /** * 基本的なアブストラクト型のsensorクラス * * センサー情報にアクセスするための標準メソッド * 通常センサーは変化が起こったときにイベントを通知します。 * 多くの場合イベントは障害物を検出するために待機するようなタスク * * 検出は180度前方であることを仮定する * 前方位置は90度である。 * 最左は0度、左は45度である。 */ public abstract class BaseSensor { protected Event event = Event.nullEvent ; protected boolean ready = true ; /** * 範囲: 障害物は検出されていない */ static final int none = -1 ; /** * 検出: 障害物は左 */ static final int left = 45 ; /** * 検出: 障害物は右 */ static final int right = 135 ; /** * 検出: 障害物は前 */ static final int front = 90 ; /** * obstacleDetectedが呼ばれることができるかどうかを示す * * 戻り:boolean: 可能ならばtrue */ public boolean ready () { return ready ; } /** * 障害物が検出されたかどうか示す * 通常、ポーリング対イベント使用のときに用いられる * * 戻り:boolean */ public abstract boolean obstacleDetected () ; /** * 初期障害物位置を示す * 単純な検出システムに対して左と右の物体検出は前方を返す * * 戻り:障害物の相対的方向 (left, right, etc.) */ public abstract int obstacleDirection () ; /** * 指定された方向にある障害物の距離を得る。 * 値noneは障害物が無いことを表す * * 入力:int direction: 探したい方向 * * 戻り:指定された方向に対する障害物までの距離 */ public abstract int obstacleDistance ( int direction ) ; /** * イベントの最小報告距離を設定する * この距離の外側での障害物は報告は起こらない * 最小値は0である。 * * 入力:int minimumDistance:障害物を検出する最少数(インチ) */ public void setMinimumEventDistance () { /* デフォールトの場合最小距離は無視する * 例えば、接触方向センサーは接触したときにだけ物体を検出できる。 */ } // このクラスあるいはサブクラスでの使用のためProtectedクラスにする /** * 報告イベントを設定する * * 入力:Event event: 変化が起こったときに報告するEventオブジェクト */ public void setEvent ( Event event ) { this.event = Event.checkEvent(event) ; } /** * 障害物のステータスが変化したときにイベントを生じる * サブクラスのメソッドによって呼ばれる */ protected void notify () { notify (null) ; } /** * 障害物のステータスが変化したときにイベントを生じる * サブクラスのメソッドによって呼ばれる */ protected void notify (Object object) { event.notify (this) ; } } |
Random sensorクラス |
---|
package JBot; import stamp.util.os.* ; import java.util.* ; // Randomクラスのため /** * Random sensorクラス * * このセンサーはランダム障害物情報を発生する * 確かめられたときに障害物情報の変化でのみ動作する * 方向と距離はランダムである */ public class RandomSensor extends BaseSensor { protected int direction ; protected int distance ; protected Random generator = new Random () ; /** * 0とlimitの間の乱数を発生する * * 入力:int limit: 乱数の最大値 * * 戻り:int 検出された障害物 */ protected int random ( int limit ) { int result = generator.next () / (Random.MAX_RAND/(limit+1)) ; return ( result > limit ) ? ( result - 1 ) : result ; } /** * 障害物が検出されたかどうか示す * 通常、確認対イベント使用のときに用いられる * * 戻り:boolean */ public boolean obstacleDetected () { if ( random ( 9 ) == 0 ) { // 障害物は1:10 で発見される direction = random(4)*45 ; // 0-180の値 distance = random(10) ; notify () ; return true ; } else { // 何も検出されない。保存された値をリセットする。 direction = 0 ; distance = none ; return false ; } } /** * 初期障害物位置を示す * 単純な検出システムに対して左と右の物体検出は前方を返す * * 戻り:障害物の相対的方向 (left, right, etc.) */ public int obstacleDirection () { return direction ; } /** * 指定された方向にある障害物の距離を得る。 * 値noneは障害物が無いことを表す * * 入力:int direction: 探したい方向 * * 戻り:指定された方向に対する障害物までの距離 */ public int obstacleDistance ( int direction ) { return distance ; } /** * イベントの最小報告距離を設定する * この距離の外側での障害物は報告は起こらない * 最小値は0である。 * * 入力:int minimumDistance:障害物を検出する最少数(インチ) */ public void setMinimumEventDistance () { /* デフォールトの場合最小距離は無視する * 例えば、接触方向センサーは接触したときにだけ物体を検出できる。 */ } } |
単純な障害物回避タスク |
---|
package JBot; import stamp.util.os.* ; /** * 単純な障害物回避タスク * * センサーオブジェクトを用いて障害物から離れているように試みる * J-Botは固定の増加量で移動する */ public class AvoidObstacleTask extends Task { JBotInterface jbot ; BaseSensor sensor ; public AvoidObstacleTask ( BaseSensor sensor, JBotInterface jbot ) { this.sensor = sensor ; this.jbot = jbot ; } protected void execute () { final int turnAround = 1 ; switch ( state ) { case initialState: if ( sensor.obstacleDetected ()) { int direction = sensor.obstacleDirection () ; if ( sensor.obstacleDistance ( direction ) < 5 ) { // 接近しすぎ、5センチバックして回転する jbot.move ( -5 ) ; jbot.wait ( turnAround ) ; } else { // オブジェクトから離れて旋回する十分な領域 if ( direction < 75 ) { // 左に何かがある jbot.pivot ( -2 ) ; } else { // 前か左に何かある jbot.pivot ( 2 ) ; } jbot.wait ( turnAround ) ; } } else { // 何もない。2センチ前に移動する。 jbot.move ( 2 ) ; jbot.wait ( initialState ) ; } break; case turnAround: // J-Botを後退させる。180度旋回させる時間 jbot.pivot ( 4 ) ; jbot.wait ( initialState ) ; break; default: // デフォールトは異常な状態を捕獲する stop () ; break; } } } |
AvoidObjstacleTaskクラスのテスト |
---|
import stamp.core.*; import stamp.util.os.* ; import JBot.* ; /** * AvoidObjstacleTaskクラスのテスト * * 障害物を避けるようにJ-Botを回転させる */ public class AvoidObstacleTaskTest1 { public static void main () { new AvoidObstacleTask ( new RandomSensor () , new RampingJBot ( new MultitaskingJBot ())) ; Task.TaskManager () ; System.out.println ( "All done" ) ; } } |
マルチタスクのステータスをサポートするクラス |
---|
package stamp.util.os; import java.io.* ; import stamp.core.* ; /** * マルチタスクのステータスをサポートするクラス * このクラスはオブジェクトのみ */ public class ShowStatus { static public PrintStream stream = System.out ; protected static void print ( Event event ) { stream.print ( "<") ; stream.print ( event.name ()) ; stream.print ( "> ") ; } protected static void print ( int value ) { stream.print ( value ) ; } protected static void print ( String string ) { stream.print ( string ) ; } protected static void println ( String string ) { stream.println ( string ) ; } protected static void println () { stream.println ( " " ) ; } } |
マルチタスクのステータスを表示する |
---|
package stamp.util.os; import java.io.* ; import stamp.core.* ; /** * マルチタスクのステータスを表示する * * アクティブタスクとフリーメモリを表示する * これはクラスオブジェクトのみ */ public class TaskStatus extends ShowStatus { protected TaskStatus () { // オブジェクトの生成を防ぐ } protected static void printTaskStatus ( int taskStatus ) { switch ( taskStatus ) { case Task.taskRunning: print ( "Running " ) ; break ; case Task.taskSuspended: print ( "Suspended " ) ; break ; case Task.taskSemaphoreWait: print ( "Semaphore " ) ; break ; default: print ( "-- Unknown status -- " ) ; break ; } } protected static void printStateName ( int state ) { switch ( state ) { case Task.initialState: print ( "initial " ) ; break ; case Task.checkTimer: print ( "sleeping" ) ; break ; case Task.interrupt: print ( "interrupt" ) ; break ; case Task.terminate: print ( "terminate" ) ; break ; case Task.stopped: print ( "stopped " ) ; break ; default: print ( state ) ; break ; } } /** * メモリーのステータスを書き出す */ public static void printMemoryStatus () { print ( Memory.freeMemory ()) ; println ( " bytes free" ) ; } /** * タスクのステータスを書き出す */ public static void printTaskStatus ( Task task ) { print ( task ) ; printTaskStatus ( task.taskStatus ) ; printStateName ( task.state ) ; println () ; } /** * タスクのリストを書き出す * * 入力:String prefix: タスクのリストの前に書く * 入力:boolean running; もし走っているタスクをリストする場合にtrue */ public static void printTasks ( String prefix, boolean running ) { println ( prefix ) ; for ( Task task = Task.taskStatusList ; task != null ; task = task.nextTaskStatus ) { if ( task.taskStatus() == task.taskRunning ) { print ( " " ) ; printTaskStatus ( task ) ; } } } /** * 全てのタスクの詳細な説明をする * */ public static void show () { Task task = Task.taskList ; println ( "== Task Status ==" ) ; printMemoryStatus () ; printTasks ( "Tasks running", true ) ; printTasks ( "Tasks not running", false ) ; if ( task == null ) { println ( "-- Empty task list --" ) ; } else { // Check taskList integrity do { task = task.nextTask ; if ( task == null ) { println ( "== Error: Task list not circular ==" ) ; break ; } } while ( Task.taskList != task ) ; } println () ; } } |
マルチタスクのステータスを表示する |
---|
package stamp.util.os; import java.io.* ; import stamp.core.* ; /** * マルチタスクのステータスを表示する * * アクティブタスクとフリーメモリを表示する * これはクラスオブジェクトのみ */ public class SemaphoreStatus extends ShowStatus { protected SemaphoreStatus () { // オブジェクトの生成を防ぐ } /** * セマフォ情報を含んだタスクステータスを書き出す */ public static void printTaskStatus ( Task task ) { // 一般的なステータスを書き出す TaskStatus.printTaskStatus ( task ) ; // 取得したセマフォを書き出す for ( Semaphore semaphore = Semaphore.semaphoreList ; semaphore != null ; semaphore = semaphore.nextSemaphore ) { if ( semaphore.acquiredTask == task ) { print ( " Acquired " ) ; print ( semaphore ) ; println () ; } } // セマフォ待ちステータスを書き出す for ( Semaphore semaphore = Semaphore.semaphoreList ; semaphore != null ; semaphore = semaphore.nextSemaphore ) { for ( Task waitingTask = semaphore.waitingTaskList ; waitingTask != null ; waitingTask = waitingTask.nextTask ) { if ( waitingTask == task ) { print ( " Waiting for " ) ; print ( semaphore ) ; println () ; } } } } /** * 全てのセマフォの詳細な説明をする */ public static void show () { println ( "== Semaphore Status ==" ) ; for ( Semaphore semaphore = Semaphore.semaphoreList ; semaphore != null ; semaphore = semaphore.nextSemaphore ) { print ( semaphore ) ; if ( semaphore.ready ()) { println ( "ready" ) ; } else { print ( "acquired by " ) ; print ( semaphore.acquiredTask) ; println () ; if ( semaphore.acquiredTask.state == Task.stopped ) { println ( " ** Error: Task stopped **" ) ; } println ( " Waiting tasks" ) ; for ( Task task = semaphore.waitingTaskList ; task != null ; task = task.nextTask ) { print ( " " ) ; print ( task ) ; println () ; } } } println () ; } } |
ヒープ空間を監視するクラス |
---|
package stamp.util.os; import stamp.core.*; import stamp.util.os.*; /** * ヒープ空間を監視するクラス * * 全てのメモリーが割り当てられた後でこのタスクを開始する * フリーメモリーを追跡し、変化を報告する。 */ public class WatchHeapTask extends Task { protected int freeMemory = 0 ; protected boolean enable = true ; public Event event ; /** * WatchHeapTaskを作る * System.outにエラーを報告する */ public WatchHeapTask () { } /** * Control error checking */ public void enable ( boolean enableNow ) { enable = enableNow ; if ( enableNow ) { freeMemory = 0 ; } } /** * タスク名を返す */ public String name () { return "WatchHeap" ; } /** * WatchHeapTaskを作る * イベントを通知することによりエラーを報告する * * 入力け:Event event:ヒープが成長したときに通知するイベント */ public WatchHeapTask ( Event event ) { this.event = event ; } protected void execute () { /* Memory.freeMemoryはスタック位置依存である * 一貫性のある情報を与えるために同じ位置で呼ばれる必要がある */ int latestFreeMemory = Memory.freeMemory () ; // このタスクだけが走っているならば終了する if ( nextTask == this ) { stop () ; return ; } if ( enable ) { if ( freeMemory == 0 ) { freeMemory = latestFreeMemory ; } else if ( freeMemory != latestFreeMemory ) { // Memory usage has increased (cannot decrease) if ( event == null ) { System.out.println ( "Error: Memory leak" ) ; System.out.print ( " Last: " ) ; System.out.println ( freeMemory ) ; System.out.print ( " Now: " ) ; System.out.println ( latestFreeMemory ) ; } else { event.notify () ; } // Reset low water mark freeMemory = latestFreeMemory ; } } } } |
MutlitaskingTest6 |
---|
import stamp.core.*; import stamp.util.os.*; /** * MutlitaskingTest6 */ public class MutlitaskingTest6 extends Task { // execute() states final static int state1 = 1 ; final static int state2 = 2 ; final static int state3 = 3 ; static Semaphore semaphore = new Semaphore () ; String name ; MutlitaskingTest6 ( String name ) { this.name = name ; } /** * タスク名を得る * * 戻り: タスク名 */ public String name () { return name ; } public void show ( String text ) { System.out.print ( name ) ; System.out.print ( ": " ) ; System.out.println ( text ) ; } protected void execute () { switch ( state ) { case initialState: show ( "Initial state" ) ; nextState ( state1 ) ; break ; case state1: show ( "State 1" ) ; new Integer ( 0 ) ; // memory leak !!! nextState ( state2 ) ; break ; case state2: show ( "State 2" ) ; if ( ! semaphore.acquire ( state3 )) { stop () ; } break ; case state3: show ( "State 3" ) ; default: // おかしな状態を捕獲した場合はデフォールトで終了 stop () ; break; } } public static void main() { Task task1 = new MutlitaskingTest6 ( "Task 1" ) ; Task task2 = new MutlitaskingTest6 ( "Task 2" ) ; Task task3 = new MutlitaskingTest6 ( "Task 3" ) ; Task task4 = new WatchHeapTask () ; // 一般的なステータスを表示 TaskStatus.show () ; SemaphoreStatus.show () ; // タスクを走らせる Task.TaskManager () ; // 一般的なステータスを表示 TaskStatus.show () ; SemaphoreStatus.show () ; // ステータスを表示 SemaphoreStatus.printTaskStatus ( task1 ) ; SemaphoreStatus.printTaskStatus ( task2 ) ; SemaphoreStatus.printTaskStatus ( task3 ) ; SemaphoreStatus.printTaskStatus ( task4 ) ; System.out.println ( "All done" ) ; } } |