view src/base/ptr.h @ 185:db386ec98dc3

base/ptr: Add yptr_rc_t implementation
author Lewin Bormann <lbo@spheniscida.de>
date Sun, 29 Sep 2019 14:42:18 +0200
parents
children
line wrap: on
line source

#ifndef base_ptr_h
#define base_ptr_h

#include <stdlib.h>

/**
 * @file ptr.h
 * @addtogroup base-ptr
 * @{
 * @brief Smart pointers for C.
 */

/// Called when an object needs to be freed.
typedef void (*yptr_delete_handler_t)(void*);

struct yptr_rc_counter;

/**
 * @brief A reference-counted smart-pointer.
 */
typedef struct {
    /// ptr points to the referenced object. It must point to dynamic memory and
    /// is freed when there are no references left.
    void* ptr;

    /// Internal, do not rely on this.
    struct yptr_rc_counter* count;
} yptr_rc_t;

/**
 * @brief Move a pointer into a smart pointer.
 */
#define YPTR_RC(rawp, deletehandler) \
    (assert(rawp), yptr_rc_new(rawp, sizeof(*rawp), deletehandler))

/**
 * @brief Move a pointer into a smart pointer. It is recommended to use YPTR_RC
 * instead.
 *
 * `deletehandler` is called when the last reference is deleted, if it is not NULL.
 */
yptr_rc_t yptr_rc_new(void* ptr, size_t size,
                      yptr_delete_handler_t deletehandler);

/**
 * @brief Dereference a reference-counted pointer.
 */
#define YPTR_DEREF(rcptr, typ) (typ*)(yptr_rc_deref(rcptr))

void* yptr_rc_deref(yptr_rc_t rcp);

/// @brief Create an additional reference.
yptr_rc_t yptr_rc_clone(yptr_rc_t rcp);

/// @brief Remove an existing reference. Frees all memory if rcp is the last
/// existing reference.
void yptr_rc_delete(yptr_rc_t rcp);

/// @brief How many references exist currently. Never returns 0.
size_t yptr_rc_refs(yptr_rc_t rcp);

/**
 * @}
 */

#endif