next up previous contents
Next: Synchrony Up: Basics Previous: dicerc file   Contents


Types

A type in DICElib is a variable type. To share variables between computers, DICElib has to store them internally in such a way that it may be sent to the other nodes.

Types are registed automatically when you start your program. Once registered, a type will exist until DICElib is closed. Types consume a very small amount of memory, and you may register as many as you like. Note that types are case sensitive.

If you want to define a new type, you must write three functions:

char *foo_pack (void *data, int *n);

void *foo_unpack (char *data, int *n);

void foo_free (void *data); 

if any of the three is not available, the type won't be registered.

Now, what do these functions do?

You can access these three functions indirectly, using respectively:

char *DICE_type_pack ( char *type, void *data, int *n ); 

void *DICE_type_unpack ( char *type, char *packet, int *n );

int DICE_type_free ( char *type, void *data ); 

They are work exactly like the above description, but receive the type as an extra argument.

DICElib provides some default types2.1. All of them receive pointers to the data, so pass by reference:

Last, but not least, in order for DICElib to find your new types automatically, you must define the DICE_MyTypes variable:

DICE_Type DICE_MyTypes[] = { 
{ "foo type", foo_pack, foo_unpack, foo_free }, 

{ NULL, NULL, NULL, NULL } 

};
It's a simple array of structures, and each structure should get (in this order): the type name, the pack functions, the unpack function, and the free function. Important: the last element of the array must be { NULL, NULL, NULL, NULL }.

If you don't create any new types, you have to add this line to your code, declaring it as you would declare a global variable:

DICE_no_types;
Since I'm sure you are completely lost, it's time for an example. Suppose your application works with 3D floating points vectors, like:

float vec[3];
and you want to share this type. You may consider it as 3 floats, etc, but it's easier to work it as a whole thing. So, here are the three functions:

char *float3_pack ( void *data, int *n ) { 
char   *buf, *t; 

float   *vec; 

int   m; 

/* reconvert the data to float, so we can work with it */

vec = (float *)data; 

/* allocate memory for the packet *//

buf = (char *)malloc(3*4); 

if ( !buf ) 

return NULL;  

/* now pack it using DICElib's floats */

t = DICE_type_pack("float", (void *)&vec[0], &m); 

memcpy(buf, t, 4); 

free(t); 

t = DICE_type_pack("float", (void *)&vec[1], &m); 

memcpy(buf+4, t, 4); 

free(t); 

t = DICE_type_pack("float", (void *)&vec[2], &m); 

memcpy(buf+8, t, 4); 

free(t); 

*n = 12; 

return buf; 

}  

void *float3_unpack ( char *data, int *n ) { 

float   *vec, *f; 

int   m;  

/* malloc memory for the float */

vec = (float *)malloc(3*sizeof(float)); 

/* three floats */ 

if ( !vec ) 

return NULL; 
f = (float *)DICE_type_unpack("float", data, &m); 

vec[0] = *f; 

free(f); 

f = (float *)DICE_type_unpack("float", data+4, &m); 

vec[1] = *f; free(f); 

f = (float *)DICE_type_unpack("float", data+8, &m); 

vec[2] = *f; 

free(f); 

*n = 12; 

return (void *)vec; 


void float3_free  ( void *data ) { 

if ( data ) free(data); 
}

DICE_Type DICE_MyTypes[] = { 

{ "float3", float3_pack, float3_unpack, float3_free }, 

{ NULL, NULL, NULL, NULL } 

};

The new type name is float3. The pack and unpack functions use the existing float type to send it. This is a simple example, and it supposes that the float type is 4 bytes long, etc.

Take a look at the tests/ subdirectory, in special the var_test and rotate programs, for more examples.

Declaration of variables is dealt in the next chapters. Take notice that, while it's practical to setup arrays as a type, the entire array is transferred even if just one variable is changed, so it might not be the wisest solution.


next up previous contents
Next: Synchrony Up: Basics Previous: dicerc file   Contents
2001-12-09