2017-01-04 4 views
2

Muss ich den mongocxx :: pool manuell sperren, während ich eine Verbindung erhalte?MongoDB C++: Ist mongocxx :: pool thread sicher?

d. H. Ist das sicher? (Beispiel von Mongo Webseite kopiert)

mongocxx::instance instance{}; 
mongocxx::pool pool {mongocxx::uri{}}; 

using mongocxx::pool::entry = std::unique_ptr<client, std::function<void (client*)>> 

auto threadfunc = [](mongocxx::client &client, stdx::string_view dbname) { 
    client[dbname]["col"].insert({}); 
} 
// don't even bother sharing clients. Just give each thread its own, 
std::thread([]() { 
    // pool.acquire() returns a mongo::pool::entry type 
    mongocxx::client *c= pool.acquire().get(); 
    threadfunc(*c, "db1"); 
    threadfunc(*c, "db2"); 
}); 

std::thread([]() { 
    mongocxx::client *c = pool.acquire().get();; 
    threadfunc(*c, "db2"); 
    threadfunc(*c, "db1"); 
}); 

Antwort

3

Ja, mongocxx::pool ist Thread-sicher. Sie können gleichzeitig auf mehrere Threads zugreifen. Die einzelnen mongocxx::client Objekte, die aus dem Pool zurückgegeben werden, sind nicht thread-safe, noch sind die untergeordneten Objekte wie collection oder database von der client erhalten - Sie müssen sie nicht zwischen Threads teilen.

Beachten Sie auch, dass Ihr Beispiel (das nicht wörtlich von der Website kopiert wird, sondern von einem der Beispiele geändert wurde), einen schwerwiegenden Programmierfehler enthält.

Diese Zeile:

mongocxx::client *c= pool.acquire().get(); 

Wird ein Pool-Eintrag erhalten, extrahiert dann einen nackten Zeiger von ihm. Der Pooleintrag wird jedoch am Ende der Anweisung zerstört, wodurch das zugrunde liegende Objekt client in den Pool zurückgegeben wird. Dies ermöglicht einem anderen Thread, es möglicherweise aufzunehmen, während Sie es weiterhin verwenden.

du so schreiben sollte:

mongocxx::instance instance{}; 
mongocxx::pool pool {mongocxx::uri{}}; 

auto threadfunc = [](mongocxx::client &client, stdx::string_view dbname) { 
    client[dbname]["col"].insert({}); 
} 
// don't even bother sharing clients. Just give each thread its own, 
std::thread([]() { 
    // pool.acquire() returns a mongo::pool::entry type 
    auto c = pool.acquire(); 
    threadfunc(*c, "db1"); 
    threadfunc(*c, "db2"); 
}); 

std::thread([]() { 
    auto c = pool.acquire(); 
    threadfunc(*c, "db2"); 
    threadfunc(*c, "db1"); 
}); 

Auf diese Weise behält jeder Thread den Pool-Eintrag, bis es fertig ist mit, an welcher Stelle es automatisch zurückgegeben werden, wenn der unique_ptr in c zerstört wird.

+0

@xcorat es ist höflich, die besten Antworten auf Fragen, die Sie gestellt haben, zu verbessern und/oder zu akzeptieren. – acm

+0

meine Güte! Ich lese gerade die Antwort: p (jk, aber ja, ich lese es gerade, danke :) – xcorat

+0

Und ja, ich habe meinen Code geändert, um genau zu bestimmen, wie Sie es repariert haben, und dachte, ich habe die Frage bearbeitet, aber ich denke, ich hatte es nicht t. Danke noch einmal! – xcorat