2.12.2021, 9:00 - 11:00: Due to updates GitLab may be unavailable for some minutes between 09:00 and 11:00.

Commit bc11fde2 authored by Christian Schulte zu Berge's avatar Christian Schulte zu Berge
Browse files

Finished work on implementing asynchroneous signals:

* Slight changes to the API: renamed signal::trigger() to signal::triggerSignal() and signal::queue() to signal::queueSignal()
* Replaced all sigslot signal emits through operator() with emits through emitSignal() to enable debug feature.
* Fixed a possible race condition when deleting a GeometryTransferFunction and its editor window at the same time (as this will happen from different threads).

refs #384
parent d07ebc73
......@@ -269,7 +269,7 @@ namespace campvis {
_luaVmState->execString("inspect(pipelines)");
#endif
s_PipelinesChanged();
s_PipelinesChanged.emitSignal();
}
void CampVisApplication::initGlContextAndPipeline(tgt::GLCanvas* canvas, AbstractPipeline* pipeline) {
......@@ -296,7 +296,7 @@ namespace campvis {
DataContainer* CampVisApplication::createAndAddDataContainer(const std::string& name) {
DataContainer* dc = new DataContainer(name);
_dataContainers.push_back(dc);
s_DataContainersChanged();
s_DataContainersChanged.emitSignal();
return dc;
}
......
......@@ -38,7 +38,8 @@ namespace campvis {
}
AbstractTransferFunctionEditor::~AbstractTransferFunctionEditor() {
_transferFunction->s_changed.disconnect(this);
if (_transferFunction != nullptr)
_transferFunction->s_changed.disconnect(this);
}
void AbstractTransferFunctionEditor::onTFChanged() {
......
......@@ -59,25 +59,16 @@ namespace campvis {
{
_selectedGeometry = 0;
setupGUI();
tf->s_geometryCollectionChanged.connect(this, &Geometry1DTransferFunctionEditor::onGeometryCollectionChanged);
tf->s_aboutToBeDeleted.connect(this, &Geometry1DTransferFunctionEditor::onTfAboutToBeDeleted);
updateManipulators();
setEventTypes(tgt::Event::MOUSEPRESSEVENT);
}
Geometry1DTransferFunctionEditor::~Geometry1DTransferFunctionEditor() {
tbb::mutex::scoped_lock lock(_localMutex);
// clearEventListeners and delete former stuff
_selectedGeometry = 0;
for (std::vector<AbstractTFGeometryManipulator*>::iterator it = _manipulators.begin(); it != _manipulators.end(); ++it) {
if (WholeTFGeometryManipulator* tester = dynamic_cast<WholeTFGeometryManipulator*>(*it)) {
tester->s_selected.disconnect(this);
}
delete *it;
}
Geometry1DTransferFunction* gtf = static_cast<Geometry1DTransferFunction*>(_transferFunction);
gtf->s_geometryCollectionChanged.disconnect(this);
disconnectFromTf();
if (OpenGLJobProcessor::isInited())
GLJobProc.deregisterContext(_canvas);
......@@ -215,7 +206,7 @@ namespace campvis {
}
updateManipulators();
g->s_changed();
g->s_changed.emitSignal();
}
else {
_selectedGeometry = 0;
......@@ -352,5 +343,31 @@ namespace campvis {
invalidate();
}
void Geometry1DTransferFunctionEditor::onTfAboutToBeDeleted() {
disconnectFromTf();
}
void Geometry1DTransferFunctionEditor::disconnectFromTf() {
tbb::mutex::scoped_lock lock(_localMutex);
// clearEventListeners and delete former stuff
_selectedGeometry = 0;
for (std::vector<AbstractTFGeometryManipulator*>::iterator it = _manipulators.begin(); it != _manipulators.end(); ++it) {
if (WholeTFGeometryManipulator* tester = dynamic_cast<WholeTFGeometryManipulator*>(*it)) {
tester->s_selected.disconnect(this);
}
delete *it;
}
_manipulators.clear();
Geometry1DTransferFunction* gtf = static_cast<Geometry1DTransferFunction*>(_transferFunction);
if (gtf != nullptr) {
gtf->s_geometryCollectionChanged.disconnect(this);
gtf->s_aboutToBeDeleted.disconnect(this);
_transferFunction->s_changed.disconnect(this);
_transferFunction = nullptr;
}
}
}
......@@ -83,6 +83,11 @@ namespace campvis {
*/
void onGeometryCollectionChanged();
/**
* Slot to be called when the handled TF is about to be deleted.
*/
void onTfAboutToBeDeleted();
/**
* Slot tp be called when a WholeTFGeometryManipulator was selected.
* \param the selected WholeTFGeometryManipulator
......@@ -107,6 +112,11 @@ namespace campvis {
void onCbLogScaleStateChanged(int state);
protected:
/**
* Disconnects this editor from the handled TF and cleans up everything.
*/
void disconnectFromTf();
/**
* Performs the painting.
*/
......
......@@ -61,19 +61,7 @@ namespace campvis {
}
Geometry2DTransferFunctionEditor::~Geometry2DTransferFunctionEditor() {
tbb::mutex::scoped_lock lock(_localMutex);
// clear and delete former stuff
_selectedGeometry = 0;
for (std::vector<AbstractTFGeometryManipulator*>::iterator it = _manipulators.begin(); it != _manipulators.end(); ++it) {
if (WholeTFGeometryManipulator* tester = dynamic_cast<WholeTFGeometryManipulator*>(*it)) {
tester->s_selected.disconnect(this);
}
delete *it;
}
Geometry2DTransferFunction* gtf = static_cast<Geometry2DTransferFunction*>(_transferFunction);
gtf->s_geometryCollectionChanged.disconnect(this);
disconnectFromTf();
if (OpenGLJobProcessor::isInited())
GLJobProc.deregisterContext(_canvas);
......@@ -298,5 +286,31 @@ namespace campvis {
}
}
void Geometry2DTransferFunctionEditor::onTfAboutToBeDeleted() {
disconnectFromTf();
}
void Geometry2DTransferFunctionEditor::disconnectFromTf() {
tbb::mutex::scoped_lock lock(_localMutex);
// clear and delete former stuff
_selectedGeometry = 0;
for (std::vector<AbstractTFGeometryManipulator*>::iterator it = _manipulators.begin(); it != _manipulators.end(); ++it) {
if (WholeTFGeometryManipulator* tester = dynamic_cast<WholeTFGeometryManipulator*>(*it)) {
tester->s_selected.disconnect(this);
}
delete *it;
}
_manipulators.clear();
Geometry2DTransferFunction* gtf = static_cast<Geometry2DTransferFunction*>(_transferFunction);
if (gtf != nullptr) {
gtf->s_geometryCollectionChanged.disconnect(this);
gtf->s_aboutToBeDeleted.disconnect(this);
_transferFunction->s_changed.disconnect(this);
_transferFunction = nullptr;
}
}
}
......@@ -82,6 +82,11 @@ namespace campvis {
*/
void onGeometryCollectionChanged();
/**
* Slot to be called when the handled TF is about to be deleted.
*/
void onTfAboutToBeDeleted();
/**
* Slot tp be called when a WholeTFGeometryManipulator was selected.
* \param the selected WholeTFGeometryManipulator
......@@ -100,6 +105,11 @@ namespace campvis {
void onBtnRemoveGeometryClicked();
protected:
/**
* Disconnects this editor from the handled TF and cleans up everything.
*/
void disconnectFromTf();
/**
* Performs the painting.
*/
......
......@@ -119,7 +119,7 @@ namespace campvis {
_layout->addWidget(propWidget);
prop->s_visibilityChanged.connect(this, &PropertyCollectionWidget::onPropertyVisibilityChanged);
prop->s_visibilityChanged(prop);
prop->s_visibilityChanged.emitSignal(prop);
}
void PropertyCollectionWidget::removeProperty(std::map<AbstractProperty*, QWidget*>::iterator it) {
......
......@@ -105,7 +105,7 @@ namespace campvis {
_keyPoint->_position = tfCoords.x;
_keyPoint->_color.a = static_cast<uint8_t>(tfCoords.y * 255.f);
std::sort(_geometry->getKeyPoints().begin(), _geometry->getKeyPoints().end());
_geometry->s_changed();
_geometry->s_changed.emitSignal();
}
// ignore here, because other listeners probably need this signal as well
e->ignore();
......@@ -119,7 +119,7 @@ namespace campvis {
if(newColor.isValid()) {
tgt::col4 tmp = QtColorTools::toTgtColor(newColor);
_keyPoint->_color = tgt::col4(tmp.xyz(), _keyPoint->_color.a);
_geometry->s_changed();
_geometry->s_changed.emitSignal();
}
e->accept();
}
......@@ -163,7 +163,7 @@ namespace campvis {
if (insideGeometry(_pressedPosition)) {
_mousePressed = true;
_valuesWhenPressed = _geometry->getKeyPoints();
s_selected(this);
s_selected.emitSignal(this);
e->accept();
}
else {
......@@ -186,7 +186,7 @@ namespace campvis {
_geometry->getKeyPoints()[i]._position = _valuesWhenPressed[i]._position + displacement.x;
}
_geometry->s_changed();
_geometry->s_changed.emitSignal();
}
// ignore here, because other listeners probably need this signal as well
e->ignore();
......@@ -203,7 +203,7 @@ namespace campvis {
for (std::vector<TFGeometry1D::KeyPoint>::iterator it = _geometry->getKeyPoints().begin(); it != _geometry->getKeyPoints().end(); ++it) {
it->_color = tgt::col4(tmp.xyz(), it->_color.a);
}
_geometry->s_changed();
_geometry->s_changed.emitSignal();
}
e->accept();
}
......
......@@ -99,8 +99,8 @@ namespace campvis {
tbb::mutex::scoped_lock lock(_localMutex);
_intensityDomain = newDomain;
}
s_intensityDomainChanged();
s_changed();
s_intensityDomainChanged.emitSignal();
s_changed.emitSignal();
}
const tgt::vec2& AbstractTransferFunction::getIntensityDomain() const {
......
......@@ -98,6 +98,9 @@ namespace campvis {
/// Signal to be emitted when the vector of T objects (_geometries) changed (The collection, not the actual geometry).
sigslot::signal0 s_geometryCollectionChanged;
/// Signal to be emitted when this TF object is about to be deleted.
sigslot::signal0 s_aboutToBeDeleted;
protected:
/**
* Creates the texture and uploads it to OpenGL.
......@@ -139,6 +142,8 @@ namespace campvis {
template<class T>
void campvis::GenericGeometryTransferFunction<T>::deinit() {
s_aboutToBeDeleted.triggerSignal(); // use trigger to force blocking signal handling in same thread
for (typename std::vector<T*>::iterator it = _geometries.begin(); it != _geometries.end(); ++it) {
(*it)->s_changed.disconnect(this);
delete *it;
......@@ -168,8 +173,8 @@ namespace campvis {
}
geometry->s_changed.connect(this, &GenericGeometryTransferFunction<T>::onGeometryChanged);
_dirtyTexture = true;
s_geometryCollectionChanged();
s_changed();
s_geometryCollectionChanged.emitSignal();
s_changed.emitSignal();
}
template<class T>
......@@ -186,14 +191,14 @@ namespace campvis {
geometry->s_changed.disconnect(this);
delete geometry;
_dirtyTexture = true;
s_geometryCollectionChanged();
s_changed();
s_geometryCollectionChanged.emitSignal();
s_changed.emitSignal();
}
template<class T>
void campvis::GenericGeometryTransferFunction<T>::onGeometryChanged() {
_dirtyTexture = true;
s_changed();
s_changed.emitSignal();
}
template<class T>
......
......@@ -82,7 +82,7 @@ namespace campvis {
_leftColor = color;
}
_dirtyTexture = true;
s_changed();
s_changed.emitSignal();
}
void SimpleTransferFunction::setRightColor(const tgt::col4& color) {
......@@ -91,7 +91,7 @@ namespace campvis {
_rightColor = color;
}
_dirtyTexture = true;
s_changed();
s_changed.emitSignal();
}
const tgt::col4& SimpleTransferFunction::getLeftColor() const {
......
......@@ -66,8 +66,8 @@ namespace campvis {
_handles.erase(name);
_handles.insert(std::make_pair(name, dh));
s_dataAdded(name, dh);
s_changed();
s_dataAdded.emitSignal(name, dh);
s_changed.emitSignal();
}
bool DataContainer::hasData(const std::string& name) const {
......
......@@ -123,7 +123,7 @@ namespace campvis {
void AbstractPipeline::onPropertyChanged(const AbstractProperty* prop) {
if (prop == &_renderTargetID) {
s_renderTargetChanged();
s_renderTargetChanged.emitSignal();
}
else if (prop == &_canvasSize && _canvas != 0 && !_ignoreCanvasSizeUpdate) {
if (_canvasSize.getValue() != _canvas->getSize()) {
......@@ -249,7 +249,7 @@ namespace campvis {
void AbstractPipeline::onDataContainerDataAdded(const std::string& name, DataHandle dh) {
if (name == _renderTargetID.getValue()) {
s_renderTargetChanged();
s_renderTargetChanged.emitSignal();
}
}
......
......@@ -111,7 +111,7 @@ namespace campvis {
do {
tmp = _level;
} while (_level.compare_and_swap(tmp | level, tmp) != tmp);
s_invalidated(this);
s_invalidated.emitSignal(this);
}
}
......@@ -120,7 +120,7 @@ namespace campvis {
do {
tmp = _level;
} while (_level.compare_and_swap(tmp & (~level), tmp) != tmp);
s_validated(this);
s_validated.emitSignal(this);
}
bool AbstractProcessor::getClockExecutionTime() const {
......
......@@ -136,7 +136,7 @@ namespace campvis {
PortMapType::const_iterator it = _portMap.find(name);
while (it != _portMap.end() && it->first == name) {
// invalidate those properties by emitting changed signal
it->second->s_changed(it->second);
it->second->s_changed.emitSignal(it->second);
++it;
}
}
......
......@@ -89,7 +89,7 @@ namespace campvis {
void AbstractProperty::setVisible(bool isVisible) {
_isVisible = isVisible;
s_visibilityChanged(this);
s_visibilityChanged.emitSignal(this);
}
}
......@@ -37,8 +37,8 @@ namespace campvis {
}
void ButtonProperty::click() {
s_clicked();
s_changed(this);
s_clicked.emitSignal();
s_changed.emitSignal(this);
}
}
......@@ -174,7 +174,7 @@ namespace campvis {
child->setDecimals(decimals);
}
this->s_decimalsChanged(this);
this->s_decimalsChanged.emitSignal(this);
}
}
......
......@@ -184,7 +184,7 @@ namespace campvis {
GenericProperty<T>* child = static_cast< GenericProperty<T>* >(*it);
child->setValue(value);
}
s_changed(this);
s_changed.emitSignal(this);
}
template<typename T>
......
......@@ -37,7 +37,7 @@ namespace campvis {
}
void MetaProperty::onPropertyChanged(const AbstractProperty* prop) {
s_changed(this);
s_changed.emitSignal(this);
}
void MetaProperty::addPropertyCollection(HasPropertyCollection& pc) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment