diff --git a/include/mutex.hpp b/include/mutex.hpp new file mode 100644 index 0000000..62821fc --- /dev/null +++ b/include/mutex.hpp @@ -0,0 +1,84 @@ +/* + * DISTRHO Cardinal Plugin + * Copyright (C) 2021-2022 Filipe Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * For a full copy of the GNU General Public License see the LICENSE file. + */ + +#pragma once + +#include + +/* replace Rack's mutex with our own custom one, which can do priority inversion. */ + +namespace rack { + + +struct SharedMutex { + pthread_mutex_t readLock, writeLock; + + SharedMutex() noexcept { + pthread_mutexattr_t attr; + + pthread_mutexattr_init(&attr); + pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&readLock, &attr); + pthread_mutexattr_destroy(&attr); + + pthread_mutexattr_init(&attr); + pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + pthread_mutex_init(&writeLock, &attr); + pthread_mutexattr_destroy(&attr); + } + + ~SharedMutex() noexcept { + pthread_mutex_destroy(&readLock); + pthread_mutex_destroy(&writeLock); + } + + // for std::lock_guard usage, writers lock + void lock() noexcept { + pthread_mutex_lock(&writeLock); + pthread_mutex_lock(&readLock); + } + void unlock() noexcept { + pthread_mutex_unlock(&readLock); + pthread_mutex_unlock(&writeLock); + } + + // for SharedLock usage, readers lock + void lock_shared() noexcept { + pthread_mutex_lock(&readLock); + } + void unlock_shared() noexcept { + pthread_mutex_unlock(&readLock); + } +}; + + +template +struct SharedLock { + Mutex& mutex; + + SharedLock(Mutex& m) noexcept : mutex(m) { + mutex.lock_shared(); + } + ~SharedLock() noexcept { + mutex.unlock_shared(); + } +}; + + +} // namespace rack