Browse Source

set_aux_data -> set_python_data

David Rose 17 years ago
parent
commit
23193a6da1

+ 1 - 1
panda/src/pipeline/conditionVar.h

@@ -30,7 +30,7 @@
 //               The ConditionVar class does not support the full
 //               semantics of POSIX condition variables.  In
 //               particular, it does not support the broadcast or
-//               signal_all function.  See ConditionVarFull for a more
+//               notify_all function.  See ConditionVarFull for a more
 //               complete (but possibly more expensive) API.
 //
 //               A condition variable is associated with a single

+ 4 - 4
panda/src/pipeline/conditionVarSimpleImpl.I

@@ -32,25 +32,25 @@ INLINE ConditionVarSimpleImpl::
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: ConditionVarSimpleImpl::signal
+//     Function: ConditionVarSimpleImpl::notify
 //       Access: Public
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void ConditionVarSimpleImpl::
 notify() {
   if (_flags & F_has_waiters) {
-    do_signal();
+    do_notify();
   }
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: ConditionVarSimpleImpl::signal_all
+//     Function: ConditionVarSimpleImpl::notify_all
 //       Access: Public
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void ConditionVarSimpleImpl::
 notify_all() {
   if (_flags & F_has_waiters) {
-    do_signal_all();
+    do_notify_all();
   }
 }

+ 6 - 6
panda/src/pipeline/conditionVarSimpleImpl.cxx

@@ -26,7 +26,7 @@
 ////////////////////////////////////////////////////////////////////
 void ConditionVarSimpleImpl::
 wait() {
-  _mutex.release();
+  _mutex.release_quietly();
 
   ThreadSimpleManager *manager = ThreadSimpleManager::get_global_ptr();
   ThreadSimpleImpl *thread = manager->get_current_thread();
@@ -43,7 +43,7 @@ wait() {
 ////////////////////////////////////////////////////////////////////
 void ConditionVarSimpleImpl::
 wait(double timeout) {
-  _mutex.release();
+  _mutex.release_quietly();
 
   // TODO.  For now this will release every frame, since we don't have
   // an interface yet on ThreadSimpleManager to do a timed wait.
@@ -58,12 +58,12 @@ wait(double timeout) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: ConditionVarSimpleImpl::do_signal
+//     Function: ConditionVarSimpleImpl::do_notify
 //       Access: Private
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 void ConditionVarSimpleImpl::
-do_signal() {
+do_notify() {
   ThreadSimpleManager *manager = ThreadSimpleManager::get_global_ptr();
   if (manager->unblock_one(this)) {
     // There had been a thread waiting on this condition variable.
@@ -75,12 +75,12 @@ do_signal() {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: ConditionVarSimpleImpl::do_signal_all
+//     Function: ConditionVarSimpleImpl::do_notify_all
 //       Access: Private
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 void ConditionVarSimpleImpl::
-do_signal_all() {
+do_notify_all() {
   ThreadSimpleManager *manager = ThreadSimpleManager::get_global_ptr();
   if (manager->unblock_all(this)) {
     // There had been a thread waiting on this condition variable.

+ 2 - 2
panda/src/pipeline/conditionVarSimpleImpl.h

@@ -39,8 +39,8 @@ public:
   INLINE void notify_all();
 
 private:
-  void do_signal();
-  void do_signal_all();
+  void do_notify();
+  void do_notify_all();
 
   MutexTrueImpl &_mutex;
 };

+ 29 - 6
panda/src/pipeline/mutexDebug.cxx

@@ -84,6 +84,22 @@ output(ostream &out) const {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: MutexDebug::output_with_holder
+//       Access: Public
+//  Description: Reports the mutex as well as the thread that is
+//               currently holding it, if any.
+////////////////////////////////////////////////////////////////////
+void MutexDebug::
+output_with_holder(ostream &out) const {
+  _global_lock->acquire();
+  output(out);
+  if (_locking_thread != (Thread *)NULL) {
+    out << " (held by " << *_locking_thread << ")\n";
+  }
+  _global_lock->release();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: MutexDebug::do_acquire
 //       Access: Private
@@ -182,12 +198,15 @@ do_acquire(Thread *current_thread) {
       }
       
       while (_locking_thread != (Thread *)NULL) {
+        thread_cat.debug()
+          << *current_thread << " still blocking on " << *this << " (held by "
+          << *_locking_thread << ")\n";
         _cvar_impl.wait();
       }
       
       if (thread_cat.is_debug()) {
         thread_cat.debug()
-          << *current_thread << " awake on " << *this << "\n";
+          << *current_thread << " acquired " << *this << "\n";
       }
       
       current_thread->_blocked_on_mutex = NULL;
@@ -234,12 +253,11 @@ do_try_acquire(Thread *current_thread) {
     // count.
     nassertr(_lock_count > 0, false);
     if (!_allow_recursion) {
-      ostringstream ostr;
-      ostr << *current_thread << " attempted to double-lock non-reentrant "
-           << *this;
-      nassert_raise(ostr.str());
+      // Non-recursive lock; return false.
+      acquired = false;
+    } else {
+      ++_lock_count;
     }
-    ++_lock_count;
 
   } else {
     // The mutex is locked by some other thread.  Return false.
@@ -338,6 +356,11 @@ do_release() {
         nassertv(_lock_count > 0);
       }
     } else {
+      
+      if (thread_cat.is_debug()) {
+        thread_cat.debug()
+          << *current_thread << " releasing " << *this << "\n";
+      }
       _cvar_impl.notify();
     }
   }

+ 1 - 0
panda/src/pipeline/mutexDebug.h

@@ -45,6 +45,7 @@ PUBLISHED:
   INLINE bool debug_is_locked() const;
 
   virtual void output(ostream &out) const;
+  void output_with_holder(ostream &out) const;
 
   typedef void VoidFunc();
 

+ 19 - 2
panda/src/pipeline/mutexSimpleImpl.I

@@ -39,7 +39,7 @@ INLINE MutexSimpleImpl::
 INLINE void MutexSimpleImpl::
 acquire() {
   if (!try_acquire()) {
-    do_lock();
+    do_acquire();
   }
 }
 
@@ -60,7 +60,8 @@ try_acquire() {
 ////////////////////////////////////////////////////////////////////
 //     Function: MutexSimpleImpl::release
 //       Access: Public
-//  Description: 
+//  Description: Releases the mutex.  An immediate context switch
+//               might occur if there were waiters on the mutex.
 ////////////////////////////////////////////////////////////////////
 INLINE void MutexSimpleImpl::
 release() {
@@ -71,3 +72,19 @@ release() {
     do_release();
   }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: MutexSimpleImpl::release_quietly
+//       Access: Public
+//  Description: Releases the mutex, without allowing a context switch
+//               to occur.
+////////////////////////////////////////////////////////////////////
+INLINE void MutexSimpleImpl::
+release_quietly() {
+  nassertv((_flags & F_lock_count) != 0);
+  _flags &= ~F_lock_count;
+
+  if (_flags & F_has_waiters) {
+    do_release_quietly();
+  }
+}

+ 13 - 2
panda/src/pipeline/mutexSimpleImpl.cxx

@@ -21,12 +21,12 @@
 #include "threadSimpleManager.h"
 
 ////////////////////////////////////////////////////////////////////
-//     Function: MutexSimpleImpl::do_lock
+//     Function: MutexSimpleImpl::do_acquire
 //       Access: Private
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 void MutexSimpleImpl::
-do_lock() {
+do_acquire() {
   // By the time we get here, we already know that someone else is
   // holding the lock: (_flags & F_lock_count) != 0.
   ThreadSimpleManager *manager = ThreadSimpleManager::get_global_ptr();
@@ -59,4 +59,15 @@ do_release() {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: MutexSimpleImpl::do_release_quietly
+//       Access: Private
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void MutexSimpleImpl::
+do_release_quietly() {
+  ThreadSimpleManager *manager = ThreadSimpleManager::get_global_ptr();
+  manager->unblock_one(this);
+}
+
 #endif  // THREAD_SIMPLE_IMPL

+ 3 - 1
panda/src/pipeline/mutexSimpleImpl.h

@@ -49,10 +49,12 @@ public:
   INLINE void acquire();
   INLINE bool try_acquire();
   INLINE void release();
+  INLINE void release_quietly();
 
 private:
-  void do_lock();
+  void do_acquire();
   void do_release();
+  void do_release_quietly();
 
   friend class ThreadSimpleManager;
 };

+ 11 - 12
panda/src/pipeline/thread.I

@@ -33,18 +33,6 @@ operator = (const Thread &copy) {
   nassertv(false);
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: Thread::get_name
-//       Access: Published
-//  Description: Returns the name of the thread.  Each thread should
-//               probably have a unique name, but this is not enforced
-//               (and not strictly required).
-////////////////////////////////////////////////////////////////////
-INLINE const string &Thread::
-get_name() const {
-  return _name;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: Thread::get_sync_name
 //       Access: Published
@@ -268,6 +256,17 @@ 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

+ 45 - 2
panda/src/pipeline/thread.cxx

@@ -44,7 +44,7 @@ TypeHandle Thread::_type_handle;
 ////////////////////////////////////////////////////////////////////
 Thread::
 Thread(const string &name, const string &sync_name) : 
-  _name(name), 
+  Namable(name), 
   _sync_name(sync_name), 
   _impl(this) 
 {
@@ -52,6 +52,12 @@ Thread(const string &name, const string &sync_name) :
   _pstats_index = -1;
   _pstats_callback = NULL;
   _pipeline_stage = 0;
+  _joinable = false;
+
+#ifdef HAVE_PYTHON
+  _python_data = Py_None;
+  Py_INCREF(_python_data);
+#endif
 
 #ifdef DEBUG_THREADS
   _blocked_on_mutex = NULL;
@@ -73,6 +79,10 @@ Thread(const string &name, const string &sync_name) :
 ////////////////////////////////////////////////////////////////////
 Thread::
 ~Thread() {
+#ifdef HAVE_PYTHON
+  Py_DECREF(_python_data);
+#endif
+
 #ifdef DEBUG_THREADS
   nassertv(_blocked_on_mutex == NULL &&
            _waiting_on_cvar == NULL &&
@@ -172,7 +182,7 @@ void Thread::
 output_blocker(ostream &out) const {
 #ifdef DEBUG_THREADS
   if (_blocked_on_mutex != (MutexDebug *)NULL) {
-    out << *_blocked_on_mutex;
+    _blocked_on_mutex->output_with_holder(out);
   } else if (_waiting_on_cvar != (ConditionVarDebug *)NULL) {
     out << *_waiting_on_cvar;
   } else if (_waiting_on_cvar_full != (ConditionVarFullDebug *)NULL) {
@@ -224,6 +234,7 @@ start(ThreadPriority priority, bool joinable) {
     return false;
   }
 
+  _joinable = joinable;
   _started = _impl.start(priority, joinable);
 
   if (!_started) {
@@ -234,6 +245,38 @@ start(ThreadPriority priority, bool joinable) {
   return _started;
 }
 
+#ifdef HAVE_PYTHON
+////////////////////////////////////////////////////////////////////
+//     Function: Thread::set_python_data
+//       Access: Published
+//  Description: Sets an arbitrary Python object that may be
+//               associated with this thread object.  This is just for
+//               the purposes of associated arbitrary Python data with
+//               the C++ object; other than managing the reference
+//               count, the C++ code does nothing with this object.
+////////////////////////////////////////////////////////////////////
+void Thread::
+set_python_data(PyObject *python_data) {
+  Py_DECREF(_python_data);
+  _python_data = python_data;
+  Py_INCREF(_python_data);
+}
+#endif  // HAVE_PYTHON
+
+#ifdef HAVE_PYTHON
+////////////////////////////////////////////////////////////////////
+//     Function: Thread::get_python_data
+//       Access: Published
+//  Description: Returns the Python object that was set with
+//               set_python_data().
+////////////////////////////////////////////////////////////////////
+PyObject *Thread::
+get_python_data() const {
+  Py_INCREF(_python_data);
+  return _python_data;
+}
+#endif  // HAVE_PYTHON
+
 #ifdef HAVE_PYTHON
 ////////////////////////////////////////////////////////////////////
 //     Function: Thread::call_python_func

+ 16 - 4
panda/src/pipeline/thread.h

@@ -16,6 +16,7 @@
 #define THREAD_H
 
 #include "pandabase.h"
+#include "namable.h"
 #include "typedReferenceCount.h"
 #include "pointerTo.h"
 #include "threadPriority.h"
@@ -46,7 +47,7 @@ class ConditionVarFullDebug;
 //               will automatically be destructed if no other pointers
 //               are referencing it.
 ////////////////////////////////////////////////////////////////////
-class EXPCL_PANDA_PIPELINE Thread : public TypedReferenceCount {
+class EXPCL_PANDA_PIPELINE Thread : public TypedReferenceCount, public Namable {
 protected:
   Thread(const string &name, const string &sync_name);
 
@@ -63,7 +64,6 @@ protected:
 PUBLISHED:
   static PT(Thread) bind_thread(const string &name, const string &sync_name);
 
-  INLINE const string &get_name() const;
   INLINE const string &get_sync_name() const;
 
   INLINE int get_pstats_index() const;
@@ -89,11 +89,17 @@ PUBLISHED:
   static void write_status(ostream &out);
 
   INLINE bool is_started() const;
+  INLINE bool is_joinable() const;
 
   bool start(ThreadPriority priority, bool joinable);
   BLOCKING INLINE void join();
   INLINE void preempt();
 
+#ifdef HAVE_PYTHON
+  void set_python_data(PyObject *python_data);
+  PyObject *get_python_data() const;
+#endif
+
   INLINE static void prepare_for_exit();
 
 public:
@@ -124,12 +130,16 @@ protected:
   bool _started;
 
 private:
-  string _name;
   string _sync_name;
   ThreadImpl _impl;
   int _pstats_index;
   int _pipeline_stage;
   PStatsCallback *_pstats_callback;
+  bool _joinable;
+
+#ifdef HAVE_PYTHON
+  PyObject *_python_data;
+#endif
 
 #ifdef DEBUG_THREADS
   MutexDebug *_blocked_on_mutex;
@@ -147,8 +157,10 @@ public:
   }
   static void init_type() {
     TypedReferenceCount::init_type();
+    Namable::init_type(),
     register_type(_type_handle, "Thread",
-                  TypedReferenceCount::get_class_type());
+                  TypedReferenceCount::get_class_type(),
+                  Namable::get_class_type());
   }
   virtual TypeHandle get_type() const {
     return get_class_type();

+ 1 - 0
panda/src/pipeline/threadSimpleManager.cxx

@@ -153,6 +153,7 @@ unblock_one(BlockerSimple *blocker) {
       blocker->_flags &= ~BlockerSimple::F_has_waiters;
       _blocked.erase(bi);
     }
+
     return true;
   }