I think I see that the blocking is caused by some bugs within your queue code:
template<typename T>
class coda_concorr
{
private:
...
bool vuota() const
{
WaitForSingleObject(mutex,INFINITE);
return la_coda.empty();
ReleaseMutex(mutex); }
bool vuota() const
{
bool RetCode;
WaitForSingleObject(mutex,INFINITE);
RetCode = la_coda.empty();
ReleaseMutex(mutex);
return RetCode;
}
bool try_pop(T& popped)
{
WaitForSingleObject(mutex,INFINITE);
if (la_coda.empty()){
return false; }
WaitForSingleObject(mutex,INFINITE); popped = la_coda.front();
la_coda.pop();
ReleaseMutex(mutex);
return true;
}
bool try_pop(T& popped)
{
WaitForSingleObject(mutex,INFINITE);
if (la_coda.empty()){
ReleaseMutex(mutex);
return false;
}
popped = la_coda.front();
la_coda.pop();
ReleaseMutex(mutex);
return true;
}
};
<V2> Another bug:
Here the incorrect code with explanation, see underlined lines:
int main()
{
coda_concorr<cv::Mat> ingresso;
coda_concorr<cv::Mat> coda1;
coda_concorr<cv::Mat> coda2;
coda_concorr<cv::Mat> uscita;
dati.out=coda1; ...
dati2.in=coda1; dati2.out=coda2;
...
}
So both threads are seeing different copies of coda1 while you would like to have them see the same instance, coda1.
Here a proposal to fix the issue, make the out queue a pointer so you can link Args structures:
struct Args
{
coda_concorr<cv::Mat> in;
coda_concorr<cv::Mat> *out; };
void grey (void *param){
...
arg->out->push(temp2);
}
arg->out->complete=true;
...
}
void soglia(void *param){
...
arg->out->push(temp2a);
}
}
arg->out->complete=true;
_endthread();
}
int main()
{
...
coda_concorr<cv::Mat> coda1; ...
dati.out=&dati2.in; ...
dati2.in=&coda1; dati2.out=&coda2;
...
while (dati2.out->try_pop(out)){
imshow("immagine",out);
waitKey(100);
}
...
}
Also there is a startup issue: When the second thread starts and its input queue is empty, it immediately exits. The same happens when the input queue becomes empty during execution (i.e. the second thread executes faster than the first one).
You have to change the design of your queuing in way that you can distinguish a "queue empty due to all work done" from a "queue empty due to previous step not yet finished".
One option would be to have a queue state added that is set when the producer is done providing data, so your thread only terminates when the queue is empty and the producer has indicated that it will not provide further data, otherwise the thread waits until the queue becomes not-empty.
<V3> Add the waiting in the queue try_pop method, this should get rid of the immediate termination at startup issue:
bool try_pop(T& popped)
{
WaitForSingleObject(mutex,INFINITE);
while (la_coda.empty())
{
if (complete)
{
ReleaseMutex(mutex);
return false;
}
else
{
ReleaseMutex(mutex);
Sleep(100); WaitForSingleObject(mutex,INFINITE);
}
}
popped = la_coda.front();
la_coda.pop();
ReleaseMutex(mutex);
return true;
}