Кто-нибудь знает, где я могу найти пример, который обертывает карту STL и делает ее потокобезопасной? Когда я говорю "безопасный поток", я имею в виду, что он предлагает только последовательный доступ к карте, по одному потоку за раз. Оптимально эта карта должна использовать только конструкции STL и boost.
С++ потоковая карта
Ответ 1
Не соответствует критериям, которые вы указали, но вы можете посмотреть контейнеры TBB. Существует так называемый concurrent_hash_map
, который позволяет нескольким потокам одновременно получать данные на карте. Есть некоторые детали, но все хорошо документировано и может дать вам представление о "параллельном контейнере". В зависимости от ваших потребностей это может быть совершенно неуместным...
Ответ 2
Как правило, не рекомендуется создавать классы сбора для обеспечения безопасности потоков, поскольку они не могут знать, как они используются. Вам будет намного лучше выполнять свои собственные блокирующие механизмы в конструкциях более высокого уровня, которые используют коллекции.
Ответ 3
Усиление shared_mutex обеспечит наилучший подход к множественному считыванию/одиночной записи для упаковки стандартной карты с учетом ваших ограничений. Я не знаю никаких "предварительно построенных" реализаций, которые выходят за них, поскольку задача обычно тривиальна.
Ответ 4
Это зависит от приложения для реализации. "Нитебезопасная" карта сделает индивидуальные вызовы в карту потокобезопасными, но многие операции должны быть выполнены в потоковом режиме через. Приложение, использующее карту, должно связывать мьютекс с картой и использовать этот мьютекс для координации доступа к нему.
Попытка создания поточно-безопасных контейнеров была ошибкой в Java, и это было бы ошибкой в С++.
Ответ 5
Вы можете посмотреть Thread Safe Template Library
Ответ 6
Попробуйте эту библиотеку
http://www.codeproject.com/KB/threads/lwsync.aspx
Он реализован в современном политическом подходе на основе С++.
Вот несколько вырезанных из ссылки, чтобы показать идею с "векторным" случаем
typedef lwsync::critical_resource<std::vector<int> > sync_vector_t;
sync_vector_t vec;
// some thread:
{
// Critical resource can be naturally used with STL containers.
sync_vector_t::const_accessor vec_access = vec.const_access();
for(std::vector<int>::const_iterator where = vec_access->begin();
where != vec_access->end();
++where;
)
std::cout << *where << std::endl;
}
sync_vector_t::accessor some_vector_action()
{
sync_vector_t::accessor vec_access = vec.access();
vec_access->push_back(10);
return vec_access;
// Access is escalated from within a some_vector_action() scope
// So that one can make some other action with vector before it becomes
// unlocked.
}
{
sync_vector_t::accessor vec_access = some_vector_action();
vec_access->push_back(20);
// Elements 10 and 20 will be placed in vector sequentially.
// Any other action with vector cannot be processed between those two
// push_back's.
}
Ответ 7
Я придумал это (что, я уверен, можно улучшить, чтобы принять более двух аргументов):
template<class T1, class T2>
class combine : public T1, public T2
{
public:
/// We always need a virtual destructor.
virtual ~combine() { }
};
Это позволяет:
// Combine an std::mutex and std::map<std::string, std::string> into
// a single instance.
SCA::combine<std::mutex, std::map<std::string, std::string>> lockableMap;
// Lock the map within scope to modify the map in a thread-safe way.
{
// Lock the map.
std::lock_guard<std::mutex> locked(lockableMap);
// Modify the map.
lockableMap["Person 1"] = "Jack";
lockableMap["Person 2"] = "Jill";
}
Если вы хотите использовать std:: recursive_mutex и std:: set, это также сработает.