1 /* ddt_new - creation/deletion of datatypes structs (private to this module)*/
3 /* Copyright (c) 2004, 2005, 2006, 2007, 2009, 2010. The SimGrid Team.
4 * All rights reserved. */
6 /* This program is free software; you can redistribute it and/or modify it
7 * under the terms of the license (GNU LGPL) which comes with this package. */
9 #include "xbt/misc.h" /* min()/max() */
11 #include "gras/DataDesc/datadesc_private.h"
13 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(gras_ddt_create, gras_ddt,
14 "Creating new datadescriptions");
17 static gras_dd_cat_field_t
18 gras_dd_find_field(gras_datadesc_type_t type, const char *field_name);
22 * gime that memory back, dude. I mean it.
24 void gras_ddt_freev(void *ddt)
26 gras_datadesc_type_t type = (gras_datadesc_type_t) ddt;
29 gras_datadesc_free(&type);
33 static gras_datadesc_type_t gras_ddt_new(const char *name)
35 gras_datadesc_type_t res;
38 res = xbt_new0(s_gras_datadesc_type_t, 1);
40 res->name = (char *) strdup(name);
41 res->name_len = strlen(name);
44 xbt_set_add(gras_datadesc_set_local, (xbt_set_elm_t) res,
50 /** @brief retrieve an existing message type from its name (or NULL if it does not exist). */
51 gras_datadesc_type_t gras_datadesc_by_name_or_null(const char *name)
54 gras_datadesc_type_t res = NULL;
57 res = gras_datadesc_by_name(name);
67 * Search the given datadesc (or raises an exception if it can't be found)
69 gras_datadesc_type_t gras_datadesc_by_name(const char *name)
72 gras_datadesc_type_t res = NULL;
73 volatile int found = 0;
76 (gras_datadesc_type_t) xbt_set_get_by_name(gras_datadesc_set_local,
81 if (e.category != not_found_error)
86 THROWF(not_found_error, 0, "No registred datatype of that name: %s",
93 * Retrieve a type from its code (or NULL if not found)
95 gras_datadesc_type_t gras_datadesc_by_id(long int code)
98 gras_datadesc_type_t res = NULL;
101 (gras_datadesc_type_t) xbt_set_get_by_id(gras_datadesc_set_local,
105 if (e.category != not_found_error)
114 * Create a new scalar and give a pointer to it
117 gras_datadesc_scalar(const char *name,
118 gras_ddt_scalar_type_t type,
119 enum e_gras_dd_scalar_encoding encoding)
122 gras_datadesc_type_t res;
126 res = gras_datadesc_by_name_or_null(name);
128 xbt_assert(res->category_code == e_gras_datadesc_type_cat_scalar,
129 "Redefinition of type %s does not match", name);
130 xbt_assert(res->category.scalar_data.encoding == encoding,
131 "Redefinition of type %s does not match", name);
132 xbt_assert(res->category.scalar_data.type == type,
133 "Redefinition of type %s does not match", name);
134 XBT_VERB("Discarding redefinition of %s", name);
137 res = gras_ddt_new(name);
139 for (arch = 0; arch < gras_arch_count; arch++) {
140 res->size[arch] = gras_arches[arch].sizeofs[type];
141 res->alignment[arch] = gras_arches[arch].boundaries[type];
142 res->aligned_size[arch] =
143 ddt_aligned(res->size[arch], res->alignment[arch]);
146 res->category_code = e_gras_datadesc_type_cat_scalar;
147 res->category.scalar_data.encoding = encoding;
148 res->category.scalar_data.type = type;
155 /** Frees one struct or union field */
156 void gras_dd_cat_field_free(void *f)
158 gras_dd_cat_field_t field = *(gras_dd_cat_field_t *) f;
168 /** \brief Declare a new structure description */
169 gras_datadesc_type_t gras_datadesc_struct(const char *name)
172 gras_datadesc_type_t res;
175 XBT_IN("(%s)", name);
176 res = gras_datadesc_by_name_or_null(name);
178 /* FIXME: Check that field redefinition matches */
179 xbt_assert(res->category_code == e_gras_datadesc_type_cat_struct,
180 "Redefinition of type %s does not match", name);
181 XBT_DEBUG("Discarding redefinition of %s", name);
184 res = gras_ddt_new(name);
186 for (arch = 0; arch < gras_arch_count; arch++) {
188 res->alignment[arch] = 0;
189 res->aligned_size[arch] = 0;
191 res->category_code = e_gras_datadesc_type_cat_struct;
192 res->category.struct_data.fields =
193 xbt_dynar_new(sizeof(gras_dd_cat_field_t), gras_dd_cat_field_free);
199 /** \brief Append a new field to a structure description */
201 gras_datadesc_struct_append(gras_datadesc_type_t struct_type,
203 gras_datadesc_type_t field_type)
206 gras_dd_cat_field_t field;
209 xbt_assert(field_type,
210 "Cannot add the field '%s' into struct '%s': its type is NULL",
211 name, struct_type->name);
212 XBT_IN("(%s %s.%s;)", field_type->name, struct_type->name, name);
213 if (struct_type->category.struct_data.closed) {
215 ("Ignoring request to add field to struct %s (closed. Redefinition?)",
220 xbt_assert(field_type->size[GRAS_THISARCH] >= 0,
221 "Cannot add a dynamically sized field in structure %s",
224 field = xbt_new(s_gras_dd_cat_field_t, 1);
225 field->name = (char *) strdup(name);
227 XBT_DEBUG("----------------");
228 XBT_DEBUG("PRE s={size=%ld,align=%ld,asize=%ld}",
229 struct_type->size[GRAS_THISARCH],
230 struct_type->alignment[GRAS_THISARCH],
231 struct_type->aligned_size[GRAS_THISARCH]);
234 for (arch = 0; arch < gras_arch_count; arch++) {
235 field->offset[arch] = ddt_aligned(struct_type->size[arch],
236 field_type->alignment[arch]);
238 struct_type->size[arch] = field->offset[arch] + field_type->size[arch];
239 struct_type->alignment[arch] = max(struct_type->alignment[arch],
240 field_type->alignment[arch]);
241 struct_type->aligned_size[arch] = ddt_aligned(struct_type->size[arch],
242 struct_type->alignment
245 field->type = field_type;
249 xbt_dynar_push(struct_type->category.struct_data.fields, &field);
251 XBT_DEBUG("Push a %s into %s at offset %ld.",
252 field_type->name, struct_type->name,
253 field->offset[GRAS_THISARCH]);
254 XBT_DEBUG(" f={size=%ld,align=%ld,asize=%ld}",
255 field_type->size[GRAS_THISARCH],
256 field_type->alignment[GRAS_THISARCH],
257 field_type->aligned_size[GRAS_THISARCH]);
258 XBT_DEBUG(" s={size=%ld,align=%ld,asize=%ld}",
259 struct_type->size[GRAS_THISARCH],
260 struct_type->alignment[GRAS_THISARCH],
261 struct_type->aligned_size[GRAS_THISARCH]);
265 /** \brief Close a structure description
267 * No new field can be added afterward, and it is mandatory to close the structure before using it.
269 void gras_datadesc_struct_close(gras_datadesc_type_t struct_type)
273 struct_type->category.struct_data.closed = 1;
274 for (arch = 0; arch < gras_arch_count; arch++) {
275 struct_type->size[arch] = struct_type->aligned_size[arch];
277 XBT_DEBUG("structure %s closed. size=%ld,align=%ld,asize=%ld",
279 struct_type->size[GRAS_THISARCH],
280 struct_type->alignment[GRAS_THISARCH],
281 struct_type->aligned_size[GRAS_THISARCH]);
285 * gras_datadesc_cycle_set:
287 * Tell GRAS that the pointers of the type described by ddt may present
288 * some loop, and that the cycle detection mechanism is needed.
290 * Note that setting this option when not needed have a rather bad effect
291 * on the performance (several times slower on big data).
293 void gras_datadesc_cycle_set(gras_datadesc_type_t ddt)
299 * gras_datadesc_cycle_unset:
301 * Tell GRAS that the pointers of the type described by ddt do not present
302 * any loop and that cycle detection mechanism are not needed.
305 void gras_datadesc_cycle_unset(gras_datadesc_type_t ddt)
310 /** \brief Declare a new union description */
312 gras_datadesc_union(const char *name, gras_datadesc_type_cb_int_t selector)
315 gras_datadesc_type_t res;
318 XBT_IN("(%s)", name);
320 "Attempt to creat an union without field_count function");
322 res = gras_datadesc_by_name_or_null(name);
324 /* FIXME: Check that field redefinition matches */
325 xbt_assert(res->category_code == e_gras_datadesc_type_cat_union,
326 "Redefinition of type %s does not match", name);
327 xbt_assert(res->category.union_data.selector == selector,
328 "Redefinition of type %s does not match", name);
329 XBT_VERB("Discarding redefinition of %s", name);
333 res = gras_ddt_new(name);
335 for (arch = 0; arch < gras_arch_count; arch++) {
337 res->alignment[arch] = 0;
338 res->aligned_size[arch] = 0;
341 res->category_code = e_gras_datadesc_type_cat_union;
342 res->category.union_data.fields =
343 xbt_dynar_new(sizeof(gras_dd_cat_field_t *), gras_dd_cat_field_free);
344 res->category.union_data.selector = selector;
349 /** \brief Append a new field to an union description */
350 void gras_datadesc_union_append(gras_datadesc_type_t union_type,
352 gras_datadesc_type_t field_type)
355 gras_dd_cat_field_t field;
358 XBT_IN("(%s %s.%s;)", field_type->name, union_type->name, name);
359 xbt_assert(field_type->size[GRAS_THISARCH] >= 0,
360 "Cannot add a dynamically sized field in union %s",
363 if (union_type->category.union_data.closed) {
364 XBT_VERB("Ignoring request to add field to union %s (closed)",
369 field = xbt_new0(s_gras_dd_cat_field_t, 1);
371 field->name = (char *) strdup(name);
372 field->type = field_type;
373 /* All offset are left to 0 in an union */
375 xbt_dynar_push(union_type->category.union_data.fields, &field);
377 for (arch = 0; arch < gras_arch_count; arch++) {
378 union_type->size[arch] = max(union_type->size[arch],
379 field_type->size[arch]);
380 union_type->alignment[arch] = max(union_type->alignment[arch],
381 field_type->alignment[arch]);
382 union_type->aligned_size[arch] = ddt_aligned(union_type->size[arch],
383 union_type->alignment
389 /** \brief Close an union description
391 * No new field can be added afterward, and it is mandatory to close the union before using it.
393 void gras_datadesc_union_close(gras_datadesc_type_t union_type)
395 union_type->category.union_data.closed = 1;
398 /** \brief Copy a type under another name
400 * This may reveal useful to circumvent parsing macro limitations
403 gras_datadesc_copy(const char *name, gras_datadesc_type_t copied)
406 gras_datadesc_type_t res = gras_ddt_new(name);
407 char *name_cpy = res->name;
409 memcpy(res, copied, sizeof(s_gras_datadesc_type_t));
410 res->name = name_cpy;
414 /** \brief Declare a new type being a reference to the one passed in arg */
416 gras_datadesc_ref(const char *name, gras_datadesc_type_t referenced_type)
419 gras_datadesc_type_t res;
420 gras_datadesc_type_t pointer_type =
421 gras_datadesc_by_name("data pointer");
424 XBT_IN("(%s)", name);
425 res = gras_datadesc_by_name_or_null(name);
427 xbt_assert(res->category_code == e_gras_datadesc_type_cat_ref,
428 "Redefinition of %s does not match", name);
429 xbt_assert(res->category.ref_data.type == referenced_type,
430 "Redefinition of %s does not match", name);
431 xbt_assert(res->category.ref_data.selector == NULL,
432 "Redefinition of %s does not match", name);
433 XBT_DEBUG("Discarding redefinition of %s", name);
437 res = gras_ddt_new(name);
439 xbt_assert(pointer_type, "Cannot get the description of data pointer");
441 for (arch = 0; arch < gras_arch_count; arch++) {
442 res->size[arch] = pointer_type->size[arch];
443 res->alignment[arch] = pointer_type->alignment[arch];
444 res->aligned_size[arch] = pointer_type->aligned_size[arch];
447 res->category_code = e_gras_datadesc_type_cat_ref;
448 res->category.ref_data.type = referenced_type;
449 res->category.ref_data.selector = NULL;
454 /** \brief Declare a new type being a generic reference.
456 * The callback passed in argument is to be used to select which type is currently used.
457 * So, when GRAS wants to send a generic reference, it passes the current data to the selector
458 * callback and expects it to return the type description to use.
461 gras_datadesc_ref_generic(const char *name,
462 gras_datadesc_selector_t selector)
465 gras_datadesc_type_t res;
466 gras_datadesc_type_t pointer_type =
467 gras_datadesc_by_name("data pointer");
470 XBT_IN("(%s)", name);
471 res = gras_datadesc_by_name_or_null(name);
474 xbt_assert(res->category_code == e_gras_datadesc_type_cat_ref,
475 "Redefinition of type %s does not match", name);
476 xbt_assert(res->category.ref_data.type == NULL,
477 "Redefinition of type %s does not match", name);
478 xbt_assert(res->category.ref_data.selector == selector,
479 "Redefinition of type %s does not match", name);
480 XBT_VERB("Discarding redefinition of %s", name);
483 res = gras_ddt_new(name);
485 xbt_assert(pointer_type, "Cannot get the description of data pointer");
487 for (arch = 0; arch < gras_arch_count; arch++) {
488 res->size[arch] = pointer_type->size[arch];
489 res->alignment[arch] = pointer_type->alignment[arch];
490 res->aligned_size[arch] = pointer_type->aligned_size[arch];
493 res->category_code = e_gras_datadesc_type_cat_ref;
495 res->category.ref_data.type = NULL;
496 res->category.ref_data.selector = selector;
501 /** \brief Declare a new type being an array of fixed size and content */
503 gras_datadesc_array_fixed(const char *name,
504 gras_datadesc_type_t element_type,
508 gras_datadesc_type_t res;
511 XBT_IN("(%s)", name);
512 res = gras_datadesc_by_name_or_null(name);
514 xbt_assert(res->category_code == e_gras_datadesc_type_cat_array,
515 "Redefinition of type %s does not match", name);
517 if (res->category.array_data.type != element_type) {
519 ("Redefinition of type %s does not match: array elements differ",
521 gras_datadesc_type_dump(res->category.array_data.type);
522 gras_datadesc_type_dump(element_type);
525 xbt_assert(res->category.array_data.fixed_size == fixed_size,
526 "Redefinition of type %s does not match", name);
527 xbt_assert(res->category.array_data.dynamic_size == NULL,
528 "Redefinition of type %s does not match", name);
529 XBT_VERB("Discarding redefinition of %s", name);
533 res = gras_ddt_new(name);
535 xbt_assert(fixed_size >= 0, "'%s' is a array of negative fixed size",
537 for (arch = 0; arch < gras_arch_count; arch++) {
538 res->size[arch] = fixed_size * element_type->aligned_size[arch];
539 res->alignment[arch] = element_type->alignment[arch];
540 res->aligned_size[arch] = res->size[arch];
543 res->category_code = e_gras_datadesc_type_cat_array;
545 res->category.array_data.type = element_type;
546 res->category.array_data.fixed_size = fixed_size;
547 res->category.array_data.dynamic_size = NULL;
552 /** \brief Declare a new type being an array of fixed size, but accepting several content types. */
553 gras_datadesc_type_t gras_datadesc_array_dyn(const char *name,
556 gras_datadesc_type_cb_int_t
560 gras_datadesc_type_t res;
563 XBT_IN("(%s)", name);
564 xbt_assert(dynamic_size,
565 "'%s' is a dynamic array without size discriminant", name);
567 res = gras_datadesc_by_name_or_null(name);
569 xbt_assert(res->category_code == e_gras_datadesc_type_cat_array,
570 "Redefinition of type %s does not match", name);
571 xbt_assert(res->category.array_data.type == element_type,
572 "Redefinition of type %s does not match", name);
573 xbt_assert(res->category.array_data.fixed_size == -1,
574 "Redefinition of type %s does not match", name);
575 xbt_assert(res->category.array_data.dynamic_size == dynamic_size,
576 "Redefinition of type %s does not match", name);
577 XBT_VERB("Discarding redefinition of %s", name);
582 res = gras_ddt_new(name);
584 for (arch = 0; arch < gras_arch_count; arch++) {
585 res->size[arch] = 0; /* make sure it indicates "dynamic" */
586 res->alignment[arch] = element_type->alignment[arch];
587 res->aligned_size[arch] = 0; /*FIXME: That was so in GS, but looks stupid */
590 res->category_code = e_gras_datadesc_type_cat_array;
592 res->category.array_data.type = element_type;
593 res->category.array_data.fixed_size = -1;
594 res->category.array_data.dynamic_size = dynamic_size;
599 /** \brief Declare a new type being an array which size can be found with \ref gras_cbps_i_pop
601 * Most of the time, you want to include a reference in your structure which
602 * is a pointer to a dynamic array whose size is fixed by another field of
605 * This case pops up so often that this function was created to take care of
606 * this case. It creates a dynamic array type whose size is poped from the
607 * current cbps, and then create a reference to it.
609 * The name of the created datatype will be the name of the element type, with
610 * '[]*' appended to it.
612 * Then to use it, you just have to make sure that your structure pre-callback
613 * does push the size of the array in the cbps (using #gras_cbps_i_push), and
616 * But be remember that this is a stack. If you have two different pop_arr, you
617 * should push the second one first, so that the first one is on the top of the
618 * list when the first field gets transfered.
622 gras_datadesc_ref_pop_arr(gras_datadesc_type_t element_type)
625 gras_datadesc_type_t res, ddt2;
626 char *name = (char *) xbt_malloc(strlen(element_type->name) + 4);
628 sprintf(name, "%s[]", element_type->name);
629 /* Make sure we are not trying to redefine a ddt with the same name */
630 ddt2 = gras_datadesc_by_name_or_null(name);
634 name = bprintf("%s[]_%d", element_type->name, cpt++);
635 ddt2 = gras_datadesc_by_name_or_null(name);
638 res = gras_datadesc_array_dyn(name, element_type, gras_datadesc_cb_pop);
640 sprintf(name, "%s[]*", element_type->name);
642 ddt2 = gras_datadesc_by_name_or_null(name);
645 name = bprintf("%s[]*_%d", element_type->name, cpt++);
646 ddt2 = gras_datadesc_by_name_or_null(name);
649 res = gras_datadesc_ref(name, res);
658 *## Constructor of container datatypes
662 static void gras_datadesc_dynar_cb(gras_datadesc_type_t typedesc,
663 gras_cbps_t vars, void *data)
665 gras_datadesc_type_t subtype;
666 xbt_dynar_t dynar = (xbt_dynar_t) data;
668 memcpy(&dynar->free_f, &typedesc->extra, sizeof(dynar->free_f));
670 /* search for the elemsize in what we have. If elements are "int", typedesc got is "int[]*" */
671 subtype = gras_dd_find_field(typedesc, "data")->type;
673 /* this is now a ref to array of what we're looking for */
674 subtype = subtype->category.ref_data.type;
675 subtype = subtype->category.array_data.type;
677 XBT_DEBUG("subtype is %s", subtype->name);
679 dynar->elmsize = subtype->size[GRAS_THISARCH];
680 dynar->size = dynar->used;
684 /** \brief Declare a new type being a dynar in which each elements are of the given type
686 * The type gets registered under the name "dynar(%s)_s", where %s is the name of the subtype.
687 * For example, a dynar of doubles will be called "dynar(double)_s" and a dynar of dynar of
688 * strings will be called "dynar(dynar(string)_s)_s".
690 * \param elm_t: the datadesc of the elements
691 * \param free_func: the function to use to free the elements when the dynar gets freed
694 gras_datadesc_dynar(gras_datadesc_type_t elm_t, void_f_pvoid_t free_func)
698 gras_datadesc_type_t res;
700 buffname = bprintf("s_xbt_dynar_of_%s", elm_t->name);
702 res = gras_datadesc_struct(buffname);
704 gras_datadesc_struct_append(res, "size",
705 gras_datadesc_by_name("unsigned long int"));
707 gras_datadesc_struct_append(res, "used",
708 gras_datadesc_by_name("unsigned long int"));
710 gras_datadesc_struct_append(res, "elmsize",
711 gras_datadesc_by_name("unsigned long int"));
713 gras_datadesc_struct_append(res, "data",
714 gras_datadesc_ref_pop_arr(elm_t));
716 gras_datadesc_struct_append(res, "free_f",
717 gras_datadesc_by_name("function pointer"));
718 memcpy(res->extra, &free_func, sizeof(free_func));
720 gras_datadesc_struct_append(res, "mutex",
721 gras_datadesc_by_name("data pointer"));
723 gras_datadesc_struct_close(res);
725 gras_datadesc_cb_field_push(res, "used");
726 gras_datadesc_cb_recv(res, &gras_datadesc_dynar_cb);
728 /* build a ref to it */
730 buffname = bprintf("xbt_dynar_of_%s", elm_t->name);
731 res = gras_datadesc_ref(buffname, res);
736 #include "xbt/matrix.h"
737 static void gras_datadesc_matrix_cb(gras_datadesc_type_t typedesc,
738 gras_cbps_t vars, void *data)
740 gras_datadesc_type_t subtype;
741 xbt_matrix_t matrix = (xbt_matrix_t) data;
743 memcpy(&matrix->free_f, &typedesc->extra, sizeof(matrix->free_f));
745 /* search for the elemsize in what we have. If elements are "int", typedesc got is "int[]*" */
746 subtype = gras_dd_find_field(typedesc, "data")->type;
748 /* this is now a ref to array of what we're looking for */
749 subtype = subtype->category.ref_data.type;
750 subtype = subtype->category.array_data.type;
752 XBT_DEBUG("subtype is %s", subtype->name);
754 matrix->elmsize = subtype->size[GRAS_THISARCH];
758 gras_datadesc_matrix(gras_datadesc_type_t elm_t,
759 void_f_pvoid_t const free_f)
762 gras_datadesc_type_t res;
764 buffname = bprintf("s_xbt_matrix_t(%s)", elm_t->name);
765 res = gras_datadesc_struct(buffname);
767 gras_datadesc_struct_append(res, "lines",
768 gras_datadesc_by_name("unsigned int"));
769 gras_datadesc_struct_append(res, "rows",
770 gras_datadesc_by_name("unsigned int"));
772 gras_datadesc_struct_append(res, "elmsize",
773 gras_datadesc_by_name("unsigned long int"));
775 gras_datadesc_struct_append(res, "data",
776 gras_datadesc_ref_pop_arr(elm_t));
777 gras_datadesc_struct_append(res, "free_f",
778 gras_datadesc_by_name("function pointer"));
779 gras_datadesc_struct_close(res);
781 gras_datadesc_cb_field_push(res, "lines");
782 gras_datadesc_cb_field_push_multiplier(res, "rows");
784 gras_datadesc_cb_recv(res, &gras_datadesc_matrix_cb);
785 memcpy(res->extra, &free_f, sizeof(free_f));
787 /* build a ref to it */
789 buffname = bprintf("xbt_matrix_t(%s)", elm_t->name);
790 res = gras_datadesc_ref(buffname, res);
796 gras_datadesc_import_nws(const char *name,
797 const DataDescriptor * desc,
798 unsigned long howmany)
804 * (useful to push the sizes of the upcoming arrays, for example)
806 void gras_datadesc_cb_send(gras_datadesc_type_t type,
807 gras_datadesc_type_cb_void_t send)
813 * (useful to put the function pointers to the rigth value, for example)
815 void gras_datadesc_cb_recv(gras_datadesc_type_t type,
816 gras_datadesc_type_cb_void_t recv)
822 * gras_dd_find_field:
824 * Returns the type descriptor of the given field. Abort on error.
826 static gras_dd_cat_field_t
827 gras_dd_find_field(gras_datadesc_type_t type, const char *field_name)
829 xbt_dynar_t field_array;
831 gras_dd_cat_field_t field = NULL;
832 unsigned int field_num;
834 if (type->category_code == e_gras_datadesc_type_cat_union) {
835 field_array = type->category.union_data.fields;
836 } else if (type->category_code == e_gras_datadesc_type_cat_struct) {
837 field_array = type->category.struct_data.fields;
839 XBT_ERROR("%s (%p) is not a struct nor an union. There is no field.",
840 type->name, (void *) type);
843 xbt_dynar_foreach(field_array, field_num, field) {
844 if (!strcmp(field_name, field->name)) {
848 XBT_ERROR("No field named '%s' in '%s'", field_name, type->name);
854 * The given datadesc must be a struct or union (abort if not).
855 * (useful to push the sizes of the upcoming arrays, for example)
857 void gras_datadesc_cb_field_send(gras_datadesc_type_t type,
858 const char *field_name,
859 gras_datadesc_type_cb_void_t send)
862 gras_dd_cat_field_t field = gras_dd_find_field(type, field_name);
868 * The value, which must be an int, unsigned int, long int or unsigned long int
869 * is pushed to the stacks of sizes and can then be retrieved with
870 * \ref gras_datadesc_ref_pop_arr or directly with \ref gras_cbps_i_pop.
872 void gras_datadesc_cb_field_push(gras_datadesc_type_t type,
873 const char *field_name)
876 gras_dd_cat_field_t field = gras_dd_find_field(type, field_name);
877 gras_datadesc_type_t sub_type = field->type;
879 XBT_DEBUG("add a PUSHy cb to '%s' field (type '%s') of '%s'",
880 field_name, sub_type->name, type->name);
881 if (!strcmp("int", sub_type->name)) {
882 field->send = gras_datadesc_cb_push_int;
883 } else if (!strcmp("unsigned int", sub_type->name)) {
884 field->send = gras_datadesc_cb_push_uint;
885 } else if (!strcmp("long int", sub_type->name)) {
886 field->send = gras_datadesc_cb_push_lint;
887 } else if (!strcmp("unsigned long int", sub_type->name)) {
888 field->send = gras_datadesc_cb_push_ulint;
891 ("Field %s is not an int, unsigned int, long int neither unsigned long int",
898 * Any previously pushed value is poped and the field value is multiplied to
899 * it. The result is then pushed back into the stack of sizes. It can then be
900 * retrieved with \ref gras_datadesc_ref_pop_arr or directly with \ref
903 * The field must be an int, unsigned int, long int or unsigned long int.
905 void gras_datadesc_cb_field_push_multiplier(gras_datadesc_type_t type,
906 const char *field_name)
909 gras_dd_cat_field_t field = gras_dd_find_field(type, field_name);
910 gras_datadesc_type_t sub_type = field->type;
912 XBT_DEBUG("add a MPUSHy cb to '%s' field (type '%s') of '%s'",
913 field_name, sub_type->name, type->name);
914 if (!strcmp("int", sub_type->name)) {
915 field->send = gras_datadesc_cb_push_int_mult;
916 } else if (!strcmp("unsigned int", sub_type->name)) {
917 field->send = gras_datadesc_cb_push_uint_mult;
918 } else if (!strcmp("long int", sub_type->name)) {
919 field->send = gras_datadesc_cb_push_lint_mult;
920 } else if (!strcmp("unsigned long int", sub_type->name)) {
921 field->send = gras_datadesc_cb_push_ulint_mult;
924 ("Field %s is not an int, unsigned int, long int neither unsigned long int",
931 * The given datadesc must be a struct or union (abort if not).
932 * (useful to put the function pointers to the right value, for example)
934 void gras_datadesc_cb_field_recv(gras_datadesc_type_t type,
935 const char *field_name,
936 gras_datadesc_type_cb_void_t recv)
939 gras_dd_cat_field_t field = gras_dd_find_field(type, field_name);
944 * Free a datadesc. Should only be called at xbt_exit.
946 void gras_datadesc_free(gras_datadesc_type_t * type)
949 XBT_DEBUG("Let's free ddt %s", (*type)->name);
951 switch ((*type)->category_code) {
952 case e_gras_datadesc_type_cat_scalar:
953 case e_gras_datadesc_type_cat_ref:
954 case e_gras_datadesc_type_cat_array:
955 /* nothing to free in there */
958 case e_gras_datadesc_type_cat_struct:
959 xbt_dynar_free(&((*type)->category.struct_data.fields));
962 case e_gras_datadesc_type_cat_union:
963 xbt_dynar_free(&((*type)->category.union_data.fields));
967 /* datadesc was invalid. Killing it is like euthanasy, I guess */
976 * gras_datadesc_type_cmp:
978 * Compares two datadesc types with the same semantic than strcmp.
980 * This comparison does not take the set headers into account (name and ID),
981 * but only the payload (actual type description).
983 int gras_datadesc_type_cmp(const gras_datadesc_type_t d1,
984 const gras_datadesc_type_t d2)
988 gras_dd_cat_field_t field1, field2;
989 gras_datadesc_type_t field_desc_1, field_desc_2;
992 return 0; /* easy optimization */
995 XBT_DEBUG("ddt_cmp: !d1 && d2 => 1");
999 XBT_DEBUG("ddt_cmp: !d1 && !d2 => 0");
1003 XBT_DEBUG("ddt_cmp: d1 && !d2 => -1");
1007 for (cpt = 0; cpt < gras_arch_count; cpt++) {
1008 if (d1->size[cpt] != d2->size[cpt]) {
1009 XBT_DEBUG("ddt_cmp: %s->size=%ld != %s->size=%ld (on %s)",
1010 d1->name, d1->size[cpt], d2->name, d2->size[cpt],
1011 gras_arches[cpt].name);
1012 return d1->size[cpt] > d2->size[cpt] ? 1 : -1;
1015 if (d1->alignment[cpt] != d2->alignment[cpt]) {
1016 XBT_DEBUG("ddt_cmp: %s->alignment=%ld != %s->alignment=%ld (on %s)",
1017 d1->name, d1->alignment[cpt], d2->name, d2->alignment[cpt],
1018 gras_arches[cpt].name);
1019 return d1->alignment[cpt] > d2->alignment[cpt] ? 1 : -1;
1022 if (d1->aligned_size[cpt] != d2->aligned_size[cpt]) {
1024 ("ddt_cmp: %s->aligned_size=%ld != %s->aligned_size=%ld (on %s)",
1025 d1->name, d1->aligned_size[cpt], d2->name,
1026 d2->aligned_size[cpt], gras_arches[cpt].name);
1027 return d1->aligned_size[cpt] > d2->aligned_size[cpt] ? 1 : -1;
1031 if (d1->category_code != d2->category_code) {
1032 XBT_DEBUG("ddt_cmp: %s->cat=%s != %s->cat=%s",
1033 d1->name, gras_datadesc_cat_names[d1->category_code],
1034 d2->name, gras_datadesc_cat_names[d2->category_code]);
1035 return d1->category_code > d2->category_code ? 1 : -1;
1038 if (d1->send != d2->send) {
1039 XBT_DEBUG("ddt_cmp: %s->send=%p != %s->send=%p",
1040 d1->name, (void *) d1->send, d2->name, (void *) d2->send);
1041 return 1; /* ISO C forbids ordered comparisons of pointers to functions */
1044 if (d1->recv != d2->recv) {
1045 XBT_DEBUG("ddt_cmp: %s->recv=%p != %s->recv=%p",
1046 d1->name, (void *) d1->recv, d2->name, (void *) d2->recv);
1047 return 1; /* ISO C forbids ordered comparisons of pointers to functions */
1050 switch (d1->category_code) {
1051 case e_gras_datadesc_type_cat_scalar:
1052 if (d1->category.scalar_data.encoding !=
1053 d2->category.scalar_data.encoding)
1054 return d1->category.scalar_data.encoding >
1055 d2->category.scalar_data.encoding ? 1 : -1;
1058 case e_gras_datadesc_type_cat_struct:
1059 if (xbt_dynar_length(d1->category.struct_data.fields) !=
1060 xbt_dynar_length(d2->category.struct_data.fields)) {
1061 XBT_DEBUG("ddt_cmp: %s (having %lu fields) != %s (having %lu fields)",
1062 d1->name, xbt_dynar_length(d1->category.struct_data.fields),
1063 d2->name, xbt_dynar_length(d2->category.struct_data.fields));
1065 return xbt_dynar_length(d1->category.struct_data.fields) >
1066 xbt_dynar_length(d2->category.struct_data.fields) ? 1 : -1;
1068 xbt_dynar_foreach(d1->category.struct_data.fields, cpt, field1) {
1071 xbt_dynar_get_as(d2->category.struct_data.fields, cpt,
1072 gras_dd_cat_field_t);
1073 field_desc_1 = field1->type;
1074 field_desc_2 = field2->type;
1075 ret = gras_datadesc_type_cmp(field_desc_1, field_desc_2);
1077 XBT_DEBUG("%s->field[%d]=%s != %s->field[%d]=%s",
1078 d1->name, cpt, field1->name, d2->name, cpt, field2->name);
1085 case e_gras_datadesc_type_cat_union:
1086 if (d1->category.union_data.selector !=
1087 d2->category.union_data.selector)
1088 return 1; /* ISO C forbids ordered comparisons of pointers to functions */
1090 if (xbt_dynar_length(d1->category.union_data.fields) !=
1091 xbt_dynar_length(d2->category.union_data.fields))
1092 return xbt_dynar_length(d1->category.union_data.fields) >
1093 xbt_dynar_length(d2->category.union_data.fields) ? 1 : -1;
1095 xbt_dynar_foreach(d1->category.union_data.fields, cpt, field1) {
1098 xbt_dynar_get_as(d2->category.union_data.fields, cpt,
1099 gras_dd_cat_field_t);
1100 field_desc_1 = field1->type;
1101 field_desc_2 = field2->type;
1102 ret = gras_datadesc_type_cmp(field_desc_1, field_desc_2);
1110 case e_gras_datadesc_type_cat_ref:
1111 if (d1->category.ref_data.selector != d2->category.ref_data.selector)
1112 return 1; /* ISO C forbids ordered comparisons of pointers to functions */
1114 if (d1->category.ref_data.type != d2->category.ref_data.type)
1115 return d1->category.ref_data.type >
1116 d2->category.ref_data.type ? 1 : -1;
1119 case e_gras_datadesc_type_cat_array:
1120 if (d1->category.array_data.type != d2->category.array_data.type)
1121 return d1->category.array_data.type >
1122 d2->category.array_data.type ? 1 : -1;
1124 if (d1->category.array_data.fixed_size !=
1125 d2->category.array_data.fixed_size)
1126 return d1->category.array_data.fixed_size >
1127 d2->category.array_data.fixed_size ? 1 : -1;
1129 if (d1->category.array_data.dynamic_size !=
1130 d2->category.array_data.dynamic_size)
1131 return 1; /* ISO C forbids ordered comparisons of pointers to functions */
1136 /* two stupidly created ddt are equally stupid ;) */