~ubuntu-branches/ubuntu/warty/aqsis/warty

« back to all changes in this revision

Viewing changes to libaqsistypes/memorypool.h

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2004-08-24 07:25:04 UTC
  • Revision ID: james.westby@ubuntu.com-20040824072504-zf993vnevvisdsvb
Tags: upstream-0.9.1
Import upstream version 0.9.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Aqsis
 
2
// Copyright � 1997 - 2001, Paul C. Gregory
 
3
//
 
4
// Contact: pgregory@aqsis.com
 
5
//
 
6
// This library is free software; you can redistribute it and/or
 
7
// modify it under the terms of the GNU General Public
 
8
// License as published by the Free Software Foundation; either
 
9
// version 2 of the License, or (at your option) any later version.
 
10
//
 
11
// This library is distributed in the hope that it will be useful,
 
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
// General Public License for more details.
 
15
//
 
16
// You should have received a copy of the GNU General Public
 
17
// License along with this library; if not, write to the Free Software
 
18
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
19
 
 
20
 
 
21
/** \file
 
22
                \brief Declares the CqMemoryPool class for providing managed memory allocation.
 
23
                \author Paul C. Gregory (pgregory@aqsis.com)
 
24
*/
 
25
 
 
26
//? Is .h included already?
 
27
#ifndef MEMORYPOOL_H_INCLUDED 
 
28
//{
 
29
#define MEMORYPOOL_H_INCLUDED 1
 
30
 
 
31
#include        <vector>
 
32
 
 
33
#include        "aqsis.h"
 
34
 
 
35
#include        "ri.h"
 
36
 
 
37
START_NAMESPACE( Aqsis )
 
38
 
 
39
 
 
40
#define MEMORYPOOL_DEFAULTBLOCKSIZE 512
 
41
 
 
42
//----------------------------------------------------------------------
 
43
/** \class CqMemoryPool
 
44
 * Template class for memory pool allocation
 
45
 */
 
46
 
 
47
template <class T, long S = MEMORYPOOL_DEFAULTBLOCKSIZE>
 
48
class CqMemoryPool
 
49
{
 
50
public:
 
51
    CqMemoryPool() : m_pHead( 0 ), m_pFirstBlock( 0 )
 
52
    {}
 
53
    virtual     ~CqMemoryPool()
 
54
    {
 
55
        // Delete any remaining objects.
 
56
        // Note if this happens and anyone is pointing to the
 
57
        // allocated objects, you're in trouble.
 
58
                Flush();
 
59
    }
 
60
 
 
61
    /** Allocate a block from the pool.
 
62
     * \param size The requested size of the block, should be sizeof T, if not something is wrong.
 
63
     * \return void* pointer to memory block.
 
64
     */
 
65
    void*       Alloc( size_t size )
 
66
    {
 
67
 
 
68
        // send requests of the "wrong" size to ::operator new();
 
69
        if ( size != sizeof( T ) )
 
70
            return ::operator new( size );
 
71
 
 
72
        T* p = m_pHead;    // Point to the first free block.
 
73
 
 
74
        // if p is valid, just move the list head to the
 
75
        // next element in the free list
 
76
        if ( p ) m_pHead = p->m_pNext;
 
77
        else
 
78
        {
 
79
            // The free list is empty. Allocate a block of memory
 
80
            // big enough hold S objects
 
81
            char* p_newBlock = static_cast<char*>( ::operator new( S*sizeof( T ) + sizeof(char*) ) );
 
82
            T* newBlock = reinterpret_cast<T*>( p_newBlock + sizeof(char*) );
 
83
 
 
84
                        // Either initialise, or continue the linked list of blocks.
 
85
                        if( m_pFirstBlock != NULL )
 
86
                        {
 
87
                                void* pLastBlock = m_pFirstBlock;
 
88
                                while( static_cast<void**>( pLastBlock )[0] != 0 )
 
89
                                        pLastBlock = static_cast<void**>( pLastBlock )[0];
 
90
                                static_cast<void**>( pLastBlock )[0] = p_newBlock;
 
91
                                reinterpret_cast<void**>( p_newBlock )[0] = 0;
 
92
                        }
 
93
                        else
 
94
                        {
 
95
                                reinterpret_cast<void**>( p_newBlock )[0] = 0;
 
96
                                m_pFirstBlock = p_newBlock;
 
97
                        }
 
98
 
 
99
            // form a new free list by linking the memory chunks
 
100
            // together; skip the zeroth element, because you'll
 
101
            // return that to the caller of operator new
 
102
            for ( int i = 1; i < S - 1; ++i )
 
103
                newBlock[ i ].m_pNext = &newBlock[ i + 1 ];
 
104
 
 
105
            // terminate the linked list with a null pointer
 
106
            newBlock[ S - 1 ].m_pNext = 0;
 
107
 
 
108
            // set p to front of list, headOfFreeList to
 
109
            // chunk immediately following
 
110
            p = newBlock;
 
111
            m_pHead = &newBlock[ 1 ];
 
112
        }
 
113
        return ( p );
 
114
    }
 
115
 
 
116
    /** Deallocate a block from the pool.
 
117
     * \param p Pointer to the block, should be in a valid pool, if not something is wrong.
 
118
     * \param size The requested size of the block, should be sizeof T, if not something is wrong.
 
119
     */
 
120
    void        DeAlloc( void* p, size_t size )
 
121
    {
 
122
        if ( p == 0 ) return ;
 
123
 
 
124
        if ( size != sizeof( T ) )
 
125
        {
 
126
            ::operator delete( p );
 
127
            return;
 
128
        }
 
129
 
 
130
        T *carcass = static_cast<T*>( p );
 
131
 
 
132
        carcass->m_pNext = m_pHead;
 
133
        m_pHead = carcass;
 
134
    }
 
135
 
 
136
        /** Flush the pool block allocations.
 
137
         */
 
138
        void    Flush()
 
139
        {
 
140
                void* p_Block = m_pFirstBlock;
 
141
                while( p_Block )
 
142
                {
 
143
                        void* p_nextBlock = static_cast<void**>( p_Block )[0];
 
144
                        delete( p_Block );
 
145
                        p_Block = p_nextBlock;
 
146
                }
 
147
                m_pFirstBlock = 0;
 
148
                m_pHead = 0;
 
149
        }
 
150
 
 
151
private:
 
152
    T*  m_pHead;                ///< Pointer to the first free block in the pool.
 
153
        void*   m_pFirstBlock;
 
154
}
 
155
;
 
156
 
 
157
 
 
158
//----------------------------------------------------------------------
 
159
/** \class CqPoolable
 
160
 * Tamplate class to add the ability for a derived class to use a memory pool.
 
161
 */
 
162
 
 
163
template <class T, long S = MEMORYPOOL_DEFAULTBLOCKSIZE>
 
164
class CqPoolable
 
165
{
 
166
public:
 
167
    CqPoolable() : m_pNext( 0 )
 
168
    {}
 
169
    ~CqPoolable()
 
170
    {}
 
171
 
 
172
    /** Overridden operator new to allocate micropolys from a pool.
 
173
     */
 
174
    void* operator new( size_t size )
 
175
    {
 
176
        return( m_thePool.Alloc( size ) );
 
177
    }
 
178
 
 
179
    /** Overridden operator delete to allocate micropolys from a pool.
 
180
     */
 
181
    void operator delete( void* p )
 
182
    {
 
183
        m_thePool.DeAlloc( p, sizeof( T ) );
 
184
    }
 
185
 
 
186
    T*  m_pNext;        ///< Pointer to the next object.
 
187
 
 
188
    static      CqMemoryPool<T, S>      m_thePool;      ///< Static pool to allocated micropolys from.
 
189
    static void Flush() {       m_thePool.Flush();      }
 
190
}
 
191
;
 
192
 
 
193
 
 
194
//-----------------------------------------------------------------------
 
195
/** Define the static memory pool for a poolable class.
 
196
 */
 
197
 
 
198
#define DEFINE_STATIC_MEMORYPOOL(A, S)  CqMemoryPool<A, S>      CqPoolable<A, S>::m_thePool
 
199
 
 
200
 
 
201
//-----------------------------------------------------------------------
 
202
 
 
203
END_NAMESPACE( Aqsis )
 
204
 
 
205
//}  // End of #ifdef MEMORYPOOL_H_INCLUDED
 
206
#endif