https://www.chromium.org/developers/coding-style/important-abstractions-and-data-structures

TaskRunnerSequencedTaskRunnerSingleThreadTaskRunner

base::CallbacksのタスクをTaskRunnerで実行するためのインターフェース。TaskRunnerは実行を保証しない(順序、同期、または全く実行されないなど)。SequencedTaskRunnderは実行の順序をあるていど保証する(大まかにいえばFIFO、でも詳細はコードを見て)。SingleThreadTaskRunnerSequencedTaskRunnerと同じくらい保証するが、すべてのタスクは同じスレッドで行われる。MessageLoopProxyは規範的なSingleThreadTaskRunnerの実例。これらのインターフェースは独立性投入経由でテストをするのに役立つ。注:TaskRunnerのポストに成功したからといって実行されるとは限らない。

注:TaskRunnerのメンバ関数PostTaskAndReply()はとても役に立つ。仕事が終わったら元の人にリプライを返してくれる。

MessageLoopMessageLoopProxyBrowserThreadRunLoop

これらはタスクをポストするための様々なAPI。MessageLoopMessageLoopProxyによって使われる具体オブジェクト(Chromiumでもっとも広く使われるコード)。MessageLoopの代わりにMessageLoopProxyを使うべき、もしchrome/content/のコードの中なら、BrowserThreadを使うことができる。MessageLoopデストラクト時に起こるレーシングも回避している。MessageLoopProxyBrowserThreadは配下のMessageLoopが消えた後はタスクを削除する。注:MessageLoop(Proxy)へのポストが成功したからといって、タスクが実行されるとは限らない。

追記:SequencedTaskRunnerMessageLoopProxy,BrowserThreadをいつ使うべきかには議論がある。インタフェースクァすであるSequencedTaskRunnerはコードをより抽象化・再利用化・テスト可能化する。一方直接性が失われるため、コードが明白でなくなる。具体クラスのBrowserThreadIDは直接的明白で、そのスレッドで実行されることがわかる。もっともSequencedTaskRunner変数を適切に命名することでより明白にはなる。現時点での決定は、必要に応じて、BrowserThreadのコードをTaskRunnerサブクラスに変えていくことのみである。MessageLoopProxySingleThreadTaskRunnerまたはSequencedTaskRunnerインタフェースとしてやり取りされるべきだろうと思われる。

base::SequencedWorkerPoolbase::WorkerPool

Chromiumでの2つの主要なワーカプール。SequencedWorderPoolはもっとも複雑なワーカプールでTaskRunnerから継承し、シーケンスにタスクを処理する方法を提供する(SequenceTokenの共有により)。それからシャットダウン時の動作も指定できる(タスク実行時はシャットダウンをブロック、ブラウザがシャットダウン時はタスクを実行しないか実行していたならシャットダウンをブロック、ブラウザのシャットダウンに関わりなく実行を許可してシャットダウンをブロックしない、など)。 SequencedWorkerPool also provides a facility to return a SequencedTaskRunner based on a SequenceToken. The Chromium browser process will shutdown base::SequencedWorkerPool after all main browser threads (other than the main thread) have stopped. base::WorkerPool is a global object that is not shutdown on browser process shutdown, so all the tasks running on it will not be joined. It's generally unadvisable to use base::WorkerPool since tasks may have dependencies on other objects that may be in the process of being destroyed during browser shutdown.

base::Callbackbase::Bind()

base::Callbackは内部的に参照カウントされたコールバッククラス、可変長引数で任意の戻り値のコールバックに対応。コピー可能だが関数ポインタとバインドされた引数は共有する。base::Bind()は引数と関数ポインタをバインドして(内部では関数ポインタと引数を参照カウンタオブジェクトで管理)base::Callbackを返す。base::Bind()にメンバ関数が渡されたときは魔法のように自動的に最初の引数に対してAddRef()/Release()が実行される。もしそれが参照カウンタオブジェクトでないなら怒られる(これを防ぐにはbase::WeakPtrbase::Unretainedを使う。また引数については、COMPILE_ASSERTを使いそれらが参照カウンタ対象への生ポインタでないかを検証する(forwardされていない完全型情報のときのみ可能)。バグを防ぐためには、scoped_refptrsmake_scoped_refptr()を使うこと。更に、base::Bind()base::WeakPtrを理解している。もし関数がメンバ関数で最初の引数がbase::WeakPtrなら、base::Bind()はラッパ関数を挿入し、WeakPtrがNULLでないときのみ実行する。base::Bind()は引数のために以下のようなヘルパ関数を提供する。

  • base::Unretained()はメンバ関数のオブジェクト(それは参照カウントされていないタイプかもしれない)の参照カウントを無効にし、引数のCOMPILE_ASSERTを無効にする。オブジェクトの生存時間に注意して使うこと。この点base::WeakPtrの方が安全である。
  • base::Owned()は生ポインタのオーナーを戻り値のbase::Callbackストレージに移転する。TaskRunnerはシャットダウン時の実行を保証しないため(そこでオブジェクトを削除したいかもしれない)コールバックが所有権を持てば、シャットダウン時のリークを防げる。
  • base::Passed()は範囲付されたオブジェクト(scoped_ptr/ScopedVector/etc)をコールバックに渡すのに便利。base::Owned()とbase::Passed()の違いは、base::Passed()は関数署名が範囲付された型のパラメータを取ることを要求し、これによりrelease()経由で所有権を移転できる。注意:範囲付タイプの範囲は関数範囲なので、base::Callbackは一度のみ呼ぶことができる。base::Owned()の方を使うべき。
  • base::ConstRef()はコールバックが引数をコピーして保持するのではなくコンスト参照として保持する。パフォーマンス改善が期待できるが、使うべきではない。オブジェクトがコールバックがコールされるまで生存していることを保証しなければならないため。
  • base::IgnoreResult()は関数ポインタをともに使い戻り値を無視する。Closureしか取らないTaskRunnerで使える(Closureは引数を持たず値を返さないもの)。

scoped_refptr<T> & base::RefCounted & base::RefCountedThreadSafe

参照カウントは便利だが、所有権がちゃんと考えられていない場合が多い。所有権が本当に共有されている時に使うこと(例えば、複数のタブが同じレンダラプロセスを共有する時)。オブジェクトの生涯管理が難しいときは使わないこと。

Singleton & base::LazyInstance

これらはグーロバルなので一般的には使用を避けるべき。しかしグローバルを使うときはこれらを使ったほうが良い。base::LazyInstanceの方がSingletonよりもよい。これらのクラスを使う理由は、構築が遅延するからである。これにより初期化時に遅くなることを防止できる。破壊の順番もちゃんと定義されている。破壊は構築の逆順で行われる(AtExitManagerが破壊された時)。Chromiumのブラウザプロセスでは、AtExitManagerはメインスレッド(UIスレッド)でのみインスタンス化されるので、破壊はメインスレッドで行われる(たとえ構築が別スレッドで行われても)。base::LazyInstanceのようが好ましい理由は、データセグメントでスペースを予約しヒープの断片化を避けるからである。注意:Singletonとbase::LazyInstanceの両方とも"leaky"トレイトを提供しシャットダウン時にリークさせることができ、シャットダウン時に動作を遅くしないためにしていできる。valgrindにはこのトレイトに関する抑止機能がある。

base::Thread & base::PlatformThread

タスクはすでに存在しているTaskRunnerにポストするので、一般的にはこれらを使用すべきでない。PlatformThreadはプラットフォーム固有のスレッド。base::ThreadはPlatformThreadで動作するMessageLoopを含む。

base::WeakPtr & base::WeakPtrFactory

ほとんどのスレッドセーフの弱いポインタは参照が破壊されていたならNULLを返す。スレッド間で渡すこともでき他のスレッドで破壊することもできる。しかし通常はそれを作成したスレッドで使うべき。base::WeakPtrFactoryはbase::WeakPtrが破棄されたとき自動でbase::Callbacksをキャンセルする。

FilePath

クロスプラットフォームのファイルパス。プラットフォーム固有の方法は使わずこれを使うべき。

ObserverList & ObserverListThreadSafe

ObserverListはスレッドセーフなオブジェクトで、クラスのメンバ変数として使用されることを想定している。Observerオブジェクトのイテレートを行う簡単なインタフェースを提供するし、通知メソッドを呼び出す。

ObserverListThreadSafeも同様。これは複数のObserverListを保持し、オブザーバ通知はオブザーバが登録されたのと同じPlatformThreadIdで呼び出される。よってスレッド間の通知のプロキシとなり個々のオブザーバにとってはシングルスレッドでオブザーバを扱える。

Pickle

Pickleはオブジェクトの連続化と脱連続化機能を提供する。

Value

Valueは再帰的データクラスで基本型を持つ時使える。JSONへの連続化ができる。

LOG

ログの基本インタフェース

FileUtilProxy

基本的にはファイル操作をjank-sensitiveなスレッド(BrowserThread::UIとBrowserThread::IO)で行うべきではない。他のスレッド(BrowserThread::FILEのような)で行いプロキシにすべきである。

Time, TimeDelta, TimeTicks, Timer

安定したティックカウンタ(Timeはユーザがコンピュータのクロックを変えると変わる)のために一般的にはTimeの代わりにTimeTicksを使うべき。

PrefService, ExtensionPrefs

ユーザプロファイルの永続状態のためのコンテナ

--- Done:2018/09/30 (日) 19:22:43

Page last modified on September 30, 2018, at 07:22 PM
Powered by PmWiki