8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-25 00:03:03 +01:00
firebird-mirror/src/jrd/inuse.cpp

254 lines
5.7 KiB
C++
Raw Normal View History

2001-05-23 15:26:42 +02:00
/*
* PROGRAM: JRD Access Method
* MODULE: inuse.c
* DESCRIPTION: Keep track of objects that are in use
*
* The contents of this file are subject to the Interbase Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy
* of the License at http://www.Inprise.com/IPL.html
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
* or implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code was created by Inprise Corporation
* and its predecessors. Portions created by Inprise Corporation are
* Copyright (C) Inprise Corporation.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*/
#include "firebird.h"
2001-05-23 15:26:42 +02:00
#include "../jrd/ib_stdio.h"
#include "../jrd/jrd.h"
#include "../jrd/gds_proto.h"
#include "../jrd/inuse_proto.h"
#include "../jrd/thd_proto.h"
static void cleanup(void *);
static void init(void);
static IUO free_list = NULL;
static MUTX_T inuse_mutex[1];
static BOOLEAN initialized = FALSE;
BOOLEAN INUSE_cleanup(IUO inuse, void (*cleanup_routine) ())
{
/**************************************
*
* I N U S E _ c l e a n u p
*
**************************************
*
* Functional description
* Cleanup an in-use structure. If any
* objects are found to be non-NULL,
* call the cleanup routine. Return TRUE
* if there was something to do.
*
**************************************/
void **ptr, **end;
BOOLEAN needed_cleaning;
IUO secondary_inuse;
needed_cleaning = FALSE;
secondary_inuse = inuse->iuo_next;
do {
ptr = inuse->iuo_object;
for (end = ptr + inuse->iuo_in_use_count; ptr < end; ptr++)
if (*ptr) {
reinterpret_cast <
void (*) (void *) >(*cleanup_routine) (*ptr);
needed_cleaning = TRUE;
}
inuse->iuo_in_use_count = 0;
} while (inuse = inuse->iuo_next);
if (secondary_inuse) {
IUO *secondary_end_ptr;
for (secondary_end_ptr = &secondary_inuse->iuo_next;
*secondary_end_ptr;)
secondary_end_ptr = &(*secondary_end_ptr)->iuo_next;
THD_MUTEX_LOCK(inuse_mutex);
*secondary_end_ptr = free_list;
free_list = secondary_inuse;
THD_MUTEX_UNLOCK(inuse_mutex);
}
return needed_cleaning;
}
void INUSE_clear(IUO inuse)
{
/**************************************
*
* I N U S E _ c l e a r
*
**************************************
*
* Functional description
* Initialize an in-use block.
*
**************************************/
if (!initialized)
init();
inuse->iuo_in_use_count = 0;
inuse->iuo_next = NULL;
}
BOOLEAN INUSE_insert(IUO inuse, void *new_object, BOOLEAN dup_flag)
{
/**************************************
*
* I N U S E _ i n s e r t
*
**************************************
*
* Functional description
* Insert an object into an in-use structure.
* If dup_flag is TRUE, then duplicate entries
* are permitted. If it is FALSE, then a
* duplicate entry will not be inserted.
* Return TRUE if the object was inserted.
*
**************************************/
void **ptr, **end;
ptr = inuse->iuo_object;
for (end = ptr + inuse->iuo_in_use_count; ptr < end; ptr++)
if (!*ptr) {
if (!dup_flag)
while (ptr < --end)
if (*end == new_object)
return FALSE;
*ptr = new_object;
return TRUE;
}
else if (!dup_flag && *ptr == new_object)
return FALSE;
if (inuse->iuo_in_use_count >= FB_NELEM(inuse->iuo_object)) {
2001-05-23 15:26:42 +02:00
IUO new_inuse;
#ifdef DEV_BUILD
gds__log("in-use block overflow. secondary block allocated.");
#endif
THD_MUTEX_LOCK(inuse_mutex);
if (new_inuse = free_list) {
free_list = new_inuse->iuo_next;
THD_MUTEX_UNLOCK(inuse_mutex);
}
else {
THD_MUTEX_UNLOCK(inuse_mutex);
new_inuse = (IUO) gds__alloc((SLONG) sizeof(struct iuo));
/* FREE: at process exit, by cleanup handler cleanup() in this module */
if (!new_inuse) { /* NOMEM: */
DEV_REPORT("INUSE_insert: out of memory");
return FALSE; /* error handling too difficult */
}
}
INUSE_clear(new_inuse);
inuse->iuo_next = new_inuse;
inuse = new_inuse;
}
inuse->iuo_object[inuse->iuo_in_use_count++] = new_object;
return TRUE;
}
BOOLEAN INUSE_remove(IUO inuse, void *old_object, BOOLEAN dup_flag)
{
/**************************************
*
* I N U S E _ r e m o v e
*
**************************************
*
* Functional description
* Remove an object from an in-use structure.
* If dup_flag is TRUE, remove every occurrence
* of the object. Otherwise, only remove the
* first. Return TRUE if an object was removed.
*
**************************************/
void **ptr, **end;
BOOLEAN removed;
removed = FALSE;
do {
ptr = inuse->iuo_object;
for (end = ptr + inuse->iuo_in_use_count; ptr < end; ptr++)
if (*ptr == old_object) {
*ptr = NULL;
if (ptr + 1 == end)
while (!*(--end) && --inuse->iuo_in_use_count);
if (!dup_flag)
return TRUE;
removed = TRUE;
}
} while (inuse = inuse->iuo_next);
return removed;
}
static void cleanup(void *arg)
{
/**************************************
*
* c l e a n u p
*
**************************************
*
* Functional description
*
**************************************/
IUO iuo;
THD_MUTEX_DESTROY(inuse_mutex);
while (free_list) {
iuo = free_list;
free_list = iuo->iuo_next;
gds__free(iuo);
}
initialized = FALSE;
}
static void init(void)
{
/**************************************
*
* i n i t
*
**************************************
*
* Functional description
*
**************************************/
if (!initialized) {
THD_INIT;
THD_GLOBAL_MUTEX_LOCK;
if (!initialized) {
THD_MUTEX_INIT(inuse_mutex);
gds__register_cleanup(cleanup, 0);
initialized = TRUE;
}
THD_GLOBAL_MUTEX_UNLOCK;
}
}