Ejemplo n.º 1
0
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 */

}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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;
}