[vtk-developers] [Paraview-developers] Moving vtkMemberFunctionCommand to VTK
David Gobbi
david.gobbi at gmail.com
Wed Oct 6 03:08:27 EDT 2010
Here's a new patch that has a working test, to show that
the weak pointers still work for vtkObjectBase objects
but that non-vtkObjectBase handlers work, too.
David
-------------- next part --------------
diff --git a/Common/Testing/Cxx/TestObservers.cxx b/Common/Testing/Cxx/TestObservers.cxx
index 5828177..54833a8 100644
--- a/Common/Testing/Cxx/TestObservers.cxx
+++ b/Common/Testing/Cxx/TestObservers.cxx
@@ -39,6 +39,22 @@ vtkStandardNewMacro(vtkHandler);
int vtkHandler::VoidEventCounts = 0;
vtkstd::map<int, int> vtkHandler::EventCounts;
+class OtherHandler
+{
+public:
+ static vtkstd::map<int, int> EventCounts;
+ static int VoidEventCounts;
+public:
+ void VoidCallback() { this->VoidEventCounts++; }
+ void CallbackWithArguments(vtkObject*, unsigned long event, void*)
+ {
+ this->EventCounts[event]++;
+ }
+};
+
+int OtherHandler::VoidEventCounts = 0;
+vtkstd::map<int, int> OtherHandler::EventCounts;
+
int TestObservers(int, char*[])
{
vtkHandler* handler = vtkHandler::New();
@@ -74,7 +90,8 @@ int TestObservers(int, char*[])
volcano->InvokeEvent(1001);
volcano->InvokeEvent(1002);
- volcano->Delete();
+ // remove the final observer
+ volcano->RemoveObserver(event0);
if (vtkHandler::VoidEventCounts == 2 &&
vtkHandler::EventCounts[1000] == 0 &&
@@ -82,8 +99,55 @@ int TestObservers(int, char*[])
vtkHandler::EventCounts[1002] == 1)
{
cout << "All callback counts as expected." << endl;
+ }
+ else
+ {
+ cerr << "Mismatched callback counts" << endl;
+ volcano->Delete();
+ return 1;
+ }
+
+ // Test again, with a non-VTK object
+
+ OtherHandler *handler2 = new OtherHandler();
+
+ unsigned long event3 = volcano->AddObserver(
+ 1003, handler2, &OtherHandler::VoidCallback);
+ unsigned long event4 = volcano->AddObserver(
+ 1004, handler2, &OtherHandler::CallbackWithArguments);
+ unsigned long event5 = volcano->AddObserver(
+ 1005, handler2, &OtherHandler::CallbackWithArguments);
+
+ volcano->InvokeEvent(1003);
+ volcano->InvokeEvent(1004);
+ volcano->InvokeEvent(1005);
+
+ // let's see if removing an observer works
+ volcano->RemoveObserver(event5);
+ volcano->InvokeEvent(1003);
+ volcano->InvokeEvent(1004);
+ volcano->InvokeEvent(1005);
+
+ // if we delete this non-vtkObject observer, we will
+ // have dangling pointers and will see a crash...
+ // so let's not do that until the events are removed
+
+ volcano->RemoveObserver(event3);
+ volcano->RemoveObserver(event4);
+ delete handler2;
+
+ // delete the observed object
+ volcano->Delete();
+
+ if (OtherHandler::VoidEventCounts == 2 &&
+ OtherHandler::EventCounts[1003] == 0 &&
+ OtherHandler::EventCounts[1004] == 2 &&
+ OtherHandler::EventCounts[1005] == 1)
+ {
+ cout << "All callback counts as expected." << endl;
return 0;
}
- cerr << "Mismatched callback counts" << endl;
+
+ cerr << "Mismatched callback counts " << OtherHandler::EventCounts[1003] << " " << OtherHandler::EventCounts[1004] << " " << OtherHandler::EventCounts[1005] << endl;
return 1;
}
diff --git a/Common/vtkObject.h b/Common/vtkObject.h
index f945c53..034a430 100644
--- a/Common/vtkObject.h
+++ b/Common/vtkObject.h
@@ -227,10 +227,11 @@ private:
void operator=(const vtkObject&); // Not implemented.
// Description:
- // Following classes (vtkClassMemberCallbackBase and vtkClassMemberCallback) along with
+ // Following classes (vtkClassMemberCallbackBase and
+ // vtkClassMemberCallback) along with
// vtkObjectCommandInternal are for supporting
- // templated AddObserver() overloads that allow developers to add event
- // callbacks that are class member functions.
+ // templated AddObserver() overloads that allow developers
+ // to add event callbacks that are class member functions.
class vtkClassMemberCallbackBase
{
public:
@@ -239,7 +240,37 @@ private:
virtual void operator()(vtkObject*, unsigned long, void*) = 0;
virtual ~vtkClassMemberCallbackBase(){}
protected:
- vtkWeakPointerBase Handler;
+
+ // Description:
+ // A weak pointer for vtkObjects, and a void pointer
+ // for everything else.
+ class DualPointer
+ {
+ public:
+ void operator=(vtkObjectBase *o)
+ {
+ this->VoidPointer = 0;
+ this->WeakPointer = o;
+ }
+ void operator=(void *o)
+ {
+ this->VoidPointer = o;
+ this->WeakPointer = 0;
+ }
+ vtkObjectBase *GetPointer()
+ {
+ return this->WeakPointer.GetPointer();
+ }
+ void *GetVoidPointer()
+ {
+ return this->VoidPointer;
+ }
+ private:
+ vtkWeakPointerBase WeakPointer;
+ void *VoidPointer;
+ };
+
+ DualPointer Handler;
};
template <class T>
@@ -266,11 +297,23 @@ private:
virtual ~vtkClassMemberCallback() { }
// Called when the event is invoked
- virtual void operator()(vtkObject* caller, unsigned long event, void* calldata)
+ virtual void operator()(
+ vtkObject* caller, unsigned long event, void* calldata)
{
+ // VoidPointer is for a non-vtkObjectBase handler
+ T* handler = static_cast<T*>(this->Handler.GetVoidPointer());
+ // Pointer is weak pointer for a vtkObjectBase handler
if (this->Handler.GetPointer())
{
- T* handler = dynamic_cast<T*>(this->Handler.GetPointer());
+ handler = dynamic_cast<T*>(this->Handler.GetPointer());
+ // For when dynamic_cast fails due to shared object boundaries
+ if (handler == 0)
+ {
+ handler = (T *)this->Handler.GetPointer();
+ }
+ }
+ if (handler)
+ {
if (this->Method1)
{
(handler->*this->Method1)();
diff --git a/Wrapping/Python/vtkPythonArgs.cxx b/Wrapping/Python/vtkPythonArgs.cxx
index 8e6fd1e..b18634b 100644
--- a/Wrapping/Python/vtkPythonArgs.cxx
+++ b/Wrapping/Python/vtkPythonArgs.cxx
@@ -36,7 +36,7 @@ resulting in wrapper code that is faster and more compact.
#define VTK_PYTHON_FLOAT_CHECK()\
if (PyFloat_Check(o) && \
PyErr_Warn(PyExc_DeprecationWarning, \
- "integer argument expected, got float")) \
+ (char *)"integer argument expected, got float")) \
{ \
return false; \
}
More information about the vtk-developers
mailing list