Allocator.cxx
1 // Copyright (C) 2001-2010 Vivien Mallet, INRIA
2 // Author(s): Vivien Mallet, Marc Fragu
3 //
4 // This file is part of the linear-algebra library Seldon,
5 // http://seldon.sourceforge.net/.
6 //
7 // Seldon is free software; you can redistribute it and/or modify it under the
8 // terms of the GNU Lesser General Public License as published by the Free
9 // Software Foundation; either version 2.1 of the License, or (at your option)
10 // any later version.
11 //
12 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
13 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15 // more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public License
18 // along with Seldon. If not, see http://www.gnu.org/licenses/.
19 
20 
21 #ifndef SELDON_FILE_ALLOCATOR_CXX
22 
23 #include "Allocator.hxx"
24 
25 namespace Seldon
26 {
27 
28 
30  // MALLOCOBJECT //
32 
33 
34  template <class T>
35  typename MallocObject<T>::pointer
36  MallocObject<T>::allocate(size_t num, void* h)
37  {
38  // The cast from char* to T* may lead to a memory shift (because of
39  // alignment issues) under MS Windows. It requires that one allocates more
40  // memory than necessary for memory_block.
41 
42  void* memory_block = malloc(sizeof(size_t) + sizeof(char*) +
43  (num + 2) * sizeof(T));
44  memcpy(memory_block, &num, sizeof(size_t));
45  char* data = static_cast<char*>(memory_block)
46  + sizeof(size_t) + sizeof(char*) + sizeof(T);
47 
48  // The memory shift can occur here.
49  pointer data_P = reinterpret_cast<pointer>(new(data) T[num]);
50  size_t taille = sizeof(char*);
51  memcpy(reinterpret_cast<char *>(data_P) - sizeof(char*),
52  &memory_block, taille);
53 
54  return data_P;
55  }
56 
57 
58  template <class T>
59  void MallocObject<T>::deallocate(pointer data, size_t num, void* h)
60  {
61  void * memory_block;
62  char* ptr = reinterpret_cast<char *>(data) - sizeof(char*);
63  size_t taille = sizeof(char*);
64  memcpy(&memory_block, ptr, taille);
65  for (size_t i = 0; i < num; i++)
66  data[i].~T();
67 
68  free(memory_block);
69  }
70 
71 
72  template <class T>
73  void* MallocObject<T>::reallocate(pointer data, size_t num, void* h)
74  {
75  if (data == NULL)
76  return allocate(num, h);
77 
78  void * memory_block; size_t taille = sizeof(char*);
79  memcpy(&memory_block,
80  reinterpret_cast<char *>(data) - sizeof(char*), taille);
81 
82  size_t initial_num = *reinterpret_cast<long*>(memory_block);
83 
84  if (initial_num < num)
85  {
86  memory_block = realloc(memory_block, sizeof(size_t) + sizeof(char*) +
87  (num + 2) * sizeof(T));
88 
89  new(static_cast<char *>(memory_block) + sizeof(size_t) + sizeof(T) +
90  sizeof(char*) + initial_num * sizeof(T)) T[num - initial_num];
91  }
92  else if (initial_num > num)
93  {
94  for (size_t i = num; i < initial_num; i++)
95  data[i].~T();
96 
97  memory_block = realloc(memory_block, sizeof(size_t) + sizeof(char*) +
98  (num + 2) * sizeof(T));
99 
100  }
101  else
102  return data;
103 
104  memcpy(memory_block, &num, sizeof(size_t));
105 
106  pointer data_P =
107  reinterpret_cast<pointer>(static_cast<char*>(memory_block) +
108  sizeof(size_t) + sizeof(char*) + sizeof(T));
109  memcpy(reinterpret_cast<char *>(data_P) - sizeof(char*),
110  &memory_block, taille);
111 
112  return data_P;
113  }
114 
115 
116  template <class T>
117  void MallocObject<T>::memoryset(pointer data, char c, size_t num)
118  {
119  memset(reinterpret_cast<void*>(data), c, num);
120  }
121 
122 
123  template <class T>
124  void
125  MallocObject<T>::memorycpy(pointer datat, pointer datas, size_t num)
126  {
127  for (size_t i = 0; i < num; i++)
128  datat[i] = datas[i];
129  }
130 
131 
133  // NANALLOC //
135 
136 
137  template <class T>
138  typename NaNAlloc<T>::pointer
139  NaNAlloc<T>::allocate(size_t num, void* h)
140  {
141  pointer data = static_cast<pointer>( malloc(num * sizeof(T)) );
142  if (numeric_limits<value_type>::has_signaling_NaN)
143  for (size_t i = 0; i < num; i++)
144  data[i] = numeric_limits<value_type>::signaling_NaN();
145  else if (numeric_limits<value_type>::has_quiet_NaN)
146  for (size_t i = 0; i < num; i++)
147  data[i] = numeric_limits<value_type>::quiet_NaN();
148  else if (numeric_limits<value_type>::has_infinity)
149  for (size_t i = 0; i < num; i++)
150  data[i] = numeric_limits<value_type>::infinity();
151  return data;
152  }
153 
154  template <class T>
155  void* NaNAlloc<T>::reallocate(pointer data, size_t num, void* h)
156  {
157  void* datav = realloc(reinterpret_cast<void*>(data), num * sizeof(T));
158  pointer datap = reinterpret_cast<pointer>(datav);
159  if (numeric_limits<value_type>::has_signaling_NaN)
160  for (size_t i = 0; i < num; i++)
161  datap[i] = numeric_limits<value_type>::signaling_NaN();
162  else if (numeric_limits<value_type>::has_quiet_NaN)
163  for (size_t i = 0; i < num; i++)
164  datap[i] = numeric_limits<value_type>::quiet_NaN();
165  else if (numeric_limits<value_type>::has_infinity)
166  for (size_t i = 0; i < num; i++)
167  datap[i] = numeric_limits<value_type>::infinity();
168  return datav;
169  }
170 
171 } // namespace Seldon.
172 
173 #define SELDON_FILE_ALLOCATOR_CXX
174 #endif
Seldon
Seldon namespace.
Definition: Array.cxx:24