目次
はじめに
React hooks の context API、Golang の context パッケージ、Flutter の BuildContext など、度々 context という単語を目にします。
最近 Go 言語による並行処理を読んだので、書籍の内容を引用しつつ、 Context とは何かという自分の考えをまとめます。
Context
コンテキストはある操作がアトミックであると考えられる境界
Go 言語による並行処理
アトミック性
何かがアトミック、あるいはアトミック性があると考えられる場合、それが操作されている特定のコンテキストの中では分割不能、あるいは中断不可であること意味します
では次に「分割不能」と「中断不可」という言葉を見てみましょう。これらはあなたが定めたコンテキストの中で、何かアトミックな処理が起きた場合には、そのコンテキスト全体で処理をしていて、その他の何かが同時には起きていない、という意味です。
Go 言語による並行処理
例として、単純な i をインクリメントする処理(i++
)で考えます。
i++
は、以下の操作に分割できます。
- i の値を取得する
- i の値を 1 増やす
- i の値を保存する
ひとつひとつの操作はアトミックで、分割不可かつ、中断不可です。
これら3つを組み合わせたときに、アトミック性があると思えそうですが、そうではなくコンテキストに依存します。
この一連の処理が main 関数や並行処理で書かれており、i を公開していない場合はアトミック性を持っています。
i が別の場所から書き換えらる場合はアトミック性を持っていません。言い換えると、コンテキストを跨っていると捉えられます。
つまり、アトミック性を強制すること ≒ コンテキストの粒度を考えることとも考えられます。
なぜアトミック性が重要なのか
いつの間にかアトミックの話になっているのですが、何故アトミックを意識する必要があるのかという疑問があります。
簡単にまとめると、論理的に正しい・安全なプログラムを書く一端を担うためです。
仮にコンテキストを跨った処理をしていると、同じ処理をしても違う結果になる可能性(割り込みを受ける)があります。
また、コンテキストを認識をすると、仕様をコードへ落としたときに可読性が上がります。
OSS から Context の例を見てみる
Flutter
BuildContext objects are actually Element objects. The BuildContext interface is used to discourage direct manipulation of Element objects.
BuildContext abstract class(https://api.flutter.dev/flutter/widgets/BuildContext-class.html)
Flutter の BuildContext を見てみると BuildContext を自由に書き換えられず、Element オブジェクトを安全に扱えるものであることがわかります。
context パッケージ(Go)
Context パッケージは並行処理のキャンセルを管理します。また、キャンセルの処理(Done 関数)は Context パッケージの中で定義されています。
使い方としては context を通じてキャンセル処理を行いますが、アトミック性が担保できないときは別の context を生成してそれを使います。
コンテキスト を意識しつつ、並列処理でアトミック性を担保するためのパッケージと理解しました。