Imported Upstream version 3.2.2
[debian/gnuradio] / pmt / src / lib / pmt_pool.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2007 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  * 
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 #include <pmt_pool.h>
26 #include <algorithm>
27 #include <stdint.h>
28
29 static inline size_t
30 ROUNDUP(size_t x, size_t stride)
31 {
32   return ((((x) + (stride) - 1)/(stride)) * (stride));
33 }
34
35 pmt_pool::pmt_pool(size_t itemsize, size_t alignment,
36                    size_t allocation_size, size_t max_items)
37   : d_cond(&d_mutex),
38     d_itemsize(ROUNDUP(itemsize, alignment)),
39     d_alignment(alignment),
40     d_allocation_size(std::max(allocation_size, 16 * itemsize)),
41     d_max_items(max_items), d_n_items(0),
42     d_freelist(0)
43 {
44 }
45
46 pmt_pool::~pmt_pool()
47 {
48   for (unsigned int i = 0; i < d_allocations.size(); i++){
49     delete [] d_allocations[i];
50   }
51 }
52
53 void *
54 pmt_pool::malloc()
55 {
56   omni_mutex_lock l(d_mutex);
57   item *p;
58
59   if (d_max_items != 0){
60     while (d_n_items >= d_max_items)
61       d_cond.wait();
62   }
63
64   if (d_freelist){      // got something?
65     p = d_freelist;
66     d_freelist = p->d_next;
67     d_n_items++;
68     return p;
69   }
70
71   // allocate a new chunk
72   char *alloc = new char[d_allocation_size + d_alignment - 1];
73   d_allocations.push_back(alloc);
74
75   // get the alignment we require
76   char *start = (char *)(((uintptr_t)alloc + d_alignment-1) & -d_alignment);
77   char *end = alloc + d_allocation_size + d_alignment - 1;
78   size_t n = (end - start) / d_itemsize;
79
80   // link the new items onto the free list.
81   p = (item *) start;
82   for (size_t i = 0; i < n; i++){
83     p->d_next = d_freelist;
84     d_freelist = p;
85     p = (item *)((char *) p + d_itemsize);
86   }
87
88   // now return the first one
89   p = d_freelist;
90   d_freelist = p->d_next;
91   d_n_items++;
92   return p;
93 }
94
95 void
96 pmt_pool::free(void *foo)
97 {
98   if (!foo)
99     return;
100
101   omni_mutex_lock l(d_mutex);
102
103   item *p = (item *) foo;
104   p->d_next = d_freelist;
105   d_freelist = p;
106   d_n_items--;
107   if (d_max_items != 0)
108     d_cond.signal();
109 }