summaryrefslogtreecommitdiff
path: root/libs/ardour/rt_tasklist.cc
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2017-10-30 05:52:18 +0100
committerRobin Gareus <robin@gareus.org>2017-10-30 16:31:38 +0100
commitfba0fce4416578de29b7701cf4d400399d44ceff (patch)
tree612caec1860667d2e83c5b43b86b81065862fd67 /libs/ardour/rt_tasklist.cc
parentc0dbe8eaaf45369b4fc40c881ff4d60bedef6b81 (diff)
Add a RT-Tasklist
Diffstat (limited to 'libs/ardour/rt_tasklist.cc')
-rw-r--r--libs/ardour/rt_tasklist.cc171
1 files changed, 171 insertions, 0 deletions
diff --git a/libs/ardour/rt_tasklist.cc b/libs/ardour/rt_tasklist.cc
new file mode 100644
index 0000000000..db2a33015c
--- /dev/null
+++ b/libs/ardour/rt_tasklist.cc
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2017 Robin Gareus <robin@gareus.org>
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#include "pbd/pthread_utils.h"
+
+#include "ardour/audioengine.h"
+#include "ardour/debug.h"
+#include "ardour/rt_tasklist.h"
+#include "ardour/utils.h"
+
+#include "pbd/i18n.h"
+
+using namespace ARDOUR;
+
+RTTaskList::RTTaskList ()
+ : _threads_active (0)
+ , _task_run_sem ("rt_task_run", 0)
+ , _task_end_sem ("rt_task_done", 0)
+{
+ reset_thread_list ();
+}
+
+RTTaskList::~RTTaskList ()
+{
+ drop_threads ();
+}
+
+void
+RTTaskList::drop_threads ()
+{
+ Glib::Threads::Mutex::Lock pm (_process_mutex);
+ g_atomic_int_set (&_threads_active, 0);
+
+ uint32_t nt = _threads.size ();
+ for (uint32_t i = 0; i < nt; ++i) {
+ _task_run_sem.signal ();
+ }
+ for (std::vector<pthread_t>::const_iterator i = _threads.begin (); i != _threads.end (); ++i)
+ {
+ pthread_join (*i, NULL);
+ }
+ _threads.clear ();
+ _task_run_sem.reset ();
+ _task_end_sem.reset ();
+}
+
+/*static*/ void*
+RTTaskList::_thread_run (void *arg)
+{
+ RTTaskList *d = static_cast<RTTaskList *>(arg);
+ d->run ();
+ pthread_exit (0);
+ return 0;
+}
+
+void
+RTTaskList::reset_thread_list ()
+{
+ drop_threads ();
+
+ const uint32_t num_threads = how_many_dsp_threads ();
+ if (num_threads < 2) {
+ return;
+ }
+
+ Glib::Threads::Mutex::Lock pm (_process_mutex);
+
+ g_atomic_int_set (&_threads_active, 1);
+ for (uint32_t i = 0; i < num_threads; ++i) {
+ pthread_t thread_id;
+ size_t stacksize = 100000;
+ if (!AudioEngine::instance()->is_realtime ()
+ ||
+ pbd_realtime_pthread_create (PBD_SCHED_FIFO, -22, stacksize, &thread_id, _thread_run, this)) {
+ pthread_attr_t attr;
+ pthread_attr_init (&attr);
+ pthread_attr_setstacksize (&attr, stacksize);
+ if (pthread_create (&thread_id, &attr, _thread_run, this)) {
+ PBD::fatal << _("Cannot create thread for TaskList!") << endmsg;
+ /* NOT REACHED */
+ }
+ pthread_attr_destroy (&attr);
+ }
+ pbd_mach_set_realtime_policy (thread_id, 5. * 1e-5);
+ _threads.push_back (thread_id);
+ }
+}
+
+void
+RTTaskList::run ()
+{
+ Glib::Threads::Mutex::Lock tm (_tasklist_mutex, Glib::Threads::NOT_LOCK);
+ bool wait = true;
+
+ while (true) {
+ if (wait) {
+ _task_run_sem.wait ();
+ }
+
+ if (0 == g_atomic_int_get (&_threads_active)) {
+ _task_end_sem.signal ();
+ break;
+ }
+
+ wait = false;
+
+ boost::function<void ()> to_run;
+ tm.acquire ();
+ if (_tasklist.size () > 0) {
+ to_run = _tasklist.front();
+ _tasklist.pop_front ();
+ }
+ tm.release ();
+
+ if (!to_run.empty ()) {
+ to_run ();
+ continue;
+ }
+
+ if (!wait) {
+ _task_end_sem.signal ();
+ }
+
+ wait = true;
+ }
+}
+
+void
+RTTaskList::process (TaskList const& tl)
+{
+ Glib::Threads::Mutex::Lock pm (_process_mutex);
+ _tasklist = tl;
+ process_tasklist ();
+ _tasklist.clear ();
+}
+
+void
+RTTaskList::process_tasklist ()
+{
+ if (0 == g_atomic_int_get (&_threads_active) || _threads.size () == 0) {
+ for (TaskList::iterator i = _tasklist.begin (); i != _tasklist.end(); ++i) {
+ (*i)();
+ }
+ return;
+ }
+
+ uint32_t nt = std::min (_threads.size (), _tasklist.size ());
+
+ for (uint32_t i = 0; i < nt; ++i) {
+ _task_run_sem.signal ();
+ }
+ for (uint32_t i = 0; i < nt; ++i) {
+ _task_end_sem.wait ();
+ }
+}