Add a TriMesh to TriMesh collision demo.
[ode.git] / ode / src / obstack.cpp
blob541f0e3335ee366c056bf8c02b6c8925b30ba084
1 /*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
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 *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
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. *
20 * *
21 *************************************************************************/
23 #include <ode/common.h>
24 #include <ode/error.h>
25 #include <ode/memory.h>
26 #include "config.h"
27 #include "obstack.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 //****************************************************************************
40 // dObStack
42 dObStack::dObStack():
43 m_first(NULL), m_last(NULL),
44 m_current_arena(NULL), m_current_ofs(0)
49 dObStack::~dObStack()
51 // free all arenas
52 Arena *a,*nexta;
53 a = m_first;
54 while (a) {
55 nexta = a->m_next;
56 dFree (a,dOBSTACK_ARENA_SIZE);
57 a = nexta;
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;
69 if (m_last != 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;
74 } else {
75 last_ptr = &m_last->m_next;
76 last_alloc_needed = true;
79 } else {
80 last_ptr = &m_last;
81 last_alloc_needed = true;
84 if (last_alloc_needed) {
85 Arena *new_last = (Arena *) dAlloc (dOBSTACK_ARENA_SIZE);
86 new_last->m_next = 0;
87 *last_ptr = new_last;
88 if (m_first == NULL) {
89 m_first = new_last;
91 m_last = new_last;
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);
104 return c;
108 void dObStack::freeAll()
110 Arena *current = m_first;
111 m_last = current;
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
114 while (current) {
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) {
131 return 0;
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;
147 if (!next_arena) {
148 return 0;
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) {
154 return 0;
156 return ((char*) next_arena) + m_current_ofs;