1 /*************************************************************************
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
21 *************************************************************************/
23 #include <ode/common.h>
24 #include <ode/error.h>
25 #include <ode/memory.h>
30 //****************************************************************************
31 // macros and constants
33 #define ROUND_UP_OFFSET_TO_EFFICIENT_SIZE(arena,ofs) \
34 ofs = (sizeint) (dEFFICIENT_SIZE( ((sizeint)(arena)) + ofs ) - ((sizeint)(arena)) )
36 #define MAX_ALLOC_SIZE \
37 ((sizeint)(dOBSTACK_ARENA_SIZE - sizeof (Arena) - EFFICIENT_ALIGNMENT + 1))
39 //****************************************************************************
43 m_first(NULL
), m_last(NULL
),
44 m_current_arena(NULL
), m_current_ofs(0)
56 dFree (a
,dOBSTACK_ARENA_SIZE
);
62 void *dObStack::alloc (sizeint num_bytes
)
64 if (num_bytes
> MAX_ALLOC_SIZE
) dDebug (0,"num_bytes too large");
66 bool last_alloc_needed
= false, last_init_needed
= false;
67 Arena
**last_ptr
= NULL
;
70 if ((m_last
->m_used
+ num_bytes
) > dOBSTACK_ARENA_SIZE
) {
71 if (m_last
->m_next
!= NULL
) {
72 m_last
= m_last
->m_next
;
73 last_init_needed
= true;
75 last_ptr
= &m_last
->m_next
;
76 last_alloc_needed
= true;
81 last_alloc_needed
= true;
84 if (last_alloc_needed
) {
85 Arena
*new_last
= (Arena
*) dAlloc (dOBSTACK_ARENA_SIZE
);
88 if (m_first
== NULL
) {
92 last_init_needed
= true;
95 if (last_init_needed
) {
96 m_last
->m_used
= sizeof (Arena
);
97 ROUND_UP_OFFSET_TO_EFFICIENT_SIZE (m_last
,m_last
->m_used
);
100 // allocate an area in the arena
101 char *c
= ((char*) m_last
) + m_last
->m_used
;
102 m_last
->m_used
+= num_bytes
;
103 ROUND_UP_OFFSET_TO_EFFICIENT_SIZE (m_last
,m_last
->m_used
);
108 void dObStack::freeAll()
110 Arena
*current
= m_first
;
112 // It is necessary to reset used sizes in whole arena chain
113 // otherwise enumeration may proceed to remains of old deleted joints in unused arenas
115 current
->m_used
= sizeof(Arena
);
116 ROUND_UP_OFFSET_TO_EFFICIENT_SIZE (current
,current
->m_used
);
117 current
= current
->m_next
;
122 void *dObStack::rewind()
124 return switch_to_arena(m_first
);
127 void *dObStack::next (sizeint num_bytes
)
129 // this functions like alloc, except that no new storage is ever allocated
130 if (!m_current_arena
) {
134 m_current_ofs
+= num_bytes
;
135 ROUND_UP_OFFSET_TO_EFFICIENT_SIZE (m_current_arena
,m_current_ofs
);
137 if (m_current_ofs
< m_current_arena
->m_used
) {
138 return ((char*) m_current_arena
) + m_current_ofs
;
141 return switch_to_arena(m_current_arena
->m_next
);
144 void *dObStack::switch_to_arena(Arena
*next_arena
)
146 m_current_arena
= next_arena
;
150 m_current_ofs
= sizeof (Arena
);
151 ROUND_UP_OFFSET_TO_EFFICIENT_SIZE (next_arena
, m_current_ofs
);
152 // Check if end of allocation has been reached
153 if (m_current_ofs
>= next_arena
->m_used
) {
156 return ((char*) next_arena
) + m_current_ofs
;