Как я могу синхронизировать три потока?
Мое приложение состоит из основного процесса и двух потоков, причем все они работают одновременно и используют три очереди fifo:
FIFO-Q - это Qmain, Q1 и Q2. Внутри каждой очереди используется счетчик, который увеличивается, когда элемент помещается в очередь, и уменьшается, когда элемент «извлекается» из очереди.
Обработка включает в себя два потока,
QMaster, который получают из Q1 и Q2 и помещают в Qmain,
Монитор, который положил в Q2,
и основной процесс, который получают из Qmain и помещают в Q1.
Цикл QMaster-thread последовательно проверяет счетчики Q1 и Q2 и, если какие-либо элементы находятся в q, он получает их и помещает их в Qmain.
Цикл Monitor-thread получает данные из внешних источников, упаковывает их и помещает в Q2.
Основной процесс приложения также запускает цикл, проверяющий счетчик Qmain, и, если он есть, получает элемент из Qmain на каждой итерации цикла и обрабатывает его дальше. Во время этой обработки он иногда помещает элемент в Q1 для последующей обработки (когда он по очереди получает от Qmain).
Эта проблема:
Я реализовал все как описано выше, и он работает в течение случайного (короткого) времени, а затем зависает. Мне удалось определить причину сбоя в увеличении / уменьшении счетчика fifo-q (это может произойти в любом из них).
Что я пробовал:
Используя три мьютекса: QMAIN_LOCK, Q1_LOCK и Q2_LOCK, которые я блокирую всякий раз, когда любая операция get / put выполняется на соответствующем fifo-q. Результат: приложение не запускается, просто зависает.
Основной процесс должен продолжаться все время, не должен блокироваться при «чтении» (сбой именованных каналов, сбой сокета пары).
Любой совет?
Я думаю, что неправильно внедряю мьютекс, как это должно быть сделано?
(Любые комментарии по улучшению вышеуказанного дизайна также приветствуются)
[edit] ниже приведены процессы и шаблон fifo-q:
Где и как в этом месте разместить мьютекс, чтобы избежать проблем, описанных выше?
main-process:
...
start thread QMaster
start thread Monitor
...
while (!quit)
{
...
if (Qmain.count() > 0)
{
X = Qmain.get();
process(X)
delete X;
}
...
//at some random time:
Q2.put(Y);
...
}
Monitor:
{
while (1)
{
//obtain & package data
Q2.put(data)
}
}
QMaster:
{
while(1)
{
if (Q1.count() > 0)
Qmain.put(Q1.get());
if (Q2.count() > 0)
Qmain.put(Q2.get());
}
}
fifo_q:
template < class X* > class fifo_q
{
struct item
{
X* data;
item *next;
item() { data=NULL; next=NULL; }
}
item *head, *tail;
int count;
public:
fifo_q() { head=tail=NULL; count=0; }
~fifo_q() { clear(); /*deletes all items*/ }
void put(X x) { item i=new item(); (... adds to tail...); count++; }
X* get() { X *d = h.data; (...deletes head ...); count--; return d; }
clear() {...}
};