add thread-safe reference count functions

This commit is contained in:
David Rose 2009-07-10 00:14:25 +00:00
parent 4d2ffd8e77
commit dc6c73108c
4 changed files with 66 additions and 18 deletions

View File

@ -41,6 +41,8 @@ P3D_instance_start_func *P3D_instance_start;
P3D_instance_finish_func *P3D_instance_finish; P3D_instance_finish_func *P3D_instance_finish;
P3D_instance_setup_window_func *P3D_instance_setup_window; P3D_instance_setup_window_func *P3D_instance_setup_window;
P3D_object_incref_func *P3D_object_incref;
P3D_object_decref_func *P3D_object_decref;
P3D_make_class_definition_func *P3D_make_class_definition; P3D_make_class_definition_func *P3D_make_class_definition;
P3D_new_undefined_object_func *P3D_new_undefined_object; P3D_new_undefined_object_func *P3D_new_undefined_object;
P3D_new_none_object_func *P3D_new_none_object; P3D_new_none_object_func *P3D_new_none_object;
@ -165,6 +167,8 @@ load_plugin(const string &p3d_plugin_filename) {
P3D_instance_finish = (P3D_instance_finish_func *)get_func(module, "P3D_instance_finish"); P3D_instance_finish = (P3D_instance_finish_func *)get_func(module, "P3D_instance_finish");
P3D_instance_setup_window = (P3D_instance_setup_window_func *)get_func(module, "P3D_instance_setup_window"); P3D_instance_setup_window = (P3D_instance_setup_window_func *)get_func(module, "P3D_instance_setup_window");
P3D_object_incref = (P3D_object_incref_func *)get_func(module, "P3D_object_incref");
P3D_object_decref = (P3D_object_decref_func *)get_func(module, "P3D_object_decref");
P3D_make_class_definition = (P3D_make_class_definition_func *)get_func(module, "P3D_make_class_definition"); P3D_make_class_definition = (P3D_make_class_definition_func *)get_func(module, "P3D_make_class_definition");
P3D_new_undefined_object = (P3D_new_undefined_object_func *)get_func(module, "P3D_new_undefined_object"); P3D_new_undefined_object = (P3D_new_undefined_object_func *)get_func(module, "P3D_new_undefined_object");
P3D_new_none_object = (P3D_new_none_object_func *)get_func(module, "P3D_new_none_object"); P3D_new_none_object = (P3D_new_none_object_func *)get_func(module, "P3D_new_none_object");
@ -190,6 +194,8 @@ load_plugin(const string &p3d_plugin_filename) {
P3D_instance_finish == NULL || P3D_instance_finish == NULL ||
P3D_instance_setup_window == NULL || P3D_instance_setup_window == NULL ||
P3D_object_incref == NULL ||
P3D_object_decref == NULL ||
P3D_make_class_definition == NULL || P3D_make_class_definition == NULL ||
P3D_new_undefined_object == NULL || P3D_new_undefined_object == NULL ||
P3D_new_none_object == NULL || P3D_new_none_object == NULL ||
@ -214,6 +220,8 @@ load_plugin(const string &p3d_plugin_filename) {
<< "\nP3D_instance_finish = " << P3D_instance_finish << "\nP3D_instance_finish = " << P3D_instance_finish
<< "\nP3D_instance_setup_window = " << P3D_instance_setup_window << "\nP3D_instance_setup_window = " << P3D_instance_setup_window
<< "\nP3D_object_incref = " << P3D_object_incref
<< "\nP3D_object_decref = " << P3D_object_decref
<< "\nP3D_make_class_definition = " << P3D_make_class_definition << "\nP3D_make_class_definition = " << P3D_make_class_definition
<< "\nP3D_new_undefined_object = " << P3D_new_undefined_object << "\nP3D_new_undefined_object = " << P3D_new_undefined_object
<< "\nP3D_new_none_object = " << P3D_new_none_object << "\nP3D_new_none_object = " << P3D_new_none_object
@ -293,6 +301,8 @@ unload_dso() {
P3D_instance_finish = NULL; P3D_instance_finish = NULL;
P3D_instance_setup_window = NULL; P3D_instance_setup_window = NULL;
P3D_object_incref = NULL;
P3D_object_decref = NULL;
P3D_make_class_definition = NULL; P3D_make_class_definition = NULL;
P3D_new_undefined_object = NULL; P3D_new_undefined_object = NULL;
P3D_new_none_object = NULL; P3D_new_none_object = NULL;

View File

@ -27,6 +27,8 @@ extern P3D_instance_start_func *P3D_instance_start;
extern P3D_instance_finish_func *P3D_instance_finish; extern P3D_instance_finish_func *P3D_instance_finish;
extern P3D_instance_setup_window_func *P3D_instance_setup_window; extern P3D_instance_setup_window_func *P3D_instance_setup_window;
extern P3D_object_incref_func *P3D_object_incref;
extern P3D_object_decref_func *P3D_object_decref;
extern P3D_make_class_definition_func *P3D_make_class_definition; extern P3D_make_class_definition_func *P3D_make_class_definition;
extern P3D_new_undefined_object_func *P3D_new_undefined_object; extern P3D_new_undefined_object_func *P3D_new_undefined_object;
extern P3D_new_none_object_func *P3D_new_none_object; extern P3D_new_none_object_func *P3D_new_none_object;

View File

@ -121,6 +121,26 @@ P3D_instance_setup_window(P3D_instance *instance,
RELEASE_LOCK(_api_lock); RELEASE_LOCK(_api_lock);
} }
void
P3D_object_incref(P3D_object *object) {
assert(P3DInstanceManager::get_global_ptr()->is_initialized());
ACQUIRE_LOCK(_api_lock);
P3D_OBJECT_INCREF(object);
RELEASE_LOCK(_api_lock);
}
void
P3D_object_decref(P3D_object *object) {
assert(P3DInstanceManager::get_global_ptr()->is_initialized());
ACQUIRE_LOCK(_api_lock);
P3D_OBJECT_DECREF(object);
RELEASE_LOCK(_api_lock);
}
P3D_class_definition * P3D_class_definition *
P3D_make_class_definition() { P3D_make_class_definition() {
assert(P3DInstanceManager::get_global_ptr()->is_initialized()); assert(P3DInstanceManager::get_global_ptr()->is_initialized());

View File

@ -307,19 +307,20 @@ typedef enum {
P3D_OT_object, P3D_OT_object,
} P3D_object_type; } P3D_object_type;
/* Most methods and functions that return a P3D_object return it with /* Methods and functions that return a P3D_object return it with its
its reference count already incremented by one for the benefit of reference count already incremented by one for the benefit of the
the caller, leaving the caller the owner of the implicit reference caller, leaving the caller the owner of the implicit reference
count. This is referred to as returning a "new reference", using count. This is referred to as returning a "new reference", using
the Python naming convention. Similarly, most methods that receive the Python naming convention. Similarly, methods that receive a
a P3D_object will implicitly increment the reference count P3D_object as a parameter will generally *not* adjust that object's
internally if necessary, leaving the caller still the owner of its reference count (except to increment it the object is stored
own reference count. Thus, it is the caller's responsibility to internally), leaving the caller still the owner of the original
call P3D_OBJECT_DECREF() on any P3D_objects it has received but no reference. 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. */ longer wishes to keep. */
/* This method is called to deallocate the object and all of its /* This method is called internally to deallocate the object and all
internal structures. Do not call it directly; call of its internal structures. Do not call it directly; call
P3D_OBJECT_DECREF() instead. */ P3D_OBJECT_DECREF() instead. */
typedef void typedef void
P3D_object_finish_method(P3D_object *object); P3D_object_finish_method(P3D_object *object);
@ -376,10 +377,13 @@ P3D_object_get_repr_method(P3D_object *object,
typedef P3D_object * typedef P3D_object *
P3D_object_get_property_method(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 /* Changes the value at the indicated property. The new value is
already at the corresponding property is deleted. If the value assigned to the indicating property, and its reference count is
pointer is NULL, the property is deleted. Returns true on success, correspondingly incremented. Any existing object previously
false on failure. */ assigned to the corresponding property is replaced, and its
reference count decremented. If the value pointer is NULL, the
property is removed altogether. Returns true on success, false on
failure. */
typedef bool typedef bool
P3D_object_set_property_method(P3D_object *object, const char *property, P3D_object_set_property_method(P3D_object *object, const char *property,
P3D_object *value); P3D_object *value);
@ -405,7 +409,7 @@ P3D_object_call_method(P3D_object *object, const char *method_name,
P3D_object *params[], int num_params); P3D_object *params[], int num_params);
/* Evaluates an arbitrary JavaScript expression in the context of the /* Evaluates an arbitrary JavaScript expression in the context of the
object. object. Python objects do not support this method.
The return value is a new-reference P3D_object on success, or NULL The return value is a new-reference P3D_object on success, or NULL
on failure. */ on failure. */
@ -459,14 +463,24 @@ struct _P3D_object {
#define P3D_OBJECT_EVAL(object, expression) ((object)->_class->_eval((object), (expression))) #define P3D_OBJECT_EVAL(object, expression) ((object)->_class->_eval((object), (expression)))
/* These macros are provided to manipulate the reference count of the /* These macros are provided to manipulate the reference count of the
indicated object. Following Python's convention, XDECREF is indicated object. They are not thread-safe; they should be called
provided to decrement the reference count for a pointer that might only within the main thread. If you need a thread-safe reference
be NULL (it does nothing in the case of a NULL pointer). */ count adjustment, see the similarly-named function calls below.
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). */
#define P3D_OBJECT_INCREF(object) (++(object)->_ref_count) #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_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); } } #define P3D_OBJECT_XDECREF(object) { if ((object) != (P3D_object *)NULL) { P3D_OBJECT_DECREF(object); } }
/* Use these functions for thread-safe variants of the above. */
typedef void
P3D_object_incref_func(P3D_object *object);
typedef void
P3D_object_decref_func(P3D_object *object);
/* End of method pointer definitions. The following function types /* End of method pointer definitions. The following function types
are once again meant to define actual function pointers to be found are once again meant to define actual function pointers to be found
@ -746,6 +760,8 @@ EXPCL_P3D_PLUGIN P3D_instance_start_func P3D_instance_start;
EXPCL_P3D_PLUGIN P3D_instance_finish_func P3D_instance_finish; EXPCL_P3D_PLUGIN P3D_instance_finish_func P3D_instance_finish;
EXPCL_P3D_PLUGIN P3D_instance_setup_window_func P3D_instance_setup_window; EXPCL_P3D_PLUGIN P3D_instance_setup_window_func P3D_instance_setup_window;
EXPCL_P3D_PLUGIN P3D_object_incref_func P3D_object_incref;
EXPCL_P3D_PLUGIN P3D_object_decref_func P3D_object_decref;
EXPCL_P3D_PLUGIN P3D_make_class_definition_func P3D_make_class_definition; EXPCL_P3D_PLUGIN P3D_make_class_definition_func P3D_make_class_definition;
EXPCL_P3D_PLUGIN P3D_new_undefined_object_func P3D_new_undefined_object; EXPCL_P3D_PLUGIN P3D_new_undefined_object_func P3D_new_undefined_object;
EXPCL_P3D_PLUGIN P3D_new_none_object_func P3D_new_none_object; EXPCL_P3D_PLUGIN P3D_new_none_object_func P3D_new_none_object;