forked from LMMS/lmms
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9584375
commit 72a6a0c
Showing
10 changed files
with
548 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
/* | ||
* Lv2Worker.h - Lv2Worker class | ||
* | ||
* Copyright (c) 2022-2022 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@> | ||
* | ||
* This file is part of LMMS - https://lmms.io | ||
* | ||
* 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 2 of the License, or (at your option) 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. | ||
* | ||
* You should have received a copy of the GNU General Public | ||
* License along with this program (see COPYING); if not, write to the | ||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
* Boston, MA 02110-1301 USA. | ||
* | ||
*/ | ||
|
||
#ifndef LV2WORKER_H | ||
#define LV2WORKER_H | ||
|
||
#include "lmmsconfig.h" | ||
|
||
#ifdef LMMS_HAVE_LV2 | ||
|
||
#include <lilv/lilv.h> | ||
#include <lv2/lv2plug.in/ns/ext/worker/worker.h> | ||
#include <thread> | ||
|
||
#include "LocklessRingBuffer.h" | ||
#include "Semaphore.h" | ||
|
||
namespace lmms | ||
{ | ||
|
||
/** | ||
Worker container | ||
*/ | ||
class Lv2Worker | ||
{ | ||
public: | ||
// CTOR/DTOR/feature access | ||
Lv2Worker(LV2_Handle handle, const LV2_Worker_Interface* iface, Semaphore& common_work_lock, bool threaded); | ||
~Lv2Worker(); | ||
const LV2_Worker_Schedule* feature() const { return &m_scheduleFeature; } | ||
|
||
// public API | ||
void emitResponses(); | ||
void notifyPluginThatRunFinished() | ||
{ | ||
if(iface->end_run) { iface->end_run(m_scheduleFeature.handle); } | ||
} | ||
|
||
// to be called only by static functions | ||
LV2_Worker_Status scheduleWork(uint32_t size, const void* data); | ||
LV2_Worker_Status respond(uint32_t size, const void* data); | ||
|
||
private: | ||
// functions | ||
void* workerFunc(); | ||
static std::size_t bufferSize(); //!< size of internal buffers | ||
|
||
// parameters | ||
const LV2_Worker_Interface* iface; | ||
bool threaded; | ||
LV2_Handle handle; | ||
LV2_Worker_Schedule m_scheduleFeature; | ||
|
||
// threading/synchronization | ||
std::thread thread; | ||
std::vector<char> response; | ||
LocklessRingBuffer<char> requests, responses; | ||
LocklessRingBufferReader<char> requestsReader, responsesReader; | ||
std::atomic<bool> exit = false; | ||
Semaphore sem; | ||
Semaphore& work_lock; | ||
}; | ||
|
||
|
||
} // namespace lmms | ||
|
||
#endif // LMMS_HAVE_LV2 | ||
|
||
#endif // LV2WORKER_H | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/* | ||
* Semaphore.h - Semaphore declaration | ||
* | ||
* Copyright (c) 2022-2022 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@> | ||
* | ||
* This file is part of LMMS - https://lmms.io | ||
* | ||
* 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 2 of the License, or (at your option) 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. | ||
* | ||
* You should have received a copy of the GNU General Public | ||
* License along with this program (see COPYING); if not, write to the | ||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
* Boston, MA 02110-1301 USA. | ||
* | ||
*/ | ||
|
||
/* | ||
* This code has been copied and adapted from https://github.com/drobilla/jalv | ||
* File src/zix/sem.h | ||
*/ | ||
|
||
#ifndef LMMS_SEMAPHORE_H | ||
#define LMMS_SEMAPHORE_H | ||
|
||
#ifdef LMMS_BUILD_APPLE | ||
# include <mach/mach.h> | ||
#elif defined(LMMS_BUILD_WIN32) | ||
# include <windows.h> | ||
#else | ||
# include <semaphore.h> | ||
#endif | ||
|
||
#include <system_error> | ||
|
||
/** | ||
A counting semaphore. | ||
This is an integer that is always positive, and has two main operations: | ||
increment (post) and decrement (wait). If a decrement can not be performed | ||
(i.e. the value is 0) the caller will be blocked until another thread posts | ||
and the operation can succeed. | ||
Semaphores can be created with any starting value, but typically this will | ||
be 0 so the semaphore can be used as a simple signal where each post | ||
corresponds to one wait. | ||
Semaphores are very efficient (much moreso than a mutex/cond pair). In | ||
particular, at least on Linux, post is async-signal-safe, which means it | ||
does not block and will not be interrupted. If you need to signal from | ||
a realtime thread, this is the most appropriate primitive to use. | ||
@note Likely outdated with C++20's std::counting_semaphore | ||
(though we have to check that this will be RT conforming on all platforms) | ||
*/ | ||
class Semaphore | ||
{ | ||
public: | ||
Semaphore(unsigned initial); | ||
Semaphore(const Semaphore&) = delete; | ||
Semaphore& operator=(const Semaphore&) = delete; | ||
Semaphore(Semaphore&&) = delete; | ||
Semaphore& operator=(Semaphore&&) = delete; | ||
~Semaphore(); | ||
|
||
void post(); | ||
void wait(); | ||
bool try_wait(); | ||
|
||
private: | ||
#ifdef LMMS_BUILD_APPLE | ||
semaphore_t sem; | ||
#elif defined(LMMS_BUILD_WIN32) | ||
HANDLE sem; | ||
#else | ||
sem_t sem; | ||
#endif | ||
}; | ||
|
||
#endif // LMMS_SEMAPHORE_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
/* | ||
* Semaphore.cpp - Semaphore implementation | ||
* | ||
* Copyright (c) 2022-2022 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@> | ||
* | ||
* This file is part of LMMS - https://lmms.io | ||
* | ||
* 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 2 of the License, or (at your option) 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. | ||
* | ||
* You should have received a copy of the GNU General Public | ||
* License along with this program (see COPYING); if not, write to the | ||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
* Boston, MA 02110-1301 USA. | ||
* | ||
*/ | ||
|
||
/* | ||
* This code has been copied and adapted from https://github.com/drobilla/jalv | ||
* File src/zix/sem.h | ||
*/ | ||
|
||
#include "Semaphore.h" | ||
|
||
#if defined(LMMS_BUILD_WIN32) | ||
# include <limits.h> | ||
#else | ||
# include <errno.h> | ||
#endif | ||
|
||
#include <system_error> | ||
|
||
#ifdef LMMS_BUILD_APPLE | ||
Semaphore::Semaphore(unsigned val) | ||
{ | ||
kern_return_t rval = semaphore_create(mach_task_self(), &sem, SYNC_POLICY_FIFO, val); | ||
if(rval != 0) | ||
throw std::system_error(rval, std::system_category(), "Could not create semaphore"); | ||
} | ||
|
||
Semaphore::~Semaphore() | ||
{ | ||
semaphore_destroy(mach_task_self(), sem); | ||
} | ||
|
||
void Semaphore::post() | ||
{ | ||
semaphore_signal(sem); | ||
} | ||
|
||
void Semaphore::wait() | ||
{ | ||
kern_return_t rval = semaphore_wait(sem); | ||
if (rval != KERN_SUCCESS) { | ||
throw std::system_error(rval, std::system_category(), "Waiting for semaphore failed"); | ||
} | ||
} | ||
|
||
bool Semaphore::try_wait() | ||
{ | ||
const mach_timespec_t zero = { 0, 0 }; | ||
return semaphore_timedwait(sem, zero) == KERN_SUCCESS; | ||
} | ||
|
||
#elif defined(LMMS_BUILD_WIN32) | ||
|
||
Semaphore::Semaphore(unsigned initial) | ||
{ | ||
if(CreateSemaphore(NULL, initial, LONG_MAX, NULL) == nullptr) | ||
throw std::system_error(GetLastError(), std::syssystem_category(), "Could not create semaphore"); | ||
} | ||
|
||
Semaphore::~Semaphore() | ||
{ | ||
CloseHandle(sem); | ||
} | ||
|
||
void Semaphore::post() | ||
{ | ||
ReleaseSemaphore(sem, 1, NULL); | ||
} | ||
|
||
void Semaphore::wait() | ||
{ | ||
if (WaitForSingleObject(sem, INFINITE) != WAIT_OBJECT_0) { | ||
throw std::system_error(GetLastError(), std::syssystem_category(), "Waiting for semaphore failed"); | ||
} | ||
} | ||
|
||
bool Semaphore::try_wait() | ||
{ | ||
return WaitForSingleObject(sem, 0) == WAIT_OBJECT_0; | ||
} | ||
|
||
#else /* !defined(LMMS_BUILD_APPLE) && !defined(LMMS_BUILD_WIN32) */ | ||
|
||
Semaphore::Semaphore(unsigned initial) | ||
{ | ||
if(sem_init(&sem, 0, initial) != 0) | ||
throw std::system_error(errno, std::generic_category(), "Could not create semaphore"); | ||
} | ||
|
||
Semaphore::~Semaphore() | ||
{ | ||
sem_destroy(&sem); | ||
} | ||
|
||
void Semaphore::post() | ||
{ | ||
sem_post(&sem); | ||
} | ||
|
||
void Semaphore::wait() | ||
{ | ||
while (sem_wait(&sem) != 0) { | ||
if (errno != EINTR) { | ||
throw std::system_error(errno, std::generic_category(), "Waiting for semaphore failed"); | ||
} | ||
/* Otherwise, interrupted, so try again. */ | ||
} | ||
} | ||
|
||
bool Semaphore::try_wait() | ||
{ | ||
return (sem_trywait(&sem) == 0); | ||
} | ||
|
||
#endif | ||
|
Oops, something went wrong.