1 /* ddt_exchange - send/recv data described */
3 /* Copyright (c) 2003-2009 The SimGrid Team. All rights reserved. */
5 /* This program is free software; you can redistribute it and/or modify it
6 * under the terms of the license (GNU LGPL) which comes with this package. */
9 #include "gras/DataDesc/datadesc_private.h"
10 #include "gras/Transport/transport_interface.h" /* gras_trp_send/recv */
12 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(gras_ddt_exchange, gras_ddt,
13 "Sending data over the network");
14 const char *gras_datadesc_cat_names[9] = {
16 "scalar", "struct", "union", "ref", "array", "ignored",
20 static gras_datadesc_type_t int_type = NULL;
21 static gras_datadesc_type_t pointer_type = NULL;
23 static XBT_INLINE void
24 gras_dd_send_int(gras_socket_t sock, int *i, int stable)
28 int_type = gras_datadesc_by_name("int");
32 DEBUG1("send_int(%u)", *i);
33 gras_trp_send(sock, (char *) i, int_type->size[GRAS_THISARCH], stable);
36 static XBT_INLINE void
37 gras_dd_recv_int(gras_socket_t sock, int r_arch, int *i)
41 int_type = gras_datadesc_by_name("int");
45 if (int_type->size[GRAS_THISARCH] >= int_type->size[r_arch]) {
46 gras_trp_recv(sock, (char *) i, int_type->size[r_arch]);
47 if (r_arch != GRAS_THISARCH)
48 gras_dd_convert_elm(int_type, 1, r_arch, i, i);
50 void *ptr = xbt_malloc(int_type->size[r_arch]);
52 gras_trp_recv(sock, (char *) ptr, int_type->size[r_arch]);
53 if (r_arch != GRAS_THISARCH)
54 gras_dd_convert_elm(int_type, 1, r_arch, ptr, i);
57 DEBUG1("recv_int(%u)", *i);
61 * Note: here we suppose that the remote NULL is a sequence
62 * of 'length' bytes set to 0.
63 * FIXME: Check in configure?
65 static XBT_INLINE int gras_dd_is_r_null(char **r_ptr, long int length)
69 for (i = 0; i < length; i++) {
70 if (((unsigned char *) r_ptr)[i]) {
78 static XBT_INLINE void gras_dd_alloc_ref(xbt_dict_t refs, long int size, char **r_ref, long int r_len, /* pointer_type->size[r_arch] */
79 char **l_ref, int detect_cycle)
83 xbt_assert1(size > 0, "Cannot allocate %ld bytes!", size);
84 l_data = xbt_malloc((size_t) size);
87 DEBUG5("alloc_ref: l_data=%p, &l_data=%p; r_ref=%p; *r_ref=%p, r_len=%ld",
88 (void *) l_data, (void *) &l_data,
89 (void *) r_ref, (void *) (r_ref ? *r_ref : NULL), r_len);
90 if (detect_cycle && r_ref && !gras_dd_is_r_null(r_ref, r_len)) {
91 void *ptr = xbt_malloc(sizeof(void *));
93 memcpy(ptr, l_ref, sizeof(void *));
95 DEBUG2("Insert l_ref=%p under r_ref=%p", *(void **) ptr,
99 xbt_dict_set_ext(refs, (const char *) r_ref, r_len, ptr, xbt_free_f);
104 gras_datadesc_memcpy_rec(gras_cbps_t state,
106 gras_datadesc_type_t type,
107 char *src, char *dst, int subsize, int detect_cycle)
112 gras_datadesc_type_t sub_type; /* type on which we recurse */
115 VERB5("Copy a %s (%s) from %p to %p (local sizeof=%ld)",
116 type->name, gras_datadesc_cat_names[type->category_code],
117 src, dst, type->size[GRAS_THISARCH]);
120 type->send(type, state, src);
123 switch (type->category_code) {
124 case e_gras_datadesc_type_cat_scalar:
125 memcpy(dst, src, type->size[GRAS_THISARCH]);
126 count += type->size[GRAS_THISARCH];
129 case e_gras_datadesc_type_cat_struct:{
130 gras_dd_cat_struct_t struct_data;
131 gras_dd_cat_field_t field;
135 struct_data = type->category.struct_data;
136 xbt_assert1(struct_data.closed,
137 "Please call gras_datadesc_declare_struct_close on %s before copying it",
139 VERB1(">> Copy all fields of the structure %s", type->name);
140 xbt_dynar_foreach(struct_data.fields, cpt, field) {
141 field_src = src + field->offset[GRAS_THISARCH];
142 field_dst = dst + field->offset[GRAS_THISARCH];
144 sub_type = field->type;
147 field->send(type, state, field_src);
149 DEBUG1("Copy field %s", field->name);
151 gras_datadesc_memcpy_rec(state, refs, sub_type, field_src,
152 field_dst, 0, detect_cycle
155 if (XBT_LOG_ISENABLED(gras_ddt_exchange, xbt_log_priority_verbose)) {
156 if (sub_type == gras_datadesc_by_name("unsigned int")) {
157 VERB2("Copied value for field '%s': %d (type: unsigned int)",
158 field->name, *(unsigned int *) field_dst);
159 } else if (sub_type == gras_datadesc_by_name("int")) {
160 VERB2("Copied value for field '%s': %d (type: int)", field->name,
163 } else if (sub_type == gras_datadesc_by_name("unsigned long int")) {
165 ("Copied value for field '%s': %ld (type: unsigned long int)",
166 field->name, *(unsigned long int *) field_dst);
167 } else if (sub_type == gras_datadesc_by_name("long int")) {
168 VERB2("Copied value for field '%s': %ld (type: long int)",
169 field->name, *(long int *) field_dst);
171 } else if (sub_type == gras_datadesc_by_name("string")) {
172 VERB2("Copied value for field '%s': '%s' (type: string)",
173 field->name, *(char **) field_dst);
175 VERB1("Copied a value for field '%s' (type not scalar?)",
181 VERB1("<< Copied all fields of the structure %s", type->name);
186 case e_gras_datadesc_type_cat_union:{
187 gras_dd_cat_union_t union_data;
188 gras_dd_cat_field_t field = NULL;
189 unsigned int field_num;
191 union_data = type->category.union_data;
193 xbt_assert1(union_data.closed,
194 "Please call gras_datadesc_declare_union_close on %s before copying it",
196 /* retrieve the field number */
197 field_num = union_data.selector(type, state, src);
199 xbt_assert1(field_num > 0,
200 "union field selector of %s gave a negative value",
203 xbt_assert3(field_num < xbt_dynar_length(union_data.fields),
204 "union field selector of %s returned %d but there is only %lu fields",
205 type->name, field_num, xbt_dynar_length(union_data.fields));
207 /* Copy the content */
209 xbt_dynar_get_as(union_data.fields, field_num, gras_dd_cat_field_t);
210 sub_type = field->type;
213 field->send(type, state, src);
215 count += gras_datadesc_memcpy_rec(state, refs, sub_type, src, dst, 0,
216 detect_cycle || sub_type->cycle);
221 case e_gras_datadesc_type_cat_ref:{
222 gras_dd_cat_ref_t ref_data;
225 int reference_is_to_cpy;
227 ref_data = type->category.ref_data;
229 /* Detect the referenced type */
230 sub_type = ref_data.type;
231 if (sub_type == NULL) {
232 sub_type = (*ref_data.selector) (type, state, src);
235 /* Send the pointed data only if not already sent */
236 if (*(void **) src == NULL) {
237 VERB0("Not copying NULL referenced data");
238 *(void **) dst = NULL;
241 o_ref = (char **) src;
243 reference_is_to_cpy = 1;
245 (n_ref=xbt_dict_get_or_null_ext(refs, (char *) o_ref, sizeof(char *)))) {
246 /* already known, no need to copy it */
247 //INFO0("Cycle detected");
248 reference_is_to_cpy = 0;
251 if (reference_is_to_cpy) {
252 int subsubcount = -1;
253 void *l_referenced = NULL;
254 VERB2("Copy a ref to '%s' referenced at %p", sub_type->name,
258 pointer_type = gras_datadesc_by_name("data pointer");
259 xbt_assert(pointer_type);
262 if (sub_type->category_code == e_gras_datadesc_type_cat_array) {
263 /* Damn. Reference to a dynamic array. Allocating the space for it is more complicated */
264 gras_dd_cat_array_t array_data = sub_type->category.array_data;
265 gras_datadesc_type_t subsub_type;
267 subsub_type = array_data.type;
268 subsubcount = array_data.fixed_size;
269 if (subsubcount == -1)
270 subsubcount = array_data.dynamic_size(subsub_type, state, *o_ref);
272 if (subsubcount != 0)
273 gras_dd_alloc_ref(refs,
274 subsub_type->size[GRAS_THISARCH] * subsubcount,
275 o_ref, pointer_type->size[GRAS_THISARCH],
276 (char **) &l_referenced, detect_cycle);
278 gras_dd_alloc_ref(refs, sub_type->size[GRAS_THISARCH],
279 o_ref, pointer_type->size[GRAS_THISARCH],
280 (char **) &l_referenced, detect_cycle);
283 count += gras_datadesc_memcpy_rec(state, refs, sub_type,
284 *o_ref, (char *) l_referenced,
285 subsubcount, detect_cycle
288 *(void **) dst = l_referenced;
289 VERB3("'%s' previously referenced at %p now at %p",
290 sub_type->name, *(void **) o_ref, l_referenced);
294 ("NOT copying data previously referenced @%p (already done, @%p now)",
295 *(void **) o_ref, *(void **) n_ref);
297 *(void **) dst = *n_ref;
303 case e_gras_datadesc_type_cat_array:{
304 gras_dd_cat_array_t array_data;
305 unsigned long int array_count;
310 array_data = type->category.array_data;
312 /* determine and send the element count */
313 array_count = array_data.fixed_size;
314 if (array_count == -1)
315 array_count = subsize;
316 if (array_count == -1) {
317 array_count = array_data.dynamic_size(type, state, src);
318 xbt_assert1(array_count >= 0,
319 "Invalid (negative) array size for type %s", type->name);
322 /* send the content */
323 sub_type = array_data.type;
324 elm_size = sub_type->aligned_size[GRAS_THISARCH];
325 if (sub_type->category_code == e_gras_datadesc_type_cat_scalar) {
326 VERB1("Array of %ld scalars, copy it in one shot", array_count);
327 memcpy(dst, src, sub_type->aligned_size[GRAS_THISARCH] * array_count);
328 count += sub_type->aligned_size[GRAS_THISARCH] * array_count;
329 } else if (sub_type->category_code == e_gras_datadesc_type_cat_array &&
330 sub_type->category.array_data.fixed_size > 0 &&
331 sub_type->category.array_data.type->category_code ==
332 e_gras_datadesc_type_cat_scalar) {
334 VERB1("Array of %ld fixed array of scalars, copy it in one shot",
337 sub_type->category.array_data.type->aligned_size[GRAS_THISARCH]
338 * array_count * sub_type->category.array_data.fixed_size);
340 sub_type->category.array_data.type->aligned_size[GRAS_THISARCH]
341 * array_count * sub_type->category.array_data.fixed_size;
344 VERB1("Array of %ld stuff, copy it in one after the other",
346 for (cpt = 0; cpt < array_count; cpt++) {
347 VERB2("Copy the %dth stuff out of %ld", cpt, array_count);
349 gras_datadesc_memcpy_rec(state, refs, sub_type, src_ptr, dst_ptr,
350 0, detect_cycle || sub_type->cycle);
359 xbt_die("Invalid type");
366 * gras_datadesc_memcpy:
368 * Copy the data pointed by src and described by type
369 * to a new location, and store a pointer to it in dst.
372 int gras_datadesc_memcpy(gras_datadesc_type_t type, void *src, void *dst)
375 static gras_cbps_t state = NULL;
376 static xbt_dict_t refs = NULL; /* all references already sent */
379 xbt_assert0(type, "called with NULL type descriptor");
381 DEBUG3("Memcopy a %s from %p to %p", gras_datadesc_get_name(type), src,
384 state = gras_cbps_new();
385 refs = xbt_dict_new();
390 gras_datadesc_memcpy_rec(state, refs, type, (char *) src, (char *) dst,
393 xbt_dict_reset(refs);
394 gras_cbps_reset(state);
402 *** Direct use functions
406 gras_datadesc_send_rec(gras_socket_t sock,
409 gras_datadesc_type_t type,
410 char *data, int detect_cycle)
414 gras_datadesc_type_t sub_type; /* type on which we recurse */
416 VERB2("Send a %s (%s)",
417 type->name, gras_datadesc_cat_names[type->category_code]);
419 if (!strcmp(type->name, "string"))
420 VERB1("value: '%s'", *(char **) data);
423 type->send(type, state, data);
424 DEBUG0("Run the emission callback");
427 switch (type->category_code) {
428 case e_gras_datadesc_type_cat_scalar:
429 gras_trp_send(sock, data, type->size[GRAS_THISARCH], 1);
432 case e_gras_datadesc_type_cat_struct:{
433 gras_dd_cat_struct_t struct_data;
434 gras_dd_cat_field_t field;
437 struct_data = type->category.struct_data;
438 xbt_assert1(struct_data.closed,
439 "Please call gras_datadesc_declare_struct_close on %s before sending it",
441 VERB1(">> Send all fields of the structure %s", type->name);
442 xbt_dynar_foreach(struct_data.fields, cpt, field) {
444 field_data += field->offset[GRAS_THISARCH];
446 sub_type = field->type;
449 DEBUG1("Run the emission callback of field %s", field->name);
450 field->send(type, state, field_data);
453 VERB1("Send field %s", field->name);
454 gras_datadesc_send_rec(sock, state, refs, sub_type, field_data,
455 detect_cycle || sub_type->cycle);
458 VERB1("<< Sent all fields of the structure %s", type->name);
463 case e_gras_datadesc_type_cat_union:{
464 gras_dd_cat_union_t union_data;
465 gras_dd_cat_field_t field = NULL;
468 union_data = type->category.union_data;
470 xbt_assert1(union_data.closed,
471 "Please call gras_datadesc_declare_union_close on %s before sending it",
473 /* retrieve the field number */
474 field_num = union_data.selector(type, state, data);
476 xbt_assert1(field_num > 0,
477 "union field selector of %s gave a negative value",
480 xbt_assert3(field_num < xbt_dynar_length(union_data.fields),
481 "union field selector of %s returned %d but there is only %lu fields",
482 type->name, field_num, xbt_dynar_length(union_data.fields));
484 /* Send the field number */
485 gras_dd_send_int(sock, &field_num, 0 /* not stable */ );
487 /* Send the content */
489 xbt_dynar_get_as(union_data.fields, field_num, gras_dd_cat_field_t);
490 sub_type = field->type;
493 field->send(type, state, data);
495 gras_datadesc_send_rec(sock, state, refs, sub_type, data,
496 detect_cycle || sub_type->cycle);
501 case e_gras_datadesc_type_cat_ref:{
502 gras_dd_cat_ref_t ref_data;
503 void **ref = (void **) data;
504 int reference_is_to_send;
506 ref_data = type->category.ref_data;
508 /* Detect the referenced type and send it to peer if needed */
509 sub_type = ref_data.type;
510 if (sub_type == NULL) {
511 sub_type = (*ref_data.selector) (type, state, data);
512 gras_dd_send_int(sock, &(sub_type->code), 1 /*stable */ );
515 /* Send the actual value of the pointer for cycle handling */
517 pointer_type = gras_datadesc_by_name("data pointer");
518 xbt_assert(pointer_type);
521 gras_trp_send(sock, (char *) data,
522 pointer_type->size[GRAS_THISARCH], 1 /*stable */ );
524 /* Send the pointed data only if not already sent */
525 if (*(void **) data == NULL) {
526 VERB0("Not sending NULL referenced data");
530 reference_is_to_send = 1;
531 /* return ignored. Just checking whether it's known or not */
532 if (detect_cycle && xbt_dict_get_or_null_ext(refs, (char *) ref, sizeof(char *))) {
533 //INFO0("Cycle detected");
534 reference_is_to_send = 0;
537 if (reference_is_to_send) {
538 VERB1("Sending data referenced at %p", (void *) *ref);
540 xbt_dict_set_ext(refs, (char *) ref, sizeof(void *), ref, NULL);
541 gras_datadesc_send_rec(sock, state, refs, sub_type, *ref,
542 detect_cycle || sub_type->cycle);
545 VERB1("Not sending data referenced at %p (already done)",
552 case e_gras_datadesc_type_cat_array:{
553 gras_dd_cat_array_t array_data;
558 array_data = type->category.array_data;
560 /* determine and send the element count */
561 count = array_data.fixed_size;
563 count = array_data.dynamic_size(type, state, data);
564 xbt_assert1(count >= 0,
565 "Invalid (negative) array size for type %s", type->name);
566 gras_dd_send_int(sock, &count, 0 /*non-stable */ );
569 /* send the content */
570 sub_type = array_data.type;
571 elm_size = sub_type->aligned_size[GRAS_THISARCH];
572 if (sub_type->category_code == e_gras_datadesc_type_cat_scalar) {
573 VERB1("Array of %d scalars, send it in one shot", count);
574 gras_trp_send(sock, data,
575 sub_type->aligned_size[GRAS_THISARCH] * count,
576 0 /* not stable */ );
577 } else if (sub_type->category_code == e_gras_datadesc_type_cat_array &&
578 sub_type->category.array_data.fixed_size > 0 &&
579 sub_type->category.array_data.type->category_code ==
580 e_gras_datadesc_type_cat_scalar) {
582 VERB1("Array of %d fixed array of scalars, send it in one shot",
584 gras_trp_send(sock, data,
585 sub_type->category.array_data.
586 type->aligned_size[GRAS_THISARCH]
587 * count * sub_type->category.array_data.fixed_size,
588 0 /* not stable */ );
591 for (cpt = 0; cpt < count; cpt++) {
592 gras_datadesc_send_rec(sock, state, refs, sub_type, ptr,
593 detect_cycle || sub_type->cycle);
601 xbt_die("Invalid type");
606 * gras_datadesc_send:
608 * Copy the data pointed by src and described by type to the socket
611 void gras_datadesc_send(gras_socket_t sock,
612 gras_datadesc_type_t type, void *src)
616 static gras_cbps_t state = NULL;
617 static xbt_dict_t refs = NULL; /* all references already sent */
619 xbt_assert0(type, "called with NULL type descriptor");
622 state = gras_cbps_new();
623 refs = xbt_dict_new();
627 gras_datadesc_send_rec(sock, state, refs, type, (char *) src,
630 xbt_dict_reset(refs);
631 gras_cbps_reset(state);
638 * gras_datadesc_recv_rec:
640 * Do the data reception job recursively.
642 * subsize used only to deal with vicious case of reference to dynamic array.
643 * This size is needed at the reference reception level (to allocate enough
644 * space) and at the array reception level (to fill enough room).
646 * Having this size passed as an argument of the recursive function is a crude
647 * hack, but I was told that working code is sometimes better than neat one ;)
650 gras_datadesc_recv_rec(gras_socket_t sock,
653 gras_datadesc_type_t type,
657 char *l_data, int subsize, int detect_cycle)
661 gras_datadesc_type_t sub_type;
663 VERB2("Recv a %s @%p", type->name, (void *) l_data);
666 switch (type->category_code) {
667 case e_gras_datadesc_type_cat_scalar:
668 if (type->size[GRAS_THISARCH] == type->size[r_arch]) {
669 gras_trp_recv(sock, (char *) l_data, type->size[r_arch]);
670 if (r_arch != GRAS_THISARCH)
671 gras_dd_convert_elm(type, 1, r_arch, l_data, l_data);
673 void *ptr = xbt_malloc(type->size[r_arch]);
675 gras_trp_recv(sock, (char *) ptr, type->size[r_arch]);
676 if (r_arch != GRAS_THISARCH)
677 gras_dd_convert_elm(type, 1, r_arch, ptr, l_data);
682 case e_gras_datadesc_type_cat_struct:{
683 gras_dd_cat_struct_t struct_data;
684 gras_dd_cat_field_t field;
686 struct_data = type->category.struct_data;
688 xbt_assert1(struct_data.closed,
689 "Please call gras_datadesc_declare_struct_close on %s before receiving it",
691 VERB1(">> Receive all fields of the structure %s", type->name);
692 xbt_dynar_foreach(struct_data.fields, cpt, field) {
693 char *field_data = l_data + field->offset[GRAS_THISARCH];
695 sub_type = field->type;
697 gras_datadesc_recv_rec(sock, state, refs, sub_type,
700 detect_cycle || sub_type->cycle);
703 DEBUG1("Run the reception callback of field %s", field->name);
704 field->recv(type, state, (void *) l_data);
708 VERB1("<< Received all fields of the structure %s", type->name);
713 case e_gras_datadesc_type_cat_union:{
714 gras_dd_cat_union_t union_data;
715 gras_dd_cat_field_t field = NULL;
718 union_data = type->category.union_data;
720 xbt_assert1(union_data.closed,
721 "Please call gras_datadesc_declare_union_close on %s before receiving it",
723 /* retrieve the field number */
724 gras_dd_recv_int(sock, r_arch, &field_num);
726 THROW1(mismatch_error, 0,
727 "Received union field for %s is negative", type->name);
728 if (field_num > xbt_dynar_length(union_data.fields))
729 THROW3(mismatch_error, 0,
730 "Received union field for %s is said to be #%d but there is only %lu fields",
731 type->name, field_num, xbt_dynar_length(union_data.fields));
733 /* Recv the content */
735 xbt_dynar_get_as(union_data.fields, field_num, gras_dd_cat_field_t);
736 sub_type = field->type;
738 gras_datadesc_recv_rec(sock, state, refs, sub_type,
740 l_data, -1, detect_cycle || sub_type->cycle);
742 field->recv(type, state, l_data);
747 case e_gras_datadesc_type_cat_ref:{
750 gras_dd_cat_ref_t ref_data;
751 int reference_is_to_recv = 0;
753 ref_data = type->category.ref_data;
755 /* Get the referenced type locally or from peer */
756 sub_type = ref_data.type;
757 if (sub_type == NULL) {
759 gras_dd_recv_int(sock, r_arch, &ref_code);
760 sub_type = gras_datadesc_by_id(ref_code);
763 /* Get the actual value of the pointer for cycle handling */
765 pointer_type = gras_datadesc_by_name("data pointer");
766 xbt_assert(pointer_type);
769 r_ref = xbt_malloc(pointer_type->size[r_arch]);
771 gras_trp_recv(sock, (char *) r_ref, pointer_type->size[r_arch]);
773 /* Receive the pointed data only if not already sent */
774 if (gras_dd_is_r_null(r_ref, pointer_type->size[r_arch])) {
775 VERB1("Not receiving data remotely referenced @%p since it's NULL",
777 *(void **) l_data = NULL;
782 reference_is_to_recv = 1;
783 if (detect_cycle && (l_ref =
784 xbt_dict_get_or_null_ext(refs, (char *) r_ref,
785 pointer_type->size[r_arch]))) {
786 reference_is_to_recv = 0;
787 //INFO0("Cycle detected");
790 if (reference_is_to_recv) {
791 int subsubcount = -1;
792 void *l_referenced = NULL;
794 VERB2("Receiving a ref to '%s', remotely @%p",
795 sub_type->name, *(void **) r_ref);
796 if (sub_type->category_code == e_gras_datadesc_type_cat_array) {
797 /* Damn. Reference to a dynamic array. Allocating the space for it is more complicated */
798 gras_dd_cat_array_t array_data = sub_type->category.array_data;
799 gras_datadesc_type_t subsub_type;
801 subsubcount = array_data.fixed_size;
802 if (subsubcount == -1)
803 gras_dd_recv_int(sock, r_arch, &subsubcount);
805 subsub_type = array_data.type;
807 if (subsubcount != 0)
808 gras_dd_alloc_ref(refs,
809 subsub_type->size[GRAS_THISARCH] * subsubcount,
810 r_ref, pointer_type->size[r_arch],
811 (char **) &l_referenced, detect_cycle);
815 gras_dd_alloc_ref(refs, sub_type->size[GRAS_THISARCH],
816 r_ref, pointer_type->size[r_arch],
817 (char **) &l_referenced, detect_cycle);
820 if (l_referenced != NULL)
821 gras_datadesc_recv_rec(sock, state, refs, sub_type,
822 r_arch, r_ref, pointer_type->size[r_arch],
823 (char *) l_referenced, subsubcount,
824 detect_cycle || sub_type->cycle);
826 *(void **) l_data = l_referenced;
827 VERB3("'%s' remotely referenced at %p locally at %p",
828 sub_type->name, *(void **) r_ref, l_referenced);
832 ("NOT receiving data remotely referenced @%p (already done, @%p here)",
833 *(void **) r_ref, *(void **) l_ref);
835 *(void **) l_data = *l_ref;
842 case e_gras_datadesc_type_cat_array:{
843 gras_dd_cat_array_t array_data;
848 array_data = type->category.array_data;
849 /* determine element count locally, or from caller, or from peer */
850 count = array_data.fixed_size;
854 gras_dd_recv_int(sock, r_arch, &count);
856 THROW1(mismatch_error, 0,
857 "Invalid (=-1) array size for type %s", type->name);
859 /* receive the content */
860 sub_type = array_data.type;
861 if (sub_type->category_code == e_gras_datadesc_type_cat_scalar) {
862 VERB1("Array of %d scalars, get it in one shoot", count);
863 if (sub_type->aligned_size[GRAS_THISARCH] >=
864 sub_type->aligned_size[r_arch]) {
865 gras_trp_recv(sock, (char *) l_data,
866 sub_type->aligned_size[r_arch] * count);
867 if (r_arch != GRAS_THISARCH)
868 gras_dd_convert_elm(sub_type, count, r_arch, l_data, l_data);
870 ptr = xbt_malloc(sub_type->aligned_size[r_arch] * count);
872 gras_trp_recv(sock, (char *) ptr, sub_type->size[r_arch] * count);
873 if (r_arch != GRAS_THISARCH)
874 gras_dd_convert_elm(sub_type, count, r_arch, ptr, l_data);
877 } else if (sub_type->category_code == e_gras_datadesc_type_cat_array &&
878 sub_type->category.array_data.fixed_size >= 0 &&
879 sub_type->category.array_data.type->category_code ==
880 e_gras_datadesc_type_cat_scalar) {
881 gras_datadesc_type_t subsub_type;
882 array_data = sub_type->category.array_data;
883 subsub_type = array_data.type;
885 VERB1("Array of %d fixed array of scalars, get it in one shot",
887 if (subsub_type->aligned_size[GRAS_THISARCH] >=
888 subsub_type->aligned_size[r_arch]) {
889 gras_trp_recv(sock, (char *) l_data,
890 subsub_type->aligned_size[r_arch] * count *
891 array_data.fixed_size);
892 if (r_arch != GRAS_THISARCH)
893 gras_dd_convert_elm(subsub_type, count * array_data.fixed_size,
894 r_arch, l_data, l_data);
897 xbt_malloc(subsub_type->aligned_size[r_arch] * count *
898 array_data.fixed_size);
900 gras_trp_recv(sock, (char *) ptr,
901 subsub_type->size[r_arch] * count *
902 array_data.fixed_size);
903 if (r_arch != GRAS_THISARCH)
904 gras_dd_convert_elm(subsub_type, count * array_data.fixed_size,
905 r_arch, ptr, l_data);
911 /* not scalar content, get it recursively (may contain pointers) */
912 elm_size = sub_type->aligned_size[GRAS_THISARCH];
913 VERB2("Receive a %d-long array of %s", count, sub_type->name);
916 for (cpt = 0; cpt < count; cpt++) {
917 gras_datadesc_recv_rec(sock, state, refs, sub_type,
918 r_arch, NULL, 0, ptr, -1,
919 detect_cycle || sub_type->cycle);
928 xbt_die("Invalid type");
932 type->recv(type, state, l_data);
934 if (!strcmp(type->name, "string"))
935 VERB1("value: '%s'", *(char **) l_data);
940 * gras_datadesc_recv:
942 * Get an instance of the datatype described by @type from the @socket,
943 * and store a pointer to it in @dst
947 gras_datadesc_recv(gras_socket_t sock,
948 gras_datadesc_type_t type, int r_arch, void *dst)
952 static gras_cbps_t state = NULL; /* callback persistent state */
953 static xbt_dict_t refs = NULL; /* all references already sent */
956 state = gras_cbps_new();
957 refs = xbt_dict_new();
960 xbt_assert0(type, "called with NULL type descriptor");
962 gras_datadesc_recv_rec(sock, state, refs, type,
963 r_arch, NULL, 0, (char *) dst, -1, type->cycle);
965 xbt_dict_reset(refs);
966 gras_cbps_reset(state);