From fbf81f90eb0a578d9c5d4352fa554489eb1e44d0 Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 9 Jul 2009 20:14:19 +0000 Subject: [PATCH] P3D_object needs to be reference-counted --- direct/src/plugin/p3dBoolObject.cxx | 8 +- direct/src/plugin/p3dBoolObject.h | 8 +- direct/src/plugin/p3dFloatObject.cxx | 10 +- direct/src/plugin/p3dFloatObject.h | 10 +- direct/src/plugin/p3dInstance.cxx | 60 +++++--- direct/src/plugin/p3dInstanceManager.I | 37 +++++ direct/src/plugin/p3dInstanceManager.cxx | 25 ++++ direct/src/plugin/p3dInstanceManager.h | 9 ++ direct/src/plugin/p3dIntObject.cxx | 8 +- direct/src/plugin/p3dIntObject.h | 8 +- direct/src/plugin/p3dNoneObject.cxx | 6 +- direct/src/plugin/p3dNoneObject.h | 6 +- direct/src/plugin/p3dObject.I | 36 ----- direct/src/plugin/p3dObject.cxx | 122 ++++++----------- direct/src/plugin/p3dObject.h | 34 ++--- direct/src/plugin/p3dPythonObject.cxx | 38 +++--- direct/src/plugin/p3dPythonObject.h | 20 +-- direct/src/plugin/p3dSession.cxx | 30 ++-- direct/src/plugin/p3dSession.h | 2 +- direct/src/plugin/p3dStringObject.cxx | 8 +- direct/src/plugin/p3dStringObject.h | 8 +- direct/src/plugin/p3dUndefinedObject.cxx | 6 +- direct/src/plugin/p3dUndefinedObject.h | 6 +- direct/src/plugin/p3d_plugin.cxx | 11 +- direct/src/plugin/p3d_plugin.h | 144 ++++++++++---------- direct/src/plugin/p3d_plugin_common.h | 2 +- direct/src/plugin_npapi/ppBrowserObject.cxx | 18 +-- direct/src/plugin_npapi/ppInstance.cxx | 8 +- direct/src/plugin_npapi/ppInstance.h | 2 +- direct/src/plugin_npapi/ppPandaObject.I | 4 + direct/src/plugin_npapi/ppPandaObject.cxx | 33 +++-- 31 files changed, 380 insertions(+), 347 deletions(-) diff --git a/direct/src/plugin/p3dBoolObject.cxx b/direct/src/plugin/p3dBoolObject.cxx index 979cf4345f..6f82e7354d 100644 --- a/direct/src/plugin/p3dBoolObject.cxx +++ b/direct/src/plugin/p3dBoolObject.cxx @@ -41,7 +41,7 @@ P3DBoolObject(const P3DBoolObject ©) : // Description: Returns the fundamental type of this kind of object. //////////////////////////////////////////////////////////////////// P3D_object_type P3DBoolObject:: -get_type() const { +get_type() { return P3D_OT_bool; } @@ -52,7 +52,7 @@ get_type() const { // possible. //////////////////////////////////////////////////////////////////// bool P3DBoolObject:: -get_bool() const { +get_bool() { return _value; } @@ -63,7 +63,7 @@ get_bool() const { // possible. //////////////////////////////////////////////////////////////////// int P3DBoolObject:: -get_int() const { +get_int() { return _value; } @@ -74,7 +74,7 @@ get_int() const { // of this object coerced to a string. //////////////////////////////////////////////////////////////////// void P3DBoolObject:: -make_string(string &value) const { +make_string(string &value) { if (_value) { value = "True"; } else { diff --git a/direct/src/plugin/p3dBoolObject.h b/direct/src/plugin/p3dBoolObject.h index eff3eb1cc1..e07bf8f691 100644 --- a/direct/src/plugin/p3dBoolObject.h +++ b/direct/src/plugin/p3dBoolObject.h @@ -28,10 +28,10 @@ public: P3DBoolObject(const P3DBoolObject ©); public: - virtual P3D_object_type get_type() const; - virtual bool get_bool() const; - virtual int get_int() const; - virtual void make_string(string &value) const; + virtual P3D_object_type get_type(); + virtual bool get_bool(); + virtual int get_int(); + virtual void make_string(string &value); private: bool _value; diff --git a/direct/src/plugin/p3dFloatObject.cxx b/direct/src/plugin/p3dFloatObject.cxx index 5bb08042ca..2de0343fe3 100644 --- a/direct/src/plugin/p3dFloatObject.cxx +++ b/direct/src/plugin/p3dFloatObject.cxx @@ -41,7 +41,7 @@ P3DFloatObject(const P3DFloatObject ©) : // Description: Returns the fundamental type of this kind of object. //////////////////////////////////////////////////////////////////// P3D_object_type P3DFloatObject:: -get_type() const { +get_type() { return P3D_OT_float; } @@ -52,7 +52,7 @@ get_type() const { // possible. //////////////////////////////////////////////////////////////////// bool P3DFloatObject:: -get_bool() const { +get_bool() { return (_value != 0.0); } @@ -63,7 +63,7 @@ get_bool() const { // possible. //////////////////////////////////////////////////////////////////// int P3DFloatObject:: -get_int() const { +get_int() { return (int)_value; } @@ -74,7 +74,7 @@ get_int() const { // value, if possible. //////////////////////////////////////////////////////////////////// double P3DFloatObject:: -get_float() const { +get_float() { return _value; } @@ -85,7 +85,7 @@ get_float() const { // of this object coerced to a string. //////////////////////////////////////////////////////////////////// void P3DFloatObject:: -make_string(string &value) const { +make_string(string &value) { ostringstream strm; strm << _value; value = strm.str(); diff --git a/direct/src/plugin/p3dFloatObject.h b/direct/src/plugin/p3dFloatObject.h index 9be4927af0..e397993404 100644 --- a/direct/src/plugin/p3dFloatObject.h +++ b/direct/src/plugin/p3dFloatObject.h @@ -28,11 +28,11 @@ public: P3DFloatObject(const P3DFloatObject ©); public: - virtual P3D_object_type get_type() const; - virtual bool get_bool() const; - virtual int get_int() const; - virtual double get_float() const; - virtual void make_string(string &value) const; + virtual P3D_object_type get_type(); + virtual bool get_bool(); + virtual int get_int(); + virtual double get_float(); + virtual void make_string(string &value); private: double _value; diff --git a/direct/src/plugin/p3dInstance.cxx b/direct/src/plugin/p3dInstance.cxx index af5a48f326..d6111add3f 100644 --- a/direct/src/plugin/p3dInstance.cxx +++ b/direct/src/plugin/p3dInstance.cxx @@ -73,9 +73,7 @@ P3DInstance:: ~P3DInstance() { assert(_session == NULL); - if (_browser_script_object != NULL) { - P3D_OBJECT_FINISH(_browser_script_object); - } + P3D_OBJECT_XDECREF(_browser_script_object); DESTROY_LOCK(_request_lock); @@ -118,6 +116,7 @@ set_fparams(const P3DFileParams &fparams) { strm << inst_mgr->get_unique_session_index(); _session_key = strm.str(); + // TODO. _python_version = "python24"; @@ -200,7 +199,8 @@ get_panda_script_object() const { } if (result == NULL) { - result = new P3DUndefinedObject; + P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); + result = inst_mgr->new_undefined_object(); } return result; @@ -211,16 +211,18 @@ get_panda_script_object() const { // Access: Public // Description: Stores a pointer to the top-level window object // of the browser, to be used by Panda code to control -// JavaScript. Ownership of this object is passed into -// the instance. +// JavaScript. The new object's reference count is +// incremented, and the previous object's is +// decremented. //////////////////////////////////////////////////////////////////// void P3DInstance:: set_browser_script_object(P3D_object *browser_script_object) { if (browser_script_object != _browser_script_object) { - if (_browser_script_object != NULL) { - P3D_OBJECT_FINISH(_browser_script_object); - } + P3D_OBJECT_XDECREF(_browser_script_object); _browser_script_object = browser_script_object; + if (_browser_script_object != NULL) { + P3D_OBJECT_INCREF(_browser_script_object); + } if (_session != NULL) { send_browser_script_object(); @@ -317,6 +319,36 @@ void P3DInstance:: finish_request(P3D_request *request, bool handled) { assert(request != NULL); + switch (request->_request_type) { + case P3D_RT_stop: + break; + + case P3D_RT_get_url: + free((char *)request->_request._get_url._url); + break; + + case P3D_RT_post_url: + free((char *)request->_request._post_url._url); + free((char *)request->_request._post_url._post_data); + break; + + case P3D_RT_notify: + free((char *)request->_request._notify._message); + break; + + case P3D_RT_script: + { + P3D_OBJECT_DECREF(request->_request._script._object); + if (request->_request._script._property_name != NULL) { + free((char *)request->_request._script._property_name); + } + for (int i = 0; i < request->_request._script._num_values; ++i) { + P3D_OBJECT_DECREF(request->_request._script._values[i]); + } + } + break; + } + delete request; } @@ -519,7 +551,7 @@ handle_script_request(P3D_request *request) { doc->LinkEndChild(xcommand); if (result != NULL) { xcommand->LinkEndChild(_session->p3dobj_to_xml(result)); - P3D_OBJECT_FINISH(result); + P3D_OBJECT_DECREF(result); } if (needs_response) { @@ -598,10 +630,6 @@ handle_script_request(P3D_request *request) { P3D_OBJECT_CALL(object, request->_request._script._property_name, request->_request._script._values, request->_request._script._num_values); - // Reset the value count to 0 so we won't double-delete the - // parameter values when the request is deleted (the above call - // has already deleted them). - request->_request._script._num_values = 0; // Feed the result back down to the subprocess. TiXmlDocument *doc = new TiXmlDocument; @@ -615,7 +643,7 @@ handle_script_request(P3D_request *request) { if (result != NULL) { xcommand->LinkEndChild(_session->p3dobj_to_xml(result)); - P3D_OBJECT_FINISH(result); + P3D_OBJECT_DECREF(result); } if (needs_response) { @@ -654,7 +682,7 @@ handle_script_request(P3D_request *request) { if (result != NULL) { xcommand->LinkEndChild(_session->p3dobj_to_xml(result)); - P3D_OBJECT_FINISH(result); + P3D_OBJECT_DECREF(result); } logfile << "eval response: " << *doc << "\n"; diff --git a/direct/src/plugin/p3dInstanceManager.I b/direct/src/plugin/p3dInstanceManager.I index 50e3b8edbe..b816349824 100644 --- a/direct/src/plugin/p3dInstanceManager.I +++ b/direct/src/plugin/p3dInstanceManager.I @@ -70,3 +70,40 @@ inline int P3DInstanceManager:: get_num_instances() const { return _instances.size(); } + +//////////////////////////////////////////////////////////////////// +// Function: P3DInstanceManager::new_undefined_object +// Access: Public +// Description: Returns the singleton "undefined" object, as a new +// reference. +//////////////////////////////////////////////////////////////////// +inline P3D_object *P3DInstanceManager:: +new_undefined_object() { + P3D_OBJECT_INCREF(_undefined_object); + return _undefined_object; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DInstanceManager::new_none_object +// Access: Public +// Description: Returns the singleton "none" object, as a new +// reference. +//////////////////////////////////////////////////////////////////// +inline P3D_object *P3DInstanceManager:: +new_none_object() { + P3D_OBJECT_INCREF(_none_object); + return _none_object; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DInstanceManager::new_bool_object +// Access: Public +// Description: Returns the singleton "true" or "false" object, as a +// new reference. +//////////////////////////////////////////////////////////////////// +inline P3D_object *P3DInstanceManager:: +new_bool_object(bool value) { + P3D_object *obj = (value) ? _true_object : _false_object; + P3D_OBJECT_INCREF(obj); + return obj; +} diff --git a/direct/src/plugin/p3dInstanceManager.cxx b/direct/src/plugin/p3dInstanceManager.cxx index 9a105b3009..aba9b679c4 100644 --- a/direct/src/plugin/p3dInstanceManager.cxx +++ b/direct/src/plugin/p3dInstanceManager.cxx @@ -18,6 +18,9 @@ #include "p3dPackage.h" #include "p3d_plugin_config.h" #include "p3dWinSplashWindow.h" +#include "p3dUndefinedObject.h" +#include "p3dNoneObject.h" +#include "p3dBoolObject.h" #include "find_root_dir.h" #include "mkdir_complete.h" @@ -43,6 +46,12 @@ P3DInstanceManager() { _started_notify_thread = false; INIT_THREAD(_notify_thread); + // Initialize the singleton objects. + _undefined_object = new P3DUndefinedObject(); + _none_object = new P3DNoneObject(); + _true_object = new P3DBoolObject(true); + _false_object = new P3DBoolObject(false); + #ifdef _WIN32 // Ensure the appropriate Windows common controls are available to // this application. @@ -72,6 +81,22 @@ P3DInstanceManager:: assert(_instances.empty()); assert(_sessions.empty()); + nout << "counts: " << _undefined_object->_ref_count + << " " << _none_object->_ref_count + << " " << _true_object->_ref_count + << " " << _false_object->_ref_count + << "\n" << flush; + + assert(_undefined_object->_ref_count == 1); + assert(_none_object->_ref_count == 1); + assert(_true_object->_ref_count == 1); + assert(_false_object->_ref_count == 1); + + P3D_OBJECT_DECREF(_undefined_object); + P3D_OBJECT_DECREF(_none_object); + P3D_OBJECT_DECREF(_true_object); + P3D_OBJECT_DECREF(_false_object); + #ifdef _WIN32 P3DWinSplashWindow::unregister_window_class(); #endif diff --git a/direct/src/plugin/p3dInstanceManager.h b/direct/src/plugin/p3dInstanceManager.h index 01f1e6c7d0..28c4c88921 100644 --- a/direct/src/plugin/p3dInstanceManager.h +++ b/direct/src/plugin/p3dInstanceManager.h @@ -66,6 +66,10 @@ public: P3D_class_definition *make_class_definition() const; + inline P3D_object *new_undefined_object(); + inline P3D_object *new_none_object(); + inline P3D_object *new_bool_object(bool value); + static P3DInstanceManager *get_global_ptr(); static void delete_global_ptr(); @@ -82,6 +86,11 @@ private: string _download_url; string _platform; + P3D_object *_undefined_object; + P3D_object *_none_object; + P3D_object *_true_object; + P3D_object *_false_object; + typedef set Instances; Instances _instances; diff --git a/direct/src/plugin/p3dIntObject.cxx b/direct/src/plugin/p3dIntObject.cxx index 7334613a92..6c38a9cfa8 100644 --- a/direct/src/plugin/p3dIntObject.cxx +++ b/direct/src/plugin/p3dIntObject.cxx @@ -41,7 +41,7 @@ P3DIntObject(const P3DIntObject ©) : // Description: Returns the fundamental type of this kind of object. //////////////////////////////////////////////////////////////////// P3D_object_type P3DIntObject:: -get_type() const { +get_type() { return P3D_OT_int; } @@ -52,7 +52,7 @@ get_type() const { // possible. //////////////////////////////////////////////////////////////////// bool P3DIntObject:: -get_bool() const { +get_bool() { return (_value != 0); } @@ -63,7 +63,7 @@ get_bool() const { // possible. //////////////////////////////////////////////////////////////////// int P3DIntObject:: -get_int() const { +get_int() { return _value; } @@ -74,7 +74,7 @@ get_int() const { // of this object coerced to a string. //////////////////////////////////////////////////////////////////// void P3DIntObject:: -make_string(string &value) const { +make_string(string &value) { ostringstream strm; strm << _value; value = strm.str(); diff --git a/direct/src/plugin/p3dIntObject.h b/direct/src/plugin/p3dIntObject.h index 75c62e8e46..829ba0c62e 100644 --- a/direct/src/plugin/p3dIntObject.h +++ b/direct/src/plugin/p3dIntObject.h @@ -28,10 +28,10 @@ public: P3DIntObject(const P3DIntObject ©); public: - virtual P3D_object_type get_type() const; - virtual bool get_bool() const; - virtual int get_int() const; - virtual void make_string(string &value) const; + virtual P3D_object_type get_type(); + virtual bool get_bool(); + virtual int get_int(); + virtual void make_string(string &value); private: int _value; diff --git a/direct/src/plugin/p3dNoneObject.cxx b/direct/src/plugin/p3dNoneObject.cxx index c1305d5a60..04d3f618af 100644 --- a/direct/src/plugin/p3dNoneObject.cxx +++ b/direct/src/plugin/p3dNoneObject.cxx @@ -29,7 +29,7 @@ P3DNoneObject() { // Description: Returns the fundamental type of this kind of object. //////////////////////////////////////////////////////////////////// P3D_object_type P3DNoneObject:: -get_type() const { +get_type() { return P3D_OT_none; } @@ -40,7 +40,7 @@ get_type() const { // possible. //////////////////////////////////////////////////////////////////// bool P3DNoneObject:: -get_bool() const { +get_bool() { return false; } @@ -51,6 +51,6 @@ get_bool() const { // of this object coerced to a string. //////////////////////////////////////////////////////////////////// void P3DNoneObject:: -make_string(string &value) const { +make_string(string &value) { value = "None"; } diff --git a/direct/src/plugin/p3dNoneObject.h b/direct/src/plugin/p3dNoneObject.h index fa04e58237..657d35400d 100644 --- a/direct/src/plugin/p3dNoneObject.h +++ b/direct/src/plugin/p3dNoneObject.h @@ -28,9 +28,9 @@ public: P3DNoneObject(); public: - virtual P3D_object_type get_type() const; - virtual bool get_bool() const; - virtual void make_string(string &value) const; + virtual P3D_object_type get_type(); + virtual bool get_bool(); + virtual void make_string(string &value); }; #endif diff --git a/direct/src/plugin/p3dObject.I b/direct/src/plugin/p3dObject.I index 6e6ec72a74..7941e68468 100644 --- a/direct/src/plugin/p3dObject.I +++ b/direct/src/plugin/p3dObject.I @@ -37,39 +37,3 @@ P3DObject(const P3DObject ©) { _class = copy._class; _ref_count = 1; } - -//////////////////////////////////////////////////////////////////// -// Function: P3DObject::ref -// Access: Public -// Description: Increments the reference count. -//////////////////////////////////////////////////////////////////// -inline void P3DObject:: -ref() const { - ++(((P3DObject *)this)->_ref_count); -} - -//////////////////////////////////////////////////////////////////// -// Function: P3DObject::unref -// Access: Public -// Description: Decrements the reference count, and returns the new -// count. -//////////////////////////////////////////////////////////////////// -inline int P3DObject:: -unref() const { - --(((P3DObject *)this)->_ref_count); - return _ref_count; -} - -//////////////////////////////////////////////////////////////////// -// Function: P3DObject::unref_delete -// Access: Public, Static -// Description: Decrements the reference count on the indicated -// object, and deletes it if the reference count reaches -// zero. -//////////////////////////////////////////////////////////////////// -inline void P3DObject:: -unref_delete(P3DObject *obj) { - if (obj->unref() <= 0) { - delete obj; - } -} diff --git a/direct/src/plugin/p3dObject.cxx b/direct/src/plugin/p3dObject.cxx index ae66159d87..8b362d8457 100644 --- a/direct/src/plugin/p3dObject.cxx +++ b/direct/src/plugin/p3dObject.cxx @@ -21,47 +21,42 @@ // P3D_object structure. static void object_finish(P3D_object *object) { - P3DObject::unref_delete(((P3DObject *)object)); -} - -static P3D_object * -object_copy(const P3D_object *object) { - return ((const P3DObject *)object)->make_copy(); + delete (P3DObject *)object; } static P3D_object_type -object_get_type(const P3D_object *object) { - return ((const P3DObject *)object)->get_type(); +object_get_type(P3D_object *object) { + return ((P3DObject *)object)->get_type(); } static bool -object_get_bool(const P3D_object *object) { - return ((const P3DObject *)object)->get_bool(); +object_get_bool(P3D_object *object) { + return ((P3DObject *)object)->get_bool(); } static int -object_get_int(const P3D_object *object) { - return ((const P3DObject *)object)->get_int(); +object_get_int(P3D_object *object) { + return ((P3DObject *)object)->get_int(); } static double -object_get_float(const P3D_object *object) { - return ((const P3DObject *)object)->get_float(); +object_get_float(P3D_object *object) { + return ((P3DObject *)object)->get_float(); } static int -object_get_string(const P3D_object *object, char *buffer, int buffer_length) { - return ((const P3DObject *)object)->get_string(buffer, buffer_length); +object_get_string(P3D_object *object, char *buffer, int buffer_length) { + return ((P3DObject *)object)->get_string(buffer, buffer_length); } static int -object_get_repr(const P3D_object *object, char *buffer, int buffer_length) { - return ((const P3DObject *)object)->get_repr(buffer, buffer_length); +object_get_repr(P3D_object *object, char *buffer, int buffer_length) { + return ((P3DObject *)object)->get_repr(buffer, buffer_length); } static P3D_object * -object_get_property(const P3D_object *object, const char *property) { - return ((const P3DObject *)object)->get_property(property); +object_get_property(P3D_object *object, const char *property) { + return ((P3DObject *)object)->get_property(property); } static bool @@ -71,27 +66,26 @@ object_set_property(P3D_object *object, const char *property, } static bool -object_has_method(const P3D_object *object, const char *method_name) { - return ((const P3DObject *)object)->has_method(method_name); +object_has_method(P3D_object *object, const char *method_name) { + return ((P3DObject *)object)->has_method(method_name); } static P3D_object * -object_call(const P3D_object *object, const char *method_name, +object_call(P3D_object *object, const char *method_name, P3D_object *params[], int num_params) { if (method_name == NULL) { method_name = ""; } - return ((const P3DObject *)object)->call(method_name, params, num_params); + return ((P3DObject *)object)->call(method_name, params, num_params); } static P3D_object * -object_eval(const P3D_object *object, const char *expression) { - return ((const P3DObject *)object)->eval(expression); +object_eval(P3D_object *object, const char *expression) { + return ((P3DObject *)object)->eval(expression); } P3D_class_definition P3DObject::_object_class = { &object_finish, - &object_copy, &object_get_type, &object_get_bool, &object_get_int, @@ -116,14 +110,8 @@ generic_finish(P3D_object *object) { nout << "Warning! default object_finish() method does nothing; object will leak.\n" << flush; } -static P3D_object * -generic_copy(const P3D_object *object) { - nout << "Warning! default object_copy() method does nothing; object pointer will be shared.\n" << flush; - return (P3D_object *)object; -} - static P3D_object_type -generic_get_type(const P3D_object *object) { +generic_get_type(P3D_object *object) { // We assume anyone going through the trouble of subclassing this // will want to return an object, not one of the other fundamental // types. @@ -131,66 +119,59 @@ generic_get_type(const P3D_object *object) { } static bool -generic_get_bool(const P3D_object *object) { +generic_get_bool(P3D_object *object) { return false; } static int -generic_get_int(const P3D_object *object) { +generic_get_int(P3D_object *object) { return 0; } static double -generic_get_float(const P3D_object *object) { +generic_get_float(P3D_object *object) { return 0.0; } static int -generic_get_string(const P3D_object *object, char *buffer, int buffer_length) { +generic_get_string(P3D_object *object, char *buffer, int buffer_length) { return 0; } static int -generic_get_repr(const P3D_object *object, char *buffer, int buffer_length) { +generic_get_repr(P3D_object *object, char *buffer, int buffer_length) { return 0; } static P3D_object * -generic_get_property(const P3D_object *object, const char *property) { +generic_get_property(P3D_object *object, const char *property) { return NULL; } static bool generic_set_property(P3D_object *object, const char *property, P3D_object *value) { - if (value != NULL) { - P3D_OBJECT_FINISH(value); - } return false; } static bool -generic_has_method(const P3D_object *object, const char *method_name) { - return ((const P3DObject *)object)->has_method(method_name); +generic_has_method(P3D_object *object, const char *method_name) { + return false; } static P3D_object * -generic_call(const P3D_object *object, const char *method_name, +generic_call(P3D_object *object, const char *method_name, P3D_object *params[], int num_params) { - for (int i = 0; i < num_params; ++i) { - P3D_OBJECT_FINISH(params[i]); - } return NULL; } static P3D_object * -generic_eval(const P3D_object *object, const char *expression) { +generic_eval(P3D_object *object, const char *expression) { return NULL; } P3D_class_definition P3DObject::_generic_class = { &generic_finish, - &generic_copy, &generic_get_type, &generic_get_bool, &generic_get_int, @@ -211,20 +192,7 @@ P3D_class_definition P3DObject::_generic_class = { //////////////////////////////////////////////////////////////////// P3DObject:: ~P3DObject() { -} - -//////////////////////////////////////////////////////////////////// -// Function: P3DObject::make_copy -// Access: Public, Virtual -// Description: Returns a new copy of the object, if necessary. If -// the object type is static and all instances are -// identical, this actually simply ups the reference -// count and returns the same object. -//////////////////////////////////////////////////////////////////// -P3DObject *P3DObject:: -make_copy() const { - ref(); - return (P3DObject *)this; + assert(_ref_count == 0); } //////////////////////////////////////////////////////////////////// @@ -234,7 +202,7 @@ make_copy() const { // possible. //////////////////////////////////////////////////////////////////// int P3DObject:: -get_int() const { +get_int() { return 0; } @@ -245,7 +213,7 @@ get_int() const { // value, if possible. //////////////////////////////////////////////////////////////////// double P3DObject:: -get_float() const { +get_float() { return get_int(); } @@ -260,7 +228,7 @@ get_float() const { // was too small). //////////////////////////////////////////////////////////////////// int P3DObject:: -get_string(char *buffer, int buffer_length) const { +get_string(char *buffer, int buffer_length) { string result; make_string(result); strncpy(buffer, result.c_str(), buffer_length); @@ -274,7 +242,7 @@ get_string(char *buffer, int buffer_length) const { // similar to get_string(), above. //////////////////////////////////////////////////////////////////// int P3DObject:: -get_repr(char *buffer, int buffer_length) const { +get_repr(char *buffer, int buffer_length) { ostringstream strm; output(strm); string result = strm.str(); @@ -290,7 +258,7 @@ get_repr(char *buffer, int buffer_length) const { // that must be deleted by the caller, or NULL on error. //////////////////////////////////////////////////////////////////// P3D_object *P3DObject:: -get_property(const string &property) const { +get_property(const string &property) { return NULL; } @@ -303,9 +271,6 @@ get_property(const string &property) const { //////////////////////////////////////////////////////////////////// bool P3DObject:: set_property(const string &property, P3D_object *value) { - if (value != NULL) { - P3D_OBJECT_FINISH(value); - } return false; } @@ -316,7 +281,7 @@ set_property(const string &property, P3D_object *value) { // object, false otherwise. //////////////////////////////////////////////////////////////////// bool P3DObject:: -has_method(const string &method_name) const { +has_method(const string &method_name) { return false; } @@ -329,10 +294,7 @@ has_method(const string &method_name) const { // on success, NULL on error. //////////////////////////////////////////////////////////////////// P3D_object *P3DObject:: -call(const string &method_name, P3D_object *params[], int num_params) const { - for (int i = 0; i < num_params; ++i) { - P3D_OBJECT_FINISH(params[i]); - } +call(const string &method_name, P3D_object *params[], int num_params) { return NULL; } @@ -343,7 +305,7 @@ call(const string &method_name, P3D_object *params[], int num_params) const { // of the P3DObject classes implement this. //////////////////////////////////////////////////////////////////// P3D_object *P3DObject:: -eval(const string &expression) const { +eval(const string &expression) { return NULL; } @@ -355,7 +317,7 @@ eval(const string &expression) const { // assistance. //////////////////////////////////////////////////////////////////// void P3DObject:: -output(ostream &out) const { +output(ostream &out) { string value; make_string(value); out << value; diff --git a/direct/src/plugin/p3dObject.h b/direct/src/plugin/p3dObject.h index b06f5ef092..8118e003e7 100644 --- a/direct/src/plugin/p3dObject.h +++ b/direct/src/plugin/p3dObject.h @@ -33,32 +33,24 @@ protected: public: virtual ~P3DObject(); - virtual P3DObject *make_copy() const; - virtual P3D_object_type get_type() const=0; - virtual bool get_bool() const=0; - virtual int get_int() const; - virtual double get_float() const; + virtual P3D_object_type get_type()=0; + virtual bool get_bool()=0; + virtual int get_int(); + virtual double get_float(); - int get_string(char *buffer, int buffer_length) const; - int get_repr(char *buffer, int buffer_length) const; - virtual void make_string(string &value) const=0; + int get_string(char *buffer, int buffer_length); + int get_repr(char *buffer, int buffer_length); + virtual void make_string(string &value)=0; - virtual P3D_object *get_property(const string &property) const; + virtual P3D_object *get_property(const string &property); virtual bool set_property(const string &property, P3D_object *value); - virtual bool has_method(const string &method_name) const; + virtual bool has_method(const string &method_name); virtual P3D_object *call(const string &method_name, - P3D_object *params[], int num_params) const; - virtual P3D_object *eval(const string &expression) const; + P3D_object *params[], int num_params); + virtual P3D_object *eval(const string &expression); - virtual void output(ostream &out) const; - - inline void ref() const; - inline int unref() const; - static inline void unref_delete(P3DObject *obj); - -private: - int _ref_count; + virtual void output(ostream &out); public: static P3D_class_definition _object_class; @@ -71,7 +63,7 @@ public: // virtual method to write the output simply. (For classes that // inherit only from P3D_object, we have to use the generic C method // defined in p3d_plugin_common.h, a little clumsier.) -inline ostream &operator << (ostream &out, const P3DObject &value) { +inline ostream &operator << (ostream &out, P3DObject &value) { value.output(out); return out; } diff --git a/direct/src/plugin/p3dPythonObject.cxx b/direct/src/plugin/p3dPythonObject.cxx index 0278b463d9..96f0f35079 100644 --- a/direct/src/plugin/p3dPythonObject.cxx +++ b/direct/src/plugin/p3dPythonObject.cxx @@ -42,7 +42,7 @@ P3DPythonObject:: // Description: Returns the fundamental type of this kind of object. //////////////////////////////////////////////////////////////////// P3D_object_type P3DPythonObject:: -get_type() const { +get_type() { return P3D_OT_object; } @@ -53,13 +53,13 @@ get_type() const { // possible. //////////////////////////////////////////////////////////////////// bool P3DPythonObject:: -get_bool() const { +get_bool() { bool bresult = 0; P3D_object *result = call("__bool__", NULL, 0); if (result != NULL) { bresult = P3D_OBJECT_GET_BOOL(result); - P3D_OBJECT_FINISH(result); + P3D_OBJECT_DECREF(result); } return bresult; @@ -72,13 +72,13 @@ get_bool() const { // possible. //////////////////////////////////////////////////////////////////// int P3DPythonObject:: -get_int() const { +get_int() { int iresult = 0; P3D_object *result = call("__int__", NULL, 0); if (result != NULL) { iresult = P3D_OBJECT_GET_INT(result); - P3D_OBJECT_FINISH(result); + P3D_OBJECT_DECREF(result); } return iresult; @@ -91,13 +91,13 @@ get_int() const { // value, if possible. //////////////////////////////////////////////////////////////////// double P3DPythonObject:: -get_float() const { +get_float() { double fresult = 0.0; P3D_object *result = call("__float__", NULL, 0); if (result != NULL) { fresult = P3D_OBJECT_GET_FLOAT(result); - P3D_OBJECT_FINISH(result); + P3D_OBJECT_DECREF(result); } return fresult; @@ -110,7 +110,7 @@ get_float() const { // of this object coerced to a string. //////////////////////////////////////////////////////////////////// void P3DPythonObject:: -make_string(string &value) const { +make_string(string &value) { P3D_object *result = call("__str__", NULL, 0); if (result != NULL) { int size = P3D_OBJECT_GET_STRING(result, NULL, 0); @@ -119,7 +119,7 @@ make_string(string &value) const { value = string(buffer, size); delete[] buffer; - P3D_OBJECT_FINISH(result); + P3D_OBJECT_DECREF(result); } } @@ -131,7 +131,7 @@ make_string(string &value) const { // that must be deleted by the caller, or NULL on error. //////////////////////////////////////////////////////////////////// P3D_object *P3DPythonObject:: -get_property(const string &property) const { +get_property(const string &property) { P3D_object *params[1]; params[0] = new P3DStringObject(property); @@ -167,7 +167,7 @@ set_property(const string &property, P3D_object *value) { if (result != NULL) { bresult = P3D_OBJECT_GET_BOOL(result); - P3D_OBJECT_FINISH(result); + P3D_OBJECT_DECREF(result); } return bresult; @@ -180,7 +180,7 @@ set_property(const string &property, P3D_object *value) { // object, false otherwise. //////////////////////////////////////////////////////////////////// bool P3DPythonObject:: -has_method(const string &method_name) const { +has_method(const string &method_name) { bool bresult = false; P3D_object *params[1]; @@ -190,7 +190,7 @@ has_method(const string &method_name) const { if (result != NULL) { bresult = P3D_OBJECT_GET_BOOL(result); - P3D_OBJECT_FINISH(result); + P3D_OBJECT_DECREF(result); } return bresult; @@ -205,7 +205,7 @@ has_method(const string &method_name) const { // on success, NULL on error. //////////////////////////////////////////////////////////////////// P3D_object *P3DPythonObject:: -call(const string &method_name, P3D_object *params[], int num_params) const { +call(const string &method_name, P3D_object *params[], int num_params) { TiXmlDocument *doc = new TiXmlDocument; TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", ""); TiXmlElement *xcommand = new TiXmlElement("command"); @@ -222,10 +222,6 @@ call(const string &method_name, P3D_object *params[], int num_params) const { for (int i = 0; i < num_params; ++i) { TiXmlElement *xparams = _session->p3dobj_to_xml(params[i]); xcommand->LinkEndChild(xparams); - - // Now we're done with the params object passed in, we can delete - // it as promised. - P3D_OBJECT_FINISH(params[i]); } doc->LinkEndChild(decl); @@ -255,12 +251,12 @@ call(const string &method_name, P3D_object *params[], int num_params) const { // assistance. //////////////////////////////////////////////////////////////////// void P3DPythonObject:: -output(ostream &out) const { +output(ostream &out) { P3D_object *result = call("__repr__", NULL, 0); out << "Python " << _object_id; if (result != NULL) { out << ": " << *result; - P3D_OBJECT_FINISH(result); + P3D_OBJECT_DECREF(result); } } @@ -271,7 +267,7 @@ output(ostream &out) const { // identify this object in the XML stream. //////////////////////////////////////////////////////////////////// int P3DPythonObject:: -get_object_id() const { +get_object_id() { return _object_id; } diff --git a/direct/src/plugin/p3dPythonObject.h b/direct/src/plugin/p3dPythonObject.h index 394a3f9456..186b89d29c 100644 --- a/direct/src/plugin/p3dPythonObject.h +++ b/direct/src/plugin/p3dPythonObject.h @@ -34,22 +34,22 @@ public: virtual ~P3DPythonObject(); public: - virtual P3D_object_type get_type() const; - virtual bool get_bool() const; - virtual int get_int() const; - virtual double get_float() const; + virtual P3D_object_type get_type(); + virtual bool get_bool(); + virtual int get_int(); + virtual double get_float(); - virtual void make_string(string &value) const; + virtual void make_string(string &value); - virtual P3D_object *get_property(const string &property) const; + virtual P3D_object *get_property(const string &property); virtual bool set_property(const string &property, P3D_object *value); - virtual bool has_method(const string &method_name) const; + virtual bool has_method(const string &method_name); virtual P3D_object *call(const string &method_name, - P3D_object *params[], int num_params) const; + P3D_object *params[], int num_params); - virtual void output(ostream &out) const; - int get_object_id() const; + virtual void output(ostream &out); + int get_object_id(); private: P3DSession *_session; diff --git a/direct/src/plugin/p3dSession.cxx b/direct/src/plugin/p3dSession.cxx index 74724c11bd..b6897dc3db 100644 --- a/direct/src/plugin/p3dSession.cxx +++ b/direct/src/plugin/p3dSession.cxx @@ -321,21 +321,23 @@ command_and_response(TiXmlDocument *command) { // Access: Public // Description: Converts the XML representation of the particular // object value into a corresponding P3D_object. -// Returns the newly-allocated object. +// Returns the object, a new reference. //////////////////////////////////////////////////////////////////// P3D_object *P3DSession:: xml_to_p3dobj(const TiXmlElement *xvalue) { const char *type = xvalue->Attribute("type"); + P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); + if (strcmp(type, "undefined") == 0) { - return new P3DUndefinedObject; + return inst_mgr->new_undefined_object(); } else if (strcmp(type, "none") == 0) { - return new P3DNoneObject; + return inst_mgr->new_none_object(); } else if (strcmp(type, "bool") == 0) { int value; if (xvalue->QueryIntAttribute("value", &value) == TIXML_SUCCESS) { - return new P3DBoolObject(value != 0); + return inst_mgr->new_bool_object(value != 0); } } else if (strcmp(type, "int") == 0) { @@ -364,11 +366,12 @@ xml_to_p3dobj(const TiXmlElement *xvalue) { SentObjects::iterator si = _sent_objects.find(object_id); if (si == _sent_objects.end()) { // Hmm, the child process gave us a bogus object ID. - return new P3DUndefinedObject; + return inst_mgr->new_undefined_object(); } P3D_object *obj = (*si).second; - return P3D_OBJECT_COPY(obj); + P3D_OBJECT_INCREF(obj); + return obj; } } else if (strcmp(type, "python") == 0) { @@ -379,7 +382,7 @@ xml_to_p3dobj(const TiXmlElement *xvalue) { } // Something went wrong in decoding. - return new P3DUndefinedObject; + return inst_mgr->new_undefined_object(); } //////////////////////////////////////////////////////////////////// @@ -387,10 +390,11 @@ xml_to_p3dobj(const TiXmlElement *xvalue) { // Access: Public // Description: Allocates and returns a new XML structure // corresponding to the indicated value. The supplied -// P3DObject passed in is *not* deleted. +// P3DObject's reference count is not decremented; the +// caller remains responsible for decrementing it later. //////////////////////////////////////////////////////////////////// TiXmlElement *P3DSession:: -p3dobj_to_xml(const P3D_object *obj) { +p3dobj_to_xml(P3D_object *obj) { TiXmlElement *xvalue = new TiXmlElement("value"); switch (P3D_OBJECT_GET_TYPE(obj)) { @@ -443,21 +447,21 @@ p3dobj_to_xml(const P3D_object *obj) { // should pass a reference down to this particular object, so // the Python process knows to call back up to here to query it. - P3D_object *dup = P3D_OBJECT_COPY(obj); - int object_id = _next_sent_id; ++_next_sent_id; - bool inserted = _sent_objects.insert(SentObjects::value_type(object_id, dup)).second; + bool inserted = _sent_objects.insert(SentObjects::value_type(object_id, obj)).second; while (!inserted) { // Hmm, we must have cycled around the entire int space? Either // that, or there's a logic bug somewhere. Assume the former, // and keep looking for an empty slot. object_id = _next_sent_id; ++_next_sent_id; - inserted = _sent_objects.insert(SentObjects::value_type(object_id, dup)).second; + inserted = _sent_objects.insert(SentObjects::value_type(object_id, obj)).second; } + // Now that it's stored in the map, increment its reference count. // TODO: implement removing things from this map. + P3D_OBJECT_INCREF(obj); xvalue->SetAttribute("type", "browser"); xvalue->SetAttribute("object_id", object_id); diff --git a/direct/src/plugin/p3dSession.h b/direct/src/plugin/p3dSession.h index 9e00c071be..d6af610262 100644 --- a/direct/src/plugin/p3dSession.h +++ b/direct/src/plugin/p3dSession.h @@ -50,7 +50,7 @@ public: void send_command(TiXmlDocument *command); TiXmlDocument *command_and_response(TiXmlDocument *command); P3D_object *xml_to_p3dobj(const TiXmlElement *xvalue); - TiXmlElement *p3dobj_to_xml(const P3D_object *obj); + TiXmlElement *p3dobj_to_xml(P3D_object *obj); private: void install_progress(P3DPackage *package, double progress); diff --git a/direct/src/plugin/p3dStringObject.cxx b/direct/src/plugin/p3dStringObject.cxx index 167dff5db2..bb89f1ca22 100644 --- a/direct/src/plugin/p3dStringObject.cxx +++ b/direct/src/plugin/p3dStringObject.cxx @@ -50,7 +50,7 @@ P3DStringObject:: // Description: Returns the fundamental type of this kind of object. //////////////////////////////////////////////////////////////////// P3D_object_type P3DStringObject:: -get_type() const { +get_type() { return P3D_OT_string; } @@ -61,7 +61,7 @@ get_type() const { // possible. //////////////////////////////////////////////////////////////////// bool P3DStringObject:: -get_bool() const { +get_bool() { return !_value.empty(); } @@ -72,7 +72,7 @@ get_bool() const { // of this object coerced to a string. //////////////////////////////////////////////////////////////////// void P3DStringObject:: -make_string(string &value) const { +make_string(string &value) { value = _value; } @@ -84,7 +84,7 @@ make_string(string &value) const { // assistance. //////////////////////////////////////////////////////////////////// void P3DStringObject:: -output(ostream &out) const { +output(ostream &out) { out << '"'; for (string::const_iterator si = _value.begin(); si != _value.end(); ++si) { if (isprint(*si)) { diff --git a/direct/src/plugin/p3dStringObject.h b/direct/src/plugin/p3dStringObject.h index 825bfe6220..1f12cd2c26 100644 --- a/direct/src/plugin/p3dStringObject.h +++ b/direct/src/plugin/p3dStringObject.h @@ -30,11 +30,11 @@ public: public: virtual ~P3DStringObject(); - virtual P3D_object_type get_type() const; - virtual bool get_bool() const; - virtual void make_string(string &value) const; + virtual P3D_object_type get_type(); + virtual bool get_bool(); + virtual void make_string(string &value); - virtual void output(ostream &out) const; + virtual void output(ostream &out); private: string _value; diff --git a/direct/src/plugin/p3dUndefinedObject.cxx b/direct/src/plugin/p3dUndefinedObject.cxx index 3a39a0bee8..8c12e88207 100644 --- a/direct/src/plugin/p3dUndefinedObject.cxx +++ b/direct/src/plugin/p3dUndefinedObject.cxx @@ -29,7 +29,7 @@ P3DUndefinedObject() { // Description: Returns the fundamental type of this kind of object. //////////////////////////////////////////////////////////////////// P3D_object_type P3DUndefinedObject:: -get_type() const { +get_type() { return P3D_OT_undefined; } @@ -40,7 +40,7 @@ get_type() const { // possible. //////////////////////////////////////////////////////////////////// bool P3DUndefinedObject:: -get_bool() const { +get_bool() { return false; } @@ -51,6 +51,6 @@ get_bool() const { // of this object coerced to a string. //////////////////////////////////////////////////////////////////// void P3DUndefinedObject:: -make_string(string &value) const { +make_string(string &value) { value = "Undefined"; } diff --git a/direct/src/plugin/p3dUndefinedObject.h b/direct/src/plugin/p3dUndefinedObject.h index 35ac90ba55..b3ec82ea52 100644 --- a/direct/src/plugin/p3dUndefinedObject.h +++ b/direct/src/plugin/p3dUndefinedObject.h @@ -29,9 +29,9 @@ public: P3DUndefinedObject(); public: - virtual P3D_object_type get_type() const; - virtual bool get_bool() const; - virtual void make_string(string &value) const; + virtual P3D_object_type get_type(); + virtual bool get_bool(); + virtual void make_string(string &value); }; #endif diff --git a/direct/src/plugin/p3d_plugin.cxx b/direct/src/plugin/p3d_plugin.cxx index 50f1a9e248..5c57e41f2d 100644 --- a/direct/src/plugin/p3d_plugin.cxx +++ b/direct/src/plugin/p3d_plugin.cxx @@ -138,7 +138,8 @@ P3D_new_undefined_object() { assert(P3DInstanceManager::get_global_ptr()->is_initialized()); ACQUIRE_LOCK(_api_lock); - P3D_object *result = new P3DUndefinedObject(); + P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); + P3D_object *result = inst_mgr->new_undefined_object(); RELEASE_LOCK(_api_lock); return result; @@ -149,7 +150,8 @@ P3D_new_none_object() { assert(P3DInstanceManager::get_global_ptr()->is_initialized()); ACQUIRE_LOCK(_api_lock); - P3D_object *result = new P3DNoneObject(); + P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); + P3D_object *result = inst_mgr->new_none_object(); RELEASE_LOCK(_api_lock); return result; @@ -160,7 +162,8 @@ P3D_new_bool_object(bool value) { assert(P3DInstanceManager::get_global_ptr()->is_initialized()); ACQUIRE_LOCK(_api_lock); - P3D_object *result = new P3DBoolObject(value); + P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); + P3D_object *result = inst_mgr->new_bool_object(value); RELEASE_LOCK(_api_lock); return result; @@ -212,7 +215,7 @@ P3D_instance_get_panda_script_object(P3D_instance *instance) { void P3D_instance_set_browser_script_object(P3D_instance *instance, - P3D_object *object) { + P3D_object *object) { assert(P3DInstanceManager::get_global_ptr()->is_initialized()); ACQUIRE_LOCK(_api_lock); diff --git a/direct/src/plugin/p3d_plugin.h b/direct/src/plugin/p3d_plugin.h index daadf03db5..04bc2fbd36 100644 --- a/direct/src/plugin/p3d_plugin.h +++ b/direct/src/plugin/p3d_plugin.h @@ -307,25 +307,30 @@ typedef enum { P3D_OT_object, } P3D_object_type; +/* Most methods and functions that return a P3D_object return it with + its reference count already incremented by one for the benefit of + the caller, leaving the caller the owner of the implicit reference + count. This is referred to as returning a "new reference", using + the Python naming convention. Similarly, most methods that receive + a P3D_object will implicitly increment the reference count + internally if necessary, leaving the caller still the owner of its + own reference count. Thus, it is the caller's responsibility to + call P3D_OBJECT_DECREF() on any P3D_objects it has received but no + longer wishes to keep. */ + /* This method is called to deallocate the object and all of its - internal structures. */ + internal structures. Do not call it directly; call + P3D_OBJECT_DECREF() instead. */ typedef void P3D_object_finish_method(P3D_object *object); -/* Returns a new copy of the object. The caller receives ownership of - the new object and must eventually pass its pointer to - P3D_OBJECT_FINISH() to delete it, or into some other call that - transfers ownership. */ -typedef P3D_object * -P3D_object_copy_method(const P3D_object *object); - /* Returns the fundamental type of the object. This should be treated as a hint to suggest how the object can most accurately be represented; it does not limit the actual interfaces available to an object. For instance, you may call P3D_OBJECT_GET_PROPERTY() even if the object's type is not "object". */ typedef P3D_object_type -P3D_object_get_type_method(const P3D_object *object); +P3D_object_get_type_method(P3D_object *object); /* Each of the following methods returns the object's value expressed as the corresponding type. If the object is not precisely that @@ -333,15 +338,15 @@ P3D_object_get_type_method(const P3D_object *object); /* Return the object as a bool. */ typedef bool -P3D_object_get_bool_method(const P3D_object *object); +P3D_object_get_bool_method(P3D_object *object); /* Return the object as an integer. */ typedef int -P3D_object_get_int_method(const P3D_object *object); +P3D_object_get_int_method(P3D_object *object); /* Return the object as a floating-point number. */ typedef double -P3D_object_get_float_method(const P3D_object *object); +P3D_object_get_float_method(P3D_object *object); /* Get the object as a string. This method copies the string into the provided buffer, and returns the actual length of the internal @@ -352,7 +357,7 @@ P3D_object_get_float_method(const P3D_object *object); buffer = NULL and buffer_length = 0 to return just the required size of the buffer. */ typedef int -P3D_object_get_string_method(const P3D_object *object, +P3D_object_get_string_method(P3D_object *object, char *buffer, int buffer_length); /* As above, but instead of the literal object data, returns a @@ -362,23 +367,19 @@ P3D_object_get_string_method(const P3D_object *object, marks and escape characters from P3D_OBJECT_GET_REPR(). Mechanically, this function works the same way as get_string(). */ typedef int -P3D_object_get_repr_method(const P3D_object *object, +P3D_object_get_repr_method(P3D_object *object, char *buffer, int buffer_length); /* Looks up a property on the object by name, i.e. a data member or a - method. The return value is a newly-allocated P3D_object if the - property exists, or NULL if it does not. If it is not NULL, - ownership of the return value is transferred to the caller, who - will be responsible for deleting it later. */ + method. The return value is a new-reference P3D_object if the + property exists, or NULL if it does not. */ typedef P3D_object * -P3D_object_get_property_method(const P3D_object *object, const char *property); +P3D_object_get_property_method(P3D_object *object, const char *property); /* Changes the value at the indicated property. Any existing object already at the corresponding property is deleted. If the value - object pointer is NULL, the property is deleted. Returns true on - success, false on failure. The caller must have ownership of the - value object before the call; after the call, ownership of the - value object is transferred to this object. */ + pointer is NULL, the property is deleted. Returns true on success, + false on failure. */ typedef bool P3D_object_set_property_method(P3D_object *object, const char *property, P3D_object *value); @@ -389,36 +390,32 @@ P3D_object_set_property_method(P3D_object *object, const char *property, a callable object. If method_name is empty or NULL, returns true if the object itself is callable. */ typedef bool -P3D_object_has_method_method(const P3D_object *object, const char *method_name); +P3D_object_has_method_method(P3D_object *object, const char *method_name); /* Invokes a named method on the object. If method_name is empty or NULL, invokes the object itself as a function. You must pass an - array of P3D_objects as the list of parameters. The ownership of - each of the parameters in this array (but not of the array pointer - itself) is passed into this call; the objects will be deleted when - the call is completed. + array of P3D_objects as the list of parameters, and ownership of + these objects' reference counts is not transferred with the call + (you must still DECREF these objects afterwards). - The return value is a newly-allocated P3D_object on success, or - NULL on failure. Ownership of the return value is transferred to - the caller. */ + The return value is a new-reference P3D_object on success, or NULL + on failure. */ typedef P3D_object * -P3D_object_call_method(const P3D_object *object, const char *method_name, +P3D_object_call_method(P3D_object *object, const char *method_name, P3D_object *params[], int num_params); /* Evaluates an arbitrary JavaScript expression in the context of the object. - The return value is a newly-allocated P3D_object on success, or - NULL on failure. Ownership of the return value is transferred to - the caller. */ + The return value is a new-reference P3D_object on success, or NULL + on failure. */ typedef P3D_object * -P3D_object_eval_method(const P3D_object *object, const char *expression); +P3D_object_eval_method(P3D_object *object, const char *expression); /* This defines the class structure that implements all of the above methods. */ typedef struct _P3D_class_definition { P3D_object_finish_method *_finish; - P3D_object_copy_method *_copy; P3D_object_get_type_method *_get_type; P3D_object_get_bool_method *_get_bool; @@ -439,6 +436,7 @@ typedef struct _P3D_class_definition { /* And this structure defines the actual instances of P3D_object. */ struct _P3D_object { const P3D_class_definition *_class; + int _ref_count; /* Additional opaque data may be stored here. */ }; @@ -446,9 +444,6 @@ struct _P3D_object { /* These macros are defined for the convenience of invoking any of the above method functions on an object. */ -#define P3D_OBJECT_FINISH(object) ((object)->_class->_finish((object))) -#define P3D_OBJECT_COPY(object) ((object)->_class->_copy((object))) - #define P3D_OBJECT_GET_TYPE(object) ((object)->_class->_get_type((object))) #define P3D_OBJECT_GET_BOOL(object) ((object)->_class->_get_bool((object))) #define P3D_OBJECT_GET_INT(object) ((object)->_class->_get_int((object))) @@ -463,58 +458,65 @@ struct _P3D_object { #define P3D_OBJECT_CALL(object, method_name, params, num_params) ((object)->_class->_call((object), (method_name), (params), (num_params))) #define P3D_OBJECT_EVAL(object, expression) ((object)->_class->_eval((object), (expression))) +/* These macros are provided to manipulate the reference count of the + indicated object. Following Python's convention, XDECREF is + provided to decrement the reference count for a pointer that might + be NULL (it does nothing in the case of a NULL pointer). */ -/* The following function types are once again meant to define - actual function pointers to be found within the core API DLL. */ +#define P3D_OBJECT_INCREF(object) (++(object)->_ref_count) +#define P3D_OBJECT_DECREF(object) { if (--(object)->_ref_count <= 0) { (object)->_class->_finish((object)); } } +#define P3D_OBJECT_XDECREF(object) { if ((object) != (P3D_object *)NULL) { P3D_OBJECT_DECREF(object); } } -/* Returns a newly-allocated P3D_class_definition object, filled with - generic function pointers that have reasonable default behavior for - all methods. The host should use this function to get a clean + +/* End of method pointer definitions. The following function types + are once again meant to define actual function pointers to be found + within the core API DLL. */ + +/* Returns a new P3D_class_definition object, filled with generic + function pointers that have reasonable default behavior for all + methods. The host should use this function to get a clean P3D_class_definition object before calling - P3D_instance_set_browser_script_object() (see below). Note that this - pointer will automatically be freed when P3D_finalize() is + P3D_instance_set_browser_script_object() (see below). Note that + this pointer will automatically be freed when P3D_finalize() is called. */ typedef P3D_class_definition * P3D_make_class_definition_func(); -/* Allocates a new P3D_object of type "undefined". This corresponds - to the undefined or void type on JavaScript. It is similar to - Python's None, but has a subtly different shade of meaning; we map - it to an explicit Undefined instance in runp3d.py. */ +/* Returns a new-reference P3D_object of type "undefined". This + corresponds to the undefined or void type on JavaScript. It is + similar to Python's None, but has a subtly different shade of + meaning; we map it to an explicit Undefined instance in + runp3d.py. */ typedef P3D_object * P3D_new_undefined_object_func(); -/* Allocates a new P3D_object of type none. This value has no +/* Returns a new-reference P3D_object of type none. This value has no particular value and corresponds to Python's None type or JavaScript's null type. */ typedef P3D_object * P3D_new_none_object_func(); -/* Allocates a new P3D_object of type bool. */ +/* Returns a new-reference P3D_object of type bool. */ typedef P3D_object * P3D_new_bool_object_func(bool value); -/* Allocates a new P3D_object of type int. */ +/* Returns a new-reference P3D_object of type int. */ typedef P3D_object * P3D_new_int_object_func(int value); -/* Allocates a new P3D_object of type float. */ +/* Returns a new-reference P3D_object of type float. */ typedef P3D_object * P3D_new_float_object_func(double value); -/* Allocates a new P3D_object of type string. The supplied string is - copied into the object and stored internally. */ +/* Returns a new-reference P3D_object of type string. The supplied + string is copied into the object and stored internally. */ typedef P3D_object * P3D_new_string_object_func(const char *string, int length); -/* Returns a pointer to the top-level scriptable object of the - instance. Scripts running on the host may use this object to - communicate with the instance, by using the above methods to set or - query properties, and/or call methods, on the instance. - - The return value from this function is a newly-allocated object; - ownership of the object is passed to the caller, who should be - responsible for deleting it eventually. */ +/* Returns a new-reference pointer to the top-level scriptable object + of the instance. Scripts running on the host may use this object + to communicate with the instance, by using the above methods to set + or query properties, and/or call methods, on the instance. */ typedef P3D_object * P3D_instance_get_panda_script_object_func(P3D_instance *instance); @@ -528,8 +530,8 @@ P3D_instance_get_panda_script_object_func(P3D_instance *instance); have a custom P3D_class_definition pointer, which also must have been created by the host. The best way to create an appropriate class definition is call P3D_make_class_definition(), and then - replace the function pointers for at least _finish, _copy, - _get_property, _set_property, and _call. Set these pointers to the + replace the function pointers for at least _finish, _get_property, + _set_property, _has_method, and _call. Set these pointers to the host's own functions that make the appropriate changes in the DOM, or invoke the appropriate JavaScript functions. @@ -538,10 +540,10 @@ P3D_instance_get_panda_script_object_func(P3D_instance *instance); able to control the instance via P3D_instance_get_panda_script_object(), above. - Ownership of the object is passed into the instance. The caller - must have freshly allocated the object, and should no longer store - or delete it. The instance will eventually delete it by calling - its _finish method. */ + Note that the object's constructor should initialize its reference + count to 1. The instance will increment reference count as a + result of this call; the caller is responsible for calling DECREF + on the object after this call to remove its own reference. */ typedef void P3D_instance_set_browser_script_object_func(P3D_instance *instance, P3D_object *object); diff --git a/direct/src/plugin/p3d_plugin_common.h b/direct/src/plugin/p3d_plugin_common.h index 8468082f30..7446c31780 100644 --- a/direct/src/plugin/p3d_plugin_common.h +++ b/direct/src/plugin/p3d_plugin_common.h @@ -41,7 +41,7 @@ extern ostream *nout_stream; // A convenience function for formatting a generic P3D_object to an // ostream. inline ostream & -operator << (ostream &out, const P3D_object &value) { +operator << (ostream &out, P3D_object &value) { int size = P3D_OBJECT_GET_REPR(&value, NULL, 0); char *buffer = new char[size]; P3D_OBJECT_GET_REPR(&value, buffer, size); diff --git a/direct/src/plugin_npapi/ppBrowserObject.cxx b/direct/src/plugin_npapi/ppBrowserObject.cxx index 402267c435..7f24a4915e 100644 --- a/direct/src/plugin_npapi/ppBrowserObject.cxx +++ b/direct/src/plugin_npapi/ppBrowserObject.cxx @@ -26,18 +26,13 @@ object_finish(P3D_object *object) { delete ((PPBrowserObject *)object); } -static P3D_object * -object_copy(const P3D_object *object) { - return new PPBrowserObject(*(const PPBrowserObject *)object); -} - static int -object_get_repr(const P3D_object *object, char *buffer, int buffer_length) { +object_get_repr(P3D_object *object, char *buffer, int buffer_length) { return ((const PPBrowserObject *)object)->get_repr(buffer, buffer_length); } static P3D_object * -object_get_property(const P3D_object *object, const char *property) { +object_get_property(P3D_object *object, const char *property) { return ((const PPBrowserObject *)object)->get_property(property); } @@ -48,7 +43,7 @@ object_set_property(P3D_object *object, const char *property, } static P3D_object * -object_call(const P3D_object *object, const char *method_name, +object_call(P3D_object *object, const char *method_name, P3D_object *params[], int num_params) { if (method_name == NULL) { method_name = ""; @@ -57,7 +52,7 @@ object_call(const P3D_object *object, const char *method_name, } static P3D_object * -object_eval(const P3D_object *object, const char *expression) { +object_eval(P3D_object *object, const char *expression) { return ((const PPBrowserObject *)object)->eval(expression); } @@ -74,6 +69,7 @@ PPBrowserObject(PPInstance *inst, NPObject *npobj) : _npobj(npobj) { _class = get_class_definition(); + _ref_count = 1; browser->retainobject(_npobj); } @@ -88,6 +84,7 @@ PPBrowserObject(const PPBrowserObject ©) : _npobj(copy._npobj) { _class = get_class_definition(); + _ref_count = 1; browser->retainobject(_npobj); } @@ -98,6 +95,7 @@ PPBrowserObject(const PPBrowserObject ©) : //////////////////////////////////////////////////////////////////// PPBrowserObject:: ~PPBrowserObject() { + assert(_ref_count == 0); browser->releaseobject(_npobj); } @@ -162,7 +160,6 @@ set_property(const string &property, P3D_object *value) { result = browser->setproperty(_instance->get_npp_instance(), _npobj, property_name, &npvalue); browser->releasevariantvalue(&npvalue); - P3D_OBJECT_FINISH(value); } else { // Delete the property. @@ -268,7 +265,6 @@ get_class_definition() { // appropriate pointers. _browser_object_class = P3D_make_class_definition(); _browser_object_class->_finish = &object_finish; - _browser_object_class->_copy = &object_copy; _browser_object_class->_get_repr = &object_get_repr; _browser_object_class->_get_property = &object_get_property; diff --git a/direct/src/plugin_npapi/ppInstance.cxx b/direct/src/plugin_npapi/ppInstance.cxx index c759bfe02d..686417dffc 100644 --- a/direct/src/plugin_npapi/ppInstance.cxx +++ b/direct/src/plugin_npapi/ppInstance.cxx @@ -501,7 +501,7 @@ get_panda_script_object() { // NPVariant, and stores it in result. //////////////////////////////////////////////////////////////////// void PPInstance:: -p3dobj_to_variant(NPVariant *result, const P3D_object *object) { +p3dobj_to_variant(NPVariant *result, P3D_object *object) { switch (P3D_OBJECT_GET_TYPE(object)) { case P3D_OT_undefined: VOID_TO_NPVARIANT(*result); @@ -534,7 +534,7 @@ p3dobj_to_variant(NPVariant *result, const P3D_object *object) { case P3D_OT_object: { - PPPandaObject *ppobj = PPPandaObject::make_new(this, P3D_OBJECT_COPY(object)); + PPPandaObject *ppobj = PPPandaObject::make_new(this, object); OBJECT_TO_NPVARIANT(ppobj, *result); } break; @@ -571,7 +571,7 @@ variant_to_p3dobj(const NPVariant *variant) { PPPandaObject *ppobject = (PPPandaObject *)object; P3D_object *obj = ppobject->get_p3d_object(); logfile << "Found nested Panda Object " << obj << "\n" << flush; - return P3D_OBJECT_COPY(obj); + return obj; } // It's a generic NPObject of some kind. @@ -899,7 +899,7 @@ create_instance() { logfile << "Couldn't get window_object\n" << flush; } - const P3D_token *tokens = NULL; + P3D_token *tokens = NULL; if (!_tokens.empty()) { tokens = &_tokens[0]; } diff --git a/direct/src/plugin_npapi/ppInstance.h b/direct/src/plugin_npapi/ppInstance.h index e33e13189f..ed2899cc47 100644 --- a/direct/src/plugin_npapi/ppInstance.h +++ b/direct/src/plugin_npapi/ppInstance.h @@ -55,7 +55,7 @@ public: NPObject *get_panda_script_object(); - void p3dobj_to_variant(NPVariant *result, const P3D_object *object); + void p3dobj_to_variant(NPVariant *result, P3D_object *object); P3D_object *variant_to_p3dobj(const NPVariant *variant); static void output_np_variant(ostream &out, const NPVariant &result); diff --git a/direct/src/plugin_npapi/ppPandaObject.I b/direct/src/plugin_npapi/ppPandaObject.I index f723df32f4..e4ac51a6d9 100644 --- a/direct/src/plugin_npapi/ppPandaObject.I +++ b/direct/src/plugin_npapi/ppPandaObject.I @@ -18,8 +18,12 @@ // Access: Public // Description: Returns the p3d_object this PPPandaObject maps to. This // may be NULL if the object is not fully initialized. +// If not NULL, this returns a new reference. //////////////////////////////////////////////////////////////////// inline P3D_object *PPPandaObject:: get_p3d_object() const { + if (_p3d_object != NULL) { + P3D_OBJECT_INCREF(_p3d_object); + } return _p3d_object; } diff --git a/direct/src/plugin_npapi/ppPandaObject.cxx b/direct/src/plugin_npapi/ppPandaObject.cxx index 15e70a360b..7c3d06d9b2 100644 --- a/direct/src/plugin_npapi/ppPandaObject.cxx +++ b/direct/src/plugin_npapi/ppPandaObject.cxx @@ -53,16 +53,17 @@ make_new(PPInstance *inst, P3D_object *p3d_object) { // Function: PPPandaObject::set_p3d_object // Access: Public // Description: Changes the p3d_object this PPPandaObject maps to. The -// previous object, if any, is deleted. Ownership of -// the new object is passed to the PPPandaObject. +// new object's reference count is incremented, and the +// previous object's is decremented. //////////////////////////////////////////////////////////////////// void PPPandaObject:: set_p3d_object(P3D_object *p3d_object) { if (_p3d_object != p3d_object) { - if (_p3d_object != NULL) { - P3D_OBJECT_FINISH(_p3d_object); - } + P3D_OBJECT_XDECREF(_p3d_object); _p3d_object = p3d_object; + if (_p3d_object != NULL) { + P3D_OBJECT_INCREF(_p3d_object); + } } } @@ -78,7 +79,8 @@ void PPPandaObject:: construct(PPInstance *inst, P3D_object *p3d_object) { logfile << "construct: " << this << "\n" << flush; _instance = inst; - _p3d_object = p3d_object; + _p3d_object = NULL; + set_p3d_object(p3d_object); } //////////////////////////////////////////////////////////////////// @@ -141,12 +143,16 @@ invoke(NPIdentifier name, const NPVariant *args, uint32_t argCount, } P3D_object **p3dargs = new P3D_object *[argCount]; - for (unsigned int i = 0; i < argCount; ++i) { + unsigned int i; + for (i = 0; i < argCount; ++i) { p3dargs[i] = _instance->variant_to_p3dobj(&args[i]); } P3D_object *value = P3D_OBJECT_CALL(_p3d_object, method_name.c_str(), p3dargs, argCount); + for (i = 0; i < argCount; ++i) { + P3D_OBJECT_DECREF(p3dargs[i]); + } delete[] p3dargs; if (value == NULL) { @@ -156,7 +162,7 @@ invoke(NPIdentifier name, const NPVariant *args, uint32_t argCount, // We have the return value, and its value is stored in value. _instance->p3dobj_to_variant(result, value); - P3D_OBJECT_FINISH(value); + P3D_OBJECT_DECREF(value); return true; } @@ -177,12 +183,16 @@ invoke_default(const NPVariant *args, uint32_t argCount, } P3D_object **p3dargs = new P3D_object *[argCount]; - for (unsigned int i = 0; i < argCount; ++i) { + unsigned int i; + for (i = 0; i < argCount; ++i) { p3dargs[i] = _instance->variant_to_p3dobj(&args[i]); } P3D_object *value = P3D_OBJECT_CALL(_p3d_object, "", p3dargs, argCount); + for (i = 0; i < argCount; ++i) { + P3D_OBJECT_DECREF(p3dargs[i]); + } delete[] p3dargs; if (value == NULL) { @@ -192,7 +202,7 @@ invoke_default(const NPVariant *args, uint32_t argCount, // We have the return value, and its value is stored in value. _instance->p3dobj_to_variant(result, value); - P3D_OBJECT_FINISH(value); + P3D_OBJECT_DECREF(value); return true; } @@ -239,7 +249,7 @@ get_property(NPIdentifier name, NPVariant *result) { // We have the property, and its value is stored in value. _instance->p3dobj_to_variant(result, value); - P3D_OBJECT_FINISH(value); + P3D_OBJECT_DECREF(value); return true; } @@ -260,6 +270,7 @@ set_property(NPIdentifier name, const NPVariant *value) { P3D_object *object = _instance->variant_to_p3dobj(value); bool result = P3D_OBJECT_SET_PROPERTY(_p3d_object, property_name.c_str(), object); + P3D_OBJECT_DECREF(object); return result; }