rt_private void parsing_store_append(struct rt_store_context *a_context, EIF_REFERENCE object, fnptr mid, fnptr nid) { RT_GET_CONTEXT struct rt_traversal_context traversal_context; int gc_stopped; make_index = mid; need_index = nid; gc_stopped = !eif_gc_ison(); eif_gc_stop(); /* Procedure `make_index' may call the GC * while creating objects. */ /* Need to hold mutex here since we are using traversal. */ EIF_EO_STORE_LOCK; #ifdef DEBUG (void) nomark(object); #endif /* Do the traversal: mark and count the objects to store */ memset(&traversal_context, 0, sizeof(struct rt_traversal_context)); traversal_context.is_for_persistence = 1; traversal(&traversal_context, object); current_position = 0; end_of_buffer = 0; /* Write in file `file_descriptor' the count of stored objects */ buffer_write((char *) (&traversal_context.obj_nb), sizeof(uint32)); #ifndef DEBUG (void) pst_store(a_context, object,0L); /* Recursive store process */ #else { uint32 nb_stored = pst_store(a_context, object,0L); if (traversal_context.obj_nb != nb_stored) { printf("obj_nb = %d nb_stored = %d\n", traversal_context.obj_nb, nb_stored); eraise ("Eiffel partial store", EN_IO); } } if (traversal_context.obj_nb != nomark(object)) eraise ("Partial store inconsistency", EN_IO); #endif a_context->flush_buffer_function(); /* Flush the buffer */ EIF_EO_STORE_UNLOCK; /* Unlock our mutex. */ if (!gc_stopped) eif_gc_run(); /* Restart GC */ }
rt_public EIF_BOOLEAN spiso(register EIF_REFERENCE target, register EIF_REFERENCE source) { /* Compare two special objects in term of their structures. `source' * and `target' are refering two special objects. There is three cases: * 1- either the elements are direct instances: block comparison. * 2- either the elements are references: comparison of referenced * dynamic type. * 3- or the elements are expanded: call `eiso' (special objects * cannot be expanded). */ union overhead *s_zone; /* Source header */ uint32 s_flags; /* Source flags */ /*uint32 t_flags;*/ /* Target flags */ EIF_REFERENCE s_ref; EIF_REFERENCE t_ref; EIF_INTEGER count; /* Common count */ EIF_INTEGER elem_size; /* Common element size */ EIF_REFERENCE s_field, t_field; REQUIRE("special objects", (HEADER(target)->ov_flags & EO_SPEC) && (HEADER(source)->ov_flags & EO_SPEC)); if (source == target) return EIF_TRUE; s_zone = HEADER(source); #ifdef DEBUG dprintf(2)("spiso: source = 0x%lx [%d] target = 0x%lx [%d]\n", source, RT_SPECIAL_COUNT(source), target, RT_SPECIAL_COUNT(target)); #endif count = RT_SPECIAL_COUNT(source); if (count != RT_SPECIAL_COUNT(target)) return EIF_FALSE; /* Second condition: same element size */ elem_size = RT_SPECIAL_ELEM_SIZE(source); if (elem_size != RT_SPECIAL_ELEM_SIZE(target)) return EIF_FALSE; s_flags = s_zone->ov_flags; /* In final mode, we can do block comparison on special of basic types * or on special of expanded which have no references since they have no header. * In workbench mode, block comparison is only possible on special of basic types. */ #ifdef WORKBENCH if (!(s_flags & EO_REF) && !(s_flags & EO_COMP)) { #else if (!(s_flags & EO_REF)) { #endif /* Case 1: specials filled with direct instances: block comparison */ return EIF_TEST(!memcmp (source, target, (rt_uint_ptr) count * (rt_uint_ptr) elem_size)); } if (s_flags & EO_TUPLE) { EIF_TYPED_VALUE * l_source = (EIF_TYPED_VALUE *) source; EIF_TYPED_VALUE * l_target = (EIF_TYPED_VALUE *) target; /* Don't forget that first element of TUPLE is the BOOLEAN * `object_comparison' attribute. */ for (; count > 0; count--, l_source++, l_target++) { if (eif_is_reference_tuple_item(l_source) && eif_is_reference_tuple_item(l_target)) { s_field = eif_reference_tuple_item (l_source); t_field = eif_reference_tuple_item (l_target); if ((s_field == NULL) && (t_field == NULL)) { continue; } else if ((s_field) && (t_field) && (Dtype(s_field) == Dtype(t_field))) { continue; } else { return EIF_FALSE; } } } return EIF_TRUE; } else if ((s_flags & EO_REF) && !(s_flags & EO_COMP)) { /* Case 2: specials filled with references: we have to check fields * one by one. */ for( s_ref = (EIF_REFERENCE)source, t_ref = (EIF_REFERENCE) target; count > 0; count --, s_ref = (EIF_REFERENCE) ((EIF_REFERENCE *) s_ref + 1), t_ref = (EIF_REFERENCE) ((EIF_REFERENCE *) t_ref + 1) ) { /* Evaluation of two references */ s_field = *(EIF_REFERENCE *) s_ref; t_field = *(EIF_REFERENCE *) t_ref; if ((!s_field) && (!t_field)) /* Two void references */ continue; else if ( (((EIF_REFERENCE) 0) != s_field) && (((EIF_REFERENCE) 0) != t_field) && (Dtype(s_field) == Dtype(t_field)) ) /* Two non-void references on objects of same dynamic type */ continue; else /* No ismorphism */ return EIF_FALSE; } return EIF_TRUE; } /* Case 3: special objects filled with (non-special) expanded objects. * we call then standard isomorphism test on normal objects. */ for ( s_ref = source +OVERHEAD, t_ref = target+OVERHEAD; count >0; count--, s_ref += elem_size, t_ref += elem_size ) { /* Iteration on expanded elements */ if (!eiso(t_ref, s_ref)) return EIF_FALSE; } return EIF_TRUE; } rt_public EIF_BOOLEAN ediso(EIF_REFERENCE target, EIF_REFERENCE source) { /* Compare recursively the structure attached to `target' to the * one attached to `source'. This is the standard Eiffel feature * because it called recursively the standard isomorhic Eiffel * feature. * Return a boolean. */ RT_GET_CONTEXT EIF_BOOLEAN result; #ifdef ISE_GC char g_status; /* Save GC status */ g_status = eif_gc_ison(); if (g_status) eif_gc_stop(); /* Stop GC if enabled*/ #endif eif_equality_table = s_create(100); /* Create search table */ result = rdeepiso(target,source); /* Recursive isomorphism test */ #ifdef ISE_GC if (g_status) eif_gc_run(); /* Enabled GC it was previously enabled */ #endif eif_rt_xfree((EIF_REFERENCE) (eif_equality_table->s_keys)); /* Free search table keys */ eif_rt_xfree((EIF_REFERENCE) eif_equality_table); /* Free search table descriptor */ eif_equality_table = NULL; return result; }
rt_public EIF_REFERENCE eif_once_objects_of_result_type(EIF_TYPE result_type) /* All once objects held by the system */ { RT_GET_CONTEXT EIF_REFERENCE Result; union overhead *zone; struct obj_array l_found; size_t i; #if defined(EIF_THREADS) && defined(ISE_GC) size_t l_threads_count; #endif char gc_stopped; /* Lock global once mutex. */ #ifdef EIF_THREADS EIF_ASYNC_SAFE_CS_LOCK(eif_global_once_set_mutex); #endif /* Initialize structure that will hold found objects */ l_found.count = 0; l_found.capacity = 64; l_found.area = malloc (sizeof (EIF_REFERENCE) * l_found.capacity); if (!l_found.area) { enomem(); } #ifndef EIF_THREADS #ifdef WORKBENCH rt_ostack_lookup (&l_found, &once_set); #else rt_oastack_lookup (&l_found, &once_set); #endif #else rt_oastack_lookup(&l_found, &global_once_set); #ifdef ISE_GC l_threads_count = once_set_list.count; i = 0; while (i < l_threads_count) { rt_ostack_lookup (&l_found, once_set_list.threads.ostack[i++]); i++; } #endif #endif /* Unlock global once mutex */ #ifdef EIF_THREADS EIF_ASYNC_SAFE_CS_UNLOCK(eif_global_once_set_mutex); #endif /* Now `l_found' is properly populated so let's create * SPECIAL objects of type `result_type' that we will return. * We turn off GC since we do not want objects to be moved. */ gc_stopped = !eif_gc_ison(); eif_gc_stop(); Result = spmalloc (l_found.count, sizeof (EIF_REFERENCE), EIF_FALSE); zone = HEADER (Result); zone->ov_flags |= EO_REF; zone->ov_dftype = result_type.id; zone->ov_dtype = To_dtype(result_type.id); RT_SPECIAL_COUNT(Result) = l_found.count; RT_SPECIAL_ELEM_SIZE(Result) = sizeof(EIF_REFERENCE); RT_SPECIAL_CAPACITY(Result) = l_found.count; /* Now, populate `Result' with content of `l_found'. Since we just * created a new Eiffel objects. */ for (i = 0 ; i < l_found.count ; i++) { /* Store object in `Result'. */ *((EIF_REFERENCE*) Result + i) = l_found.area [i]; RTAR(Result, l_found.area [i]); } free (l_found.area); /* Let's turn back the GC on */ if (!gc_stopped) eif_gc_run(); return Result; }