open_toontown_panda3d/panda/src/pipeline/threadSimpleImpl.h

147 lines
4.1 KiB
C++

// Filename: threadSimpleImpl.h
// Created by: drose (18Jun07)
//
////////////////////////////////////////////////////////////////////
//
// 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."
//
////////////////////////////////////////////////////////////////////
#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"
#ifdef HAVE_PYTHON
#undef _POSIX_C_SOURCE
#include <Python.h>
#endif // HAVE_PYTHON
class Thread;
class ThreadSimpleManager;
class MutexSimpleImpl;
////////////////////////////////////////////////////////////////////
// Class : ThreadSimpleImpl
// Description : 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();
string get_unique_id() const;
static void prepare_for_exit();
INLINE static Thread *get_current_thread();
INLINE static void bind_thread(Thread *thread);
INLINE static bool is_threading_supported();
INLINE static bool is_true_threads();
INLINE static void sleep(double seconds);
INLINE static void yield();
INLINE static void consider_yield();
void sleep_this(double seconds);
void yield_this();
INLINE void consider_yield_this();
INLINE double get_start_time() const;
INLINE static void write_status(ostream &out);
private:
static void st_begin_thread(void *data);
void begin_thread();
private:
enum Status {
S_new,
S_running,
S_finished,
S_killed,
};
static int _next_unique_id;
int _unique_id;
Thread *_parent_obj;
bool _joinable;
Status _status;
// The (approx) amount of time this thread is allowed to run each
// epoch.
double _time_per_epoch;
// This serves both as the time at which the current thread started
// to run, and also records the time at which a sleeping thread
// should wake up.
double _start_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;
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