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

C API は基本的な相互排他ロックを提供します。

type PyMutex

   相互排他ロックです。 "PyMutex" は、ロックされていない状態を表すため
   に 0 で初期化する必要があります。 例えば次のようにします。

      PyMutex mutex = {0};

   "PyMutex" のインスタンスは、コピーしたり移動したりしてはなりません
   。 "PyMutex" は内容とアドレスの両方が意味を持つため、書き込み可能な
   メモリ上の固定された場所に置き続ける必要があります。

   注釈:

     "PyMutex" は現在 1 バイトを占めますが、このサイズは安定した仕様で
     はありません。 将来の Python リリースでは、非推奨の期間を設けずに
     サイズを変更する可能性があります。

   Added in version 3.13.

void PyMutex_Lock(PyMutex *m)
    * Thread safety: Atomic.*

   ミューテックス *m* をロックします。 別のスレッドがすでにロックして
   いる場合、呼び出し元のスレッドはロックが解除されるまでブロックしま
   す。 ブロック中は、*スレッド状態* があれば一時的にデタッチします。

   Added in version 3.13.

void PyMutex_Unlock(PyMutex *m)
    * Thread safety: Atomic.*

   ミューテックス *m* のロックを解除します。 ミューテックスはロックさ
   れていなければなりません。 ロックされていない場合、この関数は致命的
   なエラーを発生させます。

   Added in version 3.13.

int PyMutex_IsLocked(PyMutex *m)
    * Thread safety: Atomic.*

   ミューテックス *m* が現在ロックされていれば 0 以外を、そうでなけれ
   ば 0 を返します。

   注釈:

     この関数はアサーションとデバッグだけを目的としています。 確認した
     直後にロックの状態が変わる可能性があるため、並行処理の制御の判断
     には使わないでください。

   Added in version 3.14.


Python のクリティカルセクション API
===================================

クリティカルセクション API は、*フリースレッドの* CPython のオブジェク
トごとのロックに、デッドロックを避ける層を加えます。 *グローバルインタ
ープリタロック* への依存を置き換えるためのもので、グローバルインタープ
リタロックを持つバージョンの Python では何もしません。

クリティカルセクションは、C API を使う拡張で実装した独自の型のためのも
のです。 "list" や "dict" などの組み込み型の公開 C API は内部でクリテ
ィカルセクションを使っているため、通常はこれらの型に対して使わないでく
ださい。 重要な例外は "PyDict_Next()" で、外側でクリティカルセクション
を開始しておく必要があります。

クリティカルセクションは、実行中のクリティカルセクションを暗黙的に中断
することでデッドロックを避けます。 そのため、"PyMutex" のような従来の
ロックが提供する排他的アクセスとは異なります。 クリティカルセクション
を開始すると、対象のオブジェクトのロックを取得します。 内部で実行する
コードが C API 関数を呼ぶと、クリティカルセクションを中断してそのロッ
クを解放する場合があります。 すると、別のスレッドが同じオブジェクトの
ロックを取得できます。

Python オブジェクトの代わりに "PyMutex" ポインタを受け取る形式もありま
す。 "PyObject" がない状況でクリティカルセクションを開始する場合に使っ
てください。 例えば、"PyObject" を拡張もラップもしていない C の型を扱
うものの、デッドロックを起こす可能性がある形で C API を呼び出す必要が
ある場合です。

注釈:

  2 個のオブジェクトを同時にロックする操作には、
  "Py_BEGIN_CRITICAL_SECTION2" を使う必要があります。 複数のオブジェク
  トを同時にロックするために、クリティカルセクションを入れ子にすること
  は *できません*。 内側のクリティカルセクションが外側のものを中断する
  場合があるためです。 この API は、3 個以上のオブジェクトを同時にロッ
  クする方法を提供しません。

使用例:

   static PyObject *
   set_field(MyObject *self, PyObject *value)
   {
      Py_BEGIN_CRITICAL_SECTION(self);
      Py_SETREF(self->field, Py_XNewRef(value));
      Py_END_CRITICAL_SECTION();
      Py_RETURN_NONE;
   }

上の例では、"Py_SETREF" が "Py_DECREF" を呼び出し、オブジェクトの解放
関数を通じて任意のコードが実行される可能性があります。 ファイナライザ
が実行するコードがブロックして "PyEval_SaveThread()" を呼び出した場合
、 クリティカルセクション API はランタイムによるクリティカルセクション
の一時的な中断を許すことで、再入やロックの順序に起因するデッドロックを
避けます。

Py_BEGIN_CRITICAL_SECTION(op)
    * This macro is available when compiling for the Stable ABI (バー
   ジョン 3.15 より).*

   オブジェクト *op* のロックを取得し、クリティカルセクションを開始し
   ます。

   フリースレッドビルドや Stable ABI 向けのビルドでは、このマクロは次
   のように展開されます。

      {
          PyCriticalSection _py_cs;
          PyCriticalSection_Begin(&_py_cs, (PyObject*)(op))

   デフォルトのビルドでは、このマクロは "{" に展開されます。

   Added in version 3.13.

Py_BEGIN_CRITICAL_SECTION_MUTEX(m)

   ミューテックス *m* をロックし、クリティカルセクションを開始します。

   フリースレッドビルドでは、このマクロは次のように展開されます。

      {
           PyCriticalSection _py_cs;
           PyCriticalSection_BeginMutex(&_py_cs, m)

   "Py_BEGIN_CRITICAL_SECTION" と異なり、このマクロは引数をキャストし
   ません。 引数は "PyMutex" ポインタでなければなりません。

   デフォルトのビルドでは、このマクロは "{" に展開されます。

   Added in version 3.14.

Py_END_CRITICAL_SECTION()
    * This macro is available when compiling for the Stable ABI (バー
   ジョン 3.15 より).*

   クリティカルセクションを終了し、オブジェクトのロックを解放します。

   フリースレッドビルドや Stable ABI 向けのビルドでは、このマクロは次
   のように展開されます。

          PyCriticalSection_End(&_py_cs);
      }

   デフォルトのビルドでは、このマクロは "}" に展開されます。

   Added in version 3.13.

Py_BEGIN_CRITICAL_SECTION2(a, b)
    * This macro is available when compiling for the Stable ABI (バー
   ジョン 3.15 より).*

   オブジェクト *a* と *b* のロックを取得し、クリティカルセクションを
   開始します。 ロックの順序によるデッドロックを避けるため、常に同じ順
   序 (アドレスが小さいものから) でロックを取得します。

   フリースレッドビルドでは、このマクロは次のように展開されます。

      {
          PyCriticalSection2 _py_cs2;
          PyCriticalSection2_Begin(&_py_cs2, (PyObject*)(a), (PyObject*)(b))

   デフォルトのビルドでは、このマクロは "{" に展開されます。

   Added in version 3.13.

Py_BEGIN_CRITICAL_SECTION2_MUTEX(m1, m2)

   ミューテックス *m1* と *m2* をロックし、クリティカルセクションを開
   始します。

   フリースレッドビルドや Stable ABI 向けのビルドでは、このマクロは次
   のように展開されます。

      {
           PyCriticalSection2 _py_cs2;
           PyCriticalSection2_BeginMutex(&_py_cs2, m1, m2)

   "Py_BEGIN_CRITICAL_SECTION2" と異なり、このマクロは引数をキャストし
   ません。 引数は "PyMutex" ポインタでなければなりません。

   デフォルトのビルドでは、このマクロは "{" に展開されます。

   Added in version 3.14.

Py_END_CRITICAL_SECTION2()
    * This macro is available when compiling for the Stable ABI (バー
   ジョン 3.15 より).*

   クリティカルセクションを終了し、オブジェクトのロックを解放します。

   フリースレッドビルドや Stable ABI 向けのビルドでは、このマクロは次
   のように展開されます。

          PyCriticalSection2_End(&_py_cs2);
      }

   デフォルトのビルドでは、このマクロは "}" に展開されます。

   Added in version 3.13.


低水準のクリティカルセクション API
----------------------------------

C のマクロを使えない場合のために、次の関数と構造体が公開されています。

void PyCriticalSection_Begin(PyCriticalSection *c, PyObject *op)
void PyCriticalSection_End(PyCriticalSection *c)
void PyCriticalSection2_Begin(PyCriticalSection2 *c, PyObject *a, PyObject *b)
void PyCriticalSection2_End(PyCriticalSection2 *c);
    * 次に属します: Stable ABI (バージョン 3.15 より).*

   この節の前半 に示したマクロの展開と同じ形でのみ使ってください。

   *フリースレッド* ではない CPython のビルドでは、これらの関数は何も
   しません。

   Added in version 3.13.

type PyCriticalSection
type PyCriticalSection2
    * 次に属します: Stable ABI (すべてのメンバーを含む) (バージョン
   3.15 より).*

   この節の前半 に示したマクロの展開と同じ形でのみ使ってください。 構
   造体の内容は非公開で、その意味は将来の Python バージョンで変わる可
   能性があります。

   Added in version 3.13.

void PyCriticalSection_BeginMutex(PyCriticalSection *c, PyMutex *m);
void PyCriticalSection2_BeginMutex(PyCriticalSection2 *c, PyMutex *m1, PyMutex *m2);

   この節の前半 に示したマクロの展開と同じ形でのみ使ってください。

   *フリースレッド* ではない CPython のビルドでは、これらの関数は何も
   しません。

   Added in version 3.14.


従来のロック API
================

これらの API は、Python 3.13 で "PyMutex" が導入されたことにより旧式と
なりました。

バージョン 3.15 で変更: これらの API は、"PyMutex" を単純にラップする
ものになりました。

type PyThread_type_lock

   相互排他ロックへのポインタです。

PY_TIMEOUT_T

   long long の *緩やかに非推奨とされた* 別名です。
   "PyThread_acquire_lock_timed()" のタイムアウト引数に使う整数型です
   。

   バージョン 3.15.2 で ソフト非推奨 <Soft deprecated>.

const long long PY_TIMEOUT_MAX

   "PyThread_acquire_lock_timed()" がサポートする最大タイムアウト値で
   、単位はマイクロ秒です。

   注釈:

     "_thread.TIMEOUT_MAX" の単位が秒であることとは異なります。

type PyLockStatus

   タイムアウト付きでロックを取得した結果です。

   enumerator PY_LOCK_FAILURE

      ロックを取得できませんでした。

   enumerator PY_LOCK_ACQUIRED

      ロックを取得しました。

   enumerator PY_LOCK_INTR

      ロックの取得がシグナルで中断されました。

PyThread_type_lock PyThread_allocate_lock(void)
    * 次に属します: Stable ABI.*

   新しいロックを確保します。

   成功するとロックを返します。 失敗すると、例外を設定せずに "0" を返
   します。

   呼び出し元に *アタッチされたスレッド状態* は必要ありません。

   バージョン 3.15 で変更: 常に "PyMutex" を使うようになりました。 以
   前のバージョンでは、オペレーティングシステムが提供するロックを使っ
   ていました。

void PyThread_free_lock(PyThread_type_lock lock)
    * 次に属します: Stable ABI.*

   *lock* を破棄します。 呼び出す際に、どのスレッドもこのロックを保持
   していてはなりません。

   呼び出し元に *アタッチされたスレッド状態* は必要ありません。

PyLockStatus PyThread_acquire_lock_timed(PyThread_type_lock lock, long long microseconds, int intr_flag)
    * 次に属します: Stable ABI.*

   タイムアウト付きで *lock* を取得します。

   ロックを取得するまで *microseconds* マイクロ秒待ちます。 タイムアウ
   トすると "PY_LOCK_FAILURE" を返します。 *microseconds* が "-1" の場
   合は、ロックが解放されるまで無期限に待ちます。

   *intr_flag* が "1" の場合、ロックの取得がシグナルで中断されることが
   あります。 その場合は "PY_LOCK_INTR" を返します。 中断されたときは
   、通常、呼び出し元が "Py_MakePendingCalls()" を呼んで Python コード
   に例外を伝えることが想定されています。

   ロックの取得に成功すると "PY_LOCK_ACQUIRED" を返します。

   呼び出し元に *アタッチされたスレッド状態* は必要ありません。

int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
    * 次に属します: Stable ABI.*

   *lock* を取得します。

   *waitflag* が "1" で、別のスレッドが現在ロックを保持している場合、
   ロックを取得できるまで待ち、常に "1" を返します。

   *waitflag* が "0" で、別のスレッドがロックを保持している場合は、待
   たずに "0" を返します。 他のスレッドがロックを保持していなければ、
   ロックを取得して "1" を返します。

   "PyThread_acquire_lock_timed()" と異なり、ロックの取得がシグナルで
   中断されることはありません。

   呼び出し元に *アタッチされたスレッド状態* は必要ありません。

int PyThread_release_lock(PyThread_type_lock lock)
    * 次に属します: Stable ABI.*

   *lock* を解放します。 *lock* が保持されていない場合、この関数は致命
   的なエラーを発生させます。

   呼び出し元に *アタッチされたスレッド状態* は必要ありません。
