| Semaphore.h | |
|---|---|
#ifndef _SEMAPHORE
#define _SEMAPHORE
#include "Event.h"
#include "Task.h"
#include "common.h"
/*
* Semaphore class
*
* 資源をコントロールするタスクによって用いられる。
* 一度に一つのタスクによって取得することができる。
* 続いて起こるタスクは中断されセマフォリストに加えられる
*/
/**
* タスクオブジェクトに対しての標準的なセマフォサポート
* ready状態から開始する
*/
class Semaphore : public Event
{
protected:
/**
* セマフォオブジェクトを作る
*/
public:
static Semaphore* semaphoreList ;
Semaphore* nextSemaphore ;
Task* acquiredTask ;
Task* waitingTaskList ;
Semaphore ();
/**
* セマフォがreadyかどうかを調べる
*
* 戻り:取得されるセマフォがreadyならばtrue
*/
bool ready ();
/**
* セマフォを取得する。タスクの次の状態を設定する
*
* この作用を実現するにはタスクは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
*/
bool acquire ( int nextState );
/**
* セマフォの解放。一つが待っていれば次のタスクを開始する
* 解放するタスクはそれをする事が許可されていると仮定する
*/
void release ();
/**
* イベントが起こったときにセマフォを解放する
* Semaphoreクラスはnotifyメソッドのみを持っている
* イベントクラスに基づいている
*/
void notify (Object object);
/**
* 名前を得る
*
* 戻り:セマフォの名前を返す
*/
char* name ();
};
#endif
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
| Semaphore.cpp |
|---|
#include "Semaphore.h"
Semaphore* Semaphore::semaphoreList = (Semaphore*)null;
Semaphore::Semaphore () {
nextSemaphore = semaphoreList ;
semaphoreList = this ;
acquiredTask = (Task*)null ;
waitingTaskList = (Task*)null ;
}
bool Semaphore::ready () {
return ( acquiredTask == (Task*)null ) ;
}
bool Semaphore::acquire ( int nextState ) {
Task* _currentTask = Task::currentTask ;
// 次の状態に行かせる
_currentTask->nextState ( nextState ) ;
if ( ready ()) {
acquiredTask = Task::currentTask ;
return false ;
}
// 実行リスト()からタスクを削除する
if ( ! _currentTask->suspend ()) {
return true ; // タスクがすでにsuspendしていた。
}
// タスクはセマフォ待ちと表す。_を付ける
_currentTask->__taskStatus = Task::taskSemaphoreWait ;
// 待ちリストにタスクを加える
if ( waitingTaskList == (Task*)null ) {
// リストが空だった
waitingTaskList = Task::currentTask ;
} else {
// リストの最後に付け加える
// 注意: task.nextTask はnullであるべき
Task* lastTask = waitingTaskList ;
// リストの最後に移動
while ( lastTask->nextTask != (Task*)null ) {
lastTask = lastTask->nextTask ;
}
// リストの最後にタスクを追加する
lastTask->nextTask = Task::currentTask ;
Task::currentTask->nextTask = (Task*)null ;
}
return true ;
}
void Semaphore::release () {
if ( waitingTaskList == (Task*)null ) {
acquiredTask = (Task*)null ;
}
else {
// nextStateセット(集合)でタスクがsuspendしている
// 最初の待機タスクをResumeする
acquiredTask = waitingTaskList ;
waitingTaskList = waitingTaskList->nextTask ;
acquiredTask->nextTask = (Task*)null ;
// 仕事をresumeするにはtaskStatusがtaskSuspendedでなければならない
acquiredTask->__taskStatus = Task::taskSuspended ;
acquiredTask->resume () ;
}
}
void Semaphore::notify (Object object) {
release () ;
}
char* Semaphore::name () {
return "Semaphore" ;
}
|
| 割り込みの場合 |
|---|
| そのタスクがInterruptTaskで割り込みが起こった場合、タスクのexecuteメソッドの次の状態値が割り込みの状態になります。セマフォのacquireメソッド呼び出しで示された状態は次のexecute呼び出しになります。同様に、割り込みの状態はセマフォが取得されるまで入りません。 |
| MultitaskingTest5 |
|---|
#include "Semaphore.h"
#include "common.h"
/**
* Multitasking Test 5 - セマフォのデモ
*/
class MultitaskingTest5 : public Task
{
private:
static const int state1 = 1;
static const int state2 = 2;
static const int state3 = 3;
public:
static Semaphore* semaphore ;
char* name ;
MultitaskingTest5 ( char* name );
void show ( char* text );
protected:
void execute ();
};
|
| MultitaskingTest5.cpp |
|---|
#include "MultitaskingTest5.h"
/**
* Multitasking Test 5 - セマフォのデモ
*/
MultitaskingTest5::MultitaskingTest5 ( char* name )
{
this->name = name ;
state = 0;
semaphore = new Semaphore () ;
}
void MultitaskingTest5::show ( char* text )
{
pc.printf ( "%s", name ) ;
pc.printf ( " : " ) ;
pc.printf ( "%s\n", text ) ;
}
void MultitaskingTest5::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;
}
}
// static
Semaphore* MultitaskingTest5::semaphore ;
|
| main.cpp |
|---|
#include "mbed.h"
#include "MultitaskingTest5.h"
Serial pc(USBTX, USBRX); // tx, rx
int main()
{
pc.baud(115200);
pc.printf("MutlitaskingTest5\n");
new MultitaskingTest5 ( "Task 1" ) ;
new MultitaskingTest5 ( "Task 2" ) ;
new MultitaskingTest5 ( "Task 3" ) ;
// 各々のタスクはセマフォを取得を試みる
// タスクは少しの期間待機する
// そして、セマフォを解放し終了する。
Task::TaskManager () ;
pc.printf( "All done\n" ) ;
}
|
MutlitaskingTest5 Task 3 : ************* Initial state - acquire semaphore Task 1 : ************* Initial state - acquire semaphore Task 2 : ************* Initial state - acquire semaphore Task 3 : ************* State 1 - semaphore acquired Task 3 : ************* State 2 - done sleeping Task 3 : Releasing semaphore Task 1 : ************* State 1 - semaphore acquired Task 1 : ************* State 2 - done sleeping Task 1 : Releasing semaphore Task 2 : ************* State 1 - semaphore acquired Task 2 : ************* State 2 - done sleeping Task 2 : Releasing semaphore All done