Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
415a05c26019b4671c01596ead00572d13ae6e0f
[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(new,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   for (arch=0; arch<gras_arch_count; arch ++) {
212     field->offset[arch] = aligned(struct_type->size[arch],
213                                   field_type->alignment[arch]);
214   }
215   field->code   = field_type->code;
216   field->pre    = NULL;
217   field->post   = NULL;
218   
219   TRY(gras_dynar_push(struct_type->category.struct_data.fields, &field));
220
221   for (arch=0; arch<gras_arch_count; arch ++) {
222     struct_type->size[arch] = field->offset[arch] + field_type->size[arch];
223     struct_type->alignment[arch] = max(struct_type->alignment[arch],
224                                        field_type->alignment[arch]);
225     struct_type->aligned_size[arch] = aligned(struct_type->size[arch],
226                                               struct_type->alignment[arch]);
227   }
228
229   DEBUG3("Push a %s into %s at offset %d.",
230          field_type->name, struct_type->name,field->offset[GRAS_THISARCH]);
231   DEBUG3("  f={size=%d,align=%d,asize=%d}",
232          field_type->size[GRAS_THISARCH], 
233          field_type->alignment, field_type->aligned_size);
234   DEBUG3("  s={size=%d,align=%d,asize=%d}",
235          struct_type->size[GRAS_THISARCH], 
236          struct_type->alignment, struct_type->aligned_size);
237   return no_error;
238 }
239 void
240 gras_datadesc_declare_struct_close(gras_datadesc_type_t  *struct_type) {
241    struct_type->category.struct_data.closed = 1;
242    INFO0("FIXME: Do something in gras_datadesc_declare_struct_close");
243 }
244
245 /**
246  * gras_datadesc_declare_union:
247  *
248  * Create a new union and give a pointer to it 
249  */
250 gras_error_t 
251 gras_datadesc_declare_union(const char                      *name,
252                    gras_datadesc_type_cb_int_t      selector,
253                    gras_datadesc_type_t           **dst) {
254
255   gras_error_t errcode;
256   gras_datadesc_type_t *res;
257   int arch;
258
259   gras_assert0(selector,
260                "Attempt to creat an union without field_count function");
261
262   TRY(gras_ddt_new(name,dst));
263   res=*dst;
264
265   for (arch=0; arch<gras_arch_count; arch ++) {
266      res->size[arch] = 0;
267      res->alignment[arch] = 0;
268      res->aligned_size[arch] = 0;
269   }
270
271   res->category_code            = e_gras_datadesc_type_cat_union;
272   TRY(gras_dynar_new(&(res->category.union_data.fields),
273                      sizeof(gras_dd_cat_field_t*),
274                      &gras_dd_cat_field_free));
275   res->category.union_data.selector = selector;
276
277   return no_error;
278 }
279
280 /**
281  * gras_datadesc_declare_union_append:
282  *
283  * Append a field to the union
284  */
285 gras_error_t 
286 gras_datadesc_declare_union_append(gras_datadesc_type_t  *union_type,
287                                    const char            *name,
288                                    gras_datadesc_type_t  *field_type) {
289
290   gras_error_t errcode;
291   gras_dd_cat_field_t *field;
292   int arch;
293
294   gras_assert1(!union_type->category.union_data.closed,
295                "Cannot add anything to the already closed union %s",
296                union_type->name);
297   gras_assert1(field_type->size >= 0,
298                "Cannot add a dynamically sized field in union %s",
299                union_type->name);
300     
301   field=malloc(sizeof(gras_dd_cat_field_t));
302   if (!field)
303     RAISE_MALLOC;
304
305   field->name   = strdup(name);
306   for (arch=0; arch<gras_arch_count; arch ++) {
307     field->offset[arch] = 0; /* that's the purpose of union ;) */
308   }
309   field->code   = field_type->code;
310   field->pre    = NULL;
311   field->post   = NULL;
312   
313   TRY(gras_dynar_push(union_type->category.union_data.fields, &field));
314
315   for (arch=0; arch<gras_arch_count; arch ++) {
316     union_type->size[arch] = max(union_type->size[arch],
317                                  field_type->size[arch]);
318     union_type->alignment[arch] = max(union_type->alignment[arch],
319                                       field_type->alignment[arch]);
320     union_type->aligned_size[arch] = aligned(union_type->size[arch],
321                                              union_type->alignment[arch]);
322   }
323   return no_error;
324 }
325
326 void
327 gras_datadesc_declare_union_close(gras_datadesc_type_t  *union_type) {
328    union_type->category.union_data.closed = 1;
329    INFO0("FIXME: Do something in gras_datadesc_declare_array_close");
330 }
331 /**
332  * gras_datadesc_declare_ref:
333  *
334  * Create a new ref to a fixed type and give a pointer to it 
335  */
336 gras_error_t 
337 gras_datadesc_declare_ref(const char             *name,
338                           gras_datadesc_type_t   *referenced_type,
339                           gras_datadesc_type_t  **dst) {
340
341   gras_error_t errcode;
342   gras_datadesc_type_t *res;
343   gras_datadesc_type_t *pointer_type = gras_datadesc_by_name("data pointer");
344   int arch;
345
346   TRY(gras_ddt_new(name,dst));
347   res=*dst;
348
349   gras_assert0(pointer_type, "Cannot get the description of data pointer");
350       
351   for (arch=0; arch<gras_arch_count; arch ++){
352     res->size[arch] = pointer_type->size[arch];
353     res->alignment[arch] = pointer_type->alignment[arch];
354     res->aligned_size[arch] = pointer_type->aligned_size[arch];
355   }
356
357   res->category_code            = e_gras_datadesc_type_cat_ref;
358
359   res->category.ref_data.code     = referenced_type->code;
360   res->category.ref_data.selector = NULL;
361
362   return no_error;
363 }
364 /**
365  * gras_datadesc_declare_ref_generic:
366  *
367  * Create a new ref to a type given at use time, and give a pointer to it 
368  */
369 gras_error_t 
370 gras_datadesc_declare_ref_generic(const char                      *name,
371                          gras_datadesc_type_cb_int_t      selector,
372                          gras_datadesc_type_t           **dst) {
373
374   gras_error_t errcode;
375   gras_datadesc_type_t *res;
376   gras_datadesc_type_t *pointer_type = gras_datadesc_by_name("data pointer");
377   int arch;
378
379   TRY(gras_ddt_new(name,dst));
380   res=*dst;
381
382   gras_assert0(pointer_type, "Cannot get the description of data pointer");
383       
384   for (arch=0; arch<gras_arch_count; arch ++) {
385     res->size[arch] = pointer_type->size[arch];
386     res->alignment[arch] = pointer_type->alignment[arch];
387     res->aligned_size[arch] = pointer_type->aligned_size[arch];
388   }
389
390   res->category_code            = e_gras_datadesc_type_cat_ref;
391
392   res->category.ref_data.code     = -1;
393   res->category.ref_data.selector = selector;
394
395   return no_error;
396 }
397
398 /**
399  * gras_datadesc_declare_array_fixed:
400  *
401  * Create a new array and give a pointer to it 
402  */
403 gras_error_t 
404 gras_datadesc_declare_array_fixed(const char              *name,
405                                   gras_datadesc_type_t    *element_type,
406                                   long int                 fixed_size,
407                                   gras_datadesc_type_t   **dst) {
408
409   gras_error_t errcode;
410   gras_datadesc_type_t *res;
411   int arch;
412
413   TRY(gras_ddt_new(name,dst));
414   res=*dst;
415
416   gras_assert1(fixed_size > 0, "'%s' is a array of negative fixed size",name);
417   for (arch=0; arch<gras_arch_count; arch ++) {
418     res->size[arch] = fixed_size * element_type->aligned_size[arch];
419     res->alignment[arch] = element_type->alignment[arch];
420     res->aligned_size[arch] = res->size[arch];
421   }  
422
423   res->category_code            = e_gras_datadesc_type_cat_array;
424
425   res->category.array_data.code         = element_type->code;
426   res->category.array_data.fixed_size   = fixed_size;
427   res->category.array_data.dynamic_size = NULL;
428
429   return no_error;
430 }
431 /**
432  * gras_datadesc_declare_array_dyn:
433  *
434  * Create a new array and give a pointer to it 
435  */
436 gras_error_t 
437 gras_datadesc_declare_array_dyn(const char                      *name,
438                        gras_datadesc_type_t            *element_type,
439                        gras_datadesc_type_cb_int_t      dynamic_size,
440                        gras_datadesc_type_t           **dst) {
441
442   gras_error_t errcode;
443   gras_datadesc_type_t *res;
444   int arch;
445
446   gras_assert1(dynamic_size,
447                "'%s' is a dynamic array without size discriminant",
448                name);
449
450   TRY(gras_ddt_new(name,dst));
451   res=*dst;
452
453   for (arch=0; arch<gras_arch_count; arch ++) {
454     res->size[arch] = -1; /* make sure it indicates "dynamic" */
455     res->alignment[arch] = element_type->alignment[arch];
456     res->aligned_size[arch] = -1; /*FIXME: That was so in GS, but looks stupid*/
457   }
458
459   res->category_code            = e_gras_datadesc_type_cat_array;
460
461   res->category.array_data.code         = element_type->code;
462   res->category.array_data.fixed_size   = -1;
463   res->category.array_data.dynamic_size = dynamic_size;
464
465   return no_error;
466 }
467
468 gras_error_t
469 gras_datadesc_import_nws(const char           *name,
470                          const DataDescriptor *desc,
471                          size_t                howmany,
472                          gras_datadesc_type_t **dst) {
473   RAISE_UNIMPLEMENTED;
474 }
475
476 /**
477  * gras_datadesc_cb_set_pre:
478  *
479  * Add a pre-send callback to this datadexc
480  */
481 void gras_datadesc_cb_set_pre (gras_datadesc_type_t         *type,
482                                gras_datadesc_type_cb_void_t  pre) {
483   type->pre = pre;
484 }
485 /**
486  * gras_datadesc_cb_set_post:
487  *
488  * Add a post-send callback to this datadexc
489  */
490 void gras_datadesc_cb_set_post(gras_datadesc_type_t         *type,
491                                gras_datadesc_type_cb_void_t  post) {
492   type->post = post;
493 }
494
495 /**
496  * gras_datadesc_ref:
497  *
498  * Adds a reference to the datastruct. 
499  * ddt will be freed only when the refcount becomes 0.
500  */
501 void gras_datadesc_ref(gras_datadesc_type_t *type) {
502   type->refcounter ++;
503 }
504
505 /**
506  * gras_datadesc_unref:
507  *
508  * Adds a reference to the datastruct. 
509  * ddt will be freed only when the refcount becomes 0.
510  */
511 void gras_datadesc_unref(gras_datadesc_type_t *type) {
512   type->refcounter--;
513   if (!type->refcounter) {
514     /* even the set of ddt released that type. Let's free it */
515     DEBUG1("Let's free ddt %s",type->name);
516
517     free(type->name);
518     switch (type->category_code) {
519     case e_gras_datadesc_type_cat_scalar:
520     case e_gras_datadesc_type_cat_ref:
521     case e_gras_datadesc_type_cat_array:
522       /* nothing to free in there */
523       break;
524
525     case e_gras_datadesc_type_cat_ignored:
526       if (type->category.ignored_data.free_func) {
527         type->category.ignored_data.free_func
528           (type->category.ignored_data.default_value);
529       }
530       break;
531
532     case e_gras_datadesc_type_cat_struct:
533       gras_dynar_free(type->category.struct_data.fields);
534       break;
535
536     case e_gras_datadesc_type_cat_union:
537       gras_dynar_free(type->category.union_data.fields);
538       break;
539       
540     default:
541       /* datadesc was invalid. Killing it is like euthanasy, I guess */
542       break;
543     }
544     free(type);
545   }
546 }