X-Git-Url: https://git.sesse.net/?p=cubemap;a=blobdiff_plain;f=thread.cpp;h=f719eacb95c5379a2d664f23c49c04e0b50b767b;hp=bd4cfd1790288e6dcb712820b3bc6725b9548732;hb=71fc5575037bead8b6e927a1fffd199e4fc4514b;hpb=3fd8650ccf3da3960a946d8ac9abc305aec399ce diff --git a/thread.cpp b/thread.cpp index bd4cfd1..f719eac 100644 --- a/thread.cpp +++ b/thread.cpp @@ -1,97 +1,71 @@ -#include -#include -#include -#include -#include #include #include #include +#include +#include +#include #include "log.h" -#include "mutexlock.h" #include "thread.h" - + Thread::~Thread() {} void Thread::run() { - pthread_mutex_init(&should_stop_mutex, NULL); - should_stop_status = false; + should_stop = false; + int pipefd[2]; + if (pipe2(pipefd, O_CLOEXEC) == -1) { + log_perror("pipe"); + exit(1); + } + stop_fd_read = pipefd[0]; + stop_fd_write = pipefd[1]; pthread_create(&worker_thread, NULL, &Thread::do_work_thunk, this); } void Thread::stop() { - { - MutexLock lock(&should_stop_mutex); - should_stop_status = true; - } - wakeup(); - if (pthread_join(worker_thread, NULL) == -1) { - log_perror("pthread_join"); + should_stop = true; + char ch = 0; + int err; + do { + err = write(stop_fd_write, &ch, 1); + } while (err == -1 && errno == EINTR); + + if (err == -1) { + log_perror("write"); exit(1); } -} -void *Thread::do_work_thunk(void *arg) -{ - Thread *thread = reinterpret_cast(arg); + do { + err = close(stop_fd_write); + } while (err == -1 && errno == EINTR); - // Block SIGHUP; only the main thread should see that. - // (This isn't strictly required, but it makes it easier to debug that indeed - // SIGUSR1 was what woke us up.) - sigset_t set; - sigaddset(&set, SIGHUP); - int err = pthread_sigmask(SIG_BLOCK, &set, NULL); - if (err != 0) { - errno = err; - log_perror("pthread_sigmask"); - exit(1); + if (err == -1) { + log_perror("close"); + // Can continue (we have close-on-exec). } - // Block SIGUSR1, and store the old signal mask. - sigemptyset(&set); - sigaddset(&set, SIGUSR1); - err = pthread_sigmask(SIG_BLOCK, &set, &thread->sigset_without_usr1_block); - if (err != 0) { - errno = err; - log_perror("pthread_sigmask"); + pthread_kill(worker_thread, SIGHUP); + if (pthread_join(worker_thread, NULL) == -1) { + log_perror("pthread_join"); exit(1); } + + do { + err = close(stop_fd_read); + } while (err == -1 && errno == EINTR); - // Call the right thunk. - thread->do_work(); - return NULL; -} - -bool Thread::wait_for_activity(int fd, short events, const struct timespec *timeout_ts) -{ - pollfd pfd; - pfd.fd = fd; - pfd.events = events; - - for ( ;; ) { - int nfds = ppoll(&pfd, (fd == -1) ? 0 : 1, timeout_ts, &sigset_without_usr1_block); - if (nfds == -1 && errno == EINTR) { - return false; - } - if (nfds == -1) { - log_perror("poll"); - usleep(100000); - continue; - } - assert(nfds <= 1); - return (nfds == 1); + if (err == -1) { + log_perror("close"); + // Can continue (we have close-on-exec). } } -void Thread::wakeup() +void *Thread::do_work_thunk(void *arg) { - pthread_kill(worker_thread, SIGUSR1); + Thread *thread = reinterpret_cast(arg); + thread->do_work(); + return NULL; } -bool Thread::should_stop() -{ - MutexLock lock(&should_stop_mutex); - return should_stop_status; -}