Skip to content

Commit

Permalink
Use C++11 multi-threading features.
Browse files Browse the repository at this point in the history
No more windows.h included in header files (needed for CriticalSection). This also means that the Python bindings should compile.

Essentia multi-threading features aren't covered by unit tests, so the changes should be carefully reviewed.
  • Loading branch information
wo80 committed Jan 1, 2024
1 parent 8e36629 commit 877df4d
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 16 deletions.
20 changes: 17 additions & 3 deletions src/essentia/threading.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
#define ESSENTIA_THREADING_H


#ifdef OS_WIN32
#ifdef CPP_11
# include <mutex>
#elif defined(OS_WIN32)
# include <windows.h>
#else // OS_WIN32
# include <pthread.h>
Expand Down Expand Up @@ -59,7 +61,11 @@ class MutexLocker {
// the ForcedMutex is a real Mutex, that should always lock properly
// (ex: in FFTW, the plan creation/destruction needs to be protected no matter what)

# ifdef OS_WIN32
#ifdef CPP_11

typedef std::mutex ForcedMutex;

#elif defined(OS_WIN32)

// windows CriticalSection implementation

Expand All @@ -73,7 +79,7 @@ class ForcedMutex {
void unlock() { LeaveCriticalSection(&criticalSection); }
};

# else // OS_WIN32
#else // OS_WIN32

// posix implementation for linux and osx

Expand All @@ -92,6 +98,12 @@ class ForcedMutex {

# endif // OS_WIN32

#ifdef CPP_11

typedef std::lock_guard<std::mutex> ForcedMutexLocker;

#else

class ForcedMutexLocker {
protected:
ForcedMutex& _mutex;
Expand All @@ -100,6 +112,8 @@ class ForcedMutexLocker {
~ForcedMutexLocker() { _mutex.unlock(); }
};

# endif


} // namespace essentia

Expand Down
4 changes: 2 additions & 2 deletions src/essentia/utils/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ class Atomic {
} // namespace essentia


// life's easy in C++11
#elif __cplusplus >= 201103L
#elif defined(CPP_11)

// life's easy in C++11

#include <atomic>

Expand Down
56 changes: 45 additions & 11 deletions src/essentia/utils/ringbufferimpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@

#include "atomic.h"

#ifdef OS_WIN32
#ifdef CPP_11

#include <mutex>
#include <condition_variable>

#elif defined(OS_WIN32)

#include <windows.h>

Expand Down Expand Up @@ -116,7 +121,12 @@ class RingBufferImpl {

Real* _buffer;

#ifdef CPP_11
std::condition_variable condition;
std::mutex mutex;
#else
Condition condition;
#endif

// whether to wait for space (to add data to the buffer)
// or for availability of data (when reading data from the buffer)
Expand Down Expand Up @@ -156,14 +166,18 @@ class RingBufferImpl {
// has been set accordingly
assert(_waitingCondition == kAvailable);

#ifdef CPP_11
std::unique_lock<std::mutex> lock{mutex};
condition.wait(lock, [&] { return _available > 0; });
lock.unlock();
#else
condition.lock();

while (_available == 0)
{
condition.wait();
}

condition.unlock();
#endif
}

void waitSpace(void)
Expand All @@ -172,14 +186,18 @@ class RingBufferImpl {
// has been set accordingly
assert(_waitingCondition == kSpace);

#ifdef CPP_11
std::unique_lock<std::mutex> lock{ mutex };
condition.wait(lock, [&] { return _space > 0; });
lock.unlock();
#else
condition.lock();

while (_space == 0)
{
condition.wait();
}

condition.unlock();
#endif
}

int add(const Real* inputData, int inputSize)
Expand All @@ -200,15 +218,23 @@ class RingBufferImpl {
_space -= size;
_available += size;

// the thread that is using this ringbuffer will be waiting for
// data to become available - typically the essentia-part from
// a RingBufferInput. we signal the waiting condition here
#ifdef CPP_11
std::lock_guard<std::mutex> lock{ mutex };
if (_waitingCondition == kAvailable)
{
condition.notify_one();
}
#else
condition.lock();
if (_waitingCondition == kAvailable)
{
// the thread that is using this ringbuffer will be waiting for
// data to become available - typically the essentia-part from
// a RingBufferInput. we signal the waiting condition here
condition.signal();
}
condition.unlock();
#endif

return size;
}
Expand All @@ -232,15 +258,23 @@ class RingBufferImpl {
_available -= size;
_space += size;

// the thread that is using this ringbuffer will be waiting for
// space in the buffer - typically the essentia-part from
// a RingBufferOutput. we signal the waiting condition here
#ifdef CPP_11
std::lock_guard<std::mutex> lock{ mutex };
if (_waitingCondition == kSpace)
{
condition.notify_one();
}
#else
condition.lock();
if (_waitingCondition == kSpace)
{
// the thread that is using this ringbuffer will be waiting for
// space in the buffer - typically the essentia-part from
// a RingBufferOutput. we signal the waiting condition here
condition.signal();
}
condition.unlock();
#endif

return size;
}
Expand Down

0 comments on commit 877df4d

Please sign in to comment.