[GRASS-dev] storing pointers in CELL_TYPE maps?
Volker Wichmann
wichmann at laserdata.at
Fri Apr 27 07:47:55 EDT 2007
Glynn Clements wrote:
> Volker Wichmann wrote:
>
> > > If the list nodes are of fixed size, it's likely to be better to have
> > > a single array of nodes and uses indices to reference individual
> > > nodes.
> >
> > that's my problem: I don't know the size of the array at compile time,
> > so I have to dynamically allocate memory. My idea was to use the GRASS
> > API to do that, but it seems I have to do this on my own. Or do you know
> > of another way?
>
> For a variable-sized in-memory array, use G_realloc() to enlarge it as
> needed, e.g.:
>
> #define SIZE_INCREMENT 50
> int num_nodes;
> int max_nodes;
> struct node *nodes;
>
> int new_node(void)
> {
> int n = num_nodes++;
>
> if (num_nodes >= max_nodes)
> {
> max_nodes += SIZE_INCREMENT;
> nodes = G_realloc(nodes, max_nodes * sizeof(struct node));
> }
>
> return n;
> }
>
> Bear in mind that G_realloc() may move the base of the array, so if
> you have any pointers to elements, e.g.:
>
> struct node *node = &nodes[node_id];
>
> those pointers cease to be valid after reallocation. Essentially,
> refer to nodes primarily using indices and keep the use of pointers to
> a minimum. In particular, don't store pointers to nodes within nodes.
>
> If you need to be able to free list nodes for re-use, keep a linked
> list of free nodes and allocate from that before extending the arrary,
> e.g.:
>
> struct node {
> int next;
> /* other fields */
> };
>
> #define SIZE_INCREMENT 50
> int max_nodes;
> struct node *nodes;
> int free_list;
>
> int new_node(void)
> {
> int n, i;
>
> if (free_list > 0)
> {
> /* remove & return first node from free list */
> n = free_list;
> free_list = nodes[n].next;
> }
> else
> {
> /* enlarge array */
> n = max_nodes;
> max_nodes += SIZE_INCREMENT;
> nodes = G_realloc(nodes, max_nodes * sizeof(struct node));
>
> /* add unused nodes to free list */
> for (i = n + 1; i < max_nodes - 1; i++)
> nodes[i].next = i + 1;
>
> nodes[max_nodes - 1].next = 0;
>
> free_list = n + 1;
> }
>
> return n;
> }
>
> void free_node(int n)
> {
> nodes[n].next = free_list;
> free_list = n;
> }
>
> This is likely to be significantly more efficient than allocating
> individual list nodes with e.g. G_malloc(). Each malloc()ed block has
> a header and possibly padding, and having a large number of individual
> blocks can affect the time taken by malloc/free.
>
Thanks a lot!!! I will give this a try,
Volker
More information about the grass-dev
mailing list