File: static_pooled_class.hpp

package info (click to toggle)
supercollider 1%3A3.6.6~repack-2-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 23,792 kB
  • ctags: 25,269
  • sloc: cpp: 177,129; lisp: 63,421; ansic: 11,297; python: 1,787; perl: 766; yacc: 311; sh: 286; lex: 181; ruby: 173; makefile: 168; xml: 13
file content (187 lines) | stat: -rw-r--r-- 5,323 bytes parent folder | download
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
//  static pooled class
//  Copyright (C) 2009 Tim Blechmann
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This program 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 General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; see the file COPYING.  If not, write to
//  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
//  Boston, MA 02111-1307, USA.

#ifndef UTILITIES_STATIC_POOLED_CLASS_HPP
#define UTILITIES_STATIC_POOLED_CLASS_HPP

#include <cstddef>

#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/if.hpp>

#include "freelist.hpp"
#include "static_pool.hpp"

namespace nova
{

/**
 * base class for a class, which uses a static memory pool for
 * memory allocation.
 *
 * memory is allocated from a static pool and freed to a lock-free
 * freelist, which is freed during the memory allocation routine.
 * this way, the derived class can be allocated and freed from
 * different threads, while all the access to the pool is done from
 * the allocating thread.
 *
 * \tparam pool_locking specifies the locking policy for the object
 *         pool (default: nonblocking)
 *
 * \tparam recover_count limits the number of objects to be disposed
 *         from the freelist to avoid (default: dispose all objects
 *         of freelist)
 *
 * \todo   we could allocate one word more and store the size of the
 *         chunk just before the object. if a disposed object is large
 *         enough for a request, it wouldn't need to be added to the
 *         memory pool.
 *
 * */
template <typename tag,
          std::size_t pool_size,
          bool pool_locking = false,
          unsigned int recover_count = 0 >
class static_pooled_class
{
protected:
    static_pooled_class(void)
    {}

    static_pooled_class(static_pooled_class const & rhs)
    {}

    ~static_pooled_class(void)
    {}

private:
    /** free one object from freelist
     *
     *  \return true if freelist is empty
     *
     * */
    static inline bool free_disposed_object(void)
    {
        void * chunk = disposed_objects.pop();
        if (chunk == NULL)
            return true;
        object_pool.free(chunk);
        return false;
    }

    struct disposing_allocator
    {
        static void * allocate(std::size_t size)
        {
            free_disposed_objects();
            return object_pool.malloc(size);
        }
    };

    struct dispose_n_object_allocator
    {
        static void * allocate(std::size_t size)
        {
            for (unsigned int i = 0; i != recover_count; ++i) {
                bool freelist_empty = free_disposed_object();
                if (freelist_empty)
                    break;
            }

            for (;;)
            {
                void * ret = object_pool.malloc(size);

                if (ret)
                    return ret;
                if (free_disposed_object())
                    return NULL; /* no object in freelist, we  */
            }
        }
    };

    typedef typename boost::mpl::equal_to<boost::mpl::int_<recover_count>,
                                          boost::mpl::int_<0>
                                          > greater_zero;
    typedef typename boost::mpl::if_<greater_zero,
                                     dispose_n_object_allocator,
                                     disposing_allocator
                                     >::type allocator;

public:
    static inline void * allocate(std::size_t size)
    {
#ifndef NOVA_MEMORY_DEBUGGING
        size = std::max(2*sizeof(void*), size); /* size requirement for lockfree freelist */
        return allocator::allocate(size);
#else
        return malloc(size);
#endif
    }

    inline void* operator new(std::size_t size)
    {
        return allocate(size);
    }

    static inline void free_disposed_objects(void)
    {
        for(;;) {
            if (free_disposed_object())
                return;
        }
    }

    static inline void deallocate(void * p)
    {
#ifndef NOVA_MEMORY_DEBUGGING
        disposed_objects.push(p);
#else
        free(p);
#endif
    }

    inline void operator delete(void * p)
    {
        deallocate(p);
    }

    typedef static_pool<pool_size, pool_locking> object_pool_type;

    static object_pool_type object_pool;
    static freelist disposed_objects;
};

template <typename tag,
          std::size_t pool_size,
          bool pool_locking,
          unsigned int recover_count>
typename static_pooled_class<tag, pool_size, pool_locking, recover_count>::object_pool_type
static_pooled_class<tag, pool_size, pool_locking, recover_count>::object_pool(true);

template <typename tag,
          std::size_t pool_size,
          bool pool_locking,
          unsigned int recover_count>
freelist static_pooled_class<tag, pool_size, pool_locking, recover_count>::disposed_objects;


} /* namespace nova */

#endif /* UTILITIES_STATIC_POOLED_CLASS_HPP */