「Chromium」の版間の差分
(Bind) |
|||
1行目: | 1行目: | ||
== About == | == About == | ||
ChromiumはOSSのWebブラウザー。Google Chromeのベースコードになっている。 | ChromiumはOSSのWebブラウザー。Google Chromeのベースコードになっている。 | ||
== Bind == | |||
出典: | |||
* [https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/threading_and_tasks.md Chromium Docs - Threading and Tasks in Chrome] | |||
* [https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/callback.md Chromium Docs - OnceCallback<> and BindOnce(), RepeatingCallback<> and BindRepeating()] | |||
Bindがよく登場するので整理しておく。 | |||
PostTask(FROM_HERE, base::BindOnce(cb, 42)); | |||
cbがコールバック関数。42がコールバックの引数。 | |||
int Floor(float f) { return std::floor(f); } | |||
std::string IntToString(int i) { return base::NumberToString(i); } | |||
base::OnceCallback<int(float)> first =ase::BindOnce(&Floor); | |||
base::OnceCallback<std::string(int)> second =ase::BindOnce(&IntToString); | |||
base::BindOnce/base::BindCallbackでbase::OnceCallback/base::RepeatingCallbackを生成する。 | |||
Callbackに引数がある場合、使用するときの引数となる。Bind時の関数に、その引数受取の存在が必要になる。 | |||
バインド時に引数を設定することができる。その場合、引数の型は空にする。 | |||
void MyFunc(int i, const std::string& str) {} | |||
base::RepeatingCallback<void()> cb =ase::BindRepeating(&MyFunc, 23, "hello world"); | |||
// base::RepeatingClosure cb =ase::BindRepeating(&MyFunc, 23, "hello world"); | |||
cb.Run(); | |||
int Return5() { return 5; } | |||
base::RepeatingCallback<int()> func_cb =ase::BindRepeating(&Return5); | |||
LOG(INFO) << func_cb.Run(); // Prints 5. | |||
バインド時にインスタンスメソッドを指定する場合は第2引数にthisなどのインスタンスを指定する。staticなどインスタンスメソッドでなければ、インスタンス指定はいらない。 | |||
引数が空の場合は、base::OnceClosureと同じ意味になる。 | |||
部分的に引数を指定することもできる。例えば、コールバック呼出し時には引数を使いたいが、割り当て時に引数を指定したい時など。 | |||
void ReadIntFromFile(const std::string& filename, | |||
base::OnceCallback<void(int)> on_read); | |||
void DisplayIntWithPrefix(const std::string& prefix, int result) { | |||
LOG(INFO) << prefix << result; | |||
} | |||
void AnotherFunc(const std::string& file) { | |||
ReadIntFromFile(file, base::BindOnce(&DisplayIntWithPrefix, "MyPrefix: ")); | |||
}; | |||
上記の例だと、コールバックon_readの呼び出し時に引数にintを使用するが、このコールバックの元関数DisplayIntWithPrefixバインド時に第1引数に文字列を設定している。 | |||
RepeatingCallback/BIndRepeatingは何回も実行できるから、std::moveで渡すのではなく、コピー渡しにする必要がある。 | |||
Repeating→Onceにはそのまま暗黙に変換できる。逆はできない。 | |||
BindRepeatingの関数内で、std::moveしたいなら、引数に渡す際にはstd::refにする。違う。こうしないとクラッシュする。 | |||
std::move(cb).Run() | |||
}, base::OwnedRef(std::move(cb)) | |||
この引数が曲者。 | |||
単に変更可能な参照を渡す場合はstd::ref。コピーや既存値の移譲など、値の所有権が必要な場合、base::OwnedRefを使う。 | |||
base::BindRepeating/base::BindOnceは右辺値として渡されると、内部ストレージへパラメーターを移譲する。base::BindOnceは問答無用で移譲するが、base::BindRepeatingはbase::Passedを使用したときだけ。 | |||
base::BindOnceではstd::move/base::BindRepeatingではbase::Passedで1回だけの処理のパラメーターを移譲する。 | |||
* std::move | |||
* base::Passed: base::BIndRepeatingでの1回だけのパラメーターの移譲。 | |||
* base::Owned: コールバック削除時にパラメーターも削除。 | |||
* std::ref: 単に変更可能な参照を渡す場合。 | |||
* base::OwnedRef: コピーや既存値の移譲など、値の所有権が必要な場合。 | |||
* base::Unretained | |||
* base::RetainedRef: 参照を保持し、コールバック実行時に生ポインターを渡す。 | |||
== Debug == | == Debug == |
2023年12月26日 (火) 14:04時点における版
About
ChromiumはOSSのWebブラウザー。Google Chromeのベースコードになっている。
Bind
出典:
- Chromium Docs - Threading and Tasks in Chrome
- Chromium Docs - OnceCallback<> and BindOnce(), RepeatingCallback<> and BindRepeating()
Bindがよく登場するので整理しておく。
PostTask(FROM_HERE, base::BindOnce(cb, 42));
cbがコールバック関数。42がコールバックの引数。
int Floor(float f) { return std::floor(f); } std::string IntToString(int i) { return base::NumberToString(i); } base::OnceCallback<int(float)> first =ase::BindOnce(&Floor); base::OnceCallback<std::string(int)> second =ase::BindOnce(&IntToString);
base::BindOnce/base::BindCallbackでbase::OnceCallback/base::RepeatingCallbackを生成する。
Callbackに引数がある場合、使用するときの引数となる。Bind時の関数に、その引数受取の存在が必要になる。
バインド時に引数を設定することができる。その場合、引数の型は空にする。
void MyFunc(int i, const std::string& str) {}
base::RepeatingCallback<void()> cb =ase::BindRepeating(&MyFunc, 23, "hello world");
// base::RepeatingClosure cb =ase::BindRepeating(&MyFunc, 23, "hello world");
cb.Run(); int Return5() { return 5; }
base::RepeatingCallback<int()> func_cb =ase::BindRepeating(&Return5);
LOG(INFO) << func_cb.Run(); // Prints 5.
バインド時にインスタンスメソッドを指定する場合は第2引数にthisなどのインスタンスを指定する。staticなどインスタンスメソッドでなければ、インスタンス指定はいらない。
引数が空の場合は、base::OnceClosureと同じ意味になる。
部分的に引数を指定することもできる。例えば、コールバック呼出し時には引数を使いたいが、割り当て時に引数を指定したい時など。
void ReadIntFromFile(const std::string& filename,
base::OnceCallback<void(int)> on_read);
void DisplayIntWithPrefix(const std::string& prefix, int result) {
LOG(INFO) << prefix << result;
}
void AnotherFunc(const std::string& file) {
ReadIntFromFile(file, base::BindOnce(&DisplayIntWithPrefix, "MyPrefix: "));
};
上記の例だと、コールバックon_readの呼び出し時に引数にintを使用するが、このコールバックの元関数DisplayIntWithPrefixバインド時に第1引数に文字列を設定している。
RepeatingCallback/BIndRepeatingは何回も実行できるから、std::moveで渡すのではなく、コピー渡しにする必要がある。
Repeating→Onceにはそのまま暗黙に変換できる。逆はできない。
BindRepeatingの関数内で、std::moveしたいなら、引数に渡す際にはstd::refにする。違う。こうしないとクラッシュする。
std::move(cb).Run()
}, base::OwnedRef(std::move(cb))
この引数が曲者。
単に変更可能な参照を渡す場合はstd::ref。コピーや既存値の移譲など、値の所有権が必要な場合、base::OwnedRefを使う。
base::BindRepeating/base::BindOnceは右辺値として渡されると、内部ストレージへパラメーターを移譲する。base::BindOnceは問答無用で移譲するが、base::BindRepeatingはbase::Passedを使用したときだけ。
base::BindOnceではstd::move/base::BindRepeatingではbase::Passedで1回だけの処理のパラメーターを移譲する。
- std::move
- base::Passed: base::BIndRepeatingでの1回だけのパラメーターの移譲。
- base::Owned: コールバック削除時にパラメーターも削除。
- std::ref: 単に変更可能な参照を渡す場合。
- base::OwnedRef: コピーや既存値の移譲など、値の所有権が必要な場合。
- base::Unretained
- base::RetainedRef: 参照を保持し、コールバック実行時に生ポインターを渡す。
Debug
Logging
ChromiumはLOG/DLOGとVLOG/DVLOGの2系統のログ出力マクロが用意されている。それぞれ対応するオプションが異なる。VLOG/DVLOGが新しくて推奨されている。
情報源
- Chromium Docs - Tips for debugging on Linux
- How to enable logging
- base/logging.h - chromium/src - Git at Google
DLOG/DVLOGはis_debug=trueのときのみ有効になる。
- --log-level=0: LOG/DLOGの出力ログの制御。
- --v=0: VLOG/DVLOGの出力ログの制御。
- --enable-logging: is_debug=falseでもログ出力する?
Stacktrace
以下のようなコードでスタックトレースを出力できる (ChromiumOS Docs - How to get a stack trace at runtime for debugging purposes)。
#include "base/logging.h" #include "base/debug/stack_trace.h" LOG(ERROR) << base::debug::StackTrace(); base::debug::StackTrace().Print(); // stderr
CHECK/DCHECK
assert用のマクロがある (Chromium C++ style guide)。
DCHECKはDCHECK_IS_ONがtrueの場合にコンパイルされる。基本はこれを使う。
Option
起動オプションは [content/public/common/content_switches.cc - chromium/src - Git at Google] のソースコードにある。
GN
情報源:
GNはChromiumで採用されているBUILD.gnのビルド設定記述言語。
GN build configuration
情報源: Chromium - GN build configuration。
Chromiumのargs.gnのビルド設定で使用できる設定がいくつかある。
- is_debug=false
- dcheck_always_on=true
- is_component_build
- symol_level
- enable_nacl
- remove_webcore_debug_symbols
- target_cpu
- use_goma
- is_official_build
- is_chrome_branded
Targets
[target] というのがあって、これがビルドグラフのノードになる。一般的には、生成物のバイナリー、ライブラリーを指す。targetは別のtargetに依存する。組み込みのtargetは以下となる。gn help <targettype> で細かい情報を確認できる。
- action
- action_foreach
- bundle_data
- create_bundle
- executable
- group: targetのグループ。
- shared_library
- loadable_module
- source_set: 軽量仮想静的ライブラリー。
- static_library: .lib/.aファイル (source_setを使ったほうがいい)。
templateを使うことでカスタムtargetタイプを作れる。Chromeでは以下のtemplateを使っている。
- component: ビルドタイプに応じたsource_setかshred_library。
Variable
Configs
[configs] は名前付きオブジェクト。ディレクトリーやdefineを含むフラグの集合を指定する。[target] に適用され、依存targetに押し込まれる。
以下のように定義する。
config("myconfig") { includes = [ "src/include" ] defines = [ "ENABLE_DOOM_MELON" ] }
targetへのconfigの適用には以下のようにする。
executable("doom_melon") { configs = [ ":myconfig" ] }
一般的に、configs += “:myconfig” でデフォルトのリストに追記する。
deps
targetにリンクされる依存関係。
Public configs
targetは依存している他のtargetに設定を適用できる。もっとも一般的な例はサードパーティーtargetだ。適切なコンパイルのためのヘッダーのためのdefineやディレクトリーincludeを必要とする。サードパーティーライブラリーと同様に、そのサードパーティーライブラリーを使用するtargetもコンパイルのために、設定を適用したいでしょう。
このために、適用したい設定のconfigを以下のように書く。
config("my_external_library_config") { includes = "." defines = [ "DISABLE_JANK" ] }
それから、以下の記述でこのconfigはpublic configとしてtargetに追加される。これは依存しているtargetと同様にtargetにも両方に適用する。
shared_library("my_external_library") { ... # Targets that depend on this get this config applied. public_configs = [ ":my_external_library_config" ] }
依存targetは、public_depsとしてあなたのtargetに追加することで、他の依存ツリーレベルを前倒しできる。
static_library("intermediate_library") { ... # Targets that depend on this one also get the configs from "my external library". public_deps = [ ":my_external_library" ] }
targetは全依存物にconfigを進められる。all_dependent_configとしての設定のリンク境界に達するまで。これは推奨しない。代わりに、フラグの適用場所の制御にはpublic_depsを使う。
Chromeには、build/buildflag_header.gniのビルドフラグヘッダーシステムがある。コンパイラーdefineのdefineのために。
わかりにくいので整理する。
- public_configs: targetと依存targetの両方に指定したconfigが適用される。
- public_deps: targetと依存targetの両方に指定したtargetのconfigが適用される。
public_configsがconfig同士なのに対し、public_depsはtarget同士になる。基本はpublic_configsだろうか。
sources
target用のソースファイルのリスト。