"selectors" --- 高水準の I/O 多重化
***********************************

バージョン 3.4 で追加.

**ソースコード:** Lib/selectors.py

======================================================================


はじめに
========

このモジュールにより、"select" モジュールプリミティブに基づく高水準か
つ効率的な I/O の多重化が行えます。OS 水準のプリミティブを使用した正確
な制御を求めない限り、このモジュールの使用が推奨されます。

このモジュールは "BaseSelector" 抽象基底クラスと、いくつかの具象実装
("KqueueSelector", "EpollSelector"...) を定義しており、これらは複数の
ファイルオブジェクトの I/O の準備状況の通知の待機に使用できます。以下
では、 "ファイルオブジェクト" は、"fileno()" メソッドを持つあらゆるオ
ブジェクトか、あるいは Raw ファイル記述子を意味します。*ファイルオブジ
ェクト* を参照してください。

"DefaultSelector" は、現在のプラットフォームで利用できる、もっとも効率
的な実装の別名になります: これはほとんどのユーザーにとってのデフォルト
の選択になるはずです。

注釈:

  プラットフォームごとにサポートされているファイルオブジェクトのタイプ
  は異なります: Windows ではソケットはサポートされますが、パイプはされ
  ません。Unix では両方がサポートされます (その他の fifo やスペシャル
  ファイルデバイスなどのタイプもサポートされます)。

参考:

  "select"
     低水準の I/O 多重化モジュールです。


クラス
======

クラス階層:

   BaseSelector
   +-- SelectSelector
   +-- PollSelector
   +-- EpollSelector
   +-- DevpollSelector
   +-- KqueueSelector

以下では、*events* は与えられたファイルオブジェクトを待機すべき I/O イ
ベントを示すビット単位のマスクになります。これには以下のモジュール定数
の組み合わせを設定できます:

   +-------------------------+-------------------------------------------------+
   | 定数                    | 意味                                            |
   |=========================|=================================================|
   | "EVENT_READ"            | 読み込み可能                                    |
   +-------------------------+-------------------------------------------------+
   | "EVENT_WRITE"           | 書き込み可能                                    |
   +-------------------------+-------------------------------------------------+

class selectors.SelectorKey

   "SelectorKey" はそれの下層のファイルディスクリプタ、選択したイベン
   トマスク、および付属データへのファイルオブジェクトの関連付けに使用
   される "namedtuple" です。いくつかの "BaseSelector" メソッドを返し
   ます。

   fileobj

      登録されたファイルオブジェクトです。

   fd

      下層のファイル記述子です。

   events

      このファイルオブジェクトで待機しなければならないイベントです。

   data

      このファイルオブジェクトに関連付けられたオプションの不透明型
      (Opaque) データです。例えば、これはクライアントごとのセッション
      ID を格納するために使用できます。

class selectors.BaseSelector

   "BaseSelector" は複数のファイルオブジェクトの I/O イベントの準備状
   況の待機に使用されます。これはファイルストリームを登録、登録解除、
   およびこれらのストリームでの I/O イベントを待機 (オプションでタイム
   アウト) するメソッドをサポートします。これは抽象基底クラスであるた
   め、インスタンスを作成できません。使用する実装を明示的に指定したい
   、そしてプラットフォームがそれをサポートしている場合は、代わりに
   "DefaultSelector" を使用するか、"SelectSelector" や
   "KqueueSelector" などの一つを使用します。"BaseSelector" とその具象
   実装は *コンテキストマネージャー* プロトコルをサポートしています。

   abstractmethod register(fileobj, events, data=None)

      I/O イベントを監視するファイルオブジェクトをセレクションに登録し
      ます。

      *fileobj* は監視するファイルオブジェクトです。これは整数のファイ
      ル記述子か、"fileno()" メソッドを持つオブジェクトのどちらかにな
      ります。*events* は監視するイベントのビット幅マスクになります。
      *data* は不透明型 (Opaque) オブジェクトです。

      これは新しい "SelectorKey" インスタンスを返します。不正なイベン
      トマスク化ファイル記述子のときは "ValueError" が、ファイルオブジ
      ェクトがすでに登録済みのときは "KeyError" が送出されます。

   abstractmethod unregister(fileobj)

      ファイルオブジェクトのセレクション登録を解除し、監視対象から外し
      ます。ファイルオブジェクトの登録解除はそのクローズより前に行われ
      ます。

      *fileobj* は登録済みのファイルオブジェクトでなければなりません。

      関連付けられた "SelectorKey" インスタンスを返します。*fileobj*
      が登録されていない場合 "KeyError" を送出します。*fileobj* が不正
      な場合 (例えば *fileobj* に "fileno()" メソッドが無い場合や
      "fileno()" メソッドの戻り値が不正な場合) "ValueError" を送出しま
      す。

   modify(fileobj, events, data=None)

      登録されたファイルオブジェクトの監視されたイベントや付属データを
      変更します。

      より効率的に実装できる点を除けば、
      "BaseSelector.unregister(fileobj)()" に続けて
      "BaseSelector.register(fileobj, events, data)()" を行うのと等価
      です。

      新たな "SelectorKey" インスタンスを返します。 イベントマスクやフ
      ァイル記述子が不正な場合は "ValueError" を、ファイルオブジェクト
      が登録されていない場合は "KeyError" を送出します。

   abstractmethod select(timeout=None)

      登録されたいくつかのファイルオブジェクトが準備できたか、タイムア
      ウトするまで待機します。

      "timeout > 0" の場合、最大待機時間を秒で指定します。 "timeout <=
      0" の場合、この関数の呼び出しはブロックせず、 現在準備できている
      ファイルオブジェクトを報告します。 *timeout* が "None" の場合、
      監視しているファイルオブジェクトの一つが準備できるまでブロックし
      ます。

      この関数は "(key, events)" タプルのリストを返します。準備できた
      ファイルオブジェクトにつき1タプルです。

      *key* は準備状態のファイルオブジェクトに対応する "SelectorKey"
      インスタンスです。 *events* はそのファイルオブジェクトで準備が完
      了したイベントのビットマスクです。

      注釈:

        このメソッドは、現在のプロセスで信号を受信した場合、どのファイ
        ルオブジェクトも準備完了にならないうちに、またはタイムアウトが
        経過する前に返ることがあります。その場合、空のリストが返されま
        す。

      バージョン 3.5 で変更: このセレクタは、シグナルによって中断され
      た時に、シグナルハンドラが例外を起こさなかった場合、空のイベント
      リストを返すのではなく、再計算されたタイムアウトによってリトライ
      するようになりました (この論拠については **PEP 475** を参照して
      ください)。

   close()

      セレクタを閉じます。

      下層のリソースがすべて解放されたことを確かめるために呼ばれなけれ
      ばなりません。一旦閉じられたセレクタは使ってはいけません。

   get_key(fileobj)

      登録されたファイルオブジェクトに関連付けられたキーを返します。

      そのファイルオブジェクトに関連付けられた "SelectorKey" インスタ
      ンスを返します。そのファイルオブジェクトが登録されていない場合
      "KeyError" を送出します。

   abstractmethod get_map()

      ファイルオブジェクトからセレクタキーへのマッピングを返します。

      これは、登録済みのファイルオブジェクトを、それらに関連づけられた
      "SelectorKey" インスタンスにマッピングする "Mapping" のインスタ
      ンスを返します。

class selectors.DefaultSelector

   デフォルトの selector クラスで、現在のプラットフォームで利用できる
   最も効率的な実装を使用しています。大半のユーザはこれをデフォルトに
   すべきです。

class selectors.SelectSelector

   "select.select()" を基底とするセレクタです。

class selectors.PollSelector

   "select.poll()" を基底とするセレクタです。

class selectors.EpollSelector

   "select.epoll()" を基底とするセレクタです。

   fileno()

      下層の "select.epoll()" オブジェクトが使用しているファイル記述子
      を返します。

class selectors.DevpollSelector

   "select.devpoll()" を基底とするセレクタです。

   fileno()

      下層の "select.devpoll()" オブジェクトが使用しているファイル記述
      子を返します。

   バージョン 3.5 で追加.

class selectors.KqueueSelector

   "select.kqueue()" を基底とするセレクタです。

   fileno()

      下層の "select.kqueue()" オブジェクトが使用しているファイル記述
      子を返します。


使用例
======

簡単なエコーサーバの実装です:

   import selectors
   import socket

   sel = selectors.DefaultSelector()

   def accept(sock, mask):
       conn, addr = sock.accept()  # Should be ready
       print('accepted', conn, 'from', addr)
       conn.setblocking(False)
       sel.register(conn, selectors.EVENT_READ, read)

   def read(conn, mask):
       data = conn.recv(1000)  # Should be ready
       if data:
           print('echoing', repr(data), 'to', conn)
           conn.send(data)  # Hope it won't block
       else:
           print('closing', conn)
           sel.unregister(conn)
           conn.close()

   sock = socket.socket()
   sock.bind(('localhost', 1234))
   sock.listen(100)
   sock.setblocking(False)
   sel.register(sock, selectors.EVENT_READ, accept)

   while True:
       events = sel.select()
       for key, mask in events:
           callback = key.data
           callback(key.fileobj, mask)
