Data Structures | Macros | Typedefs | Functions
picotm-lib-shared-ref-obj.h File Reference

Contains struct picotm_shared_ref16_obj and helper functions. More...

#include "compiler.h"
#include "picotm-lib-ref.h"
#include "picotm-lib-spinlock.h"

Data Structures

struct  picotm_shared_ref16_obj
 

Macros

#define PICOTM_SHARED_REF16_OBJ_INITIALIZER
 

Typedefs

typedef bool(* picotm_shared_ref16_obj_condition_function) (struct picotm_shared_ref16_obj *ref_obj, void *data, struct picotm_error *error)
 
typedef void(* picotm_shared_ref16_obj_final_ref_function) (struct picotm_shared_ref16_obj *ref_obj, void *data, struct picotm_error *error)
 
typedef void(* picotm_shared_ref16_obj_first_ref_function) (struct picotm_shared_ref16_obj *ref_obj, void *data, struct picotm_error *error)
 

Functions

uint16_t picotm_shared_ref16_obj_count (struct picotm_shared_ref16_obj *self)
 
void picotm_shared_ref16_obj_down (struct picotm_shared_ref16_obj *self, void *data, picotm_shared_ref16_obj_condition_function cond, picotm_shared_ref16_obj_final_ref_function final_ref)
 
void picotm_shared_ref16_obj_init (struct picotm_shared_ref16_obj *self, struct picotm_error *error)
 
void picotm_shared_ref16_obj_uninit (struct picotm_shared_ref16_obj *self)
 
void picotm_shared_ref16_obj_up (struct picotm_shared_ref16_obj *self, void *data, picotm_shared_ref16_obj_condition_function cond, picotm_shared_ref16_obj_first_ref_function first_ref, struct picotm_error *error)
 

Detailed Description

The data structure struct picotm_shared_ref16_obj is the base for objects with shared reference counting. It maintains the counter and guarantees synchronization with the initializer and finalizer code. The counter of picotm_shared_ref16_obj is 16-bit wide of type struct picotm_shared_ref16. Additional shared-reference-counter types can be added for use cases with different requirements.

Instances of struct picotm_shared_ref16 are typically stored in reference-counted data structures like this.

struct ref_counted {
struct picotm_shared_ref16_obj ref_obj;
// additional data
};

An instance of picotm_shared_ref16_obj is initialized with a call to picotm_shared_ref16_obj_init() and cleaned up with a call to picotm_shared_ref16_obj_uninit(). These functions receive an instance of struct picotm_shared_ref16_obj and the init function also receives an instance of struct picotm_error, which returns error state. These functions are called in the init and un-init functions of the parent class.

void
ref_counted_init(struct ref_counted* self, struct picotm_error* error)
{
picotm_shared_ref16_obj_init(&self->ref_obj, error);
if (picotm_error_is_set(error)) {
return;
}
// additional initialization
}

At this point, the reference counter is initialized to zero and references to the object can be acquired. Next is the clean-up code.

void
ref_counted_uninit(struct ref_counted* self)
{
// additional clean-up code
if (picotm_error_is_set(error)) {
return;
}
}

References to an object are acquired with a call to picotm_shared_ref16_obj_up(). The parameters of the function consist of and instance of struct picotm_shared_ref16_obj, additional user data, an optional conditional function, and optional initializer function and in instance of struct picotm_error, which returns an error state to the caller.

If supplied, the optional conditional function can perform a test before the reference is acquired. If the test fails with a value of false, the reference is not acquired.

If supplied, the optional initializer function initializes the object if, and only if, the first reference is acquired.

The reference-counted object using struct picotm_shared_ref16_obj will typically provide wrapper functions around picotm_shared_ref16_obj_up().

static bool
up_cond(struct picotm_shared_ref16_obj* ref_obj, void* data,
struct picotm_error* error)
{
struct ref_counted* self = picotm_containerof(ref_obj,
struct ref_counted,
ref_obj);
return true; // Perform a test and return success or failure.
}
static void
first_ref(struct picotm_shared_ref16_obj* ref_obj, void* data,
struct picotm_error* error)
{
struct ref_counted* self = picotm_containerof(ref_obj,
struct ref_counted,
ref_obj);
// Perform additional initalization when acquiring the
// first reference.
}
void
ref_counted_up(struct ref_counted* self, struct picotm_error* error)
{
picotm_shared_ref16_obj_up(&self->ref_obj, NULL, up_cond,
first_ref, error);
}

With the example code above, users of struct ref_counted call ref_counted_up() to acquire a reference on an instance of the data structure.

The code for releasing a reference is very similar to code for acquiring one. This time the function picotm_shared_ref16_obj_down() is used.

static bool
down_cond(struct picotm_shared_ref16_obj* ref_obj, void* data,
struct picotm_error* error)
{
struct ref_counted* self = picotm_containerof(ref_obj,
struct ref_counted,
ref_obj);
return true; // Perform a test and return success or failure.
}
static void
final_ref(struct picotm_shared_ref16_obj* ref_obj, void* data,
struct picotm_error* error)
{
struct ref_counted* self = picotm_containerof(ref_obj,
struct ref_counted,
ref_obj);
// Perform additional cleanup when releasing the
// final reference.
}
void
ref_counted_down(struct ref_counted* self)
{
picotm_shared_ref16_obj_down(&self->ref_obj, NULL, down_cond,
final_ref);
}