]> git.sesse.net Git - cubemap/blobdiff - thread.h
Tweak the MutexLock implementation slightly, so as to confuse Coverity less.
[cubemap] / thread.h
index 26e648e5332d6a3016d0ec59d4a58b58b09033a8..728df27cd38002881f5270315344c1616307fc42 100644 (file)
--- a/thread.h
+++ b/thread.h
@@ -1,12 +1,19 @@
 #ifndef _THREAD_H
 #define _THREAD_H
 
 #ifndef _THREAD_H
 #define _THREAD_H
 
+#include <signal.h>
 #include <pthread.h>
 
 #include <pthread.h>
 
-// A rather generic thread class with start/stop functionality.
-// NOTE: stop is somewhat racy (there's no guaranteed breakout from syscalls),
-// since signals don't stick. We'll need to figure out something more
-// intelligent later, probably based on sending a signal to an fd.
+struct timespec;
+
+// A thread class with start/stop and signal functionality.
+//
+// SIGUSR1 is blocked during execution of do_work(), so that you are guaranteed
+// to receive it when doing wait_for_activity(), and never elsewhere. This means
+// that you can test whatever status flags you'd want before calling
+// wait_for_activity(), and then be sure that it actually returns immediately
+// if a SIGUSR1 (ie., wakeup()) happened, even if it were sent between your test
+// and the wait_for_activity() call.
 
 class Thread {
 public:
 
 class Thread {
 public:
@@ -15,21 +22,39 @@ public:
        void stop();
 
 protected:
        void stop();
 
 protected:
-       // Recovers the this pointer, and calls do_work().
+       // Recovers the this pointer, blocks SIGUSR1, and calls do_work().
        static void *do_work_thunk(void *arg);
 
        virtual void do_work() = 0;
 
        static void *do_work_thunk(void *arg);
 
        virtual void do_work() = 0;
 
-       volatile bool should_stop;
+       // Waits until there is activity of the given type on <fd> (or an error),
+       // or until a wakeup. Returns true if there was actually activity on
+       // the file descriptor.
+       //
+       // If fd is -1, wait until a wakeup or timeout.
+       // if timeout_ts is NULL, there is no timeout.
+       bool wait_for_activity(int fd, short events, const timespec *timeout_ts);
+
+       // Wait until a wakeup.
+       void wait_for_wakeup(const timespec *timeout_ts) { wait_for_activity(-1, 0, timeout_ts); }
+
+       // Make wait_for_activity() return. Note that this is a relatively expensive
+       // operation.
+       void wakeup();
 
 
-       // A pipe that you can poll on if you want to see when should_stop
-       // has been set to true; stop() will write a single byte to the pipe
-       // and then close the other end.
-       int stop_fd_read;
+       bool should_stop();
+
+       // The signal set as it were before we blocked SIGUSR1.
+       sigset_t sigset_without_usr1_block;
 
 private:
        pthread_t worker_thread;
 
 private:
        pthread_t worker_thread;
-       int stop_fd_write;
+
+       // Protects should_stop_status.
+       pthread_mutex_t should_stop_mutex;
+
+       // If this is set, the thread should return as soon as possible from do_work().
+       bool should_stop_status;
 };
 
 #endif  // !defined(_THREAD_H)
 };
 
 #endif  // !defined(_THREAD_H)