2017-01-04 8 views
2

Должен ли я вручную блокировать mongocxx :: pool при приобретении соединения?MongoDB C++: Есть ли mongocxx :: pool thread safe?

i.e Это безопасно? (Например, скопирован с сайта Монго)

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"); 
}); 

ответ

3

Да, mongocxx::pool потокобезопасно. Вы можете получить доступ к нему одновременно из нескольких потоков. Тем не менее, индивидуальные mongocxx::client объектов, возвращенных из бассейна, являются не потокобезопасными, а также подчиненными объектами, такими как collection или database, полученными от client - вы не должны делиться ими между потоками.

Обратите также внимание на то, что ваш пример (который не скопирован на веб-сайте, но изменен из одного из примеров) содержит серьезную ошибку программирования.

Эта линия:

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

получит вход в бассейн, а затем извлекает голый указатель из него. Однако запись пула будет уничтожена в конце инструкции, в результате чего базовый объект client будет возвращен в пул, что позволит другому потоку потенциально поднять его, пока вы продолжаете его использовать.

Вы должны написать это как:

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"); 
}); 

Таким образом, каждый поток сохраняет запись в бассейне, пока он не закончит работу с ним, после чего он будет автоматически возвращается, когда unique_ptr в c разрушается.

+0

@ xcorat вежливый, чтобы продвигать и/или принимать лучшие ответы на заданные вами вопросы. – acm

+0

geez! Я просто прочитал ответ: p (jk, но да, я просто прочитал его, спасибо :) – xcorat

+0

И да, я в конечном итоге изменил свой код на то, как вы его исправили, и подумал, что я отредактировал вопрос, но я думаю, «т. Еще раз спасибо! – xcorat