David Rose пре 17 година
родитељ
комит
7683d94100

+ 18 - 2
panda/src/event/asyncTask.cxx

@@ -445,6 +445,11 @@ do_task() {
 ////////////////////////////////////////////////////////////////////
 void AsyncTask::
 upon_birth() {
+  // Throw a generic add event for the manager.
+  string add_name = _manager->get_name() + "-addTask";
+  PT_Event event = new Event(add_name);
+  event->add_parameter(EventParameter(this));
+  throw_event(event);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -455,7 +460,10 @@ upon_birth() {
 //               parameter clean_exit is true if the task has been
 //               removed because it exited normally (returning
 //               DS_done), or false if it was removed for some other
-//               reason (e.g. AsyncTaskManager::remove()).
+//               reason (e.g. AsyncTaskManager::remove()).  By the
+//               time this method is called, _manager has been
+//               cleared, so the parameter manager indicates the
+//               original AsyncTaskManager that owned this task.
 //
 //               The normal behavior is to throw the done_event only
 //               if clean_exit is true.
@@ -463,10 +471,18 @@ upon_birth() {
 //               This function is called with the lock *not* held.
 ////////////////////////////////////////////////////////////////////
 void AsyncTask::
-upon_death(bool clean_exit) {
+upon_death(AsyncTaskManager *manager, bool clean_exit) {
   if (clean_exit && !_done_event.empty()) {
     PT_Event event = new Event(_done_event);
     event->add_parameter(EventParameter(this));
     throw_event(event);
   }
+
+  // Also throw a generic remove event for the manager.
+  if (manager != (AsyncTaskManager *)NULL) {
+    string remove_name = manager->get_name() + "-removeTask";
+    PT_Event event = new Event(remove_name);
+    event->add_parameter(EventParameter(this));
+    throw_event(event);
+  }
 }

+ 1 - 1
panda/src/event/asyncTask.h

@@ -119,7 +119,7 @@ protected:
   virtual bool is_runnable();
   virtual DoneStatus do_task();
   virtual void upon_birth();
-  virtual void upon_death(bool clean_exit);
+  virtual void upon_death(AsyncTaskManager *manager, bool clean_exit);
 
 protected:
   AtomicAdjust::Integer _task_id;

+ 2 - 2
panda/src/event/asyncTaskChain.cxx

@@ -645,7 +645,7 @@ do_cleanup() {
   // Now go back and call the upon_death functions.
   _manager->_lock.release();
   for (ti = dead.begin(); ti != dead.end(); ++ti) {
-    (*ti)->upon_death(false);
+    (*ti)->upon_death(_manager, false);
   }
   _manager->_lock.lock();
 
@@ -843,7 +843,7 @@ cleanup_task(AsyncTask *task, bool upon_death, bool clean_exit) {
 
   if (upon_death) {
     _manager->_lock.release();
-    task->upon_death(clean_exit);
+    task->upon_death(_manager, clean_exit);
     _manager->_lock.lock();
   }
 }

+ 2 - 4
panda/src/event/asyncTaskManager.cxx

@@ -15,8 +15,6 @@
 #include "asyncTaskManager.h"
 #include "event.h"
 #include "pt_Event.h"
-#include "throw_event.h"
-#include "eventParameter.h"
 #include "mutexHolder.h"
 #include "indent.h"
 #include "pStatClient.h"
@@ -375,7 +373,7 @@ remove(const AsyncTaskCollection &tasks) {
       }
       if (task->_chain->do_remove(task)) {
         _lock.release();
-        task->upon_death(false);
+        task->upon_death(this, false);
         _lock.lock();
         ++num_removed;
       } else {
@@ -727,5 +725,5 @@ void AsyncTaskManager::
 make_global_ptr() {
   nassertv(_global_ptr == (AsyncTaskManager *)NULL);
 
-  _global_ptr = new AsyncTaskManager("taskMgr");
+  _global_ptr = new AsyncTaskManager("TaskManager");
 }

+ 7 - 4
panda/src/event/asyncTaskSequence.cxx

@@ -146,7 +146,10 @@ upon_birth() {
 //               parameter clean_exit is true if the task has been
 //               removed because it exited normally (returning
 //               DS_done), or false if it was removed for some other
-//               reason (e.g. AsyncTaskManager::remove()).
+//               reason (e.g. AsyncTaskManager::remove()).  By the
+//               time this method is called, _manager has been
+//               cleared, so the parameter manager indicates the
+//               original AsyncTaskManager that owned this task.
 //
 //               The normal behavior is to throw the done_event only
 //               if clean_exit is true.
@@ -156,8 +159,8 @@ upon_birth() {
 //               return with it held.
 ////////////////////////////////////////////////////////////////////
 void AsyncTaskSequence::
-upon_death(bool clean_exit) {
-  AsyncTask::upon_death(clean_exit);
+upon_death(AsyncTaskManager *manager, bool clean_exit) {
+  AsyncTask::upon_death(manager, clean_exit);
   set_current_task(NULL, clean_exit);
 }
 
@@ -177,7 +180,7 @@ set_current_task(AsyncTask *task, bool clean_exit) {
     nassertv(_current_task->_state == S_active_nested);
     nassertv(_current_task->_manager == _manager || _manager == NULL);
     _current_task->_state = S_inactive;
-    _current_task->upon_death(clean_exit);
+    _current_task->upon_death(_manager, clean_exit);
     _current_task->_manager = NULL;
   }
 

+ 1 - 1
panda/src/event/asyncTaskSequence.h

@@ -49,7 +49,7 @@ protected:
   virtual bool is_runnable();
   virtual DoneStatus do_task();
   virtual void upon_birth();
-  virtual void upon_death(bool clean_exit);
+  virtual void upon_death(AsyncTaskManager *manager, bool clean_exit);
 
 private:
   void set_current_task(AsyncTask *task, bool clean_exit);

+ 6 - 3
panda/src/event/genericAsyncTask.cxx

@@ -101,7 +101,10 @@ upon_birth() {
 //               parameter clean_exit is true if the task has been
 //               removed because it exited normally (returning
 //               DS_done), or false if it was removed for some other
-//               reason (e.g. AsyncTaskManager::remove()).
+//               reason (e.g. AsyncTaskManager::remove()).  By the
+//               time this method is called, _manager has been
+//               cleared, so the parameter manager indicates the
+//               original AsyncTaskManager that owned this task.
 //
 //               The normal behavior is to throw the done_event only
 //               if clean_exit is true.
@@ -109,8 +112,8 @@ upon_birth() {
 //               This function is called with the lock *not* held.
 ////////////////////////////////////////////////////////////////////
 void GenericAsyncTask::
-upon_death(bool clean_exit) {
-  AsyncTask::upon_death(clean_exit);
+upon_death(AsyncTaskManager *manager, bool clean_exit) {
+  AsyncTask::upon_death(manager, clean_exit);
 
   if (_upon_death != NULL) {
     (*_upon_death)(this, clean_exit, _user_data);

+ 1 - 1
panda/src/event/genericAsyncTask.h

@@ -51,7 +51,7 @@ protected:
   virtual bool is_runnable();
   virtual DoneStatus do_task();
   virtual void upon_birth();
-  virtual void upon_death(bool clean_exit);
+  virtual void upon_death(AsyncTaskManager *manager, bool clean_exit);
 
 private:
   TaskFunc *_function;

+ 56 - 22
panda/src/event/pythonTask.cxx

@@ -205,7 +205,7 @@ get_upon_death() {
 void PythonTask::
 set_owner(PyObject *owner) {
   if (_owner != NULL && _owner != Py_None && _state != S_inactive) {
-    upon_death(false);
+    unregister_from_owner();
   }
 
   Py_XDECREF(_owner);
@@ -213,7 +213,7 @@ set_owner(PyObject *owner) {
   Py_INCREF(_owner);
 
   if (_owner != Py_None && _state != S_inactive) {
-    upon_birth();
+    register_to_owner();
   }
 }
 
@@ -477,7 +477,54 @@ do_python_task() {
 void PythonTask::
 upon_birth() {
   AsyncTask::upon_birth();
+  register_to_owner();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PythonTask::upon_death
+//       Access: Protected, Virtual
+//  Description: Override this function to do something useful when the
+//               task has been removed from the active queue.  The
+//               parameter clean_exit is true if the task has been
+//               removed because it exited normally (returning
+//               DS_done), or false if it was removed for some other
+//               reason (e.g. AsyncTaskManager::remove()).  By the
+//               time this method is called, _manager has been
+//               cleared, so the parameter manager indicates the
+//               original AsyncTaskManager that owned this task.
+//
+//               The normal behavior is to throw the done_event only
+//               if clean_exit is true.
+//
+//               This function is called with the lock *not* held.
+////////////////////////////////////////////////////////////////////
+void PythonTask::
+upon_death(AsyncTaskManager *manager, bool clean_exit) {
+  AsyncTask::upon_death(manager, clean_exit);
 
+  if (_upon_death != Py_None) {
+#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
+    // Use PyGILState to protect this asynchronous call.
+    PyGILState_STATE gstate;
+    gstate = PyGILState_Ensure();
+#endif
+    
+    call_function(_upon_death);
+    
+#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
+    PyGILState_Release(gstate);
+#endif
+  }
+  unregister_from_owner();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PythonTask::register_to_owner
+//       Access: Private
+//  Description: Tells the owner we are now his task.
+////////////////////////////////////////////////////////////////////
+void PythonTask::
+register_to_owner() {
   if (_owner != Py_None) {
 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
     // Use PyGILState to protect this asynchronous call.
@@ -494,25 +541,13 @@ upon_birth() {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: PythonTask::upon_death
-//       Access: Protected, Virtual
-//  Description: Override this function to do something useful when the
-//               task has been removed from the active queue.  The
-//               parameter clean_exit is true if the task has been
-//               removed because it exited normally (returning
-//               DS_done), or false if it was removed for some other
-//               reason (e.g. AsyncTaskManager::remove()).
-//
-//               The normal behavior is to throw the done_event only
-//               if clean_exit is true.
-//
-//               This function is called with the lock *not* held.
+//     Function: PythonTask::unregister_from_owner
+//       Access: Private
+//  Description: Tells the owner we are no longer his task.
 ////////////////////////////////////////////////////////////////////
 void PythonTask::
-upon_death(bool clean_exit) {
-  AsyncTask::upon_death(clean_exit);
-
-  if (_owner != Py_None && _upon_death != Py_None) {
+unregister_from_owner() {
+  if (_owner != Py_None) {
 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
     // Use PyGILState to protect this asynchronous call.
     PyGILState_STATE gstate;
@@ -520,7 +555,6 @@ upon_death(bool clean_exit) {
 #endif
     
     call_owner_method("_clearTask");
-    call_function(_upon_death);
     
 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
     PyGILState_Release(gstate);
@@ -530,7 +564,7 @@ upon_death(bool clean_exit) {
 
 ////////////////////////////////////////////////////////////////////
 //     Function: PythonTask::call_owner_method
-//       Access: Protected
+//       Access: Private
 //  Description: Calls the indicated method name on the given object,
 //               if defined, passing in the task object as the only
 //               parameter.
@@ -555,7 +589,7 @@ call_owner_method(const char *method_name) {
 
 ////////////////////////////////////////////////////////////////////
 //     Function: PythonTask::call_function
-//       Access: Protected
+//       Access: Private
 //  Description: Calls the indicated Python function, passing in the
 //               task object as the only parameter.
 ////////////////////////////////////////////////////////////////////

+ 4 - 1
panda/src/event/pythonTask.h

@@ -52,8 +52,11 @@ protected:
   virtual DoneStatus do_task();
   DoneStatus do_python_task();
   virtual void upon_birth();
-  virtual void upon_death(bool clean_exit);
+  virtual void upon_death(AsyncTaskManager *manager, bool clean_exit);
 
+private:
+  void register_to_owner();
+  void unregister_from_owner();
   void call_owner_method(const char *method_name);
   void call_function(PyObject *function);