iLab Neuromorphic Robotics Toolkit  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Array.H
Go to the documentation of this file.
1 /*! @file
2  @author Randolph Voorhies
3  @copyright GNU Public License (GPL v3)
4  @section License
5  @verbatim
6  // ////////////////////////////////////////////////////////////////////////
7  // The iLab Neuromorphic Robotics Toolkit (NRT) //
8  // Copyright 2010-2012 by the University of Southern California (USC) //
9  // and the iLab at USC. //
10  // //
11  // iLab - University of Southern California //
12  // Hedco Neurociences Building, Room HNB-10 //
13  // Los Angeles, Ca 90089-2520 - USA //
14  // //
15  // See http://ilab.usc.edu for information about this project. //
16  // ////////////////////////////////////////////////////////////////////////
17  // This file is part of The iLab Neuromorphic Robotics Toolkit. //
18  // //
19  // The iLab Neuromorphic Robotics Toolkit is free software: you can //
20  // redistribute it and/or modify it under the terms of the GNU General //
21  // Public License as published by the Free Software Foundation, either //
22  // version 3 of the License, or (at your option) any later version. //
23  // //
24  // The iLab Neuromorphic Robotics Toolkit is distributed in the hope //
25  // that it will be useful, but WITHOUT ANY WARRANTY; without even the //
26  // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
27  // PURPOSE. See the GNU General Public License for more details. //
28  // //
29  // You should have received a copy of the GNU General Public License //
30  // along with The iLab Neuromorphic Robotics Toolkit. If not, see //
31  // <http://www.gnu.org/licenses/>. //
32  // ////////////////////////////////////////////////////////////////////////
33  @endverbatim */
34 
35 
36 #ifndef INCLUDE_NRT_CORE_MEMORY_ARRAY_H
37 #define INCLUDE_NRT_CORE_MEMORY_ARRAY_H
38 
39 #include <nrt/External/cereal/types/memory.hpp>
40 #include <type_traits>
41 #include <memory>
42 
43 
44 namespace nrt
45 {
46  //! The Array class is an efficient way to store memory and pass it between functions
47  /*! The data held by this Array class is managed by a copy-on-write policy, so that assignments are extremely fast -
48  costing barely more than a pointer assignment and an integer increment. The class will then keep track of how many
49  references there are to the internal data storage, and will delete the contained memory if the number of
50  references to it drops to 0. Inspecting the data is also extremely fast (as fast as a standard C array) as long
51  as you use one of the constant methods (const_begin(), at(), etc...). However, accessing the data though a
52  non-constant method (begin(), operator[], etc...) may cause a deep-copy of the underlying data if there are
53  multiple references to it. Therefore, users should strive to use the faster constant methods whenever possible to
54  ensure maximum efficiency.
55 
56  \ingroup arrays */
57  template <class T>
58  class Array
59  {
60  public:
61  class Memory;
62 
63  //! Default construct an empty array
64  inline Array();
65 
66  //! Destructor
67  /*! Decrement the memory ref count, and free the memory when the last Array pointing to it is destroyed */
68  inline ~Array();
69 
70  //! Construct an array of a given size
71  /*! This constructor will not initialize the data inside of the array, so it may be filled with garbage on
72  construction. */
73  inline Array(size_t size);
74 
75  //! Construct a new array of a given size, and fill it with a value
76  inline Array(size_t size, T fillvalue);
77 
78  //! Copy an existing array
79  /*! This operation performs a shallow copy, meaning that the two arrays will both point to the exact same chunk of
80  data, and the refcount on that data will be incremented. */
81  inline Array(Array<T> const & a);
82 
83  //! Move construct an existing array
84  /*! After move construction the old array will be invalid */
85  inline Array(Array<T> && a);
86 
87  //! Construct an array by making a deep-copy of the given data
88  inline Array(T const * data, size_t size);
89 
90  //! Assign to an existing array
91  /*! This operation performs a shallow copy, meaning that the two arrays will both point to the exact same chunk of
92  data, and the refcount on that data will be incremented. */
93  Array<T> & operator=(Array<T> const & a);
94 
95  //! Move assign to an existing array
96  /*! After move assignment the old array will be invalid */
97  Array<T> & operator=(Array<T> && a);
98 
99  //! Compare to another array
100  /*! This operator will check to see if the two arrays are exactly the same, e.g point to the same chunk of
101  memory */
102  bool operator==(Array<T> const & a);
103 
104  //! Get the size of the array
105  inline size_t size() const;
106 
107  //! Get a constant reference to an item at the given index.
108  /*! Use this method to inspect a value at a given index. Because this method always returns a constant reference
109  it will never cause a deep copy to occur, and thus is very fast. If you need to change the contents of an
110  Array, you should use the [] operator. */
111  T const & at(size_t index) const;
112 
113  //! Get a non-constant reference to an item at the given index.
114  /*! Use this method to inspect or modify a value at a given index. Because this method returns a non-constant
115  reference, it may cause a deep copy of the data, and thus a severe performance penalty. Use .at() if you don't
116  need to change the data. */
117  T & operator[](size_t index);
118 
119  //! Get a const-reference to an item at the given index.
120  /*! Note that this version of [] will only be called if your Array is const to begin with.
121  If you're looking for a fast way to inpect data, you probably want the .at() method */
122  T const & operator[](size_t index) const;
123 
124  //! A constant iterator to the Array's data
125  /*! Users should use const_iterators whenever possible, as they are guaranteed to never cause a deep copy of the
126  underlying data */
127  typedef T const * const_iterator;
128 
129  //! A non-constant iterator to the Array's data
130  /*! Users should refrain from using these non-constant iterators unless they really do need to change the array's
131  data. Getting a reference to this type of iterator may cause a deep-copy of the underyling data, which will
132  cause a serious performance penalty.*/
133  typedef T * iterator;
134 
135  //! Get a constant iterator to the beginning of the data. See the typedef for const_iterator for details.
136  const_iterator begin() const;
137 
138  //! Get a constant iterator to the beginning of the data. See the typedef for const_iterator for details.
139  const_iterator const_begin() const;
140 
141  //! Get a constant iterator to the end of the data. See the typedef for
142  //! const_iterator for details.
143  const_iterator end() const;
144 
145  //! Get a constant iterator to the end of the data. See the typedef for
146  //! const_iterator for details.
147  const_iterator const_end() const;
148 
149  //! Get a non-constant iterator to the beginning of the data. See the
150  //! typedef for iterator for details.
151  iterator begin();
152 
153  //! Get a non-constant iterator to the end of the data. See the typedef
154  //! for iterator for details.
155  iterator end();
156 
157  //! Make a deep copy of our Memory.
158  /*! Immediately after a call to deepCopy(), our reference count is guaranteed to be 1 */
159  void deepCopy();
160 
161  private:
162  //! The actual ref-counted storage for the Array
163  std::shared_ptr<Memory> itsMemory;
164 
165  friend class cereal::access;
166  template <class Archive>
167  void serialize( Archive & ar )
168  {
169  ar( itsMemory );
170  }
171  }; // class Array
172 } // namespace nrt
173 
174 
175 //! If you #define NRT_ARRAY_DEEPCOPY_THROWS then ArrayDeepCopyException gets thrown after each call to deepCopy()
176 /*! The deepCopy() will still occur as planned, just you will need to catch the exception if you don't want your
177  program to crash. This can be used to debug cases when a deepCopy() should or should not occur. */
178 #ifdef NRT_ARRAY_DEEPCOPY_THROWS
179 
181 
182 namespace nrt
183 {
184  namespace exception
185  {
186  //! An exception to indicate that a deep copy occurred
187  /*! you need to #define NRT_ARRAY_DEEPCOPY_THROWS for this execption to get thrown. Use only for debugging and
188  optimizing. See example in \link test-ImageCopy.C \endlink
189  \relates Array */
190  template <class T>
191  class ArrayDeepCopyException : public Exception
192  {
193  public:
194  ArrayDeepCopyException(nrt::Array<T> const * arr) throw();
195  virtual ~ArrayDeepCopyException() throw();
196 
197  private:
198  std::string const whatstring;
199  };
200  } // namespace exception
201 } // namespace nrt
202 
203 #endif // INCLUDE_NRT_CORE_MEMORY_ARRAY_H
204 
206 
207 #endif // NRT_CORE_MEMORY_ARRAY_H