Hi, I’m trying to write a multithread program with the juce library and I’m having some trouble with the Value::Listener class. I’ve created a class called threadSafeValue, which contains a Value and a mutex to regulate the access to the value, and than I store some of this objects in a std::vector m_linesState. I associate a listenrer to each one, but, during the process, one of the Values loses his listener.
how you can see in the gdb report of the storing process, at line 117, when I push back the second object, the one I stored before (referencedObject = 0xef8120) in m_linesState loses his Listener and numUsed passes from 1 to 0.
116 for(int i=0; i<activedLinePin.size();++i){ (gdb) n 117 m_linesState.push_back(threadSafeValue(var(false))); (gdb) n 118 m_linesState[i].addListener(this); (gdb) n 119 m_signals.push_back(new Circle(0xffff0000)); (gdb) 120 addChildComponent(m_signals[i]); (gdb) 116 for(int i=0; i<activedLinePin.size();++i){ (gdb) print m_linesState $11 = std::vector of length 1, capacity 1 = {{value = {value = { referencedObject = 0xef8120}, listeners = {listeners = { data = {<juce::DummyCriticalSection> = {<No data fields>}, elements = { data = 0xf07320}, numAllocated = 8}, numUsed = 1}}}, mutex = std::shared_ptr (count 1, weak 0) 0xed7490}} (gdb) n 117 m_linesState.push_back(threadSafeValue(var(false))); (gdb) print m_linesState $12 = std::vector of length 1, capacity 1 = {{value = {value = { referencedObject = 0xef8120}, listeners = {listeners = { data = {<juce::DummyCriticalSection> = {<No data fields>}, elements = { data = 0xf07320}, numAllocated = 8}, numUsed = 1}}}, mutex = std::shared_ptr (count 1, weak 0) 0xed7490}} (gdb) n 118 m_linesState[i].addListener(this); (gdb) print m_linesState $13 = std::vector of length 2, capacity 2 = {{value = {value = { referencedObject = 0xef8120}, listeners = {listeners = { data = {<juce::DummyCriticalSection> = {<No data fields>}, elements = { data = 0x0}, numAllocated = 0}, numUsed = 0}}}, mutex = std::shared_ptr (count 1, weak 0) 0xed7490}, {value = {value = { referencedObject = 0xf3f5a0}, listeners = {listeners = { data = {<juce::DummyCriticalSection> = {<No data fields>}, elements = { data = 0x0}, numAllocated = 0}, numUsed = 0}}}, mutex = std::shared_ptr (count 1, weak 0) 0xf06f50}} (gdb) n 119 m_signals.push_back(new Circle(0xffff0000)); (gdb) print m_linesState $14 = std::vector of length 2, capacity 2 = {{value = {value = { referencedObject = 0xef8120}, listeners = {listeners = { data = {<juce::DummyCriticalSection> = {<No data fields>}, elements = { data = 0x0}, numAllocated = 0}, numUsed = 0}}}, mutex = std::shared_ptr (count 1, weak 0) 0xed7490}, {value = {value = { referencedObject = 0xf3f5a0}, listeners = {listeners = { data = {<juce::DummyCriticalSection> = {<No data fields>}, elements = { data = 0xf07440}, numAllocated = 8}, numUsed = 1}}}, mutex = std::shared_ptr (count 1, weak 0) 0xf06f50}}
the strange fact is that this problem appears only the first time this section of the code is executed. if I clear the vector and recall the same function it works fine. how can I resolve it?
here are the codes of threadSafeValue.h
#include "../JuceLibraryCode/JuceHeader.h"
#include <memory>
using namespace std;
class threadSafeValue {
private:
Value value;
shared_ptr<CriticalSection> mutex;
public:
threadSafeValue(const var&);
threadSafeValue();
~threadSafeValue();
var getValue();
void setValue(const var&);
void referTo (threadSafeValue&);
void addListener (Value::Listener*);
shared_ptr<CriticalSection>& getMutex();
Value& getUnsafeValue();
void removeListener (Value::Listener*);
};
threadSafeValue.cpp
threadSafeValue::threadSafeValue():value(),mutex(new CriticalSection()){
}
threadSafeValue::threadSafeValue(const var& newValue):value(newValue), mutex(new CriticalSection()){
}
threadSafeValue::~threadSafeValue(){
}
void
threadSafeValue::setValue(const var& newValue){
mutex->enter();
value.setValue(newValue);
mutex->exit();
}
void
threadSafeValue::referTo(threadSafeValue& ValueToRefer){
mutex=ValueToRefer.getMutex();
mutex->enter();
value.referTo(ValueToRefer.getUnsafeValue());
mutex->exit();
}
var
threadSafeValue::getValue(){
mutex->enter();
var returnValue=value.getValue();
mutex->exit();
return returnValue;
}
void
threadSafeValue::addListener(Value::Listener* newListener){
value.addListener(newListener);
}
shared_ptr<CriticalSection>&
threadSafeValue::getMutex(){
return mutex;
}
Value&
threadSafeValue::getUnsafeValue(){
return value;
}
void
threadSafeValue::removeListener(Value::Listener* Listener){
value.removeListener(Listener);
}
and the function where m_linesState is filled
void
startingGrid::setParameters(map<string,int>& activedLinePin,juce::String& portname){
for(int i=0; i<activedLinePin.size();++i){
m_linesState.push_back(threadSafeValue(var(false)));
m_linesState[i].addListener(this);
m_signals.push_back(new Circle(0xffff0000));
addChildComponent(m_signals[i]);
}
m_game.setParameters(activedLinePin, portname, m_linesState);
}
thank you very much for your help

