summaryrefslogtreecommitdiff
path: root/hieroglyph/hgmem.h
blob: aa7d2d171059d902bb6cf5afed81cebbb52144e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* 
 * hgmem.h
 * Copyright (C) 2005-2006 Akira TAGOH
 * 
 * Authors:
 *   Akira TAGOH  <at@gclab.org>
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
#ifndef __HG_MEM_H__
#define __HG_MEM_H__

#include <hieroglyph/hgtypes.h>

G_BEGIN_DECLS

/* initializer */
void hg_mem_init_stack_start(gpointer mark);
void hg_mem_init            (void);
void hg_mem_finalize        (void);
void hg_mem_set_stack_end   (gpointer mark);

/* allocator */
HgAllocator *hg_allocator_new    (const HgAllocatorVTable *vtable);
void         hg_allocator_destroy(HgAllocator             *allocator);
HgHeap      *hg_heap_new         (HgMemPool               *pool,
				  gsize                    size);
void         hg_heap_free        (HgHeap                  *heap);

/* memory pool */
#define hg_mem_get_object__inline_nocheck(__data__)			\
	((HgMemObject *)((gsize)(__data__) - sizeof (HgMemObject)))
#define hg_mem_get_object__inline(__data__, __retval__)			\
	G_STMT_START {							\
		(__retval__) = hg_mem_get_object__inline_nocheck(__data__); \
		if (!HG_CHECK_MAGIC_CODE ((__retval__), HG_MEM_HEADER))	\
			(__retval__) = NULL;				\
	} G_STMT_END


HgMemPool     *hg_mem_pool_new                    (HgAllocator   *allocator,
						   const gchar   *identity,
						   gsize          prealloc,
						   guint          flags);
void           hg_mem_pool_destroy                (HgMemPool     *pool);
const gchar   *hg_mem_pool_get_name               (HgMemPool     *pool);
gboolean       hg_mem_pool_allow_resize           (HgMemPool     *pool,
						   gboolean       flag);
gsize          hg_mem_pool_get_used_heap_size     (HgMemPool     *pool);
gsize          hg_mem_pool_get_free_heap_size     (HgMemPool     *pool);
void           hg_mem_pool_add_heap               (HgMemPool     *pool,
						   HgHeap        *heap);
guint          hg_mem_pool_get_default_access_mode(HgMemPool     *pool);
void           hg_mem_pool_set_default_access_mode(HgMemPool     *pool,
						   guint          state);
gboolean       hg_mem_pool_is_global_mode         (HgMemPool     *pool);
gboolean       hg_mem_pool_is_own_object          (HgMemPool     *pool,
						   gpointer       data);
HgMemSnapshot *hg_mem_pool_save_snapshot          (HgMemPool     *pool);
gboolean       hg_mem_pool_restore_snapshot       (HgMemPool     *pool,
						   HgMemSnapshot *snapshot,
						   guint          adjuster);
guint8         hg_mem_pool_get_age_of_snapshot    (HgMemPool     *pool);
guint          hg_mem_pool_get_n_snapshots        (HgMemPool     *pool);
HgMemSnapshot *hg_mem_pool_get_snapshot           (HgMemPool     *pool,
						   guint          n);
void           hg_mem_pool_clear_snapshot         (HgMemPool     *pool);
gboolean       hg_mem_garbage_collection          (HgMemPool     *pool);
gpointer       hg_mem_alloc                       (HgMemPool     *pool,
						   gsize          size);
gpointer       hg_mem_alloc_with_flags            (HgMemPool     *pool,
						   gsize          size,
						   guint          flags);
gboolean       hg_mem_free                        (gpointer       data);
gpointer       hg_mem_resize                      (gpointer       data,
						   gsize          size);
gsize          hg_mem_get_object_size             (gpointer       data);

/* internal use */
gboolean       _hg_mem_pool_is_own_memobject      (HgMemPool     *pool,
						   HgMemObject   *obj);
void           _hg_mem_set_flags                  (HgMemObject   *object,
						   guint          flags);

/* GC */
#define hg_mem_is_flags__inline(__obj__, __flags__)			\
	(((__flags__) & HG_MEMOBJ_MARK_AGE_MASK) ?			\
	 hg_mem_is_gc_mark__inline(__obj__) :				\
	 (((__obj__)->flags & HG_MEMOBJ_FLAGS_MASK) & (__flags__)) == (__flags__))
#define hg_mem_get_flags__inline(__obj__)				\
	(HG_MEMOBJ_GET_FLAGS (__obj__))
#define hg_mem_set_flags__inline(__obj__, __flags__, __notify__)	\
	G_STMT_START {							\
		HgObject *__hg_mem_hobj__ = (HgObject *)(__obj__)->data; \
		const HgObjectVTable const *__hg_obj_vtable__;		\
									\
		if ((__flags__) > HG_MEMOBJ_MARK_AGE_MASK) {		\
			g_warning("[BUG] Invalid flags to not be set by hg_mem_set_flags: (possibly vtable id) %X", (__flags__)); \
		} else if ((__flags__) > HG_MEMOBJ_HGOBJECT_MASK) {	\
			/* don't inherit the age to the children.	\
			 * it causes the unexpected GC.			\
			 */						\
			HG_MEMOBJ_SET_MARK_AGE ((__obj__), hg_mem_pool_get_age_of_mark((__obj__)->pool)); \
		} else if ((__flags__) > HG_MEMOBJ_FLAGS_MASK) {	\
			g_warning("[BUG] Invalid flags to not be set by hg_mem_set_flags: (possibly hgobject id) %X", (__flags__)); \
		} else {						\
			_hg_mem_set_flags((__obj__), (__flags__));	\
		}							\
		if ((__notify__) &&					\
		    HG_MEMOBJ_IS_HGOBJECT (__obj__) &&			\
		    (__hg_obj_vtable__ = hg_object_get_vtable(__hg_mem_hobj__)) != NULL && \
		    __hg_obj_vtable__->set_flags) {			\
			__hg_obj_vtable__->set_flags(__hg_mem_hobj__, (__flags__)); \
		}							\
	} G_STMT_END
#define hg_mem_add_flags__inline(__obj__, __flags__, __notify__)	\
	G_STMT_START {							\
		if (((__flags__) & HG_MEMOBJ_FLAGS_MASK) != 0 &&	\
		    ((__flags__) & HG_MEMOBJ_MARK_AGE_MASK) != 0) {	\
			g_warning("[BUG] can't set a flags with mark");	\
		} else if (((__flags__) & HG_MEMOBJ_FLAGS_MASK) == 0) {	\
			/* set a mark */				\
			hg_mem_set_flags__inline((__obj__), (__flags__), (__notify__));	\
		} else {						\
			hg_mem_set_flags__inline((__obj__),		\
						 (__flags__) | hg_mem_get_flags__inline(__obj__), \
						 (__notify__));		\
		}							\
	} G_STMT_END

#define hg_mem_gc_mark__inline(_obj)					\
	G_STMT_START {							\
		HgObject *__hg_mem_hobj__ = (HgObject *)(_obj)->data;	\
		const HgObjectVTable const *__hg_obj_vtable__;		\
									\
		HG_MEMOBJ_SET_MARK_AGE ((_obj), hg_mem_pool_get_age_of_mark((_obj)->pool)); \
		if (HG_MEMOBJ_IS_HGOBJECT (_obj) &&			\
		    (__hg_obj_vtable__ = hg_object_get_vtable(__hg_mem_hobj__)) != NULL && \
		    __hg_obj_vtable__->set_flags) {			\
			guint __hg_mem_flags__ = HG_MEMOBJ_GET_MARK_AGE ((_obj)) << 16; \
			__hg_obj_vtable__->set_flags(__hg_mem_hobj__, __hg_mem_flags__); \
		}							\
	} G_STMT_END
#define hg_mem_is_gc_mark__inline(_obj)					\
	(hg_mem_pool_get_age_of_mark((_obj)->pool) == HG_MEMOBJ_GET_MARK_AGE (_obj))
#define hg_mem_restorable(_obj)		hg_mem_set_flags__inline(_obj, hg_mem_get_flags__inline(_obj) | HG_FL_RESTORABLE, FALSE)
#define hg_mem_unrestorable(_obj)	hg_mem_set_flags__inline(_obj, hg_mem_get_flags__inline(_obj) & ~HG_FL_RESTORABLE, FALSE)
#define hg_mem_is_restorable(_obj)	hg_mem_is_flags__inline(_obj, HG_FL_RESTORABLE)
#define hg_mem_complex_mark(_obj)	hg_mem_set_flags__inline(_obj, hg_mem_get_flags__inline(_obj) | HG_FL_COMPLEX, FALSE)
#define hg_mem_complex_unmark(_obj)	hg_mem_set_flags__inline(_obj, hg_mem_get_flags__inline(_obj) & ~HG_FL_COMPLEX, FALSE)
#define hg_mem_is_complex_mark(_obj)	hg_mem_is_flags__inline(_obj, HG_FL_COMPLEX)
#define hg_mem_set_lock(_obj)		hg_mem_set_flags__inline(_obj, hg_mem_get_flags__inline(_obj) | HG_FL_LOCK, FALSE)
#define hg_mem_set_unlock(_obj)		hg_mem_set_flags__inline(_obj, hg_mem_get_flags__inline(_obj) & ~HG_FL_LOCK, FALSE)
#define hg_mem_is_locked(_obj)		hg_mem_is_flags__inline(_obj, HG_FL_LOCK)
#define hg_mem_set_copying(_obj)	hg_mem_set_flags__inline(_obj, hg_mem_get_flags__inline(_obj) | HG_FL_COPYING, FALSE)
#define hg_mem_unset_copying(_obj)	hg_mem_set_flags__inline(_obj, hg_mem_get_flags__inline(_obj) & ~HG_FL_COPYING, FALSE)
#define hg_mem_is_copying(_obj)		hg_mem_is_flags__inline(_obj, HG_FL_COPYING)
#define hg_mem_set_dead(_obj)		hg_mem_set_flags__inline(_obj, hg_mem_get_flags__inline(_obj) | HG_FL_DEAD, FALSE)
#define hg_mem_unset_dead(_obj)		hg_mem_set_flags__inline(_obj, hg_mem_get_flags__inline(_obj) & ~HG_FL_DEAD, FALSE)
#define hg_mem_is_dead(_obj)		hg_mem_is_flags__inline(_obj, HG_FL_DEAD)

guint8   hg_mem_pool_get_age_of_mark       (HgMemPool *pool);
void     hg_mem_gc_mark_array_region       (HgMemPool *pool,
					    gpointer   start,
					    gpointer   end);
void     hg_mem_pool_add_root_node         (HgMemPool *pool,
					    gpointer   data);
void     hg_mem_pool_remove_root_node      (HgMemPool *pool,
					    gpointer   data);
void     hg_mem_pool_add_pool_reference    (HgMemPool *pool,
					    HgMemPool *other_pool);
void     hg_mem_pool_remove_pool_reference (HgMemPool *pool,
					    HgMemPool *other_pool);
void     hg_mem_pool_use_periodical_gc     (HgMemPool *pool,
					    gboolean   flag);
void     hg_mem_pool_use_garbage_collection(HgMemPool *pool,
					    gboolean   flag);

/* HgObject */
#define hg_object_readable(_obj)	hg_object_add_state(_obj, HG_ST_READABLE | HG_ST_ACCESSIBLE)
#define hg_object_unreadable(_obj)	hg_object_set_state(_obj, hg_object_get_state(_obj) & ~HG_ST_READABLE)
#define hg_object_is_readable(_obj)	hg_object_is_state(_obj, HG_ST_READABLE | HG_ST_ACCESSIBLE)
#define hg_object_writable(_obj)	hg_object_add_state(_obj, HG_ST_WRITABLE | HG_ST_ACCESSIBLE)
#define hg_object_unwritable(_obj)	hg_object_set_state(_obj, hg_object_get_state(_obj) & ~HG_ST_WRITABLE)
#define hg_object_is_writable(_obj)	hg_object_is_state(_obj, HG_ST_WRITABLE | HG_ST_ACCESSIBLE)
#define hg_object_executable(_obj)	hg_object_add_state(_obj, HG_ST_EXECUTABLE)
#define hg_object_inexecutable(_obj)	hg_object_set_state(_obj, hg_object_get_state(_obj) & ~HG_ST_EXECUTABLE)
#define hg_object_is_executable(_obj)	hg_object_is_state(_obj, HG_ST_EXECUTABLE)
#define hg_object_executeonly(_obj)	hg_object_set_state(_obj, (hg_object_get_state(_obj) & ~(HG_ST_READABLE | HG_ST_WRITABLE)) | HG_ST_EXECUTEONLY)
#define hg_object_is_executeonly(_obj)	hg_object_is_state(_obj, HG_ST_EXECUTEONLY)
#define hg_object_inaccessible(_obj)	hg_object_set_state(_obj, hg_object_get_state(_obj) & ~(HG_ST_READABLE | HG_ST_WRITABLE | HG_ST_EXECUTEONLY | HG_ST_ACCESSIBLE))
#define hg_object_is_accessible(_obj)	hg_object_is_state(_obj, HG_ST_ACCESSIBLE)

guint                       hg_object_get_state (HgObject                   *object);
void                        hg_object_set_state (HgObject                   *object,
						 guint                       state);
void                        hg_object_add_state (HgObject                   *object,
						 guint                       state);
gboolean                    hg_object_is_state  (HgObject                   *object,
						 guint                       state);
gpointer                    hg_object_dup       (HgObject                   *object);
gpointer                    hg_object_copy      (HgObject                   *object);
const HgObjectVTable const *hg_object_get_vtable(HgObject                   *object);
void                        hg_object_set_vtable(HgObject                   *object,
						 const HgObjectVTable const *vtable);


G_END_DECLS

#endif /* __HG_MEM_H__ */