Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
3a91cb5c06f6ae4481f6036d3c3a56d26139d69b
[simgrid.git] / src / gras / DataDesc / ddt_create.c
1 /* $Id$ */
2
3 /* ddt_new - creation/deletion of datatypes structs (private to this module)*/
4
5 /* Copyright (c) 2004 Olivier Aumage, Martin Quinson. All rights reserved.  */
6
7 /* This program is free software; you can redistribute it and/or modify it
8  * under the terms of the license (GNU LGPL) which comes with this package. */
9
10 #include "xbt/misc.h" /* min()/max() */
11 #include "gras/DataDesc/datadesc_private.h"
12
13 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(ddt_create,datadesc,"Creating new datadescriptions");
14
15 /**
16  * gras_ddt_freev:
17  *
18  * gime that memory back, dude. I mean it.
19  */
20 void gras_ddt_freev(void *ddt) {
21   gras_datadesc_type_t type= (gras_datadesc_type_t)ddt;
22   
23   if (type) {
24     gras_datadesc_free(&type);
25   }
26 }
27
28 static gras_datadesc_type_t gras_ddt_new(const char *name) {
29   gras_datadesc_type_t res;
30
31   XBT_IN1("(%s)",name);
32   res=xbt_new0(s_gras_datadesc_type_t,1);
33
34   res->name = (char*)strdup(name);
35   res->name_len = strlen(name);
36   res->cycle = 0;
37       
38   xbt_set_add(gras_datadesc_set_local,
39                (xbt_set_elm_t)res,&gras_ddt_freev);
40   XBT_OUT;
41   return res;
42 }
43
44 /**
45  * gras_datadesc_by_name:
46  *
47  * Retrieve a type from its name
48  */
49 gras_datadesc_type_t gras_datadesc_by_name(const char *name) {
50
51   gras_datadesc_type_t type;
52
53   XBT_IN1("(%s)",name);
54   if (xbt_set_get_by_name(gras_datadesc_set_local,
55                            name,(xbt_set_elm_t*)&type) == no_error) {
56     XBT_OUT;
57     return type;
58   } else { 
59     XBT_OUT;
60     return NULL;
61   }
62 }
63
64 /**
65  * gras_datadesc_by_id:
66  *
67  * Retrieve a type from its code
68  */
69 xbt_error_t gras_datadesc_by_id(long int              code,
70                                  gras_datadesc_type_t *type) {
71   XBT_IN;
72   return xbt_set_get_by_id(gras_datadesc_set_local,
73                             code,(xbt_set_elm_t*)type);
74 }
75
76 /**
77  * gras_datadesc_scalar:
78  *
79  * Create a new scalar and give a pointer to it 
80  */
81 gras_datadesc_type_t 
82   gras_datadesc_scalar(const char                      *name,
83                        gras_ddt_scalar_type_t           type,
84                        enum e_gras_dd_scalar_encoding   encoding) {
85
86   gras_datadesc_type_t res;
87   long int arch;
88
89   XBT_IN;
90   res = gras_datadesc_by_name(name);
91   if (res) {
92     xbt_assert1(res->category_code == e_gras_datadesc_type_cat_scalar,
93                  "Redefinition of type %s does not match", name);
94     xbt_assert1(res->category.scalar_data.encoding == encoding,
95                  "Redefinition of type %s does not match", name);
96     xbt_assert1(res->category.scalar_data.type == type,
97                  "Redefinition of type %s does not match", name);
98     VERB1("Discarding redefinition of %s",name);
99     return res;
100   }
101   res = gras_ddt_new(name);
102
103   for (arch = 0; arch < gras_arch_count; arch ++) {
104 #if 0
105     long int sz;
106     long int mask;
107 #endif
108     res->size[arch]         = gras_arches[arch].sizeofs[type];
109     res->alignment[arch]    = gras_arches[arch].boundaries[type];
110     res->aligned_size[arch] = aligned(res->size[arch], res->alignment[arch]);
111 /* FIXME: kill the following after discution with Oli */
112 #if 0
113     sz = res->size[arch];
114     mask = sz;
115     
116     /* just in case you wonder, x>>1 == x/2 on all architectures when x>=0
117        and a size is always>=0 */
118     
119     /* make sure mask have all the bits under the biggest one of size set to 1
120        Example: size=000100101 => mask=0000111111 */
121     while ((sz >>= 1)) {
122       mask |= sz;
123     } 
124     
125     if (res->size[arch] & (mask >> 1)) { /* if size have bits to one beside its biggest */
126       /* size is not a power of 2 */
127       /* alignment= next power of 2 after size */
128       res->alignment[arch] = (res->size[arch] & ~(mask >> 1)) << 1;
129       xbt_assert0(res->alignment[arch] != 0,
130                    "scalar type too large");
131       
132       res->aligned_size[arch] = aligned(res->size[arch], res->alignment[arch]);
133       xbt_assert0 (res->aligned_size[arch] >= 0,
134                     "scalar type too large");
135       
136     } else {
137       /* size is a power of 2, life is great */
138       res->alignment[arch]       = res->size[arch];
139       res->aligned_size[arch]    = res->size[arch];
140     }
141 #endif     
142   }
143
144   res->category_code                 = e_gras_datadesc_type_cat_scalar;
145   res->category.scalar_data.encoding = encoding;
146   res->category.scalar_data.type     = type;
147   XBT_OUT;
148   
149   return res;
150 }
151
152
153 /**
154  * gras_dd_cat_field_free:
155  *
156  * Frees one struct or union field
157  */
158 void gras_dd_cat_field_free(void *f) {
159   gras_dd_cat_field_t field = *(gras_dd_cat_field_t *)f;
160   XBT_IN;
161   if (field) {
162     if (field->name) 
163       xbt_free(field->name);
164     xbt_free(field);
165   }
166   XBT_OUT;
167 }
168
169 /**
170  * gras_datadesc_struct:
171  *
172  * Create a new struct and give a pointer to it 
173  */
174 gras_datadesc_type_t 
175   gras_datadesc_struct(const char            *name) {
176
177   gras_datadesc_type_t res;
178   long int arch;
179   
180   XBT_IN1("(%s)",name);
181   res = gras_datadesc_by_name(name);
182   if (res) {
183     /* FIXME: Check that field redefinition matches */
184     xbt_assert1(res->category_code == e_gras_datadesc_type_cat_struct,
185                  "Redefinition of type %s does not match", name);
186     VERB1("Discarding redefinition of %s",name);
187     return res;
188   }
189   res = gras_ddt_new(name);
190
191   for (arch=0; arch<gras_arch_count; arch ++) {
192     res->size[arch] = 0;
193     res->alignment[arch] = 0;
194     res->aligned_size[arch] = 0;
195   }
196   res->category_code = e_gras_datadesc_type_cat_struct;
197   res->category.struct_data.fields = 
198        xbt_dynar_new(sizeof(gras_dd_cat_field_t),
199                       &gras_dd_cat_field_free);
200
201   XBT_OUT;
202   return res;
203 }
204
205 /**
206  * gras_datadesc_struct_append:
207  *
208  * Append a field to the struct
209  */
210 void
211 gras_datadesc_struct_append(gras_datadesc_type_t struct_type,
212                             const char          *name,
213                             gras_datadesc_type_t field_type) {
214
215   gras_dd_cat_field_t field;
216   int arch;
217
218   xbt_assert2(field_type,
219                "Cannot add the field '%s' into struct '%s': its type is NULL. Typo in get_by_name?",
220                name,struct_type->name);
221   XBT_IN3("(%s %s.%s;)",field_type->name,struct_type->name,name);
222   if (struct_type->category.struct_data.closed) {
223     VERB1("Ignoring request to add field to struct %s (closed. Redefinition?)",
224           struct_type->name);
225     return;
226   }
227
228   xbt_assert1(field_type->size != 0,
229                "Cannot add a dynamically sized field in structure %s",
230                struct_type->name);
231     
232   field=xbt_new(s_gras_dd_cat_field_t,1);
233   field->name   = (char*)strdup(name);
234
235   DEBUG0("----------------");
236   DEBUG3("PRE s={size=%ld,align=%ld,asize=%ld}",
237          struct_type->size[GRAS_THISARCH], 
238          struct_type->alignment[GRAS_THISARCH], 
239          struct_type->aligned_size[GRAS_THISARCH]);
240      
241      
242   for (arch=0; arch<gras_arch_count; arch ++) {
243     field->offset[arch] = aligned(struct_type->size[arch],
244                                   field_type->alignment[arch]);
245
246     struct_type->size[arch] = field->offset[arch] + field_type->size[arch];
247     struct_type->alignment[arch] = max(struct_type->alignment[arch],
248                                        field_type->alignment[arch]);
249     struct_type->aligned_size[arch] = aligned(struct_type->size[arch],
250                                               struct_type->alignment[arch]);
251   }
252   field->type   = field_type;
253   field->pre    = NULL;
254   field->post   = NULL;
255   
256   xbt_dynar_push(struct_type->category.struct_data.fields, &field);
257
258   DEBUG3("Push a %s into %s at offset %ld.",
259          field_type->name, struct_type->name,field->offset[GRAS_THISARCH]);
260   DEBUG3("  f={size=%ld,align=%ld,asize=%ld}",
261          field_type->size[GRAS_THISARCH], 
262          field_type->alignment[GRAS_THISARCH], 
263          field_type->aligned_size[GRAS_THISARCH]);
264   DEBUG3("  s={size=%ld,align=%ld,asize=%ld}",
265          struct_type->size[GRAS_THISARCH], 
266          struct_type->alignment[GRAS_THISARCH], 
267          struct_type->aligned_size[GRAS_THISARCH]);
268   XBT_OUT;
269 }
270
271 void
272 gras_datadesc_struct_close(gras_datadesc_type_t struct_type) {
273   XBT_IN;
274   struct_type->category.struct_data.closed = 1;
275 }
276
277 /**
278  * gras_datadesc_cycle_set:
279  * 
280  * Tell GRAS that the pointers of the type described by @ddt may present
281  * some loop, and that the cycle detection mecanism is needed.
282  *
283  * Note that setting this option when not needed have a rather bad effect 
284  * on the performance (several times slower on big data).
285  */
286 void
287 gras_datadesc_cycle_set(gras_datadesc_type_t ddt) {
288   ddt->cycle = 1;
289 }
290 /**
291  * gras_datadesc_cycle_unset:
292  * 
293  * Tell GRAS that the pointers of the type described by @ddt do not present
294  * any loop and that cycle detection mecanism are not needed.
295  * (default)
296  */
297 void
298 gras_datadesc_cycle_unset(gras_datadesc_type_t ddt) {
299   ddt->cycle = 0;
300 }
301
302 /**
303  * gras_datadesc_union:
304  *
305  * Create a new union and give a pointer to it 
306  */
307 gras_datadesc_type_t 
308 gras_datadesc_union(const char                   *name,
309                     gras_datadesc_type_cb_int_t   selector) {
310
311   gras_datadesc_type_t res;
312   int arch;
313
314   XBT_IN1("(%s)",name);
315   xbt_assert0(selector,
316                "Attempt to creat an union without field_count function");
317
318   res = gras_datadesc_by_name(name);
319   if (res) {
320     /* FIXME: Check that field redefinition matches */
321     xbt_assert1(res->category_code == e_gras_datadesc_type_cat_union,
322                  "Redefinition of type %s does not match", name);
323     xbt_assert1(res->category.union_data.selector == selector,
324                  "Redefinition of type %s does not match", name);
325     VERB1("Discarding redefinition of %s",name);
326     return res;
327   }
328
329   res = gras_ddt_new(name);
330
331   for (arch=0; arch<gras_arch_count; arch ++) {
332      res->size[arch] = 0;
333      res->alignment[arch] = 0;
334      res->aligned_size[arch] = 0;
335   }
336
337   res->category_code            = e_gras_datadesc_type_cat_union;
338   res->category.union_data.fields =
339      xbt_dynar_new(sizeof(gras_dd_cat_field_t*),
340                     &gras_dd_cat_field_free);
341   res->category.union_data.selector = selector;
342
343   return res;
344 }
345
346 /**
347  * gras_datadesc_union_append:
348  *
349  * Append a field to the union
350  */
351 void
352 gras_datadesc_union_append(gras_datadesc_type_t  union_type,
353                            const char           *name,
354                            gras_datadesc_type_t  field_type) {
355
356   gras_dd_cat_field_t field;
357   int arch;
358
359   XBT_IN3("(%s %s.%s;)",field_type->name,union_type->name,name);
360   xbt_assert1(field_type->size != 0,
361                "Cannot add a dynamically sized field in union %s",
362                union_type->name);
363
364   if (union_type->category.union_data.closed) {
365     VERB1("Ignoring request to add field to union %s (closed)",
366            union_type->name);
367     return;
368   }
369     
370   field=xbt_new0(s_gras_dd_cat_field_t,1);
371
372   field->name   = (char*)strdup(name);
373   field->type   = field_type;
374   /* All offset are left to 0 in an union */
375   
376   xbt_dynar_push(union_type->category.union_data.fields, &field);
377
378   for (arch=0; arch<gras_arch_count; arch ++) {
379     union_type->size[arch] = max(union_type->size[arch],
380                                  field_type->size[arch]);
381     union_type->alignment[arch] = max(union_type->alignment[arch],
382                                       field_type->alignment[arch]);
383     union_type->aligned_size[arch] = aligned(union_type->size[arch],
384                                              union_type->alignment[arch]);
385   }
386 }
387
388 void
389 gras_datadesc_union_close(gras_datadesc_type_t union_type) {
390    union_type->category.union_data.closed = 1;
391 }
392 /**
393  * gras_datadesc_ref:
394  *
395  * Create a new ref to a fixed type and give a pointer to it 
396  */
397 gras_datadesc_type_t 
398   gras_datadesc_ref(const char           *name,
399                     gras_datadesc_type_t  referenced_type) {
400
401   gras_datadesc_type_t res;
402   gras_datadesc_type_t pointer_type = gras_datadesc_by_name("data pointer");
403   int arch;
404
405   XBT_IN1("(%s)",name);
406   res = gras_datadesc_by_name(name);
407   if (res) {
408     xbt_assert1(res->category_code == e_gras_datadesc_type_cat_ref,
409                  "Redefinition of %s does not match",name);
410     xbt_assert1(res->category.ref_data.type == referenced_type,
411                  "Redefinition of %s does not match",name);
412     xbt_assert1(res->category.ref_data.selector == NULL,
413                  "Redefinition of %s does not match",name);
414     VERB1("Discarding redefinition of %s",name);
415     return res;
416   }
417
418   res = gras_ddt_new(name);
419
420   xbt_assert0(pointer_type, "Cannot get the description of data pointer");
421       
422   for (arch=0; arch<gras_arch_count; arch ++){
423     res->size[arch] = pointer_type->size[arch];
424     res->alignment[arch] = pointer_type->alignment[arch];
425     res->aligned_size[arch] = pointer_type->aligned_size[arch];
426   }
427   
428   res->category_code              = e_gras_datadesc_type_cat_ref;
429   res->category.ref_data.type     = referenced_type;
430   res->category.ref_data.selector = NULL;
431
432   return res;
433 }
434 /**
435  * gras_datadesc_ref_generic:
436  *
437  * Create a new ref to a type given at use time, and give a pointer to it 
438  */
439 gras_datadesc_type_t 
440   gras_datadesc_ref_generic(const char                *name,
441                             gras_datadesc_selector_t   selector) {
442
443   gras_datadesc_type_t res;
444   gras_datadesc_type_t pointer_type = gras_datadesc_by_name("data pointer");
445   int arch;
446
447   XBT_IN1("(%s)",name);
448   res = gras_datadesc_by_name(name);
449   if (res) {
450     xbt_assert1(res->category_code == e_gras_datadesc_type_cat_ref,
451                  "Redefinition of type %s does not match", name);
452     xbt_assert1(res->category.ref_data.type == NULL,
453                  "Redefinition of type %s does not match", name);
454     xbt_assert1(res->category.ref_data.selector == selector,
455                  "Redefinition of type %s does not match", name);
456     VERB1("Discarding redefinition of %s",name);
457     return res;
458   }
459   res = gras_ddt_new(name);
460
461   xbt_assert0(pointer_type, "Cannot get the description of data pointer");
462       
463   for (arch=0; arch<gras_arch_count; arch ++) {
464     res->size[arch] = pointer_type->size[arch];
465     res->alignment[arch] = pointer_type->alignment[arch];
466     res->aligned_size[arch] = pointer_type->aligned_size[arch];
467   }
468
469   res->category_code            = e_gras_datadesc_type_cat_ref;
470
471   res->category.ref_data.type     = NULL;
472   res->category.ref_data.selector = selector;
473
474   return res;
475 }
476
477 /**
478  * gras_datadesc_array_fixed:
479  *
480  * Create a new array and give a pointer to it 
481  */
482 gras_datadesc_type_t 
483   gras_datadesc_array_fixed(const char           *name,
484                             gras_datadesc_type_t  element_type,
485                             long int              fixed_size) {
486
487   gras_datadesc_type_t res;
488   int arch;
489
490   XBT_IN1("(%s)",name);
491   res = gras_datadesc_by_name(name);
492   if (res) {
493     xbt_assert1(res->category_code == e_gras_datadesc_type_cat_array,
494                  "Redefinition of type %s does not match", name);
495     xbt_assert1(res->category.array_data.type == element_type,
496                  "Redefinition of type %s does not match", name);
497     xbt_assert1(res->category.array_data.fixed_size == fixed_size,
498                  "Redefinition of type %s does not match", name);
499     xbt_assert1(res->category.array_data.dynamic_size == NULL,
500                  "Redefinition of type %s does not match", name);
501     VERB1("Discarding redefinition of %s",name);
502
503     return res;
504   }
505   res = gras_ddt_new(name);
506
507   xbt_assert1(fixed_size > 0, "'%s' is a array of null fixed size",name);
508   for (arch=0; arch<gras_arch_count; arch ++) {
509     res->size[arch] = fixed_size * element_type->aligned_size[arch];
510     res->alignment[arch] = element_type->alignment[arch];
511     res->aligned_size[arch] = res->size[arch];
512   }  
513
514   res->category_code            = e_gras_datadesc_type_cat_array;
515
516   res->category.array_data.type         = element_type;
517   res->category.array_data.fixed_size   = fixed_size;
518   res->category.array_data.dynamic_size = NULL;
519
520   return res;
521 }
522 /**
523  * gras_datadesc_array_dyn:
524  *
525  * Create a new array and give a pointer to it 
526  */
527 gras_datadesc_type_t 
528   gras_datadesc_array_dyn(const char                  *name,
529                           gras_datadesc_type_t         element_type,
530                           gras_datadesc_type_cb_int_t  dynamic_size) {
531
532   gras_datadesc_type_t res;
533   int arch;
534
535   XBT_IN1("(%s)",name);
536   xbt_assert1(dynamic_size,
537                "'%s' is a dynamic array without size discriminant",
538                name);
539
540   res = gras_datadesc_by_name(name);
541   if (res) {
542     xbt_assert1(res->category_code == e_gras_datadesc_type_cat_array,
543                  "Redefinition of type %s does not match", name);
544     xbt_assert1(res->category.array_data.type == element_type,
545                  "Redefinition of type %s does not match", name);
546     xbt_assert1(res->category.array_data.fixed_size == 0,
547                  "Redefinition of type %s does not match", name);
548     xbt_assert1(res->category.array_data.dynamic_size == dynamic_size,
549                  "Redefinition of type %s does not match", name);
550     VERB1("Discarding redefinition of %s",name);
551
552     return res;
553   }
554
555   res = gras_ddt_new(name);
556
557   for (arch=0; arch<gras_arch_count; arch ++) {
558     res->size[arch] = 0; /* make sure it indicates "dynamic" */
559     res->alignment[arch] = element_type->alignment[arch];
560     res->aligned_size[arch] = 0; /*FIXME: That was so in GS, but looks stupid*/
561   }
562
563   res->category_code            = e_gras_datadesc_type_cat_array;
564
565   res->category.array_data.type         = element_type;
566   res->category.array_data.fixed_size   = 0;
567   res->category.array_data.dynamic_size = dynamic_size;
568
569   return res;
570 }
571
572 /**
573  * gras_datadesc_ref_pop_arr:
574  *
575  * Most of the time, you want to include a reference in your structure which
576  * is a pointer to a dynamic array whose size is fixed by another field of 
577  * your structure.
578  *
579  * This case pops up so often that this function was created to take care of
580  * this case. It creates a dynamic array type whose size is poped from the 
581  * current cbps, and then create a reference to it.
582  *
583  * The name of the created datatype will be the name of the element type, with
584  * '[]*' appended to it.
585  *
586  * Then to use it, you just have to make sure that your structure pre-callback
587  * does push the size of the array in the cbps (using #gras_cbps_i_push), and 
588  * you are set. 
589  *
590  * But be remember that this is a stack. If you have two different pop_arr, you
591  * should push the second one first, so that the first one is on the top of the 
592  * list when the first field gets transfered.
593  *
594  */
595 gras_datadesc_type_t 
596   gras_datadesc_ref_pop_arr(gras_datadesc_type_t element_type) {
597
598   gras_datadesc_type_t res;
599   char *name=(char*)xbt_malloc(strlen(element_type->name) + 4);
600
601   sprintf(name,"%s[]",element_type->name);
602
603   res = gras_datadesc_array_dyn(name,element_type,
604                                 gras_datadesc_cb_pop);
605
606   sprintf(name,"%s[]*",element_type->name);
607   res = gras_datadesc_ref(name,res);
608
609   xbt_free(name);
610
611   return res;
612 }
613 xbt_error_t
614 gras_datadesc_import_nws(const char           *name,
615                          const DataDescriptor *desc,
616                          unsigned long         howmany,
617                /* OUT */ gras_datadesc_type_t *dst) {
618   RAISE_UNIMPLEMENTED;
619 }
620
621 /**
622  * gras_datadesc_cb_send:
623  *
624  * Add a pre-send callback to this datadesc.
625  * (useful to push the sizes of the upcoming arrays, for example)
626  */
627 void gras_datadesc_cb_send (gras_datadesc_type_t          type,
628                             gras_datadesc_type_cb_void_t  send) {
629   type->send = send;
630 }
631 /**
632  * gras_datadesc_cb_recv:
633  *
634  * Add a post-receive callback to this datadesc.
635  * (useful to put the function pointers to the rigth value, for example)
636  */
637 void gras_datadesc_cb_recv(gras_datadesc_type_t          type,
638                            gras_datadesc_type_cb_void_t  recv) {
639   type->recv = recv;
640 }
641 /**
642  * gras_dd_find_field:
643  * 
644  * Returns the type descriptor of the given field. Abort on error.
645  */
646 static gras_datadesc_type_t 
647   gras_dd_find_field(gras_datadesc_type_t  type,
648                      const char           *field_name) {
649    xbt_dynar_t         field_array;
650    
651    gras_dd_cat_field_t  field=NULL;
652    int                  field_num;
653    
654    if (type->category_code == e_gras_datadesc_type_cat_union) {
655       field_array = type->category.union_data.fields;
656    } else if (type->category_code == e_gras_datadesc_type_cat_struct) {
657       field_array = type->category.struct_data.fields;
658    } else {
659       ERROR2("%s (%p) is not a struct nor an union. There is no field.", type->name,(void*)type);
660       xbt_abort();
661    }
662    xbt_dynar_foreach(field_array,field_num,field) {
663       if (!strcmp(field_name,field->name)) {
664          return field->type;
665       }
666    }
667    ERROR2("No field nammed %s in %s",field_name,type->name);
668    xbt_abort();
669
670 }
671                                   
672 /**
673  * gras_datadesc_cb_field_send:
674  *
675  * Add a pre-send callback to the given field of the datadesc (which must be a struct or union).
676  * (useful to push the sizes of the upcoming arrays, for example)
677  */
678 void gras_datadesc_cb_field_send (gras_datadesc_type_t          type,
679                                   const char                   *field_name,
680                                   gras_datadesc_type_cb_void_t  send) {
681    
682    gras_datadesc_type_t sub_type=gras_dd_find_field(type,field_name);   
683    sub_type->send = send;
684 }
685
686 /**
687  * gras_datadesc_cb_field_push:
688  *
689  * Add a pre-send callback to the given field resulting in its value to be pushed to
690  * the stack of sizes. It must be a int, unsigned int, long int or unsigned long int.
691  */
692 void gras_datadesc_cb_field_push (gras_datadesc_type_t  type,
693                                   const char           *field_name) {
694    
695    gras_datadesc_type_t sub_type=gras_dd_find_field(type,field_name);
696    if (!strcmp("int",sub_type->name)) {
697       sub_type->send = gras_datadesc_cb_push_int;
698    } else if (!strcmp("unsigned int",sub_type->name)) {
699       sub_type->send = gras_datadesc_cb_push_uint;
700    } else if (!strcmp("long int",sub_type->name)) {
701       sub_type->send = gras_datadesc_cb_push_lint;
702    } else if (!strcmp("unsigned long int",sub_type->name)) {
703       sub_type->send = gras_datadesc_cb_push_ulint;
704    } else {
705       ERROR1("Field %s is not an int, unsigned int, long int neither unsigned long int",
706              sub_type->name);
707       xbt_abort();
708    }
709 }
710 /**
711  * gras_datadesc_cb_field_recv:
712  *
713  * Add a post-receive callback to the given field of the datadesc (which must be a struct or union).
714  * (useful to put the function pointers to the right value, for example)
715  */
716 void gras_datadesc_cb_field_recv(gras_datadesc_type_t          type,
717                                  const char                   *field_name,
718                                  gras_datadesc_type_cb_void_t  recv) {
719    
720    gras_datadesc_type_t sub_type=gras_dd_find_field(type,field_name);   
721    sub_type->recv = recv;
722 }
723
724 /**
725  * gras_datadesc_free:
726  *
727  * Free a datadesc. Should only be called at xbt_exit. 
728  */
729 void gras_datadesc_free(gras_datadesc_type_t *type) {
730
731   DEBUG1("Let's free ddt %s",(*type)->name);
732   
733   switch ((*type)->category_code) {
734   case e_gras_datadesc_type_cat_scalar:
735   case e_gras_datadesc_type_cat_ref:
736   case e_gras_datadesc_type_cat_array:
737     /* nothing to free in there */
738     break;
739     
740   case e_gras_datadesc_type_cat_ignored:
741     if ((*type)->category.ignored_data.free_func) {
742       (*type)->category.ignored_data.free_func
743         ((*type)->category.ignored_data.default_value);
744     }
745     break;
746     
747   case e_gras_datadesc_type_cat_struct:
748     xbt_dynar_free(&( (*type)->category.struct_data.fields ));
749     break;
750     
751   case e_gras_datadesc_type_cat_union:
752     xbt_dynar_free(&( (*type)->category.union_data.fields ));
753     break;
754     
755   default:
756     /* datadesc was invalid. Killing it is like euthanasy, I guess */
757     break;
758   }
759   xbt_free((*type)->name);
760   xbt_free(*type);
761   type=NULL;
762 }