ni: adds global references to Nit objects from C code
[nit.git] / clib / nit_main.c
index 6f7daba..239eb82 100644 (file)
@@ -125,6 +125,9 @@ void initialize_gc_option(void) {
                case nitgc: Nit_gc_init(); break;
                default: break; /* Nothing */
        }
+
+       /* Initialize global references list */
+       nitni_global_ref_list_init();
 }
 void prepare_signals(void) {
        initialize_gc_option();
@@ -198,7 +201,9 @@ void nitni_local_ref_clean( void ) {
        while ( link != NULL )
        {
                for ( i = 0; i < link->count; i ++ ) {
-                       free( link->reg[ i ] );
+                       if ( link->reg[i]->count == 0 ) { /* not registered globally */
+                               free( link->reg[ i ] );
+                       }
                }
 
                last_link = link;
@@ -212,3 +217,58 @@ void nitni_local_ref_clean( void ) {
 
        stack_frame_head->nitni_local_ref_head = NULL;
 }
+
+struct nitni_global_ref_list_t *nitni_global_ref_list;
+void nitni_global_ref_list_init() {
+       nitni_global_ref_list = (struct nitni_global_ref_list_t*)malloc(sizeof(struct nitni_global_ref_list_t));
+       nitni_global_ref_list->head = NULL;
+       nitni_global_ref_list->tail = NULL;
+}
+
+void nitni_global_ref_add( struct nitni_ref *ref ) {
+       if ( nitni_global_ref_list->head == NULL ) {
+               nitni_global_ref_list->head = ref;
+               nitni_global_ref_list->tail = ref;
+
+               ref->prev = NULL;
+       } else {
+               nitni_global_ref_list->tail->next = ref;
+               ref->prev = nitni_global_ref_list->tail;
+       }
+
+       ref->next = NULL;
+}
+
+void nitni_global_ref_remove( struct nitni_ref *ref ) {
+       if ( ref->prev == NULL ) {
+               nitni_global_ref_list->head = ref->next;
+       } else {
+               ref->prev->next = ref->next;
+       }
+
+       if ( ref->next == NULL ) {
+               nitni_global_ref_list->tail = ref->prev;
+       } else {
+               ref->next->prev = ref->prev;
+       }
+}
+
+extern void nitni_global_ref_incr( struct nitni_ref *ref ) {
+       if ( ref->count == 0 ) /* not registered */
+       {
+               /* add to list */
+               nitni_global_ref_add( ref );
+       }
+
+       ref->count ++;
+}
+
+extern void nitni_global_ref_decr( struct nitni_ref *ref ) {
+       if ( ref->count == 1 ) /* was last reference */
+       {
+               /* remove from list */
+               nitni_global_ref_remove( ref );
+       }
+
+       ref->count --;
+}