thread.h 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. // -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
  2. // Copyright (C) 2013 Henner Zeller <h.zeller@acm.org>
  3. //
  4. // This program is free software; you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation version 2.
  7. //
  8. // This program is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. // GNU General Public License for more details.
  12. //
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program. If not, see <http://gnu.org/licenses/gpl-2.0.txt>
  15. #ifndef RPI_THREAD_H
  16. #define RPI_THREAD_H
  17. #include <stdint.h>
  18. #include <pthread.h>
  19. namespace rgb_matrix {
  20. // Simple thread abstraction.
  21. class Thread {
  22. public:
  23. Thread();
  24. // The destructor waits for Run() to return so make sure it does.
  25. virtual ~Thread();
  26. // Wait for the Run() method to return.
  27. void WaitStopped();
  28. // Start thread. If realtime_priority is > 0, then this will be a
  29. // thread with SCHED_FIFO and the given priority.
  30. // If cpu_affinity is set !=, chooses the given bitmask of CPUs
  31. // this thread should have an affinity to.
  32. // On a Raspberry Pi 1, this doesn't matter, as there is only one core,
  33. // Raspberry Pi 2 can has 4 cores, so any combination of (1<<0) .. (1<<3) is
  34. // valid.
  35. virtual void Start(int realtime_priority = 0, uint32_t cpu_affinity_mask = 0);
  36. // Override this to do the work.
  37. //
  38. // This will be called in a thread once Start() has been called. You typically
  39. // will have an endless loop doing stuff.
  40. //
  41. // It is a good idea to provide a way to communicate to the thread that
  42. // it should stop (see ThreadedCanvasManipulator for an example)
  43. virtual void Run() = 0;
  44. private:
  45. static void *PthreadCallRun(void *tobject);
  46. bool started_;
  47. pthread_t thread_;
  48. };
  49. // Non-recursive Mutex.
  50. class Mutex {
  51. public:
  52. Mutex() { pthread_mutex_init(&mutex_, NULL); }
  53. ~Mutex() { pthread_mutex_destroy(&mutex_); }
  54. void Lock() { pthread_mutex_lock(&mutex_); }
  55. void Unlock() { pthread_mutex_unlock(&mutex_); }
  56. // Wait on condition. If "timeout_ms" is < 0, it waits forever, otherwise
  57. // until timeout is reached.
  58. // Returns 'true' if condition is met, 'false', if wait timed out.
  59. bool WaitOn(pthread_cond_t *cond, long timeout_ms = -1);
  60. private:
  61. pthread_mutex_t mutex_;
  62. };
  63. // Useful RAII wrapper around mutex.
  64. class MutexLock {
  65. public:
  66. MutexLock(Mutex *m) : mutex_(m) { mutex_->Lock(); }
  67. ~MutexLock() { mutex_->Unlock(); }
  68. private:
  69. Mutex *const mutex_;
  70. };
  71. } // end namespace rgb_matrix
  72. #endif // RPI_THREAD_H