chromium Callback() and Bind()

12654 ワード

文書ディレクトリ
  • 1.0、Introduction
  • 1.1 OnceCallback<> And RepeatingCallback<>
  • 1.2 Memory Management And Passing
  • 2.0 Quick reference for basic stuff
  • 2.1 Binding A Bare Function
  • 2.2 Binding A Captureless Lambda
  • 2.3 Binding A Class Method
  • 2.4 Running A Callback
  • 2.5 Creating a Callback That Does Nothing
  • 2.6 Passing Input Parameters
  • 2.7 Partial Binding Of Parameters (Currying)
  • 2.8 Avoiding Copies With Callback Parameters
  • 3.0 Quick reference for advanced binding
  • 3.1 Binding A Class Method With Weak Pointers
  • 3.2 Binding A Class Method With Manual Lifetime Management
  • 3.3 Binding A Class Method And Having The Callback Own The Class
  • 3.4 Ignoring Return Values
  • 4.0 Quick reference for binding parameters to Bind()
  • 4.1 Passing Parameters Owned By The Callback
  • 4.2 Passing Parameters As A unique_ptr
  • 4.3 Passing Parameters As A scoped_refptr
  • 4.4 Passing Parameters By Reference

  • 1.0、Introduction
    Base::Callback<>とbase::Bind()の組み合わせは、安全なコールバック方法のタイプを提供します.いくつかのパラメータをバインドして関数呼び出しを生成できます.これにより、遅延実行の関数パラメータを渡すことができます.たとえば、chromiumコードでは、異なるスレッド上でタスクをスケジュールしたり、異なるMessageLoops上でタスクをスケジュールしたりします.コールバック関数にパラメータがバインドされていない場合(base::Callback)はbase::Closureにカプセル化されます.ここでは、他の環境とは異なり、閉パッケージへの参照は保持されません.
    1.1 OnceCallback<> And RepeatingCallback<>
    OnceCallback<>はbase::BindOnce()によって作成され、この戻り関数変数は移動タイプのみで、1回しか実行できません.デフォルトでは、バインドパラメータは内部ストレージからバインド関数に移行するため、移動可能なタイプと一緒に使用しやすくなります.コールバック関数には、宣言サイクルが明確であるため、スレッド間の呼び出しがいつ破棄されるかをより容易に判断できるという優れた特性があります.このコールバックを優先し、次にRepeatingCallback
    base::RepeatingCallback<>はbase::BindRepeating()によって作成されており、明らかにこれは繰り返し呼び出すことができるので、破棄された状態であるかどうかなどの問題も判断しにくい.
    1.2 Memory Management And Passing
    base::{Once,Repeating}Callbackの場合、所有権が移転された場合は値が渡され、そうでなければ参照が渡されます.
    // |Foo| just refers to |cb| but doesn't store it nor consume it.
    bool Foo(const base::OnceCallback& cb) {
      return cb.is_null();
    }
    
    // |Bar| takes the ownership of |cb| and stores |cb| into |g_cb|.
    base::RepeatingCallback g_cb;
    void Bar(base::RepeatingCallback cb) {
      g_cb = std::move(cb);
    }
    
    // |Baz| takes the ownership of |cb| and consumes |cb| by Run().
    void Baz(base::OnceCallback cb) {
      std::move(cb).Run(42);
    }
    
    // |Qux| takes the ownership of |cb| and transfers ownership to PostTask(),
    // which also takes the ownership of |cb|.
    void Qux(base::RepeatingCallback cb) {
      PostTask(FROM_HERE, base::BindOnce(cb, 42));
      PostTask(FROM_HERE, base::BindOnce(std::move(cb), 43));
    }
    

    リファレンスを保存する必要がない場合はstd::move()を使用してこのコールバック関数に値を伝えます.そうしないと、オブジェクトが直接渡されます.関数が変数を独占する必要があり、std::move()を使用していない場合、compile errorが得られます.
    コールバック変数はReset()関数を使用すると空になり、id_null()は、コールバックの変数が空であるか否かを判断する.
    2.0 Quick reference for basic stuff
    2.1 Binding A Bare Function
    example 1:
    int Return5() { return 5; }
    base::OnceCallback func_cb = base::BindOnce(&Return5);
    LOG(INFO) << std::move(func_cb).Run();  // Prints 5.
    
    example 2:
    int Return5() { return 5; }
    base::RepeatingCallback func_cb = base::BindRepeating(&Return5);
    LOG(INFO) << func_cb.Run();  // Prints 5.
    

    2.2 Binding A Captureless Lambda
    base::Callback lambda_cb = base::Bind([] { return 4; });
    LOG(INFO) << lambda_cb.Run();  // Print 4.
    
    base::OnceCallback lambda_cb2 = base::BindOnce([] { return 3; });
    LOG(INFO) << std::move(lambda_cb2).Run();  // Print 3.
    

    2.3 Binding A Class Method
    1番目のパラメータは関数で、2番目のパラメータは対応する方法の例です.
    class Ref : public base::RefCountedThreadSafe {
     public:
      int Foo() { return 3; }
    };
    scoped_refptr ref = new Ref();
    base::Callback ref_cb = base::Bind(&Ref::Foo, ref);
    LOG(INFO) << ref_cb.Run();  // Prints out 3.
    

    デフォルトでは、オブジェクトは参照カウントをサポートする必要があります.そうしないと、compile errorが得られます.オンライン・スレッド間で使用する場合は、参照カウント・スレッドのセキュリティを保証する必要があります.参照カウントを使用したくない場合は、以下の「Advanced binding of member function」を参照してください.
    2.4 Running A Callback
    コールバック関数CallbackはRun()関数を呼び出すことができ、コールバック関数と同じパラメータを持つ.注意base::OnceCallback::Run()はコールバックオブジェクトを使用し、右の値のみで呼び出すことができます.
    void DoSomething(const base::Callback& callback) {
      callback.Run(5, "hello");
    }
    
    void DoSomethingOther(base::OnceCallback callback) {
      std::move(callback).Run(5, "hello");
    }
    

    RepeatingCallbacksは複数回実行できます.base::Passedを使用する以外は、以下を参照してください.
    void DoSomething(const base::RepeatingCallback& callback) {
      double myresult = callback.Run(3.14159);
      myresult += callback.Run(2.71828);
    }
    

    RepeatingCallbackには次の問題がありますが、OnceCallbackにはありません.OnceCallbackは常にstd::moveを使用してRun()関数を実行しているからです.
    コールバック関数を実行して自身の破棄を招く場合は、コールバックする前にstd::move、以下のようにします.
    void Foo::RunCallback() {
      std::move(&foo_deleter_callback_).Run();
    }
    

    2.5 Creating a Callback That Does Nothing
    コールバックを開始しても何もする必要はありません(test codeまたはイベントをトリガーするだけです)、デフォルトの構造の同じタイプの過去を伝えることができます.
    using MyCallback = base::OnceCallback;
    void MyFunction(MyCallback callback) {
      std::move(callback).Run(true);  // Uh oh...
    }
    ...
    MyFunction(MyCallback());  // ...this will crash when Run()!
    

    デフォルトの構造Callbackは空なのでRun()は使用できません.base::DoNothing()を使用できます.
    MyFunction(base::DoNothing());  // Can be Run(), will no-op
    

    base::DoNothing()は、voidを返す任意のOnceCallbackおよびRepeatingCallbackに使用できます.bindパラメータを与えようとするとbase::DoNothing()が無効になります.通常、パラメータをDoNothing()にバインドする唯一の理由は、管理オブジェクトの生存期間である.この場合は、DeleteSoon()やReleaseSoon()やRefCountedDeleteOnSequenceのような習慣的な使い方をできるだけ使うべきである.本当にDoNothing()にパラメータをバインドする必要がある場合、オペレータ()の暗黙的な変換ではコンパイルされないため、コールバックオブジェクトを明示的に作成する必要がある場合は、直接インスタンス化できます.
    // Binds |foo_ptr| to a no-op OnceCallback takes a scoped_refptr.
    // ANTIPATTERN WARNING: This should likely be changed to ReleaseSoon()!
    base::Bind(base::DoNothing::Once>(), foo_ptr);
    

    2.6 Passing Input Parameters
    Passing Unbound Input Parameters
    バインドパラメータとバインドされていないパラメータの違いに注意
    void MyFunc(int i, const std::string& str) {}
    base::Callback cb = base::Bind(&MyFunc);
    cb.Run(23, "hello, world");
    

    Passing Bound Input Parameters
    void MyFunc(int i, const std::string& str) {}
    base::Callback cb = base::Bind(&MyFunc, 23, "hello world");
    cb.Run();
    

    コールバックにバインドパラメータがない場合(base::Callback)はbase::Closureと呼ばれ、次の使用方法があります.
    base::Closure cb = base::Bind(&MyFunc, 23, "hello world");
      
    base::Closure cb = base::Bind(&MyClass::MyFunc, this, 23, "hello world");
    

    2.7 Partial Binding Of Parameters (Currying)
    Callbackを使用する場合はパラメータの一部を指定し、コールバックを実行するときに残りのパラメータを指定します.
    void ReadIntFromFile(const std::string& filename,
                         base::OnceCallback 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: "));
    };
    

    この技術はcurryと呼ばれ、バインドパラメータを含むアダプタクラスの代わりに使用されるべきです.上のコードには「MyPrefix:」がconst char*のパラメータがありますが、対応するbindはconst std::string&、ここではタイプ変換が行われています.
    2.8 Avoiding Copies With Callback Parameters
    コールバックパラメータのコピーを使用しないでください.Base::BindOnce()は一般的に移動構造を使用します.
    std::vector v = {1, 2, 3};
    // |v| is moved into the internal storage without copy.
    base::Bind(&Foo, std::move(v));
    
    
    // The vector is moved into the internal storage without copy.
    base::Bind(&Foo, std::vector({1, 2, 3}));
    

    逆に、base::BindRepeating()は、base::Passed()がバインドされている場合にのみstd::moveを使用してターゲットを移動します.base::BindRepeating()とbase::Passed()を使用してbase::BindOnce()の効果を達成することは推奨されません.base::BindOnce()を直接使用するとより良いです.base::Passed()とbase::BindOnce()の併用は避けましょう.std::move()は同じことをしたからです.
    void Foo(std::unique_ptr) {}
    auto p = std::make_unique(42);
    
    // |p| is moved into the internal storage of Bind(), and moved out to |Foo|.
    base::BindOnce(&Foo, std::move(p));
    base::BindRepeating(&Foo, base::Passed(&p)); // Ok, but subtle.
    base::BindRepeating(&Foo, base::Passed(std::move(p))); // Ok, but subtle.
    

    3.0 Quick reference for advanced binding
    3.1 Binding A Class Method With Weak Pointers
    クラスにメンバーがいたらthis_,このように使うことができます
    base::Bind(&MyClass::Foo, weak_this_);
    

    オブジェクトが破棄された場合callbackはRun()にはなりません.ただし、base::WeakPtrsにバインドされたクラスメソッドコールバックは、オブジェクトの削除と競合する場合があるため、オブジェクトを破棄する同じシーケンスでのみ実行できます.
    base::WeakPtrとbase::Bind()を使用するには、MyClassは通常次のように見えます.
    class MyClass {
    public:
      MyClass() {
        weak_this_ = weak_factory_.GetWeakPtr();
      }
    private:
      base::WeakPtr weak_this_;
      // MyClass member variables go here.
      base::WeakPtrFactory weak_factory_{this};
    };
    

    weak_factory_MyClassの最後のメンバー変数なので、まず破棄します.これがweakにバインドされている場合はthis_のクラスメソッドが破棄中にRun()を呼び出すと、実際には実行されません.MyClassがbase::Bind()と同じ実行コールバックのみを呼び出す場合、base::Bind()を呼び出すとweak_が呼び出されます.factory_.GetWeakPtr()は、通常、構築中に個別のweak_を使用するのではなく、安全です.this_.
    3.2 Binding A Class Method With Manual Lifetime Management
    base::Bind(&MyClass::Foo, base::Unretained(this));
    

    これにより、このオブジェクトのすべてのライフサイクルの管理が禁止され、呼び出し中にこのオブジェクトがずっと存在していることを知る必要があります.
    3.3 Binding A Class Method And Having The Callback Own The Class
    MyClass* myclass = new MyClass;
    base::Bind(&MyClass::Foo, base::Owned(myclass));
    

    このオブジェクトはcallbackが破棄されたときに削除され、Run()が呼び出されなくても、シャットダウン時にスレッドプールにタスクを送信したようになります.スマートポインタもこのような状況をサポートしています
    std::unique_ptr myclass(new MyClass);
    base::Bind(&MyClass::Foo, std::move(myclass));
    

    3.4 Ignoring Return Values
    callbackを呼び出す場合がありますが、返される値は必要ありません.このように使用できます.
    int DoSomething(int arg) { cout << arg << endl; }
    base::Callback cb =
        base::Bind(IgnoreResult(&DoSomething));
    

    4.0 Quick reference for binding parameters to Bind()
    パラメータを関数に渡すにはbase::Bind()を使用します.callbackにパラメータがない場合はbase::Closure()と呼ばれ、base::Callbackと同じものです.
    4.1 Passing Parameters Owned By The Callback
    void Foo(int* arg) { cout << *arg << endl; }
    int* pn = new int(1);
    base::Closure foo_callback = base::Bind(&foo, base::Owned(pn));
    

    callbackが破棄されるとrunがなくてもパラメータは削除されます.
    4.2 Passing Parameters As A unique_ptr
    void TakesOwnership(std::unique_ptr arg) {}
    auto f = std::make_unique();
    // f becomes null during the following call.
    base::OnceClosure cb = base::BindOnce(&TakesOwnership, std::move(f));
    

    パラメータの所有権はcallbackに従い、所有権はコールバック関数に渡されます.したがって、これは一度しか実行できません.コールバック関数が実行されていない場合は、callbackが破棄されたときに削除されます.
    4.3 Passing Parameters As A scoped_refptr
    void TakesOneRef(scoped_refptr arg) {}
    scoped_refptr f(new Foo);
    base::Closure cb = base::Bind(&TakesOneRef, f);
    

    This should “just work.” このClosureはライフサイクル中ずっと参照を持っています.
    void DontTakeRef(Foo* arg) {}
    scoped_refptr f(new Foo);
    base::Closure cb = base::Bind(&DontTakeRef, base::RetainedRef(f));
    

    base::RetainedRedはcallbackがRun()を実行するときにオブジェクトの参照を返し、元のポインタ(a raw pointer)をオブジェクトに渡します.
    4.4 Passing Parameters By Reference
    std::refとstd::cref,Example:
    void foo(const int& arg) { printf("%d %p
    ", arg, &arg); } int n = 1; base::Closure has_copy = base::Bind(&foo, n); base::Closure has_ref = base::Bind(&foo, std::cref(n)); n = 2; foo(n); // Prints "2 0xaaaaaaaaaaaa" has_copy.Run(); // Prints "1 0xbbbbbbbbbbbb" has_ref.Run(); // Prints "2 0xaaaaaaaaaaaa"

    一般的に、Closureではパラメータはcopyです.注目すべきは、std::ref and std::crefはreference or const referenceを格納する.これは、callback以外でもライフサイクル内であることを保証する必要があります.