X-Git-Url: https://git.sesse.net/?p=cubemap;a=blobdiff_plain;f=thread.cpp;h=2aaf34f11441cefe3befcba7b33cc08c6d4f6db6;hp=7aded3bb8cda25790550a3818a4b3a40ff205496;hb=562cf44b96b5c0260d1a1ab18b2dd2408b6d1fc8;hpb=94561762b1294b76508eb5554aedbb56fcaececc diff --git a/thread.cpp b/thread.cpp index 7aded3b..2aaf34f 100644 --- a/thread.cpp +++ b/thread.cpp @@ -1,23 +1,33 @@ +#include +#include +#include +#include #include #include -#include +#include +#include "log.h" +#include "mutexlock.h" #include "thread.h" - + Thread::~Thread() {} void Thread::run() { - should_stop = false; + pthread_mutex_init(&should_stop_mutex, NULL); + should_stop_status = false; pthread_create(&worker_thread, NULL, &Thread::do_work_thunk, this); } void Thread::stop() { - should_stop = true; - pthread_kill(worker_thread, SIGHUP); + { + MutexLock lock(&should_stop_mutex); + should_stop_status = true; + } + wakeup(); if (pthread_join(worker_thread, NULL) == -1) { - perror("pthread_join"); + log_perror("pthread_join"); exit(1); } } @@ -25,7 +35,62 @@ void Thread::stop() void *Thread::do_work_thunk(void *arg) { Thread *thread = reinterpret_cast(arg); + + // 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); + } + + // 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"); + exit(1); + } + + // 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); + } +} + +void Thread::wakeup() +{ + pthread_kill(worker_thread, SIGUSR1); +} + +bool Thread::should_stop() +{ + MutexLock lock(&should_stop_mutex); + return should_stop_status; +}