Currently job artifacts in CI/CD pipelines on LRZ GitLab never expire. Starting from Wed 26.1.2022 the default expiration time will be 30 days (GitLab default). Currently existing artifacts in already completed jobs will not be affected by the change. The latest artifacts for all jobs in the latest successful pipelines will be kept. More information: https://gitlab.lrz.de/help/user/admin_area/settings/continuous_integration.html#default-artifacts-expiration

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

* Introduced check whether signal emitting thread is the signal manager...

* Introduced check whether signal emitting thread is the signal manager thread. In such a case signals are now emitted synchronously per default.
* Fixed sigslot shared library builds

refs #384
parent fd355fdf
......@@ -27,6 +27,10 @@ ENDIF()
INCLUDE_DIRECTORIES(${CampvisGlobalIncludeDirs})
TARGET_LINK_LIBRARIES(sigslot tgt)
# if campvis-core is built as a shared library, CMake will define the following flag to instruct
# the code to export DLL symbols
SET_TARGET_PROPERTIES(sigslot PROPERTIES DEFINE_SYMBOL "SIGSLOT_BUILD_DLL")
################################################################################
# deployment
################################################################################
......
......@@ -26,6 +26,7 @@ namespace sigslot {
}
void signal_manager::run() {
_this_thread_id = std::this_thread::get_id();
std::unique_lock<tbb::mutex> lock(_ecMutex);
while (! _stopExecution) {
......@@ -47,6 +48,10 @@ namespace sigslot {
tgt::Runnable::stop();
}
bool signal_manager::isCurrentThreadSignalManagerThread() const {
return std::this_thread::get_id() == _this_thread_id;
}
const std::string signal_manager::loggerCat_;
......
......@@ -90,6 +90,29 @@
#ifndef SIGSLOT_H
#define SIGSLOT_H
#ifdef CAMPVIS_DYNAMIC_LIBS
#ifdef SIGSLOT_BUILD_DLL
// building library -> export symbols
#ifdef WIN32
#define SIGSLOT_API __declspec(dllexport)
#else
#define SIGSLOT_API
#endif
#else
// including library -> import symbols
#ifdef WIN32
#define SIGSLOT_API __declspec(dllimport)
#else
#define SIGSLOT_API
#endif
#endif
#else
// building/including static library -> do nothing
#define SIGSLOT_API
#endif
#include <set>
#include <list>
......@@ -110,15 +133,30 @@
namespace sigslot {
/// Base class for signal handles that provides an interface to emit the signal.
class _signal_handle_base {
public:
/// Virtual destructor
virtual ~_signal_handle_base() {};
/// Emits the signal of this signal handle.
virtual void emitSignal() const = 0;
};
// ================================================================================================
class signal_manager : public tgt::Singleton<signal_manager>, public tgt::Runnable {
/**
* Singleton class that takes care of queuing and asynchronously dispatching signals.
*
* The signal_manager implements the Runnable interface, i.e. runs in it's own thread once it
* was launched. The signal_manager takes care of dispatching signals to their connections.
* This is either done synchrnously by using triggerSignal() or asynchronously by using
* queueSignal(). Furthermore it allows to check, whether the current thread is the
* signal_manager thread. This allows the default signal emitting method operator() to
* automatically decide on the dispatch type based on the emitting thread.
*
* signal_manager can be considered as thread-safe.
*/
class SIGSLOT_API signal_manager : public tgt::Singleton<signal_manager>, public tgt::Runnable {
friend class tgt::Singleton<signal_manager>;
public:
......@@ -138,6 +176,12 @@ namespace sigslot {
*/
bool queueSignal(_signal_handle_base* signal);
/**
* Checks whether calling thread is signal_manager thread.
* \return std::this_thread::get_id() == _this_thread_id
*/
bool isCurrentThreadSignalManagerThread() const;
/// \see Runnable:run
virtual void run();
/// \see Runnable:stop
......@@ -149,6 +193,7 @@ namespace sigslot {
/// Private destructor only for singleton
~signal_manager();
/// Typedef for the signal queue
typedef tbb::concurrent_queue<_signal_handle_base*> SignalQueue;
SignalQueue _signalQueue; ///< Queue for signals to be dispatched
......@@ -156,6 +201,8 @@ namespace sigslot {
std::condition_variable _evaluationCondition; ///< conditional wait to be used when there are currently no jobs to process
tbb::mutex _ecMutex; ///< Mutex for protecting _evaluationCondition
std::thread::id _this_thread_id;
static const std::string loggerCat_;
};
......@@ -1303,17 +1350,25 @@ namespace sigslot {
pclass->signal_connect(this);
}
void emitSignal()
void trigger()
{
signal_handle0* sh = new signal_handle0(this);
signal_manager::getRef().triggerSignal(sh);
}
void operator()()
void queue()
{
signal_handle0* sh = new signal_handle0(this);
signal_manager::getRef().queueSignal(sh);
}
void operator()()
{
if (signal_manager::getRef().isCurrentThreadSignalManagerThread())
trigger();
else
queue();
}
};
template<class arg1_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
......@@ -1366,17 +1421,25 @@ namespace sigslot {
pclass->signal_connect(this);
}
void emitSignal(arg1_type a1)
void trigger(arg1_type a1)
{
signal_handle1* sh = new signal_handle1(this, a1);
signal_manager::getRef().triggerSignal(sh);
}
void operator()(arg1_type a1)
void queue(arg1_type a1)
{
signal_handle1* sh = new signal_handle1(this, a1);
signal_manager::getRef().queueSignal(sh);
}
void operator()(arg1_type a1)
{
if (signal_manager::getRef().isCurrentThreadSignalManagerThread())
trigger(a1);
else
queue(a1);
}
};
template<class arg1_type, class arg2_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
......@@ -1432,17 +1495,25 @@ namespace sigslot {
pclass->signal_connect(this);
}
void emitSignal(arg1_type a1, arg2_type a2)
void trigger(arg1_type a1, arg2_type a2)
{
signal_handle2* sh = new signal_handle2(this, a1, a2);
signal_manager::getRef().triggerSignal(sh);
}
void operator()(arg1_type a1, arg2_type a2)
void queue(arg1_type a1, arg2_type a2)
{
signal_handle2* sh = new signal_handle2(this, a1, a2);
signal_manager::getRef().queueSignal(sh);
}
void operator()(arg1_type a1, arg2_type a2)
{
if (signal_manager::getRef().isCurrentThreadSignalManagerThread())
trigger(a1, a2);
else
queue(a1, a2);
}
};
template<class arg1_type, class arg2_type, class arg3_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
......@@ -1500,17 +1571,25 @@ namespace sigslot {
pclass->signal_connect(this);
}
void emitSignal(arg1_type a1, arg2_type a2, arg3_type a3)
void trigger(arg1_type a1, arg2_type a2, arg3_type a3)
{
signal_handle3* sh = new signal_handle3(this, a1, a2, a3);
signal_manager::getRef().triggerSignal(sh);
}
void operator()(arg1_type a1, arg2_type a2, arg3_type a3)
void queue(arg1_type a1, arg2_type a2, arg3_type a3)
{
signal_handle3* sh = new signal_handle3(this, a1, a2, a3);
signal_manager::getRef().queueSignal(sh);
}
void operator()(arg1_type a1, arg2_type a2, arg3_type a3)
{
if (signal_manager::getRef().isCurrentThreadSignalManagerThread())
trigger(a1, a2, a3);
else
queue(a1, a2, a3);
}
};
template<class arg1_type, class arg2_type, class arg3_type, class arg4_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
......@@ -1570,17 +1649,25 @@ namespace sigslot {
pclass->signal_connect(this);
}
void emitSignal(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4)
void trigger(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4)
{
signal_handle4* sh = new signal_handle4(this, a1, a2, a3, a4);
signal_manager::getRef().triggerSignal(sh);
}
void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4)
void queue(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4)
{
signal_handle4* sh = new signal_handle4(this, a1, a2, a3, a4);
signal_manager::getRef().queueSignal(sh);
}
void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4)
{
if (signal_manager::getRef().isCurrentThreadSignalManagerThread())
trigger(a1, a2, a3, a4);
else
queue(a1, a2, a3, a4);
}
};
template<class arg1_type, class arg2_type, class arg3_type, class arg4_type, class arg5_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
......@@ -1642,17 +1729,25 @@ namespace sigslot {
pclass->signal_connect(this);
}
void emitSignal(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5)
void trigger(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5)
{
signal_handle5* sh = new signal_handle5(this, a1, a2, a3, a4, a5);
signal_manager::getRef().triggerSignal(sh);
}
void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5)
void queue(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5)
{
signal_handle5* sh = new signal_handle5(this, a1, a2, a3, a4, a5);
signal_manager::getRef().queueSignal(sh);
}
void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5)
{
if (signal_manager::getRef().isCurrentThreadSignalManagerThread())
trigger(a1, a2, a3, a4, a5);
else
queue(a1, a2, a3, a4, a5);
}
};
} // namespace sigslot
......
......@@ -29,7 +29,6 @@
#include <ext/threading.h>
#include <tbb/atomic.h>
#include "core/coreapi.h"
namespace tgt {
/**
......@@ -38,7 +37,7 @@ namespace tgt {
* in the run() method which has to be overwritten in subclasses. Calling stop() sets _stopExecution to true
* and waits for the thread to finish. Hence, you should test for _stopExecution in your run() method.
*/
class CAMPVIS_CORE_API Runnable {
class TGT_API Runnable {
public:
/**
* Creates a new Runnable object
......
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