/* reference counting */
-extern struct json_object* json_object_get(struct json_object *jso)
+extern struct json_object* json_object_retain(struct json_object *jso)
{
- if (jso)
- jso->_ref_count++;
+ if (!jso) return jso;
+
+ #if defined(HAVE_ATOMIC_BUILTINS) && defined(ENABLE_THREADING)
+ __sync_add_and_fetch(&jso->_ref_count, 1);
+ #else
+ ++jso->_ref_count;
+ #endif
+
return jso;
}
-int json_object_put(struct json_object *jso)
+int json_object_release(struct json_object *jso)
{
- if(jso)
- {
- jso->_ref_count--;
- if(!jso->_ref_count)
- {
- if (jso->_user_delete)
- jso->_user_delete(jso, jso->_userdata);
- jso->_delete(jso);
- return 1;
- }
- }
- return 0;
+ if(!jso) return 0;
+
+ #if defined(HAVE_ATOMIC_BUILTINS) && defined(ENABLE_THREADING)
+ /* Note: this only allow the refcount to remain correct
+ * when multiple threads are adjusting it. It is still an error
+ * for a thread to decrement the refcount if it doesn't "own" it,
+ * as that can result in the thread that loses the race to 0
+ * operating on an already-freed object.
+ */
+ if (__sync_sub_and_fetch(&jso->_ref_count, 1) > 0) return 0;
+ #else
+ if (--jso->_ref_count > 0) return 0;
+ #endif
+
+ if (jso->_user_delete)
+ jso->_user_delete(jso, jso->_userdata);
+ jso->_delete(jso);
+ return 1;
}