Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Take the gras.h from the current dir, not the installed one
[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 /* Authors: Olivier Aumage, Martin Quinson                                  */
6 /* Copyright (C) 2003, 2004 the GRAS posse.                                 */
7
8 /* This program is free software; you can redistribute it and/or modify it
9    under the terms of the license (GNU LGPL) which comes with this package. */
10
11 #include "DataDesc/datadesc_private.h"
12
13 GRAS_LOG_NEW_DEFAULT_SUBCATEGORY(create,datadesc);
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_unref(type);
25   }
26 }
27
28 static gras_error_t
29 gras_ddt_new(const char            *name,
30              gras_datadesc_type_t **dst) {
31
32   gras_error_t errcode;
33   gras_datadesc_type_t *res;
34
35   res=malloc(sizeof(gras_datadesc_type_t));
36   if (!res) 
37     RAISE_MALLOC;
38
39   memset(res, 0, sizeof(gras_datadesc_type_t));
40   res->name = strdup(name);
41   res->name_len = strlen(name);
42   res->refcounter = 1;
43   
44   TRY(gras_set_add(gras_datadesc_set_local,
45                    (gras_set_elm_t*)res,&gras_ddt_freev));
46     
47   *dst=res;
48   return no_error;
49 }
50
51 /**
52  * gras_datadesc_by_name:
53  *
54  * Retrieve a type from its name
55  */
56 gras_datadesc_type_t *gras_datadesc_by_name(const char *name) {
57
58   gras_datadesc_type_t *type;
59
60   if (gras_set_get_by_name(gras_datadesc_set_local,
61                            name,(gras_set_elm_t**)&type) == no_error) {
62     return type;
63   } else { 
64     return NULL;
65   }
66 }
67
68 /**
69  * gras_datadesc_by_id:
70  *
71  * Retrieve a type from its code
72  */
73 gras_error_t gras_datadesc_by_id(long int               code,
74                                  gras_datadesc_type_t **type) {
75   return gras_set_get_by_id(gras_datadesc_set_local,
76                             code,(gras_set_elm_t**)type);
77 }
78
79 /**
80  * gras_datadesc_declare_scalar:
81  *
82  * Create a new scalar and give a pointer to it 
83  */
84 gras_error_t 
85 gras_datadesc_declare_scalar(const char                      *name,
86                         gras_ddt_scalar_type_t           type,
87                         enum e_gras_dd_scalar_encoding   encoding,
88                         gras_datadesc_type_cb_void_t     cb,
89                         gras_datadesc_type_t           **dst) {
90
91   gras_error_t errcode;
92   gras_datadesc_type_t *res;
93   long int arch;
94
95   TRY(gras_ddt_new(name,dst));
96   res=*dst;
97
98   for (arch = 0; arch < gras_arch_count; arch ++) {
99     long int sz;
100     long int mask;
101     res->size[arch] = gras_arches[arch].sizeof_scalars[type];
102
103     sz = res->size[arch];
104     mask = sz;
105     
106     /* just in case you wonder, x>>1 == x/2 on all architectures when x>=0
107        and a size is always>=0 */
108     
109     /* make sure mask have all the bits under the biggest one of size set to 1
110        Example: size=000100101 => mask=0000111111 */
111     while ((sz >>= 1)) {
112       mask |= sz;
113     } 
114     
115     if (res->size[arch] & (mask >> 1)) { /* if size have bits to one beside its biggest */
116       /* size is not a power of 2 */
117       /* alignment= next power of 2 after size */
118       res->alignment[arch] = (res->size[arch] & ~(mask >> 1)) << 1;
119       gras_assert0(res->alignment[arch] != 0,
120                    "scalar type too large");
121       
122       res->aligned_size[arch] = aligned(res->size[arch], res->alignment[arch]);
123       gras_assert0 (res->aligned_size[arch] >= 0,
124                     "scalar type too large");
125       
126     } else {
127       /* size is a power of 2, life is great */
128       res->alignment[arch]       = res->size[arch];
129       res->aligned_size[arch]    = res->size[arch];
130     }
131   }
132
133   res->category_code                 = e_gras_datadesc_type_cat_scalar;
134   res->category.scalar_data.encoding = encoding;
135
136   res->pre = cb;
137   return no_error;
138 }
139
140
141 /**
142  * gras_dd_cat_field_free:
143  *
144  * Frees one struct or union field
145  */
146 void gras_dd_cat_field_free(void *f) {
147   gras_dd_cat_field_t *field = *(gras_dd_cat_field_t **)f;
148   if (field) {
149     if (field->name) 
150       free(field->name);
151     free(field);
152   }
153 }
154
155 /**
156  * gras_datadesc_declare_struct:
157  *
158  * Create a new struct and give a pointer to it 
159  */
160 gras_error_t 
161 gras_datadesc_declare_struct(const char                      *name,
162                         gras_datadesc_type_t           **dst) {
163
164   gras_error_t errcode;
165   gras_datadesc_type_t *res;
166   long int arch;
167
168   TRY(gras_ddt_new(name,dst));
169   res=*dst;
170
171   for (arch=0; arch<gras_arch_count; arch ++) {
172     res->size[arch] = 0;
173     res->alignment[arch] = 0;
174     res->aligned_size[arch] = 0;
175   }
176   res->category_code = e_gras_datadesc_type_cat_struct;
177   TRY(gras_dynar_new(&(res->category.struct_data.fields),
178                      sizeof(gras_dd_cat_field_t*),
179                      &gras_dd_cat_field_free));
180
181   return no_error;
182 }
183
184 /**
185  * gras_datadesc_declare_struct_append:
186  *
187  * Append a field to the struct
188  */
189 gras_error_t 
190 gras_datadesc_declare_struct_append(gras_datadesc_type_t  *struct_type,
191                                     const char            *name,
192                                     gras_datadesc_type_t  *field_type) {
193
194   gras_error_t errcode;
195   gras_dd_cat_field_t *field;
196   int arch;
197  
198   gras_assert1(!struct_type->category.struct_data.closed,
199                "Cannot add anything to the already closed struct %s",
200                struct_type->name);
201   gras_assert1(field_type->size >= 0,
202                "Cannot add a dynamically sized field in structure %s",
203                struct_type->name);
204     
205   field=malloc(sizeof(gras_dd_cat_field_t));
206   if (!field)
207     RAISE_MALLOC;
208
209   field->name   = strdup(name);
210
211   DEBUG0("----------------");
212   DEBUG4("PRE s={size=%ld,align=%ld,asize=%ld} struct_boundary=%d",
213          struct_type->size[GRAS_THISARCH], 
214          struct_type->alignment[GRAS_THISARCH], 
215          struct_type->aligned_size[GRAS_THISARCH],
216          gras_arches[GRAS_THISARCH].struct_boundary);
217      
218      
219   for (arch=0; arch<gras_arch_count; arch ++) {
220     field->offset[arch] = aligned(struct_type->size[arch],
221                                   min(field_type->alignment[arch],
222                                       gras_arches[arch].struct_boundary));
223
224     struct_type->size[arch] = field->offset[arch] + field_type->size[arch];
225     struct_type->alignment[arch] = max(struct_type->alignment[arch],
226                                        field_type->alignment[arch]);
227     struct_type->aligned_size[arch] = aligned(struct_type->size[arch],
228                                               struct_type->alignment[arch]);
229   }
230   field->code   = field_type->code;
231   field->pre    = NULL;
232   field->post   = NULL;
233   
234   TRY(gras_dynar_push(struct_type->category.struct_data.fields, &field));
235
236   DEBUG3("Push a %s into %s at offset %ld.",
237          field_type->name, struct_type->name,field->offset[GRAS_THISARCH]);
238   DEBUG3("  f={size=%ld,align=%ld,asize=%ld}",
239          field_type->size[GRAS_THISARCH], 
240          field_type->alignment[GRAS_THISARCH], 
241          field_type->aligned_size[GRAS_THISARCH]);
242   DEBUG3("  s={size=%ld,align=%ld,asize=%ld}",
243          struct_type->size[GRAS_THISARCH], 
244          struct_type->alignment[GRAS_THISARCH], 
245          struct_type->aligned_size[GRAS_THISARCH]);
246   return no_error;
247 }
248 void
249 gras_datadesc_declare_struct_close(gras_datadesc_type_t  *struct_type) {
250    struct_type->category.struct_data.closed = 1;
251    //   INFO0("FIXME: Do something in gras_datadesc_declare_struct_close");
252 }
253
254 /**
255  * gras_datadesc_declare_union:
256  *
257  * Create a new union and give a pointer to it 
258  */
259 gras_error_t 
260 gras_datadesc_declare_union(const char                   *name,
261                             gras_datadesc_type_cb_int_t   selector,
262                             gras_datadesc_type_t        **dst) {
263
264   gras_error_t errcode;
265   gras_datadesc_type_t *res;
266   int arch;
267
268   gras_assert0(selector,
269                "Attempt to creat an union without field_count function");
270
271   TRY(gras_ddt_new(name,dst));
272   res=*dst;
273
274   for (arch=0; arch<gras_arch_count; arch ++) {
275      res->size[arch] = 0;
276      res->alignment[arch] = 0;
277      res->aligned_size[arch] = 0;
278   }
279
280   res->category_code            = e_gras_datadesc_type_cat_union;
281   TRY(gras_dynar_new(&(res->category.union_data.fields),
282                      sizeof(gras_dd_cat_field_t*),
283                      &gras_dd_cat_field_free));
284   res->category.union_data.selector = selector;
285
286   return no_error;
287 }
288
289 /**
290  * gras_datadesc_declare_union_append:
291  *
292  * Append a field to the union
293  */
294 gras_error_t 
295 gras_datadesc_declare_union_append(gras_datadesc_type_t  *union_type,
296                                    const char            *name,
297                                    gras_datadesc_type_t  *field_type) {
298
299   gras_error_t errcode;
300   gras_dd_cat_field_t *field;
301   int arch;
302
303   gras_assert1(!union_type->category.union_data.closed,
304                "Cannot add anything to the already closed union %s",
305                union_type->name);
306   gras_assert1(field_type->size >= 0,
307                "Cannot add a dynamically sized field in union %s",
308                union_type->name);
309     
310   field=malloc(sizeof(gras_dd_cat_field_t));
311   if (!field)
312     RAISE_MALLOC;
313
314   field->name   = strdup(name);
315   for (arch=0; arch<gras_arch_count; arch ++) {
316     field->offset[arch] = 0; /* that's the purpose of union ;) */
317   }
318   field->code   = field_type->code;
319   field->pre    = NULL;
320   field->post   = NULL;
321   
322   TRY(gras_dynar_push(union_type->category.union_data.fields, &field));
323
324   for (arch=0; arch<gras_arch_count; arch ++) {
325     union_type->size[arch] = max(union_type->size[arch],
326                                  field_type->size[arch]);
327     union_type->alignment[arch] = max(union_type->alignment[arch],
328                                       field_type->alignment[arch]);
329     union_type->aligned_size[arch] = aligned(union_type->size[arch],
330                                              union_type->alignment[arch]);
331   }
332   return no_error;
333 }
334
335 void
336 gras_datadesc_declare_union_close(gras_datadesc_type_t  *union_type) {
337    union_type->category.union_data.closed = 1;
338    //   INFO0("FIXME: Do something in gras_datadesc_declare_union_close");
339 }
340 /**
341  * gras_datadesc_declare_ref:
342  *
343  * Create a new ref to a fixed type and give a pointer to it 
344  */
345 gras_error_t 
346 gras_datadesc_declare_ref(const char             *name,
347                           gras_datadesc_type_t   *referenced_type,
348                           gras_datadesc_type_t  **dst) {
349
350   gras_error_t errcode;
351   gras_datadesc_type_t *res;
352   gras_datadesc_type_t *pointer_type = gras_datadesc_by_name("data pointer");
353   int arch;
354
355   TRY(gras_ddt_new(name,dst));
356   res=*dst;
357
358   gras_assert0(pointer_type, "Cannot get the description of data pointer");
359       
360   for (arch=0; arch<gras_arch_count; arch ++){
361     res->size[arch] = pointer_type->size[arch];
362     res->alignment[arch] = pointer_type->alignment[arch];
363     res->aligned_size[arch] = pointer_type->aligned_size[arch];
364   }
365
366   res->category_code            = e_gras_datadesc_type_cat_ref;
367
368   res->category.ref_data.code     = referenced_type->code;
369   res->category.ref_data.selector = NULL;
370
371   return no_error;
372 }
373 /**
374  * gras_datadesc_declare_ref_generic:
375  *
376  * Create a new ref to a type given at use time, and give a pointer to it 
377  */
378 gras_error_t 
379 gras_datadesc_declare_ref_generic(const char                      *name,
380                          gras_datadesc_type_cb_int_t      selector,
381                          gras_datadesc_type_t           **dst) {
382
383   gras_error_t errcode;
384   gras_datadesc_type_t *res;
385   gras_datadesc_type_t *pointer_type = gras_datadesc_by_name("data pointer");
386   int arch;
387
388   TRY(gras_ddt_new(name,dst));
389   res=*dst;
390
391   gras_assert0(pointer_type, "Cannot get the description of data pointer");
392       
393   for (arch=0; arch<gras_arch_count; arch ++) {
394     res->size[arch] = pointer_type->size[arch];
395     res->alignment[arch] = pointer_type->alignment[arch];
396     res->aligned_size[arch] = pointer_type->aligned_size[arch];
397   }
398
399   res->category_code            = e_gras_datadesc_type_cat_ref;
400
401   res->category.ref_data.code     = -1;
402   res->category.ref_data.selector = selector;
403
404   return no_error;
405 }
406
407 /**
408  * gras_datadesc_declare_array_fixed:
409  *
410  * Create a new array and give a pointer to it 
411  */
412 gras_error_t 
413 gras_datadesc_declare_array_fixed(const char              *name,
414                                   gras_datadesc_type_t    *element_type,
415                                   long int                 fixed_size,
416                                   gras_datadesc_type_t   **dst) {
417
418   gras_error_t errcode;
419   gras_datadesc_type_t *res;
420   int arch;
421
422   TRY(gras_ddt_new(name,dst));
423   res=*dst;
424
425   gras_assert1(fixed_size > 0, "'%s' is a array of negative fixed size",name);
426   for (arch=0; arch<gras_arch_count; arch ++) {
427     res->size[arch] = fixed_size * element_type->aligned_size[arch];
428     res->alignment[arch] = element_type->alignment[arch];
429     res->aligned_size[arch] = res->size[arch];
430   }  
431
432   res->category_code            = e_gras_datadesc_type_cat_array;
433
434   res->category.array_data.code         = element_type->code;
435   res->category.array_data.fixed_size   = fixed_size;
436   res->category.array_data.dynamic_size = NULL;
437
438   return no_error;
439 }
440 /**
441  * gras_datadesc_declare_array_dyn:
442  *
443  * Create a new array and give a pointer to it 
444  */
445 gras_error_t 
446 gras_datadesc_declare_array_dyn(const char                      *name,
447                        gras_datadesc_type_t            *element_type,
448                        gras_datadesc_type_cb_int_t      dynamic_size,
449                        gras_datadesc_type_t           **dst) {
450
451   gras_error_t errcode;
452   gras_datadesc_type_t *res;
453   int arch;
454
455   gras_assert1(dynamic_size,
456                "'%s' is a dynamic array without size discriminant",
457                name);
458
459   TRY(gras_ddt_new(name,dst));
460   res=*dst;
461
462   for (arch=0; arch<gras_arch_count; arch ++) {
463     res->size[arch] = -1; /* make sure it indicates "dynamic" */
464     res->alignment[arch] = element_type->alignment[arch];
465     res->aligned_size[arch] = -1; /*FIXME: That was so in GS, but looks stupid*/
466   }
467
468   res->category_code            = e_gras_datadesc_type_cat_array;
469
470   res->category.array_data.code         = element_type->code;
471   res->category.array_data.fixed_size   = -1;
472   res->category.array_data.dynamic_size = dynamic_size;
473
474   return no_error;
475 }
476
477 gras_error_t
478 gras_datadesc_import_nws(const char           *name,
479                          const DataDescriptor *desc,
480                          size_t                howmany,
481                          gras_datadesc_type_t **dst) {
482   RAISE_UNIMPLEMENTED;
483 }
484
485 /**
486  * gras_datadesc_cb_set_pre:
487  *
488  * Add a pre-send callback to this datadexc
489  */
490 void gras_datadesc_cb_set_pre (gras_datadesc_type_t         *type,
491                                gras_datadesc_type_cb_void_t  pre) {
492   type->pre = pre;
493 }
494 /**
495  * gras_datadesc_cb_set_post:
496  *
497  * Add a post-send callback to this datadexc
498  */
499 void gras_datadesc_cb_set_post(gras_datadesc_type_t         *type,
500                                gras_datadesc_type_cb_void_t  post) {
501   type->post = post;
502 }
503
504 /**
505  * gras_datadesc_ref:
506  *
507  * Adds a reference to the datastruct. 
508  * ddt will be freed only when the refcount becomes 0.
509  */
510 void gras_datadesc_ref(gras_datadesc_type_t *type) {
511   type->refcounter ++;
512 }
513
514 /**
515  * gras_datadesc_unref:
516  *
517  * Adds a reference to the datastruct. 
518  * ddt will be freed only when the refcount becomes 0.
519  */
520 void gras_datadesc_unref(gras_datadesc_type_t *type) {
521   type->refcounter--;
522   if (!type->refcounter) {
523     /* even the set of ddt released that type. Let's free it */
524     DEBUG1("Let's free ddt %s",type->name);
525
526     free(type->name);
527     switch (type->category_code) {
528     case e_gras_datadesc_type_cat_scalar:
529     case e_gras_datadesc_type_cat_ref:
530     case e_gras_datadesc_type_cat_array:
531       /* nothing to free in there */
532       break;
533
534     case e_gras_datadesc_type_cat_ignored:
535       if (type->category.ignored_data.free_func) {
536         type->category.ignored_data.free_func
537           (type->category.ignored_data.default_value);
538       }
539       break;
540
541     case e_gras_datadesc_type_cat_struct:
542       gras_dynar_free(type->category.struct_data.fields);
543       break;
544
545     case e_gras_datadesc_type_cat_union:
546       gras_dynar_free(type->category.union_data.fields);
547       break;
548       
549     default:
550       /* datadesc was invalid. Killing it is like euthanasy, I guess */
551       break;
552     }
553     free(type);
554   }
555 }