aboutsummaryrefslogtreecommitdiff
path: root/core/bgdrtm/src/instance.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/bgdrtm/src/instance.c')
-rw-r--r--core/bgdrtm/src/instance.c763
1 files changed, 763 insertions, 0 deletions
diff --git a/core/bgdrtm/src/instance.c b/core/bgdrtm/src/instance.c
new file mode 100644
index 0000000..a91633c
--- /dev/null
+++ b/core/bgdrtm/src/instance.c
@@ -0,0 +1,763 @@
+/*
+ * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd)
+ * Copyright © 2002-2006 Fenix Team (Fenix)
+ * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix)
+ *
+ * This file is part of Bennu - Game Development
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source
+ * distribution.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef TARGET_BEOS
+#include <posix/assert.h>
+#else
+#include <assert.h>
+#endif
+
+#include "offsets.h"
+#include "bgdrtm.h"
+#include "sysprocs_p.h"
+#include "instance.h"
+#include "xstrings.h"
+
+#undef STACK_SIZE
+#define STACK_SIZE 4096
+
+/* ---------------------------------------------------------------------- */
+
+#define INSTANCE_MIN_PRIORITY -32768
+#define INSTANCE_MAX_PRIORITY 32767
+#define INSTANCE_NORMALIZE_PRIORITY 32768
+
+/* ---------------------------------------------------------------------- */
+/* Módulo de gestión de instancias, con las funciones de incialización y */
+/* destrucción, duplicado, etc. */
+/* ---------------------------------------------------------------------- */
+
+#define HASH(id) (unsigned int)((id)&0x0000ffff)
+#define HASH_PRIORITY(id) (unsigned int)(((id) + INSTANCE_NORMALIZE_PRIORITY) & 0x0000ffff)
+#define HASH_INSTANCE(id) (unsigned int)(((( uint32_t )(id)) >> 2 ) & 0x0000ffff)
+#define HASH_SIZE 65536
+
+INSTANCE ** hashed_by_id = NULL;
+INSTANCE ** hashed_by_instance = NULL;
+INSTANCE ** hashed_by_type = NULL;
+INSTANCE ** hashed_by_priority = NULL;
+
+INSTANCE * first_instance = NULL ;
+
+/* Priority lists */
+
+static INSTANCE * iterator_by_priority = NULL ;
+static int iterator_pos = HASH_SIZE;
+
+static int instance_maxid = FIRST_INSTANCE_ID ;
+
+static int instance_min_actual_prio = INSTANCE_MAX_PRIORITY ;
+static int instance_max_actual_prio = INSTANCE_MIN_PRIORITY ;
+
+/* ---------------------------------------------------------------------- */
+/* By id */
+/* ---------------------------------------------------------------------- */
+
+void instance_add_to_list_by_id( INSTANCE * r, uint32_t id )
+{
+ if ( !hashed_by_id ) hashed_by_id = calloc( HASH_SIZE, sizeof( INSTANCE * ) );
+ hashed_by_id[HASH( id )] = r;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void instance_remove_from_list_by_id( INSTANCE * r, uint32_t id )
+{
+ hashed_by_id[HASH( id )] = NULL;
+}
+
+/* ---------------------------------------------------------------------- */
+/* By instance */
+/* ---------------------------------------------------------------------- */
+
+void instance_add_to_list_by_instance( INSTANCE * r )
+{
+ unsigned int hash = HASH_INSTANCE( r );
+
+ if ( !hashed_by_instance ) hashed_by_instance = calloc( HASH_SIZE, sizeof( INSTANCE * ) );
+
+ r->prev_by_instance = NULL ;
+ r->next_by_instance = hashed_by_instance[hash];
+ if ( r->next_by_instance ) r->next_by_instance->prev_by_instance = r ;
+ hashed_by_instance[hash] = r;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void instance_remove_from_list_by_instance( INSTANCE * r )
+{
+ unsigned int hash = HASH_INSTANCE( r );
+
+ if ( r->prev_by_instance ) r->prev_by_instance->next_by_instance = r->next_by_instance ;
+ if ( r->next_by_instance ) r->next_by_instance->prev_by_instance = r->prev_by_instance ;
+
+ if ( hashed_by_instance[hash] == r ) hashed_by_instance[hash] = r->next_by_instance ;
+}
+
+/* ---------------------------------------------------------------------- */
+/* By type */
+/* ---------------------------------------------------------------------- */
+
+void instance_add_to_list_by_type( INSTANCE * r, uint32_t type )
+{
+ unsigned int hash = HASH( type );
+
+ if ( !hashed_by_type ) hashed_by_type = calloc( HASH_SIZE, sizeof( INSTANCE * ) );
+
+ r->prev_by_type = NULL ;
+ r->next_by_type = hashed_by_type[hash];
+ if ( r->next_by_type ) r->next_by_type->prev_by_type = r ;
+ hashed_by_type[hash] = r;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void instance_remove_from_list_by_type( INSTANCE * r, uint32_t type )
+{
+ unsigned int hash = HASH( type );
+
+ if ( r->prev_by_type ) r->prev_by_type->next_by_type = r->next_by_type ;
+ if ( r->next_by_type ) r->next_by_type->prev_by_type = r->prev_by_type ;
+
+ if ( hashed_by_type[hash] == r ) hashed_by_type[hash] = r->next_by_type ;
+}
+
+/* ---------------------------------------------------------------------- */
+/* By priority */
+/* ---------------------------------------------------------------------- */
+
+void instance_add_to_list_by_priority( INSTANCE * r, int32_t priority )
+{
+ unsigned int hash ;
+
+ if ( priority < INSTANCE_MIN_PRIORITY ) priority = LOCINT32( r, PRIORITY ) = INSTANCE_MIN_PRIORITY;
+ if ( priority > INSTANCE_MAX_PRIORITY ) priority = LOCINT32( r, PRIORITY ) = INSTANCE_MAX_PRIORITY;
+
+ hash = HASH_PRIORITY( priority );
+
+ if ( !hashed_by_priority ) hashed_by_priority = calloc( HASH_SIZE, sizeof( INSTANCE * ) );
+
+ r->prev_by_priority = NULL ;
+ r->next_by_priority = hashed_by_priority[hash];
+ if ( r->next_by_priority ) r->next_by_priority->prev_by_priority = r ;
+ hashed_by_priority[hash] = r;
+ r->last_priority = priority ;
+
+ if ( priority < instance_min_actual_prio ) instance_min_actual_prio = priority ;
+ if ( priority > instance_max_actual_prio ) instance_max_actual_prio = priority ;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void instance_remove_from_list_by_priority( INSTANCE * r )
+{
+ unsigned int hash = HASH_PRIORITY( r->last_priority );
+
+ /* Update iterator_by_priority if necessary */
+
+ if ( iterator_by_priority == r ) instance_next_by_priority() ;
+
+ if ( r->prev_by_priority ) r->prev_by_priority->next_by_priority = r->next_by_priority ;
+ if ( r->next_by_priority ) r->next_by_priority->prev_by_priority = r->prev_by_priority ;
+
+ if ( hashed_by_priority[hash] == r ) hashed_by_priority[hash] = r->next_by_priority ;
+
+ if ( !hashed_by_priority[hash] )
+ {
+ if ( r->last_priority == instance_min_actual_prio )
+ {
+ while ( instance_min_actual_prio < instance_max_actual_prio && !hashed_by_priority[ instance_min_actual_prio + INSTANCE_NORMALIZE_PRIORITY ] )
+ instance_min_actual_prio++;
+ }
+
+ if ( r->last_priority == instance_max_actual_prio )
+ {
+ while ( instance_max_actual_prio > instance_min_actual_prio && !hashed_by_priority[ instance_max_actual_prio + INSTANCE_NORMALIZE_PRIORITY ] )
+ instance_max_actual_prio--;
+ }
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * FUNCTION : instance_dirty
+ *
+ * Adds an instance to the dirty instances list. This is a list of all
+ * instances which priority changed since the last execution.
+ *
+ * PARAMS :
+ * i Pointer to the instance
+ *
+ * RETURN VALUE :
+ * None
+ */
+
+void instance_dirty( INSTANCE * i )
+{
+ instance_remove_from_list_by_priority( i );
+ instance_add_to_list_by_priority( i, LOCINT32( i, PRIORITY ) );
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * FUNCTION : instance_get
+ *
+ * Returns a instance, given its ID.
+ *
+ * PARAMS :
+ * id Integer ID of the instance
+ *
+ * RETURN VALUE :
+ * Pointer to the found instance or NULL if not found
+ */
+
+INSTANCE * instance_get( int id )
+{
+ if ( !hashed_by_id || !id ) return NULL;
+ return ( hashed_by_id[HASH( id )] );
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * FUNCTION : instance_getid
+ *
+ * Allocate and return a free instance identifier code.
+ *
+ * PARAMS :
+ * None
+ *
+ * RETURN VALUE :
+ * A new, unused instance identifier
+ * -1 if error
+ */
+
+int instance_getid()
+{
+ int id = instance_maxid++ ;
+
+ if ( !hashed_by_id ) hashed_by_id = calloc( HASH_SIZE, sizeof( INSTANCE * ) );
+
+ if ( id <= LAST_INSTANCE_ID && !hashed_by_id[ HASH( id ) ] ) return id;
+
+ if ( instance_maxid > LAST_INSTANCE_ID )
+ {
+ for ( instance_maxid = FIRST_INSTANCE_ID; instance_maxid <= LAST_INSTANCE_ID; instance_maxid++ )
+ {
+ if ( !hashed_by_id[HASH( instance_maxid )] ) return instance_maxid++;
+ }
+ }
+ else
+ {
+ for ( ; instance_maxid <= LAST_INSTANCE_ID; instance_maxid++ )
+ {
+ if ( !hashed_by_id[HASH( instance_maxid )] ) return instance_maxid++;
+ }
+ for ( instance_maxid = FIRST_INSTANCE_ID; instance_maxid < id; instance_maxid++ )
+ {
+ if ( !hashed_by_id[HASH( instance_maxid )] ) return instance_maxid++;
+ }
+ }
+ return -1;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * FUNCTION : instance_duplicate
+ *
+ * Create a copy of an instance, using the same local/private data
+ * - Updates the instance list, adding the new instance
+ * - Marks all local and private strings
+ * - Updates all parents local family variables
+ *
+ * The new instance uses the same code pointer as the father
+ * (it begins execution at the same line, instead of the first one)
+ *
+ * PARAMS :
+ * father Pointer to the original instance
+ *
+ * RETURN VALUE :
+ * Pointer to the new instance
+ */
+
+INSTANCE * instance_duplicate( INSTANCE * father )
+{
+ INSTANCE * r, * brother ;
+ int n, pid ;
+ uint32_t type ;
+
+ if ( ( pid = instance_getid() ) == -1 ) return NULL;
+
+ r = ( INSTANCE * ) calloc( 1, sizeof( INSTANCE ) ) ;
+ assert( r ) ;
+
+ r->pridata = ( int * ) malloc( father->private_size + 4 ) ;
+ r->pubdata = ( int * ) malloc( father->public_size + 4 ) ;
+ r->locdata = ( int * ) malloc( local_size + 4 ) ;
+ r->code = father->code ;
+ r->codeptr = father->codeptr ;
+ r->exitcode = father->exitcode ;
+ r->errorcode = father->errorcode ;
+ r->proc = father->proc ;
+ r->call_level = father->call_level ;
+
+ r->switchval = 0;
+ r->switchval_string = 0;
+ r->cased = 0;
+
+ r->breakpoint = 0 ;
+
+ r->private_size = father->private_size ;
+ r->public_size = father->public_size ;
+ r->first_run = 1 ;
+
+ if ( father->private_size > 0 ) memcpy( r->pridata, father->pridata, r->private_size ) ;
+ if ( father->public_size > 0 ) memcpy( r->pubdata, father->pubdata, r->public_size ) ;
+ if ( local_size > 0 ) memcpy( r->locdata, father->locdata, local_size ) ;
+
+ /* Inicializa datos de jerarquia */
+
+ /* Crea el proceso clónico como si lo hubiera llamado el padre */
+
+ type = LOCDWORD( father, PROCESS_TYPE ) ;
+ LOCDWORD( r, PROCESS_ID ) = pid ;
+ LOCDWORD( r, SON ) = 0 ;
+ LOCDWORD( r, SMALLBRO ) = 0 ;
+
+ LOCDWORD( r, FATHER ) = LOCDWORD( father, PROCESS_ID ) ;
+ brother = instance_get( LOCDWORD( father, SON ) ) ;
+ if ( brother )
+ {
+ LOCDWORD( r, BIGBRO ) = LOCDWORD( brother, PROCESS_ID ) ;
+ LOCDWORD( brother, SMALLBRO ) = pid ;
+ }
+ else
+ {
+ LOCDWORD( r, BIGBRO ) = 0 ;
+ }
+ LOCDWORD( father, SON ) = pid ;
+
+ /* Actualiza las cuentas de uso de las cadenas */
+
+ for ( n = 0; n < r->proc->string_count; n++ ) string_use( PRIDWORD( r, r->proc->strings[n] ) ) ; /* Strings privadas */
+ for ( n = 0; n < r->proc->pubstring_count; n++ ) string_use( PUBDWORD( r, r->proc->pubstrings[n] ) ) ; /* Strings publicas */
+ for ( n = 0; n < local_strings; n++ ) string_use( LOCDWORD( r, localstr[n] ) ) ; /* Strings locales */
+
+ r->prev = NULL ;
+ r->next = first_instance ;
+ if ( first_instance ) first_instance->prev = r;
+ first_instance = r ;
+
+ instance_add_to_list_by_id( r, pid );
+ instance_add_to_list_by_instance( r );
+ instance_add_to_list_by_type( r, type );
+ instance_add_to_list_by_priority( r, LOCINT32( r, PRIORITY ) );
+
+ /* The called_by pointer should be set only when the caller
+ * is waiting for this process to return */
+
+ r->called_by = NULL;
+
+ r->stack = malloc( father->stack[0] );
+ memmove(r->stack, father->stack, (int)father->stack_ptr - (int)father->stack);
+ r->stack_ptr = &r->stack[1];
+
+ /* Initialize list pointers */
+
+ LOCDWORD( r, STATUS ) = STATUS_RUNNING;
+
+ if ( instance_create_hook_count )
+ for ( n = 0; n < instance_create_hook_count; n++ )
+ instance_create_hook_list[n]( r );
+
+ return r ;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * FUNCTION : instance_new
+ *
+ * Create a new instance, using the default local/private data
+ * - Updates the instance list, adding the new instance
+ * - Marks all local and private strings
+ * - Updates all parents local family variables
+ *
+ * PARAMS :
+ * proc Pointer to the procedure definition
+ * father Pointer to the father instance (may be NULL)
+ *
+ * RETURN VALUE :
+ * Pointer to the new instance
+ */
+
+INSTANCE * instance_new( PROCDEF * proc, INSTANCE * father )
+{
+ INSTANCE * r, * brother;
+ int n, pid;
+
+ if ( ( pid = instance_getid() ) == -1 ) return NULL;
+
+ r = ( INSTANCE * ) calloc( 1, sizeof( INSTANCE ) ) ;
+ assert( r ) ;
+
+ r->pridata = ( int * ) malloc( proc->private_size + 4 ) ;
+ r->pubdata = ( int * ) malloc( proc->public_size + 4 ) ;
+ r->locdata = ( int * ) malloc( local_size + 4 ) ;
+ r->code = proc->code ;
+ r->codeptr = proc->code ;
+ r->exitcode = proc->exitcode ;
+ r->errorcode = proc->errorcode ;
+ r->proc = proc ;
+ r->call_level = 0 ;
+
+ r->switchval = 0;
+ r->switchval_string = 0;
+ r->cased = 0;
+
+ r->breakpoint = 0 ;
+
+ r->private_size = proc->private_size ;
+ r->public_size = proc->public_size ;
+ r->first_run = 1 ;
+
+ if ( proc->private_size > 0 ) memcpy( r->pridata, proc->pridata, proc->private_size ) ;
+ if ( proc->public_size > 0 ) memcpy( r->pubdata, proc->pubdata, proc->public_size ) ;
+ if ( local_size > 0 ) memcpy( r->locdata, localdata, local_size ) ;
+
+ /* Inicializa datos de jerarquia */
+
+ LOCDWORD( r, PROCESS_TYPE ) = proc->type ;
+ LOCDWORD( r, PROCESS_ID ) = pid ;
+ LOCDWORD( r, SON ) = 0 ;
+ LOCDWORD( r, SMALLBRO ) = 0 ;
+
+ if ( father )
+ {
+ LOCDWORD( r, FATHER ) = LOCDWORD( father, PROCESS_ID ) ;
+ brother = instance_get( LOCDWORD( father, SON ) ) ;
+ if ( brother )
+ {
+ LOCDWORD( r, BIGBRO ) = LOCDWORD( brother, PROCESS_ID ) ;
+ LOCDWORD( brother, SMALLBRO ) = pid ;
+ }
+ else
+ {
+ LOCDWORD( r, BIGBRO ) = 0 ;
+ }
+ LOCDWORD( father, SON ) = pid ;
+ }
+ else
+ {
+ LOCDWORD( r, FATHER ) = 0 ;
+ LOCDWORD( r, BIGBRO ) = 0 ;
+ }
+
+ /* Cuenta los usos de las variables tipo cadena */
+
+ for ( n = 0; n < proc->string_count; n++ ) string_use( PRIDWORD( r, proc->strings[n] ) ) ; /* Strings privadas */
+ for ( n = 0; n < proc->pubstring_count; n++ ) string_use( PUBDWORD( r, proc->pubstrings[n] ) ) ; /* Strings publicas */
+ for ( n = 0; n < local_strings; n++ ) string_use( LOCDWORD( r, localstr[n] ) ) ; /* Strings locales */
+
+ r->prev = NULL ;
+ r->next = first_instance ;
+ if ( first_instance ) first_instance->prev = r;
+ first_instance = r ;
+
+ instance_add_to_list_by_id( r, pid );
+ instance_add_to_list_by_instance( r );
+ instance_add_to_list_by_type( r, proc->type );
+ instance_add_to_list_by_priority( r, 0 );
+
+ /* The called_by pointer should be set only when the caller
+ * is waiting for this process to return */
+
+ r->called_by = NULL;
+
+ r->stack = malloc( STACK_SIZE );
+ r->stack_ptr = &r->stack[1];
+ r->stack[0] = STACK_SIZE;
+
+ /* Initialize list pointers */
+
+ LOCDWORD( r, STATUS ) = STATUS_RUNNING;
+
+ if ( instance_create_hook_count )
+ for ( n = 0; n < instance_create_hook_count; n++ )
+ instance_create_hook_list[n]( r );
+
+ return r ;
+}
+
+/* ---------------------------------------------------------------------- */
+
+INSTANCE * instance_getfather( INSTANCE * i )
+{
+ return instance_get( LOCDWORD( i, FATHER ) ) ;
+}
+
+/* ---------------------------------------------------------------------- */
+
+INSTANCE * instance_getson( INSTANCE * i )
+{
+ return instance_get( LOCDWORD( i, SON ) ) ;
+}
+
+/* ---------------------------------------------------------------------- */
+
+INSTANCE * instance_getbigbro( INSTANCE * i )
+{
+ return instance_get( LOCDWORD( i, BIGBRO ) ) ;
+}
+
+/* ---------------------------------------------------------------------- */
+
+INSTANCE * instance_getsmallbro( INSTANCE * i )
+{
+ return instance_get( LOCDWORD( i, SMALLBRO ) ) ;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * FUNCTION : instance_destroy_all
+ *
+ * Destroy all instances. Simply calls instance_destroy
+ * for any and every instance in existence.
+ *
+ * PARAMS :
+ * except Don't destroy this instance (used for LET_ME_ALONE)
+ *
+ * RETURN VALUE :
+ * None
+ */
+
+void instance_destroy_all( INSTANCE * except )
+{
+ INSTANCE * i, * next ;
+
+ i = first_instance ;
+ while ( i )
+ {
+ next = i->next ;
+ if ( i != except ) instance_destroy( i ) ;
+ i = next ;
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * FUNCTION : instance_destroy
+ *
+ * Destroy an instance, effectively
+ * - Updates any instance list, removing the given instance
+ * - Discards all local and private strings
+ * - Updates all parents local family variables
+ * - Frees any memory involved
+ *
+ * PARAMS :
+ * r Pointer to the instance
+ *
+ * RETURN VALUE :
+ * None
+ */
+
+void instance_destroy( INSTANCE * r )
+{
+ INSTANCE * father, * bigbro, * smallbro;
+ int n ;
+
+ LOCDWORD( r, STATUS ) = STATUS_RUNNING;
+
+ if ( instance_destroy_hook_count )
+ for ( n = 0; n < instance_destroy_hook_count; n++ )
+ instance_destroy_hook_list[n]( r );
+
+ /* Actualiza la cuenta de referencia de las variables tipo string */
+
+ for ( n = 0 ; n < r->proc->string_count ; n++ ) string_discard( PRIDWORD( r, r->proc->strings[n] ) ) ; /* Strings privadas */
+ for ( n = 0 ; n < r->proc->pubstring_count ; n++ ) string_discard( PUBDWORD( r, r->proc->pubstrings[n] ) ) ; /* Strings publicas */
+ for ( n = 0 ; n < local_strings ; n++ ) string_discard( LOCDWORD( r, localstr[n] ) ) ; /* Strings locales */
+
+ /* Actualiza árbol de jerarquias */
+
+ bigbro = instance_get( LOCDWORD( r, BIGBRO ) ) ; /* Tengo hermano mayor? */
+ if ( bigbro ) LOCDWORD( bigbro, SMALLBRO ) = LOCDWORD( r, SMALLBRO ) ; /* El hermano menor de mi hermano mayor es mi hermano menor */
+
+ smallbro = instance_get( LOCDWORD( r, SMALLBRO ) ) ; /* Tengo hermano menor? */
+ if ( smallbro ) LOCDWORD( smallbro, BIGBRO ) = LOCDWORD( r, BIGBRO ) ; /* El hermano mayor de mi hermano menor es mi hermano mayor */
+
+ father = instance_get( LOCDWORD( r, FATHER ) ) ; /* Tengo padre? */
+ if ( father && instance_get( LOCDWORD( father, SON ) ) == r ) LOCDWORD( father, SON ) = LOCDWORD( r, BIGBRO ); /* Si tengo padre y soy el hijo menor, mi hermano mayor pasa a ser el menor hijo de mi padre */
+
+ /* Quita la instancia de la lista */
+
+ if ( r->prev ) r->prev->next = r->next ;
+ if ( r->next ) r->next->prev = r->prev ;
+
+ if ( first_instance == r ) first_instance = r->next ;
+
+ /* Remove the instance from all hash lists */
+
+ instance_remove_from_list_by_id( r, LOCDWORD( r, PROCESS_ID ) );
+ instance_remove_from_list_by_instance( r );
+ instance_remove_from_list_by_type( r, LOCDWORD( r, PROCESS_TYPE ) );
+ instance_remove_from_list_by_priority( r );
+
+ if ( r->stack ) free( r->stack ) ;
+
+ if ( r->locdata ) free( r->locdata ) ;
+ if ( r->pubdata ) free( r->pubdata ) ;
+ if ( r->pridata ) free( r->pridata ) ;
+ free( r ) ;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * FUNCTION : instance_exists
+ *
+ * Given an instance pointer, returns TRUE if it is still valid.
+ *
+ * PARAMS :
+ * i Pointer to the instance
+ *
+ * RETURN VALUE :
+ * 1 if the instance pointer is in the global instance list, 0 otherwise
+ */
+
+int instance_exists( INSTANCE * r )
+{
+ INSTANCE * i ;
+
+ if ( !hashed_by_instance || !r ) return 0;
+
+ i = hashed_by_instance[HASH_INSTANCE( r )];
+ while ( i )
+ {
+ if ( r == i ) return 1 ;
+ i = i->next_by_instance ;
+ }
+
+ return 0 ;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * FUNCTION : instance_next_by_priority
+ *
+ * Gets the next instance pointer until no more instances are
+ * returned. Instances are returned sorted by priority.
+ *
+ * PARAMS :
+ * None
+ *
+ * RETURN VALUE :
+ * Pointer to the next priority on the list or NULL
+ * if there is no more instances. The next call in this
+ * case will return a pointer to the first instance
+ * (the one with the lower priority)
+ */
+
+INSTANCE * instance_next_by_priority()
+{
+ INSTANCE * r = iterator_by_priority ;
+
+ if ( iterator_by_priority ) iterator_by_priority = iterator_by_priority->next_by_priority;
+
+ if ( !iterator_by_priority )
+ {
+ if ( !hashed_by_priority ) return NULL;
+
+ if ( iterator_pos < ( instance_min_actual_prio + INSTANCE_NORMALIZE_PRIORITY ) ||
+ iterator_pos > ( instance_max_actual_prio + INSTANCE_NORMALIZE_PRIORITY )
+ )
+ iterator_pos = instance_max_actual_prio + INSTANCE_NORMALIZE_PRIORITY + 1;
+
+ while ( --iterator_pos >= ( instance_min_actual_prio + INSTANCE_NORMALIZE_PRIORITY ) && !( iterator_by_priority = hashed_by_priority[iterator_pos] ) );
+ }
+
+ return ( r ) ;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * FUNCTION : instance_get_by_type
+ *
+ * Returns a instance, given its type.
+ *
+ * PARAMS :
+ * type Integer type of the first instance
+ * context Pointer to an INSTANCE * use as context (internal use)
+ *
+ * RETURN VALUE :
+ * Pointer to the found instance or NULL if not found
+ */
+
+/*
+context = NULL = start scan
+context = pointer = continue scan
+context = -1 = end scan
+*/
+
+INSTANCE * instance_get_by_type( uint32_t type, INSTANCE ** context )
+{
+ INSTANCE * i;
+
+ if ( !context || !hashed_by_type || !type /* || type >= FIRST_INSTANCE_ID */ ) return NULL;
+
+ if ( !*context ) /* start scan */
+ i = hashed_by_type[HASH( type )];
+ else if ( ( i = *context ) == ( INSTANCE * ) -1 ) /* End scan */
+ return ( *context = NULL );
+
+ if ( i ) /* Valid instance, continue scan */
+ {
+ if ( i->next_by_type )
+ *context = i->next_by_type ;
+ else
+ *context = ( INSTANCE * ) -1 ; /* Next call will be "end scan" */
+
+ return i;
+ }
+
+ /* Here only if hashed_by_type[HASH( type )] is NULL */
+ return ( *context = NULL ) ; /* return is null, then end scan */
+}
+
+/* ---------------------------------------------------------------------- */