8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-24 20:43:04 +01:00
firebird-mirror/src/jrd/inuse.cpp

251 lines
5.8 KiB
C++
Raw Normal View History

2001-05-23 15:26:42 +02:00
/*
* PROGRAM: JRD Access Method
* MODULE: inuse.cpp
2001-05-23 15:26:42 +02:00
* 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"
2004-03-22 12:38:23 +01:00
#include "../jrd/common.h"
2004-04-29 00:43:34 +02:00
#include <stdio.h>
2001-05-23 15:26:42 +02:00
#include "../jrd/jrd.h"
#include "../jrd/gds_proto.h"
#include "../jrd/inuse_proto.h"
#include "../jrd/thd.h"
2001-05-23 15:26:42 +02:00
static void cleanup(void *);
static void init(void);
static IUO free_list = NULL;
static Firebird::Mutex inuse_mutex;
static bool initialized = false;
2001-05-23 15:26:42 +02:00
bool INUSE_cleanup(IUO inuse, FPTR_VOID_PTR cleanup_routine)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* 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
2001-05-23 15:26:42 +02:00
* if there was something to do.
*
**************************************/
bool needed_cleaning = false;
IUO secondary_inuse = inuse->iuo_next;
2001-05-23 15:26:42 +02:00
do {
void** ptr = inuse->iuo_object;
for (const void* const* const end = ptr + inuse->iuo_in_use_count;
ptr < end; ptr++)
{
2001-05-23 15:26:42 +02:00
if (*ptr) {
2006-05-01 06:12:30 +02:00
// dimitr: this assert is put temporarily in order to track
// mutexes that could be left acquired when we leave
// the JRD context
fb_assert(false);
(*cleanup_routine) (*ptr);
needed_cleaning = true;
2001-05-23 15:26:42 +02:00
}
}
2001-05-23 15:26:42 +02:00
inuse->iuo_in_use_count = 0;
} while (inuse = inuse->iuo_next);
if (secondary_inuse) {
IUO* secondary_end_ptr = &secondary_inuse->iuo_next;
while (*secondary_end_ptr)
2001-05-23 15:26:42 +02:00
secondary_end_ptr = &(*secondary_end_ptr)->iuo_next;
inuse_mutex.enter();
2001-05-23 15:26:42 +02:00
*secondary_end_ptr = free_list;
free_list = secondary_inuse;
inuse_mutex.leave();
2001-05-23 15:26:42 +02:00
}
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;
}
bool INUSE_insert(IUO inuse, void *new_object, bool dup_flag)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* 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
2001-05-23 15:26:42 +02:00
* duplicate entry will not be inserted.
* Return true if the object was inserted.
2001-05-23 15:26:42 +02:00
*
**************************************/
// "end" moves backwards in this loop.
void** ptr = inuse->iuo_object;
for (const void* const* end = ptr + inuse->iuo_in_use_count;
ptr < end; ptr++)
{
2001-05-23 15:26:42 +02:00
if (!*ptr) {
if (!dup_flag)
while (ptr < --end)
if (*end == new_object)
return false;
2001-05-23 15:26:42 +02:00
*ptr = new_object;
return true;
2001-05-23 15:26:42 +02:00
}
else if (!dup_flag && *ptr == new_object)
return false;
}
2001-05-23 15:26:42 +02:00
if (inuse->iuo_in_use_count >= FB_NELEM(inuse->iuo_object)) {
2001-05-23 15:26:42 +02:00
#ifdef DEV_BUILD
gds__log("in-use block overflow. secondary block allocated.");
#endif
inuse_mutex.enter();
IUO new_inuse = free_list;
if (new_inuse) {
2001-05-23 15:26:42 +02:00
free_list = new_inuse->iuo_next;
inuse_mutex.leave();
2001-05-23 15:26:42 +02:00
}
else {
inuse_mutex.leave();
2001-05-23 15:26:42 +02:00
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 */
2001-05-23 15:26:42 +02:00
}
}
INUSE_clear(new_inuse);
inuse->iuo_next = new_inuse;
inuse = new_inuse;
}
inuse->iuo_object[inuse->iuo_in_use_count++] = new_object;
return true;
2001-05-23 15:26:42 +02:00
}
bool INUSE_remove(IUO inuse, void* old_object, bool dup_flag)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* 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
2001-05-23 15:26:42 +02:00
* of the object. Otherwise, only remove the
* first. Return true if an object was removed.
2001-05-23 15:26:42 +02:00
*
**************************************/
bool removed = false;
2001-05-23 15:26:42 +02:00
do {
// "end" moves backwards here
void** ptr = inuse->iuo_object;
for (const void* const* end = ptr + inuse->iuo_in_use_count;
ptr < end; ptr++)
{
2001-05-23 15:26:42 +02:00
if (*ptr == old_object) {
*ptr = NULL;
if (ptr + 1 == end)
while (!*(--end) && --inuse->iuo_in_use_count);
if (!dup_flag)
return true;
removed = true;
2001-05-23 15:26:42 +02:00
}
}
2001-05-23 15:26:42 +02:00
} while (inuse = inuse->iuo_next);
return removed;
}
static void cleanup(void *arg)
{
/**************************************
*
* c l e a n u p
*
**************************************
*
* Functional description
*
**************************************/
while (free_list) {
IUO iuo = free_list;
2001-05-23 15:26:42 +02:00
free_list = iuo->iuo_next;
gds__free(iuo);
}
initialized = false;
2001-05-23 15:26:42 +02:00
}
static void init(void)
{
/**************************************
*
* i n i t
*
**************************************
*
* Functional description
*
**************************************/
if (!initialized) {
THD_GLOBAL_MUTEX_LOCK;
if (!initialized) {
gds__register_cleanup(cleanup, 0);
initialized = true;
2001-05-23 15:26:42 +02:00
}
THD_GLOBAL_MUTEX_UNLOCK;
}
}