Fork me on GitHub
Data Structures | Macros | Typedefs | Variables
refcount.h File Reference

Reference counter mechanism. More...

#include <glib.h>
#include "mutex.h"
Include dependency graph for refcount.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  janus_refcount
 

Macros

#define janus_refcount_containerof(refptr, type, member)   ((type *)((char *)(refptr) - offsetof(type, member)))
 Macro to programmatically address the object itself from its counter. More...
 
#define janus_refcount_init(refp, free_fn)
 Janus reference counter initialization (debug according to settings) More...
 
#define janus_refcount_init_nodebug(refp, free_fn)
 Janus reference counter initialization (no debug) More...
 
#define janus_refcount_init_debug(refp, free_fn)
 Janus reference counter initialization (debug) More...
 
#define janus_refcount_increase(refp)
 Increase the Janus reference counter (debug according to settings) More...
 
#define janus_refcount_increase_nodebug(refp)
 Increase the Janus reference counter (no debug) More...
 
#define janus_refcount_increase_debug(refp)
 Increase the Janus reference counter (debug) More...
 
#define janus_refcount_decrease(refp)
 Decrease the Janus reference counter (debug according to settings) More...
 
#define janus_refcount_decrease_debug(refp)
 Decrease the Janus reference counter (debug) More...
 
#define janus_refcount_decrease_nodebug(refp)
 Decrease the Janus reference counter (no debug) More...
 

Typedefs

typedef struct janus_refcount janus_refcount
 Janus reference counter structure. More...
 

Variables

int refcount_debug
 

Detailed Description

Reference counter mechanism.

Author
Lorenzo Miniero loren.nosp@m.zo@m.nosp@m.eetec.nosp@m.ho.c.nosp@m.om

Implementation of a simple reference counter that can be used to keep track of memory management in Janus, in order to avoid the need for timed garbage collectord and the like which have proven ineffective in the past (e.g., crashes whenever race conditions occurred). This implementation is heavily based on an excellent blog post written by Chris Wellons.

Objects interested in leveraging this reference counter mechanism must add a janus_refcount instance as one of the members of the object itself, and then call janus_refcall_init() to set it up. Initializing the reference counter just needs a pointer to the function to invoke when the object needs to be destroyed (counter reaches 0), while it will automatically set the counter to 1. To increase and decrease the counter just call janus_refcount_increase() and janus_refcount_decrease(). When the counter reaches 0, the function passed when initializing it will be invoked: this means it's up to you to then free all the resources the object may have allocated. Notice that if this involves other objects that are reference counted, freeing the resource will just mean decreasing the related counter, and not destroying it right away.

The free function must be defined like this:

void my_free_function(janus_refcount *counter);

Since the reference counter cannot know the size of the object to be freed, or where in the list of members the counter has been placed, retrieving the pointer to the object to free is up to you, using the janus_refcount_containerof macro. This is an example of how the free function we have defined above may be implemented:

typedef my_struct {
        int number;
        char *string;
        janus_refcount myref;
}

void my_free_function(janus_refcount *counter) {
        struct my_struct *my_object = janus_refcount_containerof(counter, struct my_struct, myref);
        if(my_object->string)
                free(my_object->string);
        free(my_object);
}

Core

Macro Definition Documentation

#define janus_refcount_containerof (   refptr,
  type,
  member 
)    ((type *)((char *)(refptr) - offsetof(type, member)))

Macro to programmatically address the object itself from its counter.

refptr is the pointer to the janus_refcount instance, type is the type of the object itself (e.g., struct mystruct), while member is how the janus_refcount instance is called in the object that contains it.

#define janus_refcount_decrease (   refp)
Value:
{ \
} else { \
} \
}
#define janus_refcount_decrease_debug(refp)
Decrease the Janus reference counter (debug)
Definition: refcount.h:200
int refcount_debug
Definition: janus.c:338
#define janus_refcount_decrease_nodebug(refp)
Decrease the Janus reference counter (no debug)
Definition: refcount.h:218

Decrease the Janus reference counter (debug according to settings)

Note
Will invoke the free function if the counter reaches 0
Parameters
refpPointer to the Janus reference counter instance
#define janus_refcount_decrease_debug (   refp)
Value:
{ \
JANUS_PRINT("[%s:%s:%d:decrease] %p (%d)\n", __FILE__, __FUNCTION__, __LINE__, refp, (refp)->count-1); \
if(g_atomic_int_dec_and_test((gint *)&(refp)->count)) { \
(refp)->free(refp); \
} \
}
#define JANUS_PRINT
Simple wrapper to g_print/printf.
Definition: debug.h:84

Decrease the Janus reference counter (debug)

Note
Will invoke the free function if the counter reaches 0
Parameters
refpPointer to the Janus reference counter instance
#define janus_refcount_decrease_nodebug (   refp)
Value:
{ \
if(g_atomic_int_dec_and_test((gint *)&(refp)->count)) { \
(refp)->free(refp); \
} \
}

Decrease the Janus reference counter (no debug)

Note
Will invoke the free function if the counter reaches 0
Parameters
refpPointer to the Janus reference counter instance
#define janus_refcount_increase (   refp)
Value:
{ \
} else { \
} \
}
int refcount_debug
Definition: janus.c:338
#define janus_refcount_increase_debug(refp)
Increase the Janus reference counter (debug)
Definition: refcount.h:173
#define janus_refcount_increase_nodebug(refp)
Increase the Janus reference counter (no debug)
Definition: refcount.h:168

Increase the Janus reference counter (debug according to settings)

Parameters
refpPointer to the Janus reference counter instance
#define janus_refcount_increase_debug (   refp)
Value:
{ \
JANUS_PRINT("[%s:%s:%d:increase] %p (%d)\n", __FILE__, __FUNCTION__, __LINE__, refp, (refp)->count+1); \
g_atomic_int_inc((gint *)&(refp)->count); \
}
#define JANUS_PRINT
Simple wrapper to g_print/printf.
Definition: debug.h:84

Increase the Janus reference counter (debug)

Parameters
refpPointer to the Janus reference counter instance
#define janus_refcount_increase_nodebug (   refp)
Value:
{ \
g_atomic_int_inc((gint *)&(refp)->count); \
}

Increase the Janus reference counter (no debug)

Parameters
refpPointer to the Janus reference counter instance
#define janus_refcount_init (   refp,
  free_fn 
)
Value:
{ \
} else { \
janus_refcount_init_debug(refp, free_fn); \
} \
}
int refcount_debug
Definition: janus.c:338
#define janus_refcount_init_debug(refp, free_fn)
Janus reference counter initialization (debug)
Definition: refcount.h:150
#define janus_refcount_init_nodebug(refp, free_fn)
Janus reference counter initialization (no debug)
Definition: refcount.h:131

Janus reference counter initialization (debug according to settings)

Note
Also sets the counter to 1 automatically, so no need to increase it again manually via janus_refcount_increase() after the initialization
Parameters
refpPointer to the Janus reference counter instance
free_fnPointer to the function to invoke when the object the counter refers to needs to be destroyed
#define janus_refcount_init_debug (   refp,
  free_fn 
)
Value:
{ \
(refp)->count = 1; \
JANUS_PRINT("[%s:%s:%d:init] %p (%d)\n", __FILE__, __FUNCTION__, __LINE__, refp, (refp)->count); \
(refp)->free = free_fn; \
}
#define JANUS_PRINT
Simple wrapper to g_print/printf.
Definition: debug.h:84

Janus reference counter initialization (debug)

Note
Also sets the counter to 1 automatically, so no need to increase it again manually via janus_refcount_increase() after the initialization
Parameters
refpPointer to the Janus reference counter instance
free_fnPointer to the function to invoke when the object the counter refers to needs to be destroyed
#define janus_refcount_init_nodebug (   refp,
  free_fn 
)
Value:
{ \
(refp)->count = 1; \
(refp)->free = free_fn; \
}

Janus reference counter initialization (no debug)

Note
Also sets the counter to 1 automatically, so no need to increase it again manually via janus_refcount_increase() after the initialization
Parameters
refpPointer to the Janus reference counter instance
free_fnPointer to the function to invoke when the object the counter refers to needs to be destroyed

Typedef Documentation

Janus reference counter structure.

Variable Documentation

int refcount_debug