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_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_new_undefined_object_func *P3D_new_undefined_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_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_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");
@ -190,6 +194,8 @@ load_plugin(const string &p3d_plugin_filename) {
P3D_instance_finish == NULL ||
P3D_instance_setup_window == NULL ||
P3D_object_incref == NULL ||
P3D_object_decref == NULL ||
P3D_make_class_definition == NULL ||
P3D_new_undefined_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_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_new_undefined_object = " << P3D_new_undefined_object
<< "\nP3D_new_none_object = " << P3D_new_none_object
@ -293,6 +301,8 @@ unload_dso() {
P3D_instance_finish = NULL;
P3D_instance_setup_window = NULL;
P3D_object_incref = NULL;
P3D_object_decref = NULL;
P3D_make_class_definition = NULL;
P3D_new_undefined_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_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_new_undefined_object_func *P3D_new_undefined_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);
}
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_make_class_definition() {
assert(P3DInstanceManager::get_global_ptr()->is_initialized());

View File

@ -307,19 +307,20 @@ 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
/* 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
the Python naming convention. Similarly, methods that receive a
P3D_object as a parameter will generally *not* adjust that object's
reference count (except to increment it the object is stored
internally), leaving the caller still the owner of the original
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. */
/* This method is called to deallocate the object and all of its
internal structures. Do not call it directly; call
/* This method is called internally to deallocate the object and all
of its internal structures. Do not call it directly; call
P3D_OBJECT_DECREF() instead. */
typedef void
P3D_object_finish_method(P3D_object *object);
@ -376,10 +377,13 @@ P3D_object_get_repr_method(P3D_object *object,
typedef P3D_object *
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
pointer is NULL, the property is deleted. Returns true on success,
false on failure. */
/* Changes the value at the indicated property. The new value is
assigned to the indicating property, and its reference count is
correspondingly incremented. Any existing object previously
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
P3D_object_set_property_method(P3D_object *object, const char *property,
P3D_object *value);
@ -405,7 +409,7 @@ 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.
object. Python objects do not support this method.
The return value is a new-reference P3D_object on success, or NULL
on failure. */
@ -459,14 +463,24 @@ struct _P3D_object {
#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). */
indicated object. They are not thread-safe; they should be called
only within the main thread. If you need a thread-safe reference
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_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); } }
/* 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
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_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_new_undefined_object_func P3D_new_undefined_object;
EXPCL_P3D_PLUGIN P3D_new_none_object_func P3D_new_none_object;