Skip to content

Commit

Permalink
Adding a safe reference counter for initialization/deinitialization (#47
Browse files Browse the repository at this point in the history
)

This counter is necessary when the application makes use of `multiples libraries` each dependent on `libinstpatch`. Examples: 
- `Swami` is dependent on `libinstpatch`and `fluidsynth`. `fluidsynth` could be optionally dependent on `libinstpatch`. In this case, `libinstpatch` is owned twice (by `swami` and by `fluidsynth`).
- For an application only dependent on `fluidsynth`, `libinstpatch` is only owned by `fluidsynth`.
- For an application only dependent on `libinstpatch`, `libinstpatch` is only owned by this application.

This counter ensures that internal `initialization` (or `deinitialization`) is done only one time.
This is required because `libinstpatch` is dependent on `GObject` which doesn't accept that the same `Gtype` be registered multiple times.
  • Loading branch information
jjceresa authored May 2, 2020
1 parent 8d787f2 commit a1af56b
Showing 1 changed file with 38 additions and 11 deletions.
49 changes: 38 additions & 11 deletions libinstpatch/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ static TypePropInit type_props[] =
/* name of application using libInstPatch (for saving to files) */
char *ipatch_application_name = NULL;

static gboolean initialized = FALSE;
G_LOCK_DEFINE_STATIC(lock_init);
static int init_counter = 0;

/*-----------------------------------------------------------------------------
Initialization / deinitialization of libinstpatch library.
Expand All @@ -163,6 +164,9 @@ static gboolean initialized = FALSE;
call ipatch_init() before creating other tasks, then when the application is
complete, the main task should call ipatch_close() after the other tasks are
completed.
If the application make use of multiple libraries each dependent of libinstpatch,
for each call to ipatch_init() these libraries should call ipatch_close().
-----------------------------------------------------------------------------*/

/**
Expand All @@ -178,13 +182,16 @@ ipatch_init(void)
GType type;
int i;

if(initialized)
/* do nothing if the library is already initialized */
G_LOCK(lock_init);
init_counter++;
if(init_counter > 1)
{
/* library already initialized */
G_UNLOCK(lock_init);
return;
}

initialized = TRUE;

g_type_init();

if(!g_thread_supported())
Expand Down Expand Up @@ -470,6 +477,8 @@ ipatch_init(void)
"mime-type", "audio/x-gigasampler", NULL);
ipatch_type_set(IPATCH_TYPE_SLI_FILE,
"mime-type", "audio/x-spectralis", NULL);

G_UNLOCK(lock_init);
}

/**
Expand All @@ -481,11 +490,8 @@ ipatch_init(void)
static void
ipatch_deinit(void)
{
if (!initialized)
{
return;
}
initialized = FALSE;
g_free(ipatch_application_name);

/*-------------------------------------------------------------------------
Free internal systems
-------------------------------------------------------------------------*/
Expand Down Expand Up @@ -553,16 +559,37 @@ ipatch_deinit(void)
/**
* ipatch_close:
*
* Perform cleanup of libInstPatch prior to application close. Such as deleting
* temporary files.
* This should be called prior to application close.
*
* Decrement the reference counter and if it reaches 0 performs cleanup of
* libInstPatch, such as deleting temporary files and internal caches.
* If the counter is still > 0, the function return without doing cleanup
* (the library is still owned).
*
* Does nothing if the library is already deinitialized (or was not initialized).
* Since: 1.1.0
*/
void
ipatch_close(void)
{
/* do nothing if the library is already deinitialized */
G_LOCK(lock_init);
init_counter--;
if(init_counter != 0)
{
/* library still owned by a task, do nothing */
if(init_counter < 0)
{
init_counter = 0;
}
G_UNLOCK(lock_init);
return;
}

ipatch_sample_store_swap_close();
ipatch_deinit();

G_UNLOCK(lock_init);
}

static gboolean
Expand Down

0 comments on commit a1af56b

Please sign in to comment.