4D v14.3Semaphore |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
4D v14.3
Semaphore
|
Semaphore ( semaphore {; tickCount} ) -> 戻り値 | ||||||||
引数 | 型 | 説明 | ||||||
semaphore | 文字 |
![]() |
テストと設定を行うセマフォ | |||||
tickCount | 倍長整数 |
![]() |
最大待ち時間 | |||||
戻り値 | ブール |
![]() |
FALSE: セマフォの設定に成功した TRUE: 既にセマフォが存在する | |||||
セマフォは、ワークステーション (各ユーザのコンピュータ) 間、または同一ワークステーション上のプロセス間で共有されるフラグです。セマフォは、単に存在したり存在しなかったりするだけです。各ユーザが実行しているメソッドでセマフォの存在を調べることができます。セマフォを作成する、またはその存在の有無を調べることにより、ワークステーション間でのメソッドの通信が可能になります。
Semaphore 関数はすでにセマフォが存在する場合TRUEを返し、何も行いません。セマフォが存在しない場合、Semaphore はセマフォを作成しFALSEを返します。同時に1人のユーザしかセマフォを作成することはできません。SemaphoreがFALSEを返すということは、セマフォが存在しなかったことを意味すると同時に、コマンド呼び出したプロセスに対して新たにセマフォ設定されたことを意味します。Semaphoreは、セマフォが設定されていなければFALSEを返します。またコマンドを呼び出したプロセスが既にそのセマフォを設定している場合もFALSEを返します。semaphoreは先頭の$を含めて255文字以内に制限されています。これより長い文字列を指定すると、切り捨てられた文字列を使ってセマフォがテストされます。
オプションの引数tickCountは、semaphoreが既にセットされている時の待ち時間 (tick) を設定します。
この場合、関数はセマフォが解放されるか、またはTRUEを返す前に待ち時間が終了まで待ちます。
4Dには2種類のセマフォ、ローカルセマフォとグローバルセマフォがあります。
グローバルセマフォとローカルセマフォは理論的には同じものです。違いはその有効範囲にあります。
クライアント/サーバーモードでは、グローバルセマフォはすべてのクライアントおよびサーバーで実行しているすべてのプロセス間で共用されます。ローカルセマフォは、それが作成されたマシン上で実行しているプロセス間でのみ共用されます。
スタンドアロンモードの4Dでは、ユーザは一人だけなため、グローバルセマフォもローカルセマフォもその有効範囲は同じです。ただし、シングルとマルチの両方の形でデータベースを使用する場合は、用途によってグローバルセマフォとローカルセマフォを使い分けてください。
注: インターフェースやインタープロセス変数など、クライアントアプリケーションのローカルな状態を管理するためにセマフォを使用する場合、ローカルセマフォを利用することをお勧めします。このようなケースでグローバルセマフォを使用すると、不必要なネットーワークアクセスが行われるだけでなく、不必要に他のクライアントに影響を与えてしまいます。ローカルセマフォを使用すればこのような望ましくない副作用を避けることができます。
セマフォはレコードのアクセスの保護目的には使用しません。これは4Dと4D Serverが自動的に行います。セマフォは、複数のユーザが同じ処理を同時に実行するのを防ぐために用います。
以下の例では、2人のユーザがProducts テーブルの価格を更新するのを防ぎます。以下のメソッドではセマフォを用いて、これを実現しています:
If(Semaphore("UpdatePrices")) ` セマフォの作成を試行
ALERT("Another user is already updating prices. Retry later.")
Else
DoUpdatePrices ` 料金の更新
CLEAR SEMAPHORE("UpdatePrices")) ` セマフォをクリア
End if
以下の例はローカルセマフォを使用します。複数のプロセスを持つデータベースで、To Doリストを管理する必要があるとします。このリストはテーブルではなく、インタープロセス配列で管理します。セマフォを使って同時にアクセスされるのを防ぎます。このような場合に、To Doリストは自分だけのものなため、ローカルセマフォで十分です。
インタープロセス配列はOn Startup データベースメソッドで初期化します:
ARRAY TEXT(<>ToDoList;0) ` The To Do list is initially empty
To Doリストに項目を追加するメソッドを次に示します:
` ADD TO DO LIST project method
` ADD TO DO LIST ( Text )
` ADD TO DO LIST ( To do list item )
C_TEXT($1)
If(Not(Semaphore("$AccessToDoList";300)))
` Wait 5 seconds if the semaphore already exists
$vlElem:=Size of array(<>ToDoList)+1
INSERT IN ARAY(<>ToDoList;$vlElem)
<>ToDoList{$vlElem}:=$1
CLEAR SEMAPHORE("$AccessToDoList") ` Clear the semaphore
End if
どのプロセスからも上記メソッドを呼び出せます。
以下のメソッドは、セマフォーが存在する場合コードを実行せず、呼び出し元メソッドにエラーコードとテキストメッセージを返します。
シンタックス:
$L_Error:=Semaphore_proof(->$T_Text_error)
// セマフォーを使用した保護構造
C_LONGINT($0;$L_MyError)
C_POINTER($1) // エラーメッセージ</p><p>C_TEXT($T_Sema_local;$T_Message)
// メソッド開始
$L_MyError:=0
$T_Sema_local:="$tictac"
If(Semaphore($T_Sema_local;300))
// 300 tickの待ち時間の間に、同じセマフォを作成したプロセスがWe expected 300 ticks but the semaphore
// そのセマフォを解放しなかった場合、ここで停止する
$L_MyError:=-1
Else
// このメソッドは同時に複数プロセスで実行されることがない
// このプロセスでセマフォーを設定したので、
// このプロセスで必ずセマフォーを解放しなければならない
// 処理を行う
...
// セマフォーを解放する
CLEAR SEMAPHORE($T_Sema_local)
End if
If($L_MyError=-1)
$T_Message:="セマフォー "+$T_Sema_local+" が既に設定されていたためコードは実行されませんでした。"
Else
$T_Message:="OK"
End if
$0:=$L_MyError
$1->:=$T_Message // 呼び出し元メソッドはエラーコードとメッセージテキストを受け取る
プロダクト: 4D
テーマ: プロセス (コミュニケーション)
番号:
143
変更: 4D v11 SQL
CLEAR SEMAPHORE
Test semaphore
ランゲージリファレンス ( 4D v12.4)
ランゲージリファレンス ( 4D v11 SQL Release 6)
ランゲージリファレンス ( 4D v14 R3)
ランゲージリファレンス ( 4D v14 R2)
ランゲージリファレンス ( 4D v13.5)
ランゲージリファレンス ( 4D v14.3)
ランゲージリファレンス ( 4D v14 R4)