18.5.7. 同期プリミティブ
************************

**ソースコード:** Lib/asyncio/locks.py

ロック:

* "Lock"

* "Event"

* "Condition"

セマフォ:

* "Semaphore"

* "BoundedSemaphore"

asyncio lock API は "threading" モジュールのクラス ("Lock", "Event",
"Condition", "Semaphore", "BoundedSemaphore") に近くなるよう設計されま
したが、 *timeout* 引数はありません。 "asyncio.wait_for()" 関数を用い
てタイムアオウト後にタスクをキャンセルすることが出来ます。


18.5.7.1. ロック
================


18.5.7.1.1. Lock
----------------

class asyncio.Lock(*, loop=None)

   プリミティブなロックオブジェクトです。

   プリミティブロックは、ロックされたときに特定のコルーチンに所有され
   ない同期プリミティブです。プリミティブロックは 'ロック状態' か 'ア
   ンロック状態' のどちらかの状態になります。

   これはアンロック状態で作成されます。基本メソッド "acquire()" と
   "release()" を持ちます。アンロック状態のとき、acquire() でロック状
   態に変更し直ちに返します。ロック状態のとき、acquire() は、他のコル
   ーチンが release() を呼び出しアンロック状態に変更するまでブロックし
   ます。その後 acquire() はそれをロック状態にして返します。release()
   メソッドはロック状態のとき以外に呼び出してはなりません; これは状態
   をアンロック状態に変更して直ちに返します。アンロック状態でロック解
   除を行おうとすると "RuntimeError" が送出されます。

   1 個以上のコルーチンが acquire() でブロックされ、アンロック状態への
   変更を待っている場合、release() が呼び出されアンロック状態にリセッ
   トされたとき 1 個のコルーチンのみが開始されます; 最初に acquire()
   でプロックされたコルーチンが開始されます。

   "acquire()" はコルーチンであり、"yield from" で呼び出すべきです。

   ロックはコンテキストマネージャープロトコルもサポートしています。コ
   ンテキストマネージャー表現では、"(yield from lock)" のように使用し
   ます。

   このクラスは スレッド安全ではありません。

   使い方:

      lock = Lock()
      ...
      yield from lock
      try:
          ...
      finally:
          lock.release()

   コンテキストマネージャーでの使用法:

      lock = Lock()
      ...
      with (yield from lock):
          ...

   ロックオブジェクトはロック状態か否かを確認できます:

      if not lock.locked():
          yield from lock
      else:
          # lock is acquired
          ...

   locked()

      ロック状態のとき "True" を返します。

   coroutine acquire()

      ロックを獲得します。

      このメソッドはロックが解除されるまでブロックし、ロック状態に変更
      して "True" を返します。

      このメソッドは コルーチン です。

   release()

      ロックを解放します。

      ロックがロック状態のとき、アンロック状態にリセットして返します。
      他のコルーチンがプロックされロック解除を待っている場合、そのうち
      のひとつだけ開始されます。

      アンロック状態のロックに対して呼び出された場合、"RuntimeError"
      が送出されます。

      戻り値はありません。


18.5.7.1.2. Event
-----------------

class asyncio.Event(*, loop=None)

   "threading.Event" と等価で非同期な Event 実装です。

   イベントオブジェクトを実装するクラスです。イベントは "set()" メソッ
   ドで真に設定され、"clear()" メソッドで偽にリセットされるフラグを管
   理します。"wait()" メソッドはフラグが真になるまでブロックします。フ
   ラグの最初の値は偽です。

   このクラスは スレッド安全ではありません。

   clear()

      内部フラグを偽にリセットします。その後 "wait()" を呼んでいるコル
      ーチンは "set()" が呼び出されて内部フラグが真に設定されるまでブ
      ロックします。

   is_set()

      内部フラグが真のとき "True" を返します。

   set()

      内部フラグを真に設定します。それを待っていたすべてのコルーチンが
      再開します。"wait()" を呼び出していたコルーチンへのブロックが解
      除されます。

   coroutine wait()

      内部フラグが真になるまでブロックします。

      入力時に内部フラグが真のとき直ちに "True" を返します。偽のときは
      コルーチンが "set()" を呼び出してフラグが真になるまでブロックし
      、真になった時点で "True" を返します。

      このメソッドは コルーチン です。


18.5.7.1.3. Condition
---------------------

class asyncio.Condition(lock=None, *, loop=None)

   "threading.Condition" と等価で非同期な Condition 実装です。

   このクラスは条件変数オブジェクトを実装しています。条件変数は 1 個以
   上のコルーチンが他のコルーチンから通知を受けるまで待機できるように
   します。

   引数 *lock* に非 "None" が与えられた場合、それは "Lock" オブジェク
   トでなければなりません。これは下層のロックとして使用されます。与え
   られない場合、新しく "Lock" オブジェクトが作成されます。

   このクラスは スレッド安全ではありません。

   coroutine acquire()

      下層でのロックを獲得します。

      このメソッドはロックが解除されるまでブロックし、ロック状態に変更
      して "True" を返します。

      このメソッドは コルーチン です。

   notify(n=1)

      デフォルトでは、この条件を待機しているコルーチンがあればそれが再
      開されます。呼び出したコルーチンがこのロックを獲得していない状態
      でこのメソッドが呼び出されると "RuntimeError" が送出されます。

      このメソッドではこの条件変数を待機しているうち最大で *n* 個のコ
      ルーチンが再開されます; 待機しているコルーチンがなければ何もしま
      せん。

      注釈: そのロックを獲得できるまで、再開されたコルーチンは実際に
        は自身 の "wait()" 呼び出しから復帰しません。"notify()" はロッ
        クの解 除を行わないため、呼び出し元がそれを行わなければなりま
        せん。

   locked()

      下層のロックを獲得していれば "True" を返します。

   notify_all()

      この条件を待機しているすべてのコルーチンを再開します。このメソッ
      ドは "notify()" のように振る舞いますが、1 個ではなくすべてのコル
      ーチンが再開されます。呼び出したコルーチンがロックを獲得していな
      い状態でこのメソッドが呼び出されると "RuntimeError" が送出されま
      す。

   release()

      下層のロックを解除します。

      ロックがロック状態のとき、アンロック状態にリセットされます。他に
      このロックの解除を待機していたコルーチンが存在していた場合、その
      うちの一つが再開されます。

      アンロック状態のロックに対して呼び出された場合、"RuntimeError"
      が送出されます。

      戻り値はありません。

   coroutine wait()

      通知を受けるまで待機します。

      呼び出したコルーチンがロックを獲得していない状態でこのメソッドが
      呼び出されると、"RuntimeError" が送出されます。

      このメソッドは下層のロックを解除し、その後それが他のコルーチンで
      同じ条件変数の "notify()" か "notify_all()" によって再開されるま
      でブロックします。再開されると、再びロックを獲得して "True" を返
      します。

      このメソッドは コルーチン です。

   coroutine wait_for(predicate)

      *predicate* が真になるまで待機します。

      *predicate* は呼び出し可能オブジェクトで、結果がブール値で解析で
      きなければなりません。最終的な *predicate* の結果が戻り値となり
      ます。

      このメソッドは コルーチン です。


18.5.7.2. セマフォ
==================


18.5.7.2.1. Semaphore
---------------------

class asyncio.Semaphore(value=1, *, loop=None)

   Semaphore 実装です。

   セマフォは "acquire()" の呼び出しで減算し、"release()" で加算する内
   部カウンターを管理します。カウンターは負数になることはありません;
   "acquire()" が呼び出されたときにセマフォがゼロであればブロックされ
   、他のコルーチンが "release()" を呼び出すまで待機します。

   セマフォはコンテキストマネージャープロトコルもサポートしています。

   任意の引数 *value* で内部カウンターの初期値を指定できます; デフォル
   トは "1" です。value に "0" 未満の値が指定されると、"ValueError" が
   送出されます。

   このクラスは スレッド安全ではありません。

   coroutine acquire()

      セマフォを獲得します。

      入力時内部カウンターがゼロより大きかった場合、1 減算され、直ちに
      "True" を返します。ゼロだった場合、ブロックされ、他のコルーチン
      が "release()" を呼び出してカウンター値が "0" より大きくなるまで
      待機し、獲得できると "True" を返します。

      このメソッドは コルーチン です。

   locked()

      セマフォを直ちに獲得できない場合 "True" を返します。

   release()

      セマフォを解放し、内部カウンターを 1 加算します。カウンター値が
      ゼロで他のコルーチンが待機状態にあった場合、加算後そのコルーチン
      が再開されます。


18.5.7.2.2. BoundedSemaphore
----------------------------

class asyncio.BoundedSemaphore(value=1, *, loop=None)

   "Semaphore" を継承した有限セマフォの実装です。

   "release()" 内でカウンター値が加算されて引数 *value* を超えると
   "ValueError" を送出します。
