libBLOC
Barry Restructuring object core + portable locking 22e0342 (2 years, 11 months ago)
/*
* Copyright (C) 2023 Barry
*
* This file is part of Barry's Little Objects in C Library (libBLOC).
*
* libBLOC is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* libBLOC is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTIBILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* libBLOC. If not, see <https://www.gnu.org/licenses/>.
*/
/*
* This file contains the core of the object library. It implements the basic
* operations each object needs and leaves the rest up to the respective
* program that implements the object. The object library is a resource
* manager which should help improve memory safety within a program. It
* reference counts each object and controls their instantiation and deletion.
*/
#include <string.h>
#include <BLOC/object.h>
#include "../assert.h"
#include "object.h"
/* Obtain a reference to an object */
void *
obj_get(void *addr)
{
struct ObjectHeader *obj = object_header(addr);
ASSERT(obj->magic == OBJECT_MAGIC);
__atomic_add_fetch(&obj->type->usage, 1, __ATOMIC_RELAXED);
__atomic_add_fetch(&obj->usage, 1, __ATOMIC_RELAXED);
return addr;
}
/* Release a reference to an object */
void
obj_put(void *addr)
{
struct ObjectHeader *obj = object_header(addr);
ASSERT(obj->magic == OBJECT_MAGIC);
__atomic_sub_fetch(&obj->type->usage, 1, __ATOMIC_RELAXED);
if (__atomic_sub_fetch(&obj->usage, 1, __ATOMIC_RELAXED))
return;
/* Free object */
obj_lock(addr);
if (obj->type->delete)
obj->type->delete(addr);
obj_unlock(addr);
obj->magic = 0;
free(obj);
}
/* Create a new instance of an object type */
void *
obj_new(struct ObjectType *type)
{
void *body;
struct ObjectHeader *obj;
obj = malloc(sizeof(struct ObjectType) + type->size);
body = (void *) (obj + 1);
memset(body, 0, type->size);
obj->magic = OBJECT_MAGIC;
obj->type = type;
if (type->new)
type->new(body);
return obj_get(body);
}