388 lines
15 KiB
Plaintext
388 lines
15 KiB
Plaintext
// Filename: thread.I
|
|
// Created by: drose (08Aug02)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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."
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: Thread::Copy Constructor
|
|
// Access: Private
|
|
// Description: Do not attempt to copy threads.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE Thread::
|
|
Thread(const Thread ©) : _impl(this) {
|
|
nassertv(false);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: Thread::Copy Assignment Operator
|
|
// Access: Private
|
|
// Description: Do not attempt to copy threads.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void Thread::
|
|
operator = (const Thread ©) {
|
|
nassertv(false);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: Thread::get_sync_name
|
|
// Access: Published
|
|
// Description: Returns the sync name of the thread. This name
|
|
// collects threads into "sync groups", which are
|
|
// expected to run synchronously. This is mainly used
|
|
// for the benefit of PStats; threads with the same sync
|
|
// name can be ticked all at once via the thread_tick()
|
|
// call.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE const string &Thread::
|
|
get_sync_name() const {
|
|
return _sync_name;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: Thread::get_pstats_index
|
|
// Access: Published
|
|
// Description: Returns the PStats index associated with this thread,
|
|
// or -1 if no index has yet been associated with this
|
|
// thread. This is used internally by the PStatClient;
|
|
// you should not need to call this directly.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE int Thread::
|
|
get_pstats_index() const {
|
|
return _pstats_index;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: Thread::get_unique_id
|
|
// Access: Published
|
|
// Description: Returns a string that is guaranteed to be unique to
|
|
// this thread, across all processes on the machine,
|
|
// during at least the lifetime of this process.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE string Thread::
|
|
get_unique_id() const {
|
|
return _impl.get_unique_id();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: Thread::get_pipeline_stage
|
|
// Access: Published
|
|
// Description: Returns the Pipeline stage number associated with
|
|
// this thread. The default stage is 0 if no stage is
|
|
// specified otherwise. See set_pipeline_stage().
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE int Thread::
|
|
get_pipeline_stage() const {
|
|
return _pipeline_stage;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: Thread::set_min_pipeline_stage
|
|
// Access: Published
|
|
// Description: Sets this thread's pipeline stage number to at least
|
|
// the indicated value, unless it is already larger.
|
|
// See set_pipeline_stage().
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void Thread::
|
|
set_min_pipeline_stage(int min_pipeline_stage) {
|
|
set_pipeline_stage(max(_pipeline_stage, min_pipeline_stage));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: Thread::get_main_thread
|
|
// Access: Published, Static
|
|
// Description: Returns a pointer to the "main" Thread object--this
|
|
// is the Thread that started the whole process.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE Thread *Thread::
|
|
get_main_thread() {
|
|
if (_main_thread == (Thread *)NULL) {
|
|
init_main_thread();
|
|
}
|
|
return _main_thread;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: Thread::get_external_thread
|
|
// Access: Published, Static
|
|
// Description: Returns a pointer to the "external" Thread
|
|
// object--this is a special Thread object that
|
|
// corresponds to any thread spawned outside of Panda's
|
|
// threading interface. Note that multiple different
|
|
// threads may share this same pointer.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE Thread *Thread::
|
|
get_external_thread() {
|
|
if (_external_thread == (Thread *)NULL) {
|
|
init_external_thread();
|
|
}
|
|
return _external_thread;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: Thread::get_current_thread
|
|
// Access: Published, Static
|
|
// Description: Returns a pointer to the currently-executing Thread
|
|
// object. If this is called from the main thread, this
|
|
// will return the same value as get_main_thread().
|
|
//
|
|
// This will always return some valid Thread pointer.
|
|
// It will never return NULL, even if the current thread
|
|
// was spawned outside of Panda's threading system,
|
|
// although all non-Panda threads will return the exact
|
|
// same Thread pointer.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE Thread *Thread::
|
|
get_current_thread() {
|
|
TAU_PROFILE("Thread *Thread::get_current_thread()", " ", TAU_USER);
|
|
#ifndef HAVE_THREADS
|
|
return get_main_thread();
|
|
#else // HAVE_THREADS
|
|
Thread *thread = ThreadImpl::get_current_thread();
|
|
if (thread == (Thread *)NULL) {
|
|
return Thread::get_external_thread();
|
|
}
|
|
return thread;
|
|
#endif // HAVE_THREADS
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: Thread::get_current_pipeline_stage
|
|
// Access: Published, Static
|
|
// Description: Returns the integer pipeline stage associated with
|
|
// the current thread. This is the same thing as
|
|
// get_current_thread()->get_pipeline_stage(), but it
|
|
// may be faster to retrieve in some contexts.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE int Thread::
|
|
get_current_pipeline_stage() {
|
|
TAU_PROFILE("int Thread::get_current_pipeline_stage()", " ", TAU_USER);
|
|
#ifndef THREADED_PIPELINE
|
|
// Without threaded pipelining, the result is always 0.
|
|
return 0;
|
|
#else
|
|
return get_current_thread()->get_pipeline_stage();
|
|
#endif // !THREADED_PIPELINE
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: Thread::is_threading_supported
|
|
// Access: Published, Static
|
|
// Description: Returns true if threading support has been compiled
|
|
// in and enabled, or false if no threading is available
|
|
// (and Thread::start() will always fail).
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE bool Thread::
|
|
is_threading_supported() {
|
|
if (!support_threads) {
|
|
return false;
|
|
}
|
|
return ThreadImpl::is_threading_supported();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: Thread::is_true_threads
|
|
// Access: Published, Static
|
|
// Description: Returns true if a real threading library is available
|
|
// that supports actual OS-implemented threads, or false
|
|
// if the only threading we can provide is simulated
|
|
// user-space threading.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE bool Thread::
|
|
is_true_threads() {
|
|
if (!support_threads) {
|
|
return false;
|
|
}
|
|
return ThreadImpl::is_true_threads();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: Thread::is_simple_threads
|
|
// Access: Published, Static
|
|
// Description: Returns true if Panda is currently compiled for
|
|
// "simple threads", which is to say, cooperative
|
|
// context switching only, reducing the need for quite
|
|
// so many critical section protections. This is not
|
|
// necessarily the opposite of "true threads", since one
|
|
// possible implementation of simple threads is via true
|
|
// threads with mutex protection to ensure only one runs
|
|
// at a time.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE bool Thread::
|
|
is_simple_threads() {
|
|
if (!support_threads) {
|
|
return false;
|
|
}
|
|
return ThreadImpl::is_simple_threads();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: Thread::sleep
|
|
// Access: Published, Static
|
|
// Description: Suspends the current thread for at least the
|
|
// indicated amount of time. It might be suspended for
|
|
// longer.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void Thread::
|
|
sleep(double seconds) {
|
|
TAU_PROFILE("void Thread::sleep(double)", " ", TAU_USER);
|
|
ThreadImpl::sleep(seconds);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: Thread::field_yield
|
|
// Access: Published, Static
|
|
// Description: Suspends the current thread for the rest of the
|
|
// current epoch.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void Thread::
|
|
force_yield() {
|
|
TAU_PROFILE("void Thread::yield()", " ", TAU_USER);
|
|
ThreadImpl::yield();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: Thread::consider_yield
|
|
// Access: Published, Static
|
|
// Description: Possibly suspends the current thread for the rest of
|
|
// the current epoch, if it has run for enough this
|
|
// epoch. This is especially important for the simple
|
|
// thread implementation, which relies on cooperative
|
|
// yields like this.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void Thread::
|
|
consider_yield() {
|
|
TAU_PROFILE("void Thread::consider_yield()", " ", TAU_USER);
|
|
ThreadImpl::consider_yield();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: Thread::is_started
|
|
// Access: Published
|
|
// Description: Returns true if the thread has been started, false if
|
|
// it has not, or if join() has already been called.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE bool Thread::
|
|
is_started() const {
|
|
return _started;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: Thread::is_joinable
|
|
// Access: Published
|
|
// Description: Returns the value of joinable that was passed to the
|
|
// start() call.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE bool Thread::
|
|
is_joinable() const {
|
|
return _joinable;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: Thread::join
|
|
// Access: Published
|
|
// Description: Blocks the calling process until the thread
|
|
// terminates. If the thread has already terminated,
|
|
// this returns immediately.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void Thread::
|
|
join() {
|
|
TAU_PROFILE("void Thread::join()", " ", TAU_USER);
|
|
if (_started) {
|
|
_impl.join();
|
|
_started = false;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: Thread::preempt
|
|
// Access: Published
|
|
// Description: Indicates that this thread should run as soon as
|
|
// possible, preemptying any other threads that may be
|
|
// scheduled to run. This may not be implemented on
|
|
// every platform.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void Thread::
|
|
preempt() {
|
|
if (_started) {
|
|
_impl.preempt();
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: Thread::get_current_task
|
|
// Access: Published
|
|
// Description: Returns the task currently executing on this thread
|
|
// (via the AsyncTaskManager), if any, or NULL if the
|
|
// thread is not currently servicing a task.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE AsyncTaskBase *Thread::
|
|
get_current_task() const {
|
|
return _current_task;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: Thread::prepare_for_exit
|
|
// Access: Published
|
|
// Description: Should be called by the main thread just before
|
|
// exiting the program, this blocks until any remaining
|
|
// thread cleanup has finished.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void Thread::
|
|
prepare_for_exit() {
|
|
ThreadImpl::prepare_for_exit();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: Thread::set_pstats_index
|
|
// Access: Public
|
|
// Description: Stores a PStats index to be associated with this
|
|
// thread. This is used internally by the PStatClient;
|
|
// you should not need to call this directly.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void Thread::
|
|
set_pstats_index(int pstats_index) {
|
|
_pstats_index = pstats_index;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: Thread::set_pstats_callback
|
|
// Access: Public
|
|
// Description: Stores a PStats callback to be associated with this
|
|
// thread. This is used internally by the PStatClient;
|
|
// you should not need to call this directly.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void Thread::
|
|
set_pstats_callback(Thread::PStatsCallback *pstats_callback) {
|
|
_pstats_callback = pstats_callback;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: Thread::get_pstats_callback
|
|
// Access: Public
|
|
// Description: Returns the PStats callback associated with this thread,
|
|
// or NULL if no callback has yet been associated with
|
|
// this thread. This is used internally by the
|
|
// PStatClient; you should not need to call this
|
|
// directly.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE Thread::PStatsCallback *Thread::
|
|
get_pstats_callback() const {
|
|
return _pstats_callback;
|
|
}
|
|
|
|
INLINE ostream &
|
|
operator << (ostream &out, const Thread &thread) {
|
|
thread.output(out);
|
|
return out;
|
|
}
|