2016-04-13 7 views
4

Ich habe Code, bei dem ein nicht-generischer Lamba-Ausdruck eine lokale statische Variable hat: einen Mutex für einen kritischen Bereich. Etwas, das vereinfacht werden kann:Lokale statische Variable, die zwischen allen Instanzen eines generischen Lambda-Ausdrucks geteilt wird

int i = 0; 
auto lambda = [&i](int &v) 
{ 
    static std::mutex mutex; 
    std::lock_guard<std::mutex> lock(mutex); 
    /* critical section with v and i */}; 
} 

nun der kritische Abschnitt in diesem Lambda-Ausdruck umgesetzt könnte auch für andere Typen als int & wiederverwendet wörtlich und ich würde eine Änderung so einfach gern als int mit auto im declarator ersetzen , wie folgt aus:

auto lambda = [&i](auto &v) 

Leider, wenn ich das tue, lambda(int&) und lambda(float&) die gleiche lokale statische Variable nicht mehr teilen, was die Sperre im kritischen Abschnitt besiegen werden.

Was wäre die einfachste Änderung der Code sein, der all diese Anforderungen erfüllen würde:

  • die Genericity liefern, die ich brauche; und
  • sicherstellen, dass ich einen einzigen Mutex über alle Instanzen des kritischen Abschnitts geteilt habe; und
  • aussetzt nicht die Mutex Öffentlichkeit

Eine Lösung, die den Lambda-Ausdruck zu ersetzen, mit einer Klasse mit einer Template-Methode, so etwas wie das wäre funktionieren würde:

class Lambda 
{ 
public: 
    Lambda(int &i) : i_(i) {} 
    template<class V> 
    void operator()(V &v) 
    { 
     std::lock_guard<std::mutex> lock(mutex_); 
     /* critical section with v and i_ */ 
    }; 
private: 
    static std::mutex mutex_; 
    int &i_; 
}; 
std::mutex Lambda::mutex_; 

int i = 0; 
Lambda lambda(i); 

Dieses würde funktionieren (mit Vorbehalten wie die private Referenz i_), aber es sieht sehr umständlich im Vergleich zu der ursprünglichen Lambda-Ausdruck. Wäre es etwas einfacher?

Antwort

4

Sie können init-Erfassung ein shared_ptr, die es definiert als Membervariable des Verschlusstyp und so alle Kopien des Verschlusses Objekt ähnlich sein wird, wird die gleiche Mutex teilen zu müssen:

auto lambda = [&i, m = std::make_shared<std::mutex>()](auto &v) 
    { 
     std::lock_guard<std::mutex> lock(*m); 
     /* critical section with v and i */ 
    }; 
+2

Diese So hat er keinen einzigen Mutex über alle Instanzen des kritischen Abschnitts hinweg *. Liege ich falsch? – skypjack

+0

@skypjack, oops, ich habe ursprünglich 'make_shared' geschrieben, aber ich bin nicht sicher, warum ich es in' make_unique' geändert habe (was das Lambda nicht kopierbar macht, wenn ich es mit einem geteilten Mutex kopierbar machen wollte). Ein dummer Brainfart. Jetzt behoben. –

+1

Schön. Ich denke, das OP möchte auch '(auto & v)' anstelle von '(int & v)' sehen, denn es war sein Ziel, ein generalisiertes Lambda zu haben. – skypjack

Verwandte Themen