С++ потоковая карта

Кто-нибудь знает, где я могу найти пример, который обертывает карту STL и делает ее потокобезопасной? Когда я говорю "безопасный поток", я имею в виду, что он предлагает только последовательный доступ к карте, по одному потоку за раз. Оптимально эта карта должна использовать только конструкции STL и boost.

Ответ 1

Не соответствует критериям, которые вы указали, но вы можете посмотреть контейнеры TBB. Существует так называемый concurrent_hash_map, который позволяет нескольким потокам одновременно получать данные на карте. Есть некоторые детали, но все хорошо документировано и может дать вам представление о "параллельном контейнере". В зависимости от ваших потребностей это может быть совершенно неуместным...

Ответ 2

Как правило, не рекомендуется создавать классы сбора для обеспечения безопасности потоков, поскольку они не могут знать, как они используются. Вам будет намного лучше выполнять свои собственные блокирующие механизмы в конструкциях более высокого уровня, которые используют коллекции.

Ответ 3

Усиление shared_mutex обеспечит наилучший подход к множественному считыванию/одиночной записи для упаковки стандартной карты с учетом ваших ограничений. Я не знаю никаких "предварительно построенных" реализаций, которые выходят за них, поскольку задача обычно тривиальна.

Ответ 4

Это зависит от приложения для реализации. "Нитебезопасная" карта сделает индивидуальные вызовы в карту потокобезопасными, но многие операции должны быть выполнены в потоковом режиме через. Приложение, использующее карту, должно связывать мьютекс с картой и использовать этот мьютекс для координации доступа к нему.

Попытка создания поточно-безопасных контейнеров была ошибкой в ​​Java, и это было бы ошибкой в ​​С++.

Ответ 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, это также сработает.