Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ArrayPolicies.hpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File ArrayPolicies.hpp
4 //
5 // For more information, please see: http://www.nektar.info
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Scientific Computing and Imaging Institute,
10 // University of Utah (USA) and Department of Aeronautics, Imperial
11 // College London (UK).
12 //
13 // License for the specific language governing rights and limitations under
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal in the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 // DEALINGS IN THE SOFTWARE.
31 //
32 // Description: Implementations of the array creation and destruction policies.
33 //
34 ///////////////////////////////////////////////////////////////////////////////
35 
36 
37 #ifndef NEKTAR_LIB_UTILITIES_BASIC_UTILS_ARRAY_POLICIES_HPP
38 #define NEKTAR_LIB_UTILITIES_BASIC_UTILS_ARRAY_POLICIES_HPP
39 
42 #include <boost/shared_ptr.hpp>
43 #include <boost/multi_array.hpp>
44 #include <boost/bind.hpp>
45 
46 namespace Nektar
47 {
48  template<typename ObjectType, typename enabled = void>
49  class ArrayInitializationPolicy;
50 
51  /// \internal
52  /// \brief Does nothing.
53  template<typename ObjectType>
54  class ArrayInitializationPolicy<ObjectType,
55  typename boost::enable_if<boost::is_fundamental<ObjectType> >::type >
56  {
57  public:
58  static void Initialize(ObjectType* data, unsigned int itemsToCreate)
59  {
60  }
61 
62  static void Initialize(ObjectType* data, unsigned int itemsToCreate, const ObjectType& initValue)
63  {
64  std::fill_n(data, itemsToCreate, initValue);
65  }
66 
67  static void Initialize(ObjectType* data, unsigned int itemsToCreate, const ObjectType* initValue)
68  {
69  std::copy(initValue, initValue + itemsToCreate, data);
70  }
71  };
72 
73  /// \internal
74  /// \brief Default initializes all elements.
75  ///
76  /// \internal
77  /// The user calls Initialize, which immediately calls DoInitialization. There reason
78  /// for this separation is because the code for creating an array of default initialized
79  /// elements and an array of copy constructed elements is identical except for the actual
80  /// call to placement new.
81  ///
82  ///
83  template<typename ObjectType>
84  class ArrayInitializationPolicy<ObjectType,
85  typename boost::disable_if<boost::is_fundamental<ObjectType> >::type >
86  {
87  public:
88  /// \brief Initalize each element in the array with ObjectType's default constructor.
89  /// \param data The array of values to populate.
90  /// \param itemsToCreate The size of data.
91  static void Initialize(ObjectType* data, unsigned int itemsToCreate)
92  {
93  DoInitialization(data, itemsToCreate,
94  boost::bind(&ArrayInitializationPolicy<ObjectType>::DefaultConstructionWithPlacementNew, _1));
95  }
96 
97  /// \brief Initalize each element in the array with ObjectType's copy constructor.
98  /// \param data The array of values to populate.
99  /// \param itemsToCreate The size of data.
100  /// \param initValue The inital value each element in data will have.
101  static void Initialize(ObjectType* data, unsigned int itemsToCreate, const ObjectType& initValue)
102  {
103  DoInitialization(data, itemsToCreate,
104  boost::bind(&ArrayInitializationPolicy<ObjectType>::CopyConstructionWithPlacementNew, _1, boost::ref(initValue)));
105  }
106 
107  static void Initialize(ObjectType* data, unsigned int itemsToCreate, const ObjectType* initValue)
108  {
109  DoInitialization(data, itemsToCreate,
110  boost::bind(&ArrayInitializationPolicy<ObjectType>::CopyConstructionFromArray, _1, boost::ref(initValue)));
111  }
112 
113  private:
114  template<typename CreateType>
115  static void DoInitialization(ObjectType* data, unsigned int itemsToCreate, const CreateType& f)
116  {
117  unsigned int nextObjectToCreate = 0;
118  try
119  {
120  for(unsigned int i = 0; i < itemsToCreate; ++i)
121  {
122  ObjectType* memLocation = &data[i];
123  f(memLocation);
124  ++nextObjectToCreate;
125  }
126  }
127  catch(...)
128  {
129  for(unsigned int i = 0; i < nextObjectToCreate; ++i)
130  {
131  ObjectType* memLocation = &data[nextObjectToCreate - i - 1];
132  memLocation->~ObjectType();
133  }
134  throw;
135  }
136  }
137 
138  static void DefaultConstructionWithPlacementNew(ObjectType* element)
139  {
140  new (element) ObjectType;
141  }
142 
143  static void CopyConstructionWithPlacementNew(ObjectType* element, const ObjectType& initValue)
144  {
145  new (element) ObjectType(initValue);
146  }
147 
148  static void CopyConstructionFromArray(ObjectType* element, const ObjectType*& rhs)
149  {
150  new (element) ObjectType(*rhs);
151  rhs += 1;
152  }
153  };
154 
155 
156  template<typename ObjectType, typename enabled = void>
157  class ArrayDestructionPolicy;
158 
159  template<typename ObjectType>
160  class ArrayDestructionPolicy<ObjectType,
161  typename boost::enable_if<boost::is_fundamental<ObjectType> >::type >
162  {
163  public:
164  static void Destroy(ObjectType* data, unsigned int itemsToDestroy)
165  {
166  }
167  };
168 
169  template<typename ObjectType>
170  class ArrayDestructionPolicy<ObjectType,
171  typename boost::disable_if<boost::is_fundamental<ObjectType> >::type >
172  {
173  public:
174  static void Destroy(ObjectType* data, unsigned int itemsToDestroy)
175  {
176  for(unsigned int i = 0; i < itemsToDestroy; ++i)
177  {
178  ObjectType* memLocation = &data[itemsToDestroy - i - 1];
179  memLocation->~ObjectType();
180  }
181  }
182  };
183 
184  template<typename DataType>
185  void DeleteStorage(DataType* data, unsigned int num)
186  {
187  ArrayDestructionPolicy<DataType>::Destroy(data, num);
189  }
190 
191  template<typename Dim, typename DataType, typename ExtentListType>
192  boost::shared_ptr<boost::multi_array_ref<DataType, Dim::Value> >
193  CreateStorage(const ExtentListType& extent)
194  {
195  typedef boost::multi_array_ref<DataType, Dim::Value> ArrayType;
196  unsigned int size = std::accumulate(extent.begin(), extent.end(), 1,
197  std::multiplies<unsigned int>());
198  DataType* storage = MemoryManager<DataType>::RawAllocate(size);
200  boost::bind(DeleteStorage<DataType>, storage, size),
201  storage, extent);
202  }
203 
204  template<typename DataType>
205  boost::shared_ptr<boost::multi_array_ref<DataType, 1> >
206  CreateStorage(unsigned int d1)
207  {
208  std::vector<unsigned int> extents(1, d1);
209  return CreateStorage<OneD, DataType>(extents);
210  }
211 
212  template<typename DataType>
213  boost::shared_ptr<boost::multi_array_ref<DataType, 2> >
214  CreateStorage(unsigned int d1, unsigned int d2)
215  {
216  unsigned int vals[] = {d1, d2};
217  std::vector<unsigned int> extents(vals, vals+2);
218  return CreateStorage<TwoD, DataType>(extents);
219  }
220 
221  template<typename DataType>
222  boost::shared_ptr<boost::multi_array_ref<DataType, 3> >
223  CreateStorage(unsigned int d1, unsigned int d2, unsigned int d3)
224  {
225  unsigned int vals[] = {d1, d2, d3};
226  std::vector<unsigned int> extents(vals, vals+3);
227  return CreateStorage<ThreeD, DataType>(extents);
228  }
229 }
230 
231 #endif //NEKTAR_LIB_UTILITIES_BASIC_UTILS_ARRAY_POLICIES_HPP