| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- /**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University. All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license. You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file threadSimpleImpl.h
- * @author drose
- * @date 2007-06-18
- */
- #ifndef THREADSIMPLEIMPL_H
- #define THREADSIMPLEIMPL_H
- #include "pandabase.h"
- #include "selectThreadImpl.h"
- #ifdef THREAD_SIMPLE_IMPL
- #include "pnotify.h"
- #include "threadPriority.h"
- #include "pvector.h"
- #include "contextSwitch.h"
- class Thread;
- class ThreadSimpleManager;
- class MutexSimpleImpl;
- /**
- * This is a trivial threading implementation for applications that don't
- * desire full OS-managed threading. It is a user-space implementation of
- * threads implemented via setjmp/longjmp, and therefore it cannot take
- * advantage of multiple CPU's (the application will always run on a single
- * CPU, regardless of the number of threads you spawn).
- *
- * However, since context switching is entirely cooperative, synchronization
- * primitives like mutexes and condition variables aren't necessary, and the
- * Mutex and ConditionVar classes are compiled into trivial no-op classes,
- * which can reduce overhead substantially compared to a truly threaded
- * application.
- *
- * Be sure that every thread calls Thread::consider_yield() occasionally, or
- * it will starve the rest of the running threads.
- */
- class EXPCL_PANDA_PIPELINE ThreadSimpleImpl {
- public:
- ThreadSimpleImpl(Thread *parent_obj);
- ~ThreadSimpleImpl();
- void setup_main_thread();
- bool start(ThreadPriority priority, bool joinable);
- void join();
- void preempt();
- std::string get_unique_id() const;
- static void prepare_for_exit();
- INLINE static Thread *get_current_thread();
- INLINE bool is_same_system_thread() const;
- INLINE static void bind_thread(Thread *thread);
- INLINE static bool is_threading_supported();
- static bool is_true_threads();
- INLINE static bool is_simple_threads();
- INLINE static void sleep(double seconds);
- INLINE static void yield();
- INLINE static void consider_yield();
- void sleep_this(double seconds);
- void yield_this(bool volunteer);
- INLINE void consider_yield_this();
- INLINE double get_wake_time() const;
- INLINE static void write_status(std::ostream &out);
- static bool get_context_switches(size_t &total, size_t &involuntary);
- private:
- static void st_begin_thread(void *data);
- void begin_thread();
- private:
- enum ThreadStatus {
- TS_new,
- TS_running,
- TS_finished,
- TS_killed,
- };
- static int _next_unique_id;
- int _unique_id;
- Thread *_parent_obj;
- bool _joinable;
- ThreadStatus _status;
- ThreadPriority _priority;
- // The relative weight of this thread, relative to other threads, in
- // priority.
- double _priority_weight;
- // The amount of time this thread has run recently.
- unsigned int _run_ticks;
- // This is the time at which the currently-running thread started execution.
- double _start_time;
- // This is the time at which the currently-running thread should yield.
- double _stop_time;
- // This records the time at which a sleeping thread should wake up.
- double _wake_time;
- ThreadContext *_context;
- unsigned char *_stack;
- size_t _stack_size;
- #ifdef HAVE_PYTHON
- // If we might be working with Python, we have to manage the Python thread
- // state as we switch contexts.
- PyThreadState *_python_state;
- #endif // HAVE_PYTHON
- // Threads that are waiting for this thread to finish.
- typedef pvector<ThreadSimpleImpl *> JoiningThreads;
- JoiningThreads _joining_threads;
- ThreadSimpleManager *_manager;
- static ThreadSimpleImpl *volatile _st_this;
- // We may not mix-and-match OS threads with Panda's SIMPLE_THREADS. If we
- // ever get a Panda context switch request from a different OS thread than
- // the thread we think we should be in, that's a serious error that may
- // cause major consequences. For this reason, we store the OS thread's
- // current thread ID here when the thread is constructed, and insist that it
- // never changes during the lifetime of the thread.
- #ifdef HAVE_POSIX_THREADS
- pthread_t _posix_system_thread_id;
- #endif
- #ifdef WIN32
- DWORD _win32_system_thread_id;
- #endif
- size_t _context_switches;
- size_t _involuntary_context_switches;
- friend class ThreadSimpleManager;
- };
- // We include this down here to avoid the circularity problem.
- /* okcircular */
- #include "threadSimpleManager.h"
- #include "threadSimpleImpl.I"
- #endif // THREAD_SIMPLE_IMPL
- #endif
|