Files
harbour-core/harbour/source/rtl/memvars.c
1999-07-11 20:31:46 +00:00

210 lines
5.3 KiB
C

/*
* $Id$
*
Harbour Project source code
This file is a part of Harbour Runtime Library and it contains code
that handles memory variables.
Copyright (C) 1999 Ryszard Glab
www - http://www.harbour-project.org
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version, with one exception:
The exception is that if you link the Harbour Runtime Library (HRL)
and/or the Harbour Virtual Machine (HVM) with other files to produce
an executable, this does not by itself cause the resulting executable
to be covered by the GNU General Public License. Your use of that
executable is in no way restricted on account of linking the HRL
and/or HVM code into it.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit
their web site at http://www.gnu.org/).
*/
#include <extend.h>
#include <string.h>
/* static HB_VALUE_PTR _privateTable = NULL; */
static ULONG _globalTableSize = 0;
static ULONG _globalFirstFree = 0;
static ULONG _globalLastFree = 0;
static ULONG _globalFreeCnt = 0;
static HB_VALUE_PTR _globalTable = NULL;
#define TABLE_INITHB_VALUE 10
#define TABLE_EXPANDHB_VALUE 5
/* Uncomment this to trace codeblocks activity
#define MEMVARDEBUG
*/
void hb_MemvarInit( void )
{
}
void hb_MemvarRelease( void )
{
if( _globalTable )
hb_xfree( _globalTable );
}
HB_VALUE_PTR *hb_GlobalValueBaseAddress( void )
{
return &_globalTable;
}
/*
* This function creates new global value.
*
* pSource = item value that have to be stored or NULL
* pOwner = the name of PUBLIC variable or NULL
*
* Returns:
* handle to variable memory or fails
*
*/
HB_HANDLE hb_GlobalValueNew( HB_ITEM_PTR pSource )
{
HB_VALUE_PTR pValue;
HB_HANDLE hValue;
if( ! _globalTable )
{
_globalTable = (HB_VALUE_PTR) hb_xgrab( sizeof(HB_VALUE) * TABLE_INITHB_VALUE );
_globalTableSize = TABLE_INITHB_VALUE;
_globalFreeCnt = 0;
_globalFirstFree = _globalLastFree = 1;
hValue = 0;
}
else
{
if( _globalFreeCnt )
{
/* There are holes in the table
* Get a first available hole
*/
hValue =_globalFirstFree;
--_globalFreeCnt;
/* Now find the next hole
*/
if( _globalFreeCnt )
{
while( _globalTable[ ++_globalFirstFree ].counter );
}
else
/* No more holes
*/
_globalFirstFree =_globalLastFree;
}
else
{
/* Allocate the value from the end of table
*/
if( _globalFirstFree < _globalTableSize )
{
hValue =_globalFirstFree;
_globalFirstFree = ++_globalLastFree;
}
else
{
/* No more free values in the table - expand the table
*/
hValue = _globalTableSize;
_globalFirstFree =_globalLastFree = _globalTableSize +1;
_globalTableSize += TABLE_EXPANDHB_VALUE;
_globalTable =(HB_VALUE_PTR) hb_xrealloc( _globalTable, sizeof(HB_VALUE) * _globalTableSize );
}
}
}
pValue =_globalTable + hValue;
if( pSource )
memcpy( &pValue->item, pSource, sizeof(HB_ITEM) );
else
pValue->item.type =IT_NIL;
pValue->counter =1;
#ifdef MEMVARDEBUG
printf( "\n>>>>>Global item created with handle =%i", hValue );
#endif
return hValue;
}
/*
* This function increases the number of references to passed global value
*
*/
void hb_GlobalValueIncRef( HB_HANDLE hValue )
{
#ifdef MEMVARDEBUG
if( hValue < 0 || hValue > _globalTableSize )
{
printf( "\nInvalid MEMVAR handle %i (max %li)\n", hValue, _globalTableSize );
exit( 1 );
}
#endif
_globalTable[ hValue ].counter++;
#ifdef MEMVARDEBUG
printf( "\n+++Global item (%i) increment refCounter=%li", hValue, _globalTable[ hValue ].counter );
#endif
}
/*
* This function decreases the number of references to passed global value.
* If it is the last reference then this value is deleted.
*
*/
void hb_GlobalValueDecRef( HB_HANDLE hValue )
{
HB_VALUE_PTR pValue;
#ifdef MEMVARDEBUG
if( hValue < 0 || hValue > _globalTableSize )
{
printf( "\nInvalid MEMVAR handle %i (max %li)\n", hValue, _globalTableSize );
exit( 1 );
}
#endif
pValue =_globalTable + hValue;
#ifdef MEMVARDEBUG
printf( "\n---Global item (%i) decrement refCounter=%li", hValue, pValue->counter-1 );
#endif
if( --pValue->counter == 0 )
{
ItemRelease( &pValue->item );
if( _globalFirstFree > hValue )
_globalFirstFree = hValue;
if( (_globalLastFree - hValue) == 1 )
_globalLastFree =hValue;
if( _globalFirstFree != _globalLastFree )
++_globalFreeCnt;
#ifdef MEMVARDEBUG
printf( "\n<<<<<Global item (%i) deleted", hValue );
#endif
}
}