threadSimpleImpl.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /**
  2. * PANDA 3D SOFTWARE
  3. * Copyright (c) Carnegie Mellon University. All rights reserved.
  4. *
  5. * All use of this software is subject to the terms of the revised BSD
  6. * license. You should have received a copy of this license along
  7. * with this source code in a file named "LICENSE."
  8. *
  9. * @file threadSimpleImpl.h
  10. * @author drose
  11. * @date 2007-06-18
  12. */
  13. #ifndef THREADSIMPLEIMPL_H
  14. #define THREADSIMPLEIMPL_H
  15. #include "pandabase.h"
  16. #include "selectThreadImpl.h"
  17. #ifdef THREAD_SIMPLE_IMPL
  18. #include "pnotify.h"
  19. #include "threadPriority.h"
  20. #include "pvector.h"
  21. #include "contextSwitch.h"
  22. class Thread;
  23. class ThreadSimpleManager;
  24. class MutexSimpleImpl;
  25. /**
  26. * This is a trivial threading implementation for applications that don't
  27. * desire full OS-managed threading. It is a user-space implementation of
  28. * threads implemented via setjmp/longjmp, and therefore it cannot take
  29. * advantage of multiple CPU's (the application will always run on a single
  30. * CPU, regardless of the number of threads you spawn).
  31. *
  32. * However, since context switching is entirely cooperative, synchronization
  33. * primitives like mutexes and condition variables aren't necessary, and the
  34. * Mutex and ConditionVar classes are compiled into trivial no-op classes,
  35. * which can reduce overhead substantially compared to a truly threaded
  36. * application.
  37. *
  38. * Be sure that every thread calls Thread::consider_yield() occasionally, or
  39. * it will starve the rest of the running threads.
  40. */
  41. class EXPCL_PANDA_PIPELINE ThreadSimpleImpl {
  42. public:
  43. ThreadSimpleImpl(Thread *parent_obj);
  44. ~ThreadSimpleImpl();
  45. void setup_main_thread();
  46. bool start(ThreadPriority priority, bool joinable);
  47. void join();
  48. void preempt();
  49. std::string get_unique_id() const;
  50. static void prepare_for_exit();
  51. INLINE static Thread *get_current_thread();
  52. INLINE bool is_same_system_thread() const;
  53. INLINE static void bind_thread(Thread *thread);
  54. INLINE static bool is_threading_supported();
  55. static bool is_true_threads();
  56. INLINE static bool is_simple_threads();
  57. INLINE static void sleep(double seconds);
  58. INLINE static void yield();
  59. INLINE static void consider_yield();
  60. void sleep_this(double seconds);
  61. void yield_this(bool volunteer);
  62. INLINE void consider_yield_this();
  63. INLINE double get_wake_time() const;
  64. INLINE static void write_status(std::ostream &out);
  65. static bool get_context_switches(size_t &total, size_t &involuntary);
  66. private:
  67. static void st_begin_thread(void *data);
  68. void begin_thread();
  69. private:
  70. enum ThreadStatus {
  71. TS_new,
  72. TS_running,
  73. TS_finished,
  74. TS_killed,
  75. };
  76. static int _next_unique_id;
  77. int _unique_id;
  78. Thread *_parent_obj;
  79. bool _joinable;
  80. ThreadStatus _status;
  81. ThreadPriority _priority;
  82. // The relative weight of this thread, relative to other threads, in
  83. // priority.
  84. double _priority_weight;
  85. // The amount of time this thread has run recently.
  86. unsigned int _run_ticks;
  87. // This is the time at which the currently-running thread started execution.
  88. double _start_time;
  89. // This is the time at which the currently-running thread should yield.
  90. double _stop_time;
  91. // This records the time at which a sleeping thread should wake up.
  92. double _wake_time;
  93. ThreadContext *_context;
  94. unsigned char *_stack;
  95. size_t _stack_size;
  96. #ifdef HAVE_PYTHON
  97. // If we might be working with Python, we have to manage the Python thread
  98. // state as we switch contexts.
  99. PyThreadState *_python_state;
  100. #endif // HAVE_PYTHON
  101. // Threads that are waiting for this thread to finish.
  102. typedef pvector<ThreadSimpleImpl *> JoiningThreads;
  103. JoiningThreads _joining_threads;
  104. ThreadSimpleManager *_manager;
  105. static ThreadSimpleImpl *volatile _st_this;
  106. // We may not mix-and-match OS threads with Panda's SIMPLE_THREADS. If we
  107. // ever get a Panda context switch request from a different OS thread than
  108. // the thread we think we should be in, that's a serious error that may
  109. // cause major consequences. For this reason, we store the OS thread's
  110. // current thread ID here when the thread is constructed, and insist that it
  111. // never changes during the lifetime of the thread.
  112. #ifdef HAVE_POSIX_THREADS
  113. pthread_t _posix_system_thread_id;
  114. #endif
  115. #ifdef WIN32
  116. DWORD _win32_system_thread_id;
  117. #endif
  118. size_t _context_switches;
  119. size_t _involuntary_context_switches;
  120. friend class ThreadSimpleManager;
  121. };
  122. // We include this down here to avoid the circularity problem.
  123. /* okcircular */
  124. #include "threadSimpleManager.h"
  125. #include "threadSimpleImpl.I"
  126. #endif // THREAD_SIMPLE_IMPL
  127. #endif