Я пишу программу провайдер-потребитель. Существует много очередей сообщений, и я хочу убедиться, что каждое сообщение, помещенное в очередь в каждой очереди сообщений, имеет последовательный, увеличивающийся индекс, например, <0, "msga">, <1, "msgb">, ...
. Порядок остается внутри каждой очереди, и разные очереди не имеют значения.
Для этого я использую 2 карты хешей и 2 блокировки мьютекса (я хочу использовать только одну блокировку, но не удалось).
(i) Первая хэш-карта отображает имя очереди на пару <int, mutex *>
, в которой int
означает счетчик каждой очереди, мьютекс защищает очередь в параллельных запросах. Определение
using umap_cnt = unordered_map<string, pair<int, mutex* > >;
umap_cnt counters;
(ii) Вторая карта хэша отображает имя очереди на фактическое сообщение <int, MSG>
(MSG на самом деле строка), определение
using umap_msg = unordered_map<string, vector<pair<int, msg> > >;
umap_msg messages`;
Моя логика
- найти мьютекс очереди в
counters
, заблокировать () это
- используйте counter_iter-> first в качестве индекса сообщения, поместите () его в
messages
- увеличение индекса
- unlock () блокировка мьютекса
Пример кода выглядит следующим образом
/* File A.cpp */
using umap_msg = unordered_map<string, vector<pair<int, msg> > >;
mutex mtx;
umap_msg messages;
void put(string kname, MSG msg, int index) {
// If not using mtx here, the message would be out of order.
// lock_guard<mutex> mtx;
messages[kname].push_back(make_pair<index, msg>);
}
// Many threads runs producer()
/* File B.cpp*/
using umap_cnt = unordered_map<string, pair<int, mutex* > >
void producer(string kname, MSG msg) {
umap_cnt::iterator iter = counters.find(kname);
if (iter == counters.end())
return;
// lock the queue
iter->second.second->lock();
put(kname, msg, iter->second.first);
++iter->second.first; // increase the counter
iter->second.second->unlock();
}
Проблема в том, что я не вижу единой блокировки. Мне нужно использовать 2 блокировки мьютекса, одну в производителе, а другую - на месте, в противном случае я получаю либо сообщение о неисправности, либо ошибку сегментации (понятия не имею, почему).
Моя первоначальная цель - использовать только один замок в производителе. Каждая очередь имеет свой собственный мьютекс, и никакие два потока не могут получить блокировку очереди одновременно, поэтому каждое сообщение в каждой очереди должно быть упорядочено. Однако результат оказался не таким, как я ожидал.
Зачем нужна дополнительная блокировка в строке 7? Если мне нужно использовать 2 блокировки, могу ли я оптимизировать их, потому что 2 блокировки кажутся немного тяжелыми?