1 /*
2  *  Copyright 2009-2011 Fabrice Colin
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18 
19 #ifndef _MEMORY_H
20 #define _MEMORY_H
21 
22 #include "config.h"
23 #include <execinfo.h>
24 #include <string>
25 #include <iostream>
26 #ifdef HAVE_UMEM_H
27 #include <umem.h>
28 
29 struct umem_allocator_tag
30 {
31 };
32 
33 /// Based on an example gven at http://www.ddj.com/cpp/184403759
34 template <typename T>
35 class umem_allocator
36 {
37 	public:
38 		typedef T                 value_type;
39 		typedef value_type*       pointer;
40 		typedef const value_type* const_pointer;
41 		typedef value_type&       reference;
42 		typedef const value_type& const_reference;
43 		typedef typename std::size_t size_type;
44 		typedef typename std::ptrdiff_t difference_type;
45 
46 		template <typename U>
47 		struct rebind
48 		{
49 			typedef umem_allocator<U> other;
50 		};
51 
umem_allocator()52 		umem_allocator()
53 		{
54 		}
55 		template <typename U>
umem_allocator(const umem_allocator<U> &)56 		umem_allocator(const umem_allocator<U> &)
57 		{
58 		}
~umem_allocator()59 		~umem_allocator()
60 		{
61 		}
62 
address(reference x)63 		static pointer address(reference x)
64 		{
65 			return &x;
66 		}
67 
address(const_reference x)68 		static const_pointer address(const_reference x)
69 		{
70 			return x;
71 		}
72 
max_size()73 		static size_type max_size()
74 		{
75 			return (std::numeric_limits<size_type>::max)();
76 		}
77 
construct(pointer p,const value_type & t)78 		static void construct(pointer p, const value_type &t)
79 		{
80 			new(p) T(t);
81 		}
82 
destroy(pointer p)83 		static void destroy(pointer p)
84 		{
85 			p->~T();
86 			// Avoid unused variable warning
87 			(void)p;
88 		}
89 
90 		bool operator==(const umem_allocator &) const
91 		{
92 			return true;
93 		}
94 
95 		bool operator!=(const umem_allocator &) const
96 		{
97 			return false;
98 		}
99 
allocate(size_type n)100 		static pointer allocate(size_type n)
101 		{
102 #ifdef DEBUG
103 			std::cout << "umem_allocator::allocate: allocating " << n << std::endl;
104 #endif
105 			void *ret = umem_alloc(n * sizeof(T), UMEM_DEFAULT);
106 			if (ret == NULL)
107 			{
108 				throw std::bad_alloc();
109 			}
110 			return static_cast<pointer>(ret);
111 		}
112 
allocate(const size_type n,const void * const)113 		static pointer allocate(const size_type n, const void *const)
114 		{
115 			return allocate(n);
116 		}
117 
deallocate(pointer p,size_type n)118 		static void deallocate(pointer p, size_type n)
119 		{
120 			if ((p == NULL) ||
121 				(n == 0))
122 			{
123 				return;
124 			}
125 
126 #ifdef DEBUG
127 			std::cout << "umem_allocator::deallocate: freeing " << n << std::endl;
128 #endif
129 			umem_free(static_cast<void*>(p), n * sizeof(T));
130 		}
131 
132 };
133 
134 /// Specialization for void.
135 template<>
136 class umem_allocator<void>
137 {
138 	typedef void        value_type;
139 	typedef void*       pointer;
140 	typedef const void* const_pointer;
141 
142 	template <class U>
143 	struct rebind
144 	{
145 		typedef umem_allocator<U> other;
146 	};
147 
148 };
149 #else
150 #ifdef HAVE_EXT_MALLOC_ALLOCATOR_H
151 #include <ext/malloc_allocator.h>
152 #endif
153 #endif
154 #ifdef HAVE_BOOST_POOL_POOLFWD_HPP
155 // This header should be available if poolfwd.hpp is
156 #include <boost/pool/pool_alloc.hpp>
157 #endif
158 
159 #include "Visibility.h"
160 
161 #ifdef HAVE_BOOST_POOL_POOLFWD_HPP
162 #ifdef HAVE_UMEM_H
163 // Memory pool with umem
164 typedef boost::pool_allocator<char,
165 	umem_allocator> filter_allocator;
166 #else
167 // Memory pool with malloc (glibc's or any other implementation)
168 typedef boost::pool_allocator<char,
169 	boost::default_user_allocator_malloc_free,
170 	boost::details::pool::default_mutex, 131072> filter_allocator;
171 #endif
172 typedef std::basic_string<char, std::char_traits<char>, filter_allocator > dstring;
173 #else
174 #ifdef HAVE_UMEM_H
175 // No memory pool, plain umem
176 typedef umem_allocator<char> filter_allocator;
177 typedef std::basic_string<char, std::char_traits<char>, filter_allocator > dstring;
178 #else
179 #ifdef HAVE_EXT_MALLOC_ALLOCATOR_H
180 // No memory pool, plain malloc (glibc's or any other implementation)
181 typedef __gnu_cxx::malloc_allocator<char> filter_allocator;
182 typedef std::basic_string<char, std::char_traits<char>, filter_allocator > dstring;
183 #else
184 // No memory pool, default STL allocator
185 typedef std::allocator<char> filter_allocator;
186 typedef std::string dstring;
187 #endif
188 #endif
189 #endif
190 
191 /// Memory usage related utilities.
192 class PINOT_EXPORT Memory
193 {
194 	public:
195 		/// Allocates a buffer.
196 		static char *allocateBuffer(off_t length);
197 
198 		/// Frees a buffer.
199 		static void freeBuffer(char *pBuffer, off_t length);
200 
201 		/// Returns the number of bytes in use.
202 		static int getUsage(void);
203 
204 		/// Hints to the OS it can reclaim unused memory.
205 		static void reclaim(void);
206 
207 	protected:
208 		Memory();
209 
210 };
211 
212 #endif // _MEMORY_H
213