]> git.gag.com Git - debian/gnuradio/blob - pmt/src/lib/pmt_pool.cc
05a7f590025e61aa02c960655b50f314e17d4aa5
[debian/gnuradio] / pmt / src / lib / pmt_pool.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2007,2009 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_itemsize(ROUNDUP(itemsize, alignment)),
38     d_alignment(alignment),
39     d_allocation_size(std::max(allocation_size, 16 * itemsize)),
40     d_max_items(max_items), d_n_items(0),
41     d_freelist(0)
42 {
43 }
44
45 pmt_pool::~pmt_pool()
46 {
47   for (unsigned int i = 0; i < d_allocations.size(); i++){
48     delete [] d_allocations[i];
49   }
50 }
51
52 void *
53 pmt_pool::malloc()
54 {
55   scoped_lock guard(d_mutex);
56   item *p;
57
58   if (d_max_items != 0){
59     while (d_n_items >= d_max_items)
60       d_cond.wait(guard);
61   }
62
63   if (d_freelist){      // got something?
64     p = d_freelist;
65     d_freelist = p->d_next;
66     d_n_items++;
67     return p;
68   }
69
70   // allocate a new chunk
71   char *alloc = new char[d_allocation_size + d_alignment - 1];
72   d_allocations.push_back(alloc);
73
74   // get the alignment we require
75   char *start = (char *)(((uintptr_t)alloc + d_alignment-1) & -d_alignment);
76   char *end = alloc + d_allocation_size + d_alignment - 1;
77   size_t n = (end - start) / d_itemsize;
78
79   // link the new items onto the free list.
80   p = (item *) start;
81   for (size_t i = 0; i < n; i++){
82     p->d_next = d_freelist;
83     d_freelist = p;
84     p = (item *)((char *) p + d_itemsize);
85   }
86
87   // now return the first one
88   p = d_freelist;
89   d_freelist = p->d_next;
90   d_n_items++;
91   return p;
92 }
93
94 void
95 pmt_pool::free(void *foo)
96 {
97   if (!foo)
98     return;
99
100   scoped_lock guard(d_mutex);
101
102   item *p = (item *) foo;
103   p->d_next = d_freelist;
104   d_freelist = p;
105   d_n_items--;
106   if (d_max_items != 0)
107     d_cond.notify_one();
108 }