diff options
author | Robin Gareus <robin@gareus.org> | 2015-03-01 20:55:39 +0100 |
---|---|---|
committer | Robin Gareus <robin@gareus.org> | 2015-03-01 20:55:39 +0100 |
commit | 9a30bfd0c602ee08142374b2a409d28573530fc6 (patch) | |
tree | 656fa6b50179819f1d93f5092500a331ad54f194 /libs/ardour/butler.cc | |
parent | d7727a77e0b19ecb2d1957d1e13d554dbed58243 (diff) |
use Xthreads in session butler.
(hopefully) fixes export randomly stalling on windows:
dequeue_request() was a single request (no queue) on Windows.
Butler::queue_request() is called
-> Butler goes to work..
-> while working, another request is queued
-> butler never sees this
-> deadlock
during Freewheeling/Export wait_until_finished()
waits for the 2nd request to be handled, and never returns.
Diffstat (limited to 'libs/ardour/butler.cc')
-rw-r--r-- | libs/ardour/butler.cc | 119 |
1 files changed, 8 insertions, 111 deletions
diff --git a/libs/ardour/butler.cc b/libs/ardour/butler.cc index c33b6e333d..cd00965062 100644 --- a/libs/ardour/butler.cc +++ b/libs/ardour/butler.cc @@ -49,6 +49,7 @@ Butler::Butler(Session& s) , audio_dstream_playback_buffer_size(0) , midi_dstream_buffer_size(0) , pool_trash(16) + , _xthread (true) { g_atomic_int_set(&should_do_transport_work, 0); SessionEvent::pool->set_trash (&pool_trash); @@ -74,31 +75,6 @@ Butler::config_changed (std::string p) } } -#ifndef PLATFORM_WINDOWS -int -Butler::setup_request_pipe () -{ - if (pipe (request_pipe)) { - error << string_compose(_("Cannot create transport request signal pipe (%1)"), - strerror (errno)) << endmsg; - return -1; - } - - if (fcntl (request_pipe[0], F_SETFL, O_NONBLOCK)) { - error << string_compose(_("UI: cannot set O_NONBLOCK on butler request pipe (%1)"), - strerror (errno)) << endmsg; - return -1; - } - - if (fcntl (request_pipe[1], F_SETFL, O_NONBLOCK)) { - error << string_compose(_("UI: cannot set O_NONBLOCK on butler request pipe (%1)"), - strerror (errno)) << endmsg; - return -1; - } - return 0; -} -#endif - int Butler::start_thread() { @@ -118,10 +94,6 @@ Butler::start_thread() should_run = false; -#ifndef PLATFORM_WINDOWS - if (setup_request_pipe() != 0) return -1; -#endif - if (pthread_create_and_store ("disk butler", &thread, _thread_work, this)) { error << _("Session: could not create butler thread") << endmsg; return -1; @@ -151,69 +123,6 @@ Butler::_thread_work (void* arg) return ((Butler *) arg)->thread_work (); } -bool -Butler::wait_for_requests () -{ -#ifndef PLATFORM_WINDOWS - struct pollfd pfd[1]; - - pfd[0].fd = request_pipe[0]; - pfd[0].events = POLLIN|POLLERR|POLLHUP; - - while(true) { - if (poll (pfd, 1, -1) < 0) { - - if (errno == EINTR) { - continue; - } - - error << string_compose (_("poll on butler request pipe failed (%1)"), - strerror (errno)) - << endmsg; - break; - } - - DEBUG_TRACE (DEBUG::Butler, string_compose ("%1: butler awake at @ %2\n", DEBUG_THREAD_SELF, g_get_monotonic_time())); - - if (pfd[0].revents & ~POLLIN) { - error << string_compose (_("Error on butler thread request pipe: fd=%1 err=%2"), pfd[0].fd, pfd[0].revents) << endmsg; - break; - } - - if (pfd[0].revents & POLLIN) { - return true; - } - } - return false; -#else - m_request_sem.wait (); - return true; -#endif -} - -bool -Butler::dequeue_request (Request::Type& r) -{ -#ifndef PLATFORM_WINDOWS - char req; - size_t nread = ::read (request_pipe[0], &req, sizeof (req)); - if (nread == 1) { - r = (Request::Type) req; - return true; - } else if (nread == 0) { - return false; - } else if (errno == EAGAIN) { - return false; - } else { - fatal << _("Error reading from butler request pipe") << endmsg; - abort(); /*NOTREACHED*/ - } -#else - r = (Request::Type) m_request_state.get(); -#endif - return false; -} - void * Butler::thread_work () { @@ -227,16 +136,12 @@ Butler::thread_work () if(!disk_work_outstanding) { DEBUG_TRACE (DEBUG::Butler, string_compose ("%1 butler waits for requests @ %2\n", DEBUG_THREAD_SELF, g_get_monotonic_time())); - if (wait_for_requests ()) { - Request::Type req; - - /* empty the pipe of all current requests */ -#ifdef PLATFORM_WINDOWS - dequeue_request (req); -#else - while (dequeue_request(req)) { -#endif - switch (req) { + + char msg; + /* empty the pipe of all current requests */ + if (_xthread.receive (msg, true) >= 0) { + Request::Type req = (Request::Type) msg; + switch (req) { case Request::Run: DEBUG_TRACE (DEBUG::Butler, string_compose ("%1: butler asked to run @ %2\n", DEBUG_THREAD_SELF, g_get_monotonic_time())); @@ -256,10 +161,7 @@ Butler::thread_work () default: break; - } -#ifndef PLATFORM_WINDOWS } -#endif } } @@ -425,13 +327,8 @@ Butler::schedule_transport_work () void Butler::queue_request (Request::Type r) { -#ifndef PLATFORM_WINDOWS char c = r; - (void) ::write (request_pipe[1], &c, 1); -#else - m_request_state.set (r); - m_request_sem.post (); -#endif + _xthread.deliver (c); } void |