blob: 794a0324c22b92571a40df960b0945719c2a2bf1 [file] [log] [blame]
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
#include <proton/object.h>
#include "core/memory.h"
#include <stdlib.h>
#include <assert.h>
#define pn_object_initialize NULL
#define pn_object_finalize NULL
#define pn_object_inspect NULL
uintptr_t pn_object_hashcode(void *object) { return (uintptr_t) object; }
intptr_t pn_object_compare(void *a, void *b) { return (intptr_t) a - (intptr_t) b; }
const pn_class_t PN_OBJECT[] = {PN_CLASS(pn_object)};
#define pn_void_initialize NULL
void *pn_void_new(const pn_class_t *clazz, size_t size) { return pni_mem_allocate(clazz, size); }
void pn_void_incref(void* p) {}
void pn_void_decref(void* p) {}
int pn_void_refcount(void *object) { return -1; }
#define pn_void_finalize NULL
static void pn_void_free(void *object) { pni_mem_deallocate(PN_VOID, object); }
static const pn_class_t *pn_void_reify(void *object) { return PN_VOID; }
uintptr_t pn_void_hashcode(void *object) { return (uintptr_t) object; }
intptr_t pn_void_compare(void *a, void *b) { return (intptr_t) a - (intptr_t) b; }
int pn_void_inspect(void *object, pn_string_t *dst) { return pn_string_addf(dst, "%p", object); }
const pn_class_t PN_VOID[] = {PN_METACLASS(pn_void)};
const char *pn_class_name(const pn_class_t *clazz)
{
return clazz->name;
}
pn_cid_t pn_class_id(const pn_class_t *clazz)
{
return clazz->cid;
}
void *pn_class_new(const pn_class_t *clazz, size_t size)
{
assert(clazz);
void *object = clazz->newinst(clazz, size);
if (clazz->initialize) {
clazz->initialize(object);
}
return object;
}
void *pn_class_incref(const pn_class_t *clazz, void *object)
{
assert(clazz);
if (object) {
clazz = clazz->reify(object);
clazz->incref(object);
}
return object;
}
int pn_class_refcount(const pn_class_t *clazz, void *object)
{
assert(clazz);
clazz = clazz->reify(object);
return clazz->refcount(object);
}
int pn_class_decref(const pn_class_t *clazz, void *object)
{
assert(clazz);
if (object) {
clazz = clazz->reify(object);
clazz->decref(object);
int rc = clazz->refcount(object);
if (rc == 0) {
if (clazz->finalize) {
clazz->finalize(object);
// check the refcount again in case the finalizer created a
// new reference
rc = clazz->refcount(object);
}
if (rc == 0) {
clazz->free(object);
return 0;
}
} else {
return rc;
}
}
return 0;
}
void pn_class_free(const pn_class_t *clazz, void *object)
{
assert(clazz);
if (object) {
clazz = clazz->reify(object);
int rc = clazz->refcount(object);
assert(rc == 1 || rc == -1);
if (rc == 1) {
rc = pn_class_decref(clazz, object);
assert(rc == 0);
} else {
if (clazz->finalize) {
clazz->finalize(object);
}
clazz->free(object);
}
}
}
const pn_class_t *pn_class_reify(const pn_class_t *clazz, void *object)
{
assert(clazz);
return clazz->reify(object);
}
uintptr_t pn_class_hashcode(const pn_class_t *clazz, void *object)
{
assert(clazz);
if (!object) return 0;
clazz = clazz->reify(object);
if (clazz->hashcode) {
return clazz->hashcode(object);
} else {
return (uintptr_t) object;
}
}
intptr_t pn_class_compare(const pn_class_t *clazz, void *a, void *b)
{
assert(clazz);
if (a == b) return 0;
clazz = clazz->reify(a);
if (a && b && clazz->compare) {
return clazz->compare(a, b);
} else {
return (intptr_t) a - (intptr_t) b;
}
}
bool pn_class_equals(const pn_class_t *clazz, void *a, void *b)
{
return pn_class_compare(clazz, a, b) == 0;
}
int pn_class_inspect(const pn_class_t *clazz, void *object, pn_string_t *dst)
{
assert(clazz);
clazz = clazz->reify(object);
if (!pn_string_get(dst)) {
pn_string_set(dst, "");
}
if (object && clazz->inspect) {
return clazz->inspect(object, dst);
}
const char *name = clazz->name ? clazz->name : "<anon>";
return pn_string_addf(dst, "%s<%p>", name, object);
}
typedef struct {
const pn_class_t *clazz;
int refcount;
} pni_head_t;
#define pni_head(PTR) \
(((pni_head_t *) (PTR)) - 1)
void *pn_object_new(const pn_class_t *clazz, size_t size)
{
void *object = NULL;
pni_head_t *head = (pni_head_t *) pni_mem_zallocate(clazz, sizeof(pni_head_t) + size);
if (head != NULL) {
object = head + 1;
head->clazz = clazz;
head->refcount = 1;
}
return object;
}
const pn_class_t *pn_object_reify(void *object)
{
if (object) {
return pni_head(object)->clazz;
} else {
return PN_OBJECT;
}
}
void pn_object_incref(void *object)
{
if (object) {
pni_head(object)->refcount++;
}
}
int pn_object_refcount(void *object)
{
assert(object);
return pni_head(object)->refcount;
}
void pn_object_decref(void *object)
{
pni_head_t *head = pni_head(object);
assert(head->refcount > 0);
head->refcount--;
}
void pn_object_free(void *object)
{
pni_head_t *head = pni_head(object);
pni_mem_deallocate(head->clazz, head);
}
void *pn_incref(void *object)
{
return pn_class_incref(PN_OBJECT, object);
}
int pn_decref(void *object)
{
return pn_class_decref(PN_OBJECT, object);
}
int pn_refcount(void *object)
{
return pn_class_refcount(PN_OBJECT, object);
}
void pn_free(void *object)
{
pn_class_free(PN_OBJECT, object);
}
const pn_class_t *pn_class(void *object)
{
return pn_class_reify(PN_OBJECT, object);
}
uintptr_t pn_hashcode(void *object)
{
return pn_class_hashcode(PN_OBJECT, object);
}
intptr_t pn_compare(void *a, void *b)
{
return pn_class_compare(PN_OBJECT, a, b);
}
bool pn_equals(void *a, void *b)
{
return !pn_compare(a, b);
}
int pn_inspect(void *object, pn_string_t *dst)
{
return pn_class_inspect(PN_OBJECT, object, dst);
}
#define pn_weakref_new NULL
#define pn_weakref_initialize NULL
#define pn_weakref_finalize NULL
#define pn_weakref_free NULL
static void pn_weakref_incref(void *object) {}
static void pn_weakref_decref(void *object) {}
static int pn_weakref_refcount(void *object) { return -1; }
static const pn_class_t *pn_weakref_reify(void *object) {
return PN_WEAKREF;
}
static uintptr_t pn_weakref_hashcode(void *object) {
return pn_hashcode(object);
}
static intptr_t pn_weakref_compare(void *a, void *b) {
return pn_compare(a, b);
}
static int pn_weakref_inspect(void *object, pn_string_t *dst) {
return pn_inspect(object, dst);
}
const pn_class_t PN_WEAKREF[] = {PN_METACLASS(pn_weakref)};