1 /**
2  * \file
3  * GC aware equivalente of g_ptr_array
4  *
5  * Author:
6  *	Rodrigo Kumpera  <rkumpera@novell.com>
7  *
8  * (C) 2010 Novell, Inc
9  */
10 
11 #ifndef __MONO_PTR_ARRAY_H__
12 #define __MONO_PTR_ARRAY_H__
13 
14 
15 #include <glib.h>
16 
17 #include "mono/metadata/gc-internals.h"
18 
19 /* This is an implementation of a growable pointer array that avoids doing memory allocations for small sizes.
20  * It works by allocating an initial small array on stack and only going to gc tracked memory if needed.
21  * The array elements are assumed to be object references.
22  */
23 typedef struct {
24 	void **data;
25 	int size;
26 	int capacity;
27 	MonoGCRootSource source;
28 	const char *msg;
29 } MonoPtrArray;
30 
31 #define MONO_PTR_ARRAY_MAX_ON_STACK (16)
32 
33 #define mono_ptr_array_init(ARRAY, INITIAL_SIZE, SOURCE, MSG) do {\
34 	(ARRAY).size = 0; \
35 	(ARRAY).capacity = MAX (INITIAL_SIZE, MONO_PTR_ARRAY_MAX_ON_STACK); \
36 	(ARRAY).source = SOURCE; \
37 	(ARRAY).msg = MSG; \
38 	(ARRAY).data = INITIAL_SIZE > MONO_PTR_ARRAY_MAX_ON_STACK \
39 		? (void **)mono_gc_alloc_fixed (sizeof (void*) * INITIAL_SIZE, mono_gc_make_root_descr_all_refs (INITIAL_SIZE), SOURCE, MSG) \
40 		: g_newa (void*, MONO_PTR_ARRAY_MAX_ON_STACK); \
41 } while (0)
42 
43 #define mono_ptr_array_destroy(ARRAY) do {\
44 	if ((ARRAY).capacity > MONO_PTR_ARRAY_MAX_ON_STACK) \
45 		mono_gc_free_fixed ((ARRAY).data); \
46 } while (0)
47 
48 #define mono_ptr_array_append(ARRAY, VALUE) do { \
49 	if ((ARRAY).size >= (ARRAY).capacity) {\
50 	void **__tmp = (void **)mono_gc_alloc_fixed (sizeof (void*) * (ARRAY).capacity * 2, mono_gc_make_root_descr_all_refs ((ARRAY).capacity * 2), (ARRAY).source, (ARRAY).msg); \
51 		mono_gc_memmove_aligned ((void *)__tmp, (ARRAY).data, (ARRAY).capacity * sizeof (void*)); \
52 		if ((ARRAY).capacity > MONO_PTR_ARRAY_MAX_ON_STACK)	\
53 			mono_gc_free_fixed ((ARRAY).data);	\
54 		(ARRAY).data = __tmp;	\
55 		(ARRAY).capacity *= 2;\
56 	}\
57 	((ARRAY).data [(ARRAY).size++] = VALUE); \
58 } while (0)
59 
60 #define mono_ptr_array_sort(ARRAY, COMPARE_FUNC) do { \
61 	qsort ((ARRAY).data, (ARRAY).size, sizeof (gpointer), (COMPARE_FUNC)); \
62 } while (0)
63 
64 #define mono_ptr_array_set(ARRAY, IDX, VALUE) do { \
65 	((ARRAY).data [(IDX)] = VALUE); \
66 } while (0)
67 
68 #define mono_ptr_array_get(ARRAY, IDX) ((ARRAY).data [(IDX)])
69 
70 #define mono_ptr_array_size(ARRAY) ((ARRAY).size)
71 
72 #define mono_ptr_array_reset(ARRAY) do { \
73 	(ARRAY).size = 0; \
74 } while (0)
75 
76 #define mono_ptr_array_clear(ARRAY) do { \
77 	(ARRAY).size = 0; \
78 	mono_gc_bzero_aligned ((ARRAY).data, (ARRAY).capacity * sizeof (void*)); \
79 } while (0)
80 
81 #endif
82