File: itkObjectStore.h

package info (click to toggle)
insighttoolkit5 5.4.3-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 704,384 kB
  • sloc: cpp: 783,592; ansic: 628,724; xml: 44,704; fortran: 34,250; python: 22,874; sh: 4,078; pascal: 2,636; lisp: 2,158; makefile: 464; yacc: 328; asm: 205; perl: 203; lex: 146; tcl: 132; javascript: 98; csh: 81
file content (216 lines) | stat: -rw-r--r-- 6,764 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/*=========================================================================
 *
 *  Copyright NumFOCUS
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         https://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
#ifndef itkObjectStore_h
#define itkObjectStore_h

#include "itkObjectFactory.h"
#include "itkObject.h"
#include "itkIntTypes.h"
#include <vector>

namespace itk
{
/** \class ObjectStoreEnums
 *
 * \brief enums for ObjectStore
 *
 * \ingroup ITKCommon
 */
class ObjectStoreEnums
{
public:
  /** \class GrowthStrategy
   * \ingroup ITKCommon
   * Type of memory allocation strategy */
  enum class GrowthStrategy : uint8_t
  {
    LINEAR_GROWTH = 0,
    EXPONENTIAL_GROWTH = 1
  };
};
extern ITKCommon_EXPORT std::ostream &
                        operator<<(std::ostream & out, const ObjectStoreEnums::GrowthStrategy value);

/** \class ObjectStore
 * \brief A specialized memory management object for allocating and destroying
 * contiguous blocks of objects.
 *
 * ObjectStore implements a dynamically sizeable free memory store, from which
 * instantiated objects can be borrowed and returned without always invoking
 * calls to new/delete.  This type of memory management is useful in situations
 * where calls to new/delete may be expensive, such as a multithreaded
 * environment to avoid the heap contention problem.
 *
 * ObjectStore is designed to grow dynamically.  Shrinking is a more difficult
 * problem and is only done if it will not invalidate any pointers that have
 * been "lent" to a calling application.
 *
 * This implementation uses a very simple, list-based scheme to manage
 * pointers that have been borrowed and returned.  Memory overhead incurred is
 * one pointer per object allocated.  Because of this overhead, ObjectStore is
 * not efficient for use with small objects such as native types.
 *
 * Important notes on thread-safety: This object is thread-safe in the same
 * sense that STL defines thread-safety: simultaneous operations on distinct
 * containers are safe.  It is the user's responsibility to apply appropriate
 * mutex locks if the same container is used across multiple threads. One (or
 * more) ObjectStore's can be safely be created for each thread -- and may even
 * be more efficient in terms of memory use than sharing a single ObjectStore
 * across threads. Calls to \em new and \em delete have been placed in
 * critical sections in case a compiler's implementation of new/delete is not
 * thread-safe.
 *
 * \warning  For efficiency reasons, the ObjectStore does not guard against the
 * same pointer being Returned() more than once. Doing this could result in
 * serious problems.
 * \ingroup ITKCommon
 */
template <typename TObjectType>
class ITK_TEMPLATE_EXPORT ObjectStore : public Object
{
public:
  ITK_DISALLOW_COPY_AND_MOVE(ObjectStore);

  /** Standard type alias. */
  using Self = ObjectStore;
  using Superclass = Object;
  using Pointer = SmartPointer<Self>;
  using ConstPointer = SmartPointer<const Self>;

  /** Method for creation through the object factory. */
  itkNewMacro(Self);

  /** \see LightObject::GetNameOfClass() */
  itkOverrideGetNameOfClassMacro(ObjectStore);

  /** Type of the objects in storage. */
  using ObjectType = TObjectType;

  /** Type of list for storing pointers to free memory. */
  using FreeListType = std::vector<ObjectType *>;

  using GrowthStrategyEnum = ObjectStoreEnums::GrowthStrategy;
#if !defined(ITK_LEGACY_REMOVE)
  // We need to expose the enum values at the class level
  // for backwards compatibility
  static constexpr GrowthStrategyEnum LINEAR_GROWTH = GrowthStrategyEnum::LINEAR_GROWTH;
  static constexpr GrowthStrategyEnum EXPONENTIAL_GROWTH = GrowthStrategyEnum::EXPONENTIAL_GROWTH;
#endif
  /** Borrow a pointer to an object from the memory store. */
  ObjectType *
  Borrow();

  /** Return a pointer to the memory store for reuse. WARNING: The ObjectStore
   *  assumes a pointer is returned exactly once after each time it has been
   *  borrowed. */
  void
  Return(ObjectType * p);

  /** Returns the size of the container.  This is not the number of objects
   *  available, but the total number of objects allocated. */
  itkGetConstMacro(Size, SizeValueType);

  /** Ensures that there are at least n elements allocated in the storage
   *  container.  Will not shrink the container, but may enlarge the
   *   container. */
  void
  Reserve(SizeValueType n);

  /** Attempts to free memory that is not in use and shrink the size of the
   *  container.  Not guaranteed to do anything. */
  void
  Squeeze();

  /** Frees all memory in the container */
  void
  Clear();

  /** Set/Get the linear growth size */
  itkSetMacro(LinearGrowthSize, SizeValueType);
  itkGetConstMacro(LinearGrowthSize, SizeValueType);

  /** Set/Get the growth strategy. */
  itkSetEnumMacro(GrowthStrategy, GrowthStrategyEnum);
  itkGetConstMacro(GrowthStrategy, GrowthStrategyEnum);

  /** Set growth strategy to exponential */
  void
  SetGrowthStrategyToExponential()
  {
    this->SetGrowthStrategy(GrowthStrategyEnum::EXPONENTIAL_GROWTH);
  }

  /** Set growth strategy to linear */
  void
  SetGrowthStrategyToLinear()
  {
    this->SetGrowthStrategy(GrowthStrategyEnum::LINEAR_GROWTH);
  }

protected:
  ObjectStore() = default;
  ~ObjectStore() override;
  void
  PrintSelf(std::ostream & os, Indent indent) const override;

  /** Returns a new size to grow. */
  SizeValueType
  GetGrowthSize();

  struct MemoryBlock
  {
    MemoryBlock() = default;

    MemoryBlock(SizeValueType n)
      : Size(n)
    {
      Begin = new ObjectType[n];
    }

    ~MemoryBlock() = default; // Purposely does *not* free memory

    void
    Delete()
    {
      delete[] Begin;
    }

    ObjectType *  Begin{};
    SizeValueType Size{ 0 };
  };

private:
  GrowthStrategyEnum m_GrowthStrategy{ GrowthStrategyEnum::EXPONENTIAL_GROWTH };

  SizeValueType m_Size{};
  SizeValueType m_LinearGrowthSize{ 1024 };

  /** Pointers to objects available for borrowing. */
  FreeListType m_FreeList{};

  /** A list of MemoryBlocks that have been allocated. */
  std::vector<MemoryBlock> m_Store{};
};

} // end namespace itk

#ifndef ITK_MANUAL_INSTANTIATION
#  include "itkObjectStore.hxx"
#endif

#endif