2012-04-27 7 views
4

標準std::asyncとスレッド機構を使用できないプログラムがあります。代わりに、私はそうのようなプログラムをコーディングする必要があります。lambdaを非同期コールバックとして使用する

void processor(int argument, std::function<void(int)> callback) { 
    int blub = 0; 

    std::shared_ptr<object> objptr = getObject(); 

    // Function is called later. 
    // All the internal references are bound here! 
    auto func = [=, &blub]() { 
    // !This will fail since blub is accessed by reference! 
    blub *= 2; 

    // Since objptr is copied by value it works. 
    // objptr holds the value of getObject(). 
    objptr->addSomething(blub); 

    // Finally we need to call another callback to return a value 
    callback(blub); 
    }; 

    objptr = getAnotherObject(); 

    // Puts func onto a queue and returns immediately. 
    // func is executed later. 
    startProcessing(func); 
} 

私は今、私はそれが正しいか、どのような非同期コールバックとしてラムダを使用する最善の方法があるやっているかどうかを知っていただきたいと思います。

EDIT:コードコメントに予想される動作を追加しました。 blubの問題の解決方法については、回答/コメントを参照してください。

+1

これはあいまいです。 「Xをやり遂げる最善の方法」などの質問に答えるのは難しいことです。あなたはコールバックとしてラムダを使うことができます。何を知る必要がありますか? – jalf

+0

'blub'がなくなり、labdaが実行されたときにその参照が有効ではないはずです。 –

+0

基本的には、非同期がオブジェクトの存続期間とスコープとどのように機能するかは興味深いでしょう。私が読んだすべての情報は、lambdas synchronousを使用していました - 非同期では何も見つかりません。 – abergmeier

答えて

4

関数オブジェクトには、ローカル変数blubへの参照が含まれます。 他のすべての状況では、言語でと同じように、関数の終了後にローカル変数を有効にしません。

他のすべてのキャプチャされたオブジェクトのコピーは、値によって取り込まれているため、関数オブジェクト内に格納されます。つまり、問題はありません。

関数が終了した後にライブしたい場合は、関数に寿命を結びつけることはできません。動的記憶期間が必要です。 std::unique_ptrにそのようなオブジェクトのクリーンアップを処理するために使用されていますが、「キャプチャー・バイ・移動」することはできませんので、ラムダに、それは少し迷惑を取得することができます:追加注意点としてはS

auto blub = make_unique<int>(0); // [1] 

std::shared_ptr<object> objptr = getObject(); 

// use std::bind to store the unique_ptr with the lambda 
auto func = std::bind([=](std::unique_ptr<int>& blub) { 
    *blub *= 2; 

    objptr->addSomething(*blub); 

    callback(*blub); 
}, std::move(blub)); // move the unique_ptr into the function object 

objptr = getAnotherObject(); 

// func is not copiable because it holds a unique_ptr 
startProcessing(std::move(func)); // move it 

、ラムダが値でキャプチャするとコピーされ、その奇妙なコピーのセマンティクスが正確に必要なものなので、古い廃止のstd::auto_ptrは実際にここでうまく動作します。


1. make_uniqueためGOTW #102を参照してください。

+0

ルックママ、いいえ「新」! –

+1

私は、 'std :: shared_ptr'を使ってラムダの外にあるものに常にアクセスし、それらの値を渡すべきであるというルールを終わらせるべきです。これは 'std :: bind'呼び出しの必要性をなくします。 'std :: bind'を使うと、あなたが実際にオブジェクトとしてblubを持っていて、それをラムダに移動したいならば、IMOは理にかなっています。 – abergmeier

+1

@LCIDFireはい、いいルールのようです。私は 'blub'が共有される可能性のないローカル変数であるため、ここでバインドを使用しました。 –

関連する問題