summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2020-07-06 11:58:14 -0700
committerGitHub <noreply@github.com>2020-07-06 11:58:14 -0700
commitcf62f13cdc8a7f21c78f03b097bff6edf09fdead (patch)
tree6a08ddcd4dfe39976a7dec29164da4f7b87ddfda /source
parentffd0b9c9b06a22d886c77d777d9aa0cd1298d363 (diff)
ShortList<T> and core.natvis improvements. (#1430)
* ShortList<T> and core.natvis improvements. * Fix gcc build. * add `getBuffer()` accessor to `GetArrayViewResult`
Diffstat (limited to 'source')
-rw-r--r--source/core/core.natvis51
-rw-r--r--source/core/core.vcxproj1
-rw-r--r--source/core/core.vcxproj.filters3
-rw-r--r--source/core/slang-allocator.h70
-rw-r--r--source/core/slang-basic.h1
-rw-r--r--source/core/slang-dictionary.h2
-rw-r--r--source/core/slang-list.h73
-rw-r--r--source/core/slang-short-list.h488
8 files changed, 617 insertions, 72 deletions
diff --git a/source/core/core.natvis b/source/core/core.natvis
index 2b1e3ff7e..1087b4e6a 100644
--- a/source/core/core.natvis
+++ b/source/core/core.natvis
@@ -18,7 +18,7 @@
</Expand>
</Type>
-<Type Name="Slang::List&lt;*&gt;">
+<Type Name="Slang::List&lt;*,*&gt;">
<DisplayString>{{ size={m_count} }}</DisplayString>
<Expand>
<Item Name="[size]">m_count</Item>
@@ -30,6 +30,18 @@
</Expand>
</Type>
+<Type Name="Slang::ShortList&lt;*,*,*&gt;">
+ <DisplayString>{{ size={m_count} }}</DisplayString>
+ <Expand>
+ <Item Name="[size]">m_count</Item>
+ <Item Name="[capacity]">m_capacity</Item>
+ <IndexListItems>
+ <Size>m_count</Size>
+ <ValueNode Condition="$i&lt;$T2">m_shortBuffer + $i</ValueNode>
+ <ValueNode Condition="$i&gt;=$T2">m_buffer + $i - $T2</ValueNode>
+ </IndexListItems>
+ </Expand>
+</Type>
<Type Name="Slang::Array&lt;*,*&gt;">
<DisplayString>{{ size={m_count} }}</DisplayString>
@@ -47,10 +59,33 @@
<Expand>
<Item Name="[size]">_count</Item>
<Item Name="[capacity]">bucketSizeMinusOne + 1</Item>
- <ArrayItems>
- <Size>bucketSizeMinusOne + 1</Size>
- <ValuePointer>hashMap</ValuePointer>
- </ArrayItems>
+ <CustomListItems MaxItemsPerView="5000" ExcludeView="Test">
+ <Variable Name="iBucket" InitialValue="0" />
+ <Variable Name="pBucket" InitialValue="hashMap" />
+ <Variable Name="isDeleted" InitialValue="0" />
+ <Variable Name="isEmpty" InitialValue="0" />
+ <Size>_count</Size>
+ <Exec>pBucket = hashMap</Exec>
+ <Loop>
+ <If Condition="iBucket &gt;= bucketSizeMinusOne + 1">
+ <Break/>
+ </If>
+ <Exec>
+ isDeleted = marks.m_buffer.m_count &gt; (iBucket*2+1)/32
+ ? ((marks.m_buffer.m_buffer[(iBucket*2+1)/32]&amp;(1&lt;&lt;(iBucket*2+1)%32)) != 0)
+ : 0
+ </Exec>
+ <Exec>
+ isEmpty = marks.m_buffer.m_count &gt; (iBucket*2)/32
+ ? ((marks.m_buffer.m_buffer[(iBucket*2)/32]&amp;(1&lt;&lt;(iBucket*2)%32)) == 0)
+ : 1
+ </Exec>
+ <If Condition="isDeleted+isEmpty==0">
+ <Item>*(hashMap + iBucket)</Item>
+ </If>
+ <Exec>iBucket++</Exec>
+ </Loop>
+ </CustomListItems>
</Expand>
</Type>
@@ -103,4 +138,10 @@
<StringView>(m_sizeThenContents + 1),s</StringView>
</Type>
+<Type Name="Slang::UnownedStringSlice">
+ <DisplayString>{m_begin,[m_end-m_begin]s}</DisplayString>
+ <StringView>m_begin,[m_end-m_begin]s</StringView>
+
+</Type>
+
</AutoVisualizer>
diff --git a/source/core/core.vcxproj b/source/core/core.vcxproj
index 8c4e7753c..9676bb989 100644
--- a/source/core/core.vcxproj
+++ b/source/core/core.vcxproj
@@ -198,6 +198,7 @@
<ClInclude Include="slang-secure-crt.h" />
<ClInclude Include="slang-semantic-version.h" />
<ClInclude Include="slang-shared-library.h" />
+ <ClInclude Include="slang-short-list.h" />
<ClInclude Include="slang-smart-pointer.h" />
<ClInclude Include="slang-std-writers.h" />
<ClInclude Include="slang-stream.h" />
diff --git a/source/core/core.vcxproj.filters b/source/core/core.vcxproj.filters
index 312c24b17..3cb5ec8ec 100644
--- a/source/core/core.vcxproj.filters
+++ b/source/core/core.vcxproj.filters
@@ -138,6 +138,9 @@
<ClInclude Include="windows\slang-win-visual-studio-util.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="slang-short-list.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="slang-blob.cpp">
diff --git a/source/core/slang-allocator.h b/source/core/slang-allocator.h
index 481f8810f..f25fd92c9 100644
--- a/source/core/slang-allocator.h
+++ b/source/core/slang-allocator.h
@@ -1,11 +1,15 @@
#ifndef SLANG_CORE_ALLOCATOR_H
#define SLANG_CORE_ALLOCATOR_H
+#include "slang-common.h"
+
#include <stdlib.h>
#ifdef _MSC_VER
# include <malloc.h>
#endif
+#include <type_traits>
+
namespace Slang
{
inline void* alignedAllocate(size_t size, size_t alignment)
@@ -59,6 +63,72 @@ namespace Slang
return alignedDeallocate(ptr);
}
};
+
+ // Helper utilties for calling allocators.
+ template<typename T, int isPOD>
+ class Initializer
+ {
+
+ };
+
+ template<typename T>
+ class Initializer<T, 0>
+ {
+ public:
+ static void initialize(T* buffer, int size)
+ {
+ for (int i = 0; i < size; i++)
+ new (buffer + i) T();
+ }
+ };
+ template<typename T>
+ class Initializer<T, 1>
+ {
+ public:
+ static void initialize(T* buffer, int size)
+ {
+ // It's pod so no initialization required
+ //for (int i = 0; i < size; i++)
+ // new (buffer + i) T;
+ }
+ };
+
+ template<typename T, typename TAllocator>
+ class AllocateMethod
+ {
+ public:
+ static inline T* allocateArray(Index count)
+ {
+ TAllocator allocator;
+ T* rs = (T*)allocator.allocate(count * sizeof(T));
+ Initializer<T, std::is_pod<T>::value>::initialize(rs, count);
+ return rs;
+ }
+ static inline void deallocateArray(T* ptr, Index count)
+ {
+ TAllocator allocator;
+ if (!std::is_trivially_destructible<T>::value)
+ {
+ for (Index i = 0; i < count; i++)
+ ptr[i].~T();
+ }
+ allocator.deallocate(ptr);
+ }
+ };
+
+ template<typename T>
+ class AllocateMethod<T, StandardAllocator>
+ {
+ public:
+ static inline T* allocateArray(Index count)
+ {
+ return new T[count];
+ }
+ static inline void deallocateArray(T* ptr, Index /*bufferSize*/)
+ {
+ delete[] ptr;
+ }
+ };
}
#endif
diff --git a/source/core/slang-basic.h b/source/core/slang-basic.h
index 7931749f4..5387af4aa 100644
--- a/source/core/slang-basic.h
+++ b/source/core/slang-basic.h
@@ -6,6 +6,7 @@
#include "slang-string.h"
#include "slang-array.h"
#include "slang-list.h"
+#include "slang-short-list.h"
#include "slang-smart-pointer.h"
#include "slang-exception.h"
#include "slang-dictionary.h"
diff --git a/source/core/slang-dictionary.h b/source/core/slang-dictionary.h
index 72b24f81c..10c5a9b7d 100644
--- a/source/core/slang-dictionary.h
+++ b/source/core/slang-dictionary.h
@@ -82,7 +82,7 @@ namespace Slang
private:
inline int GetProbeOffset(int /*probeId*/) const
{
- // quadratic probing
+ // linear probing
return 1;
}
private:
diff --git a/source/core/slang-list.h b/source/core/slang-list.h
index 28180ce4f..5c1e3cbc7 100644
--- a/source/core/slang-list.h
+++ b/source/core/slang-list.h
@@ -14,72 +14,6 @@
namespace Slang
{
-
- template<typename T, int isPOD>
- class Initializer
- {
-
- };
-
- template<typename T>
- class Initializer<T, 0>
- {
- public:
- static void initialize(T* buffer, int size)
- {
- for (int i = 0; i<size; i++)
- new (buffer + i) T();
- }
- };
- template<typename T>
- class Initializer<T, 1>
- {
- public:
- static void initialize(T* buffer, int size)
- {
- // It's pod so no initialization required
- //for (int i = 0; i < size; i++)
- // new (buffer + i) T;
- }
- };
-
- template<typename T, typename TAllocator>
- class AllocateMethod
- {
- public:
- static inline T* allocateArray(Index count)
- {
- TAllocator allocator;
- T * rs = (T*)allocator.allocate(count * sizeof(T));
- Initializer<T, std::is_pod<T>::value>::initialize(rs, count);
- return rs;
- }
- static inline void deallocateArray(T* ptr, Index count)
- {
- TAllocator allocator;
- if (!std::is_trivially_destructible<T>::value)
- {
- for (Index i = 0; i < count; i++)
- ptr[i].~T();
- }
- allocator.deallocate(ptr);
- }
- };
-
- template<typename T>
- class AllocateMethod<T, StandardAllocator>
- {
- public:
- static inline T* allocateArray(Index count)
- {
- return new T[count];
- }
- static inline void deallocateArray(T* ptr, Index /*bufferSize*/)
- {
- delete [] ptr;
- }
- };
-
// List is container of values of a type held consecutively in memory (much like std::vector)
//
// Note that in this implementation, the underlying memory is backed via an allocation of T[capacity]
@@ -102,6 +36,7 @@ namespace Slang
}
template<typename... Args>
List(const T& val, Args... args)
+ : m_buffer(nullptr), m_count(0), m_capacity(0)
{
_init(val, args...);
}
@@ -611,6 +546,10 @@ namespace Slang
{
return AllocateMethod<T, TAllocator>::allocateArray(count);
}
+ static void _free(T* buffer, Index count)
+ {
+ return AllocateMethod<T, TAllocator>::deallocateArray(buffer, count);
+ }
template<typename... Args>
void _init(const T& val, Args... args)
@@ -618,6 +557,8 @@ namespace Slang
add(val);
_init(args...);
}
+
+ void _init() {}
};
template<typename T>
diff --git a/source/core/slang-short-list.h b/source/core/slang-short-list.h
new file mode 100644
index 000000000..82ad4fe1e
--- /dev/null
+++ b/source/core/slang-short-list.h
@@ -0,0 +1,488 @@
+#ifndef SLANG_CORE_SHORT_LIST_H
+#define SLANG_CORE_SHORT_LIST_H
+
+#include "../../slang.h"
+
+#include "slang-allocator.h"
+#include "slang-math.h"
+#include "slang-array-view.h"
+
+namespace Slang
+{
+ template<typename T, int shortListSize = 16, typename TAllocator = StandardAllocator>
+ class ShortList
+ {
+ private:
+ static const Index kInitialCount = 16;
+ typedef ShortList<T, shortListSize, TAllocator> ThisType;
+ public:
+ ShortList()
+ : m_buffer(nullptr), m_count(0), m_capacity(0)
+ {
+ }
+ template<typename... Args>
+ ShortList(const T& val, Args... args)
+ {
+ _init(val, args...);
+ }
+ ShortList(const ThisType& list)
+ : m_buffer(nullptr), m_count(0), m_capacity(0)
+ {
+ this->operator=(list);
+ }
+ ShortList(ThisType&& list)
+ : m_buffer(nullptr), m_count(0), m_capacity(0)
+ {
+ this->operator=(static_cast<ThisType&&>(list));
+ }
+ ~ShortList()
+ {
+ _deallocateBuffer();
+ }
+ template<int _otherShortListSize, typename TOtherAllocator>
+ ThisType& operator=(const ShortList<T, _otherShortListSize, TOtherAllocator>& list)
+ {
+ clearAndDeallocate();
+ addRange(list);
+ return *this;
+ }
+
+ ThisType& operator=(ThisType&& list)
+ {
+ // Could just do a swap here, and memory would be freed on rhs dtor
+ _deallocateBuffer();
+ m_count = list.m_count;
+ m_capacity = list.m_capacity;
+ m_buffer = list.m_buffer;
+
+ list.m_buffer = nullptr;
+ list.m_count = 0;
+ list.m_capacity = 0;
+
+ for (Index i = 0; i < Math::Min((Index)shortListSize, m_count); i++)
+ m_shortBuffer[i] = _Move(list.m_shortBuffer[i]);
+ return *this;
+ }
+
+ struct Iterator
+ {
+ ThisType* container = nullptr;
+ Index index = -1;
+ Iterator& operator++()
+ {
+ ++index;
+ return *this;
+ }
+ Iterator operator++(int)
+ {
+ Iterator rs = *this;
+ ++index;
+ return rs;
+ }
+ Iterator& operator--()
+ {
+ --index;
+ return *this;
+ }
+ Iterator operator--(int)
+ {
+ Iterator rs = *this;
+ --index;
+ return rs;
+ }
+ T* operator->()
+ {
+ SLANG_ASSERT(container);
+ return &(*container)[index];
+ }
+ T& operator*()
+ {
+ SLANG_ASSERT(container);
+ return (*container)[index];
+ }
+ bool operator==(Iterator other)
+ {
+ return container == other.container && index == other.index;
+ }
+ bool operator!=(Iterator other)
+ {
+ return index != other.index || container != other.container;
+ }
+ };
+
+ Iterator begin()
+ {
+ Iterator rs;
+ rs.container = this;
+ rs.index = 0;
+ return rs;
+ }
+ Iterator end()
+ {
+ Iterator rs;
+ rs.container = this;
+ rs.index = m_count;
+ return rs;
+ }
+
+ const T& getFirst() const
+ {
+ SLANG_ASSERT(m_count > 0);
+ return m_shortBuffer[0];
+ }
+
+ T& getFirst()
+ {
+ SLANG_ASSERT(m_count > 0);
+ return m_shortBuffer[0];
+ }
+
+ const T& getLast() const
+ {
+ SLANG_ASSERT(m_count > 0);
+ if (m_count <= shortListSize)
+ return m_shortBuffer[m_count - 1];
+ return m_buffer[m_count - shortListSize - 1];
+ }
+
+ T& getLast()
+ {
+ SLANG_ASSERT(m_count > 0);
+ if (m_count <= shortListSize)
+ return m_shortBuffer[m_count - 1];
+ return m_buffer[m_count - shortListSize - 1];
+ }
+
+ void removeLast()
+ {
+ SLANG_ASSERT(m_count > 0);
+ m_count--;
+ }
+
+ struct GetArrayViewResult
+ {
+ ArrayView<T> arrayView;
+ bool ownsStorage = false;
+
+ GetArrayViewResult() = default;
+ GetArrayViewResult(const GetArrayViewResult&) = delete;
+ GetArrayViewResult(GetArrayViewResult&& other)
+ {
+ ownsStorage = other.ownsStorage;
+ arrayView = other.arrayView;
+ other.ownsStorage = false;
+ }
+ ~GetArrayViewResult()
+ {
+ if (ownsStorage)
+ {
+ ThisType::_free(arrayView.m_buffer, arrayView.m_count);
+ }
+ }
+ T* getBuffer() { return arrayView.getBuffer(); }
+ };
+ inline GetArrayViewResult getArrayView() const
+ {
+ GetArrayViewResult result;
+ if (m_count > shortListSize)
+ {
+ result.arrayView.m_buffer = ThisType::_allocate(m_count);
+ result.arrayView.m_count = m_count;
+ for (Index i = 0; i < shortListSize; i++)
+ result.arrayView.m_buffer[i] = m_shortBuffer[i];
+ for (Index i = shortListSize; i < m_count; i++)
+ result.arrayView.m_buffer[i] = m_buffer[i - shortListSize];
+ result.ownsStorage = true;
+ }
+ else
+ {
+ result.arrayView.m_buffer = const_cast<T*>(&m_shortBuffer[0]);
+ result.arrayView.m_count = m_count;
+ }
+ return result;
+ }
+
+ inline GetArrayViewResult getArrayView(Index start, Index count) const
+ {
+ SLANG_ASSERT(start >= 0 && count >= 0 && start + count <= m_count);
+ GetArrayViewResult result;
+ if (start < shortListSize && start + count > shortListSize)
+ {
+ result.ownsStorage = true;
+ result.arrayView.m_count = count;
+ result.arrayView.m_buffer = ThisType::_allocate(count);
+ for (Index i = start; i < shortListSize; i++)
+ result.arrayView.m_buffer[i - start] = m_shortBuffer[i];
+ for (Index i = shortListSize; i < start + count; i++)
+ result.arrayView.m_buffer[i - start] = m_buffer[i - shortListSize];
+ return result;
+ }
+ else if (start + count <= shortListSize)
+ {
+ result.ownsStorage = false;
+ result.arrayView.m_count = count;
+ result.arrayView.m_buffer = const_cast<T*>(m_shortBuffer) + start;
+ return result;
+ }
+ else
+ {
+ result.ownsStorage = false;
+ result.arrayView.m_count = count;
+ result.arrayView.m_buffer = m_buffer + start - shortListSize;
+ return result;
+ }
+ }
+
+ void _maybeReserveForAdd()
+ {
+ if (m_capacity <= m_count - shortListSize)
+ {
+ Index newBufferSize = kInitialCount;
+ if (m_capacity)
+ newBufferSize = (m_capacity << 1);
+
+ reserveOverflowBuffer(newBufferSize);
+ }
+ }
+
+ void add(T&& obj)
+ {
+ if (m_count < shortListSize)
+ {
+ m_shortBuffer[m_count] = static_cast<T&&>(obj);
+ m_count++;
+ return;
+ }
+ _maybeReserveForAdd();
+ m_buffer[m_count - shortListSize] = static_cast<T&&>(obj);
+ m_count++;
+ }
+
+ void add(const T& obj)
+ {
+ if (m_count < shortListSize)
+ {
+ m_shortBuffer[m_count] = obj;
+ m_count++;
+ return;
+ }
+ _maybeReserveForAdd();
+ m_buffer[m_count - shortListSize] = obj;
+ m_count++;
+ }
+
+ Index getCount() const { return m_count; }
+
+ void addRange(const T* vals, Index n)
+ {
+ for (Index i = 0; i < n; i++)
+ add(vals[i]);
+ }
+
+ void addRange(ArrayView<T> list) { addRange(list.m_buffer, list.m_count); }
+
+ template<int _otherShortListSize, typename TOtherAllocator>
+ void addRange(const ShortList<T, _otherShortListSize, TOtherAllocator>& list)
+ {
+ for (Index i = 0; i < list.getCount(); i++)
+ add(list[i]);
+ }
+
+ void fastRemove(const T& val)
+ {
+ Index idx = indexOf(val);
+ if (idx >= 0)
+ {
+ fastRemoveAt(idx);
+ }
+ }
+
+ void fastRemoveAt(Index idx)
+ {
+ SLANG_ASSERT(idx >= 0 && idx < m_count);
+
+ if (idx != m_count - 1)
+ {
+ (*this)[idx] = _Move(getLast());
+ }
+ m_count--;
+ }
+
+ void clear() { m_count = 0; }
+
+ void clearAndDeallocate()
+ {
+ _deallocateBuffer();
+ m_count = m_capacity = 0;
+ }
+
+ void reserveOverflowBuffer(Index size)
+ {
+ if (size > m_capacity)
+ {
+ T* newBuffer = _allocate(size);
+ if (m_capacity)
+ {
+ for (Index i = 0; i < m_count - shortListSize; i++)
+ newBuffer[i] = static_cast<T&&>(m_buffer[i]);
+
+ // Default-initialize the remaining elements
+ for (Index i = m_count - shortListSize; i < size; i++)
+ {
+ new(newBuffer + i) T();
+ }
+ _deallocateBuffer();
+ }
+ m_buffer = newBuffer;
+ m_capacity = size;
+ }
+ }
+
+ void setCount(Index count)
+ {
+ if (count > shortListSize)
+ reserveOverflowBuffer(count - shortListSize);
+ m_count = count;
+ }
+
+ void unsafeShrinkToCount(Index count) { m_count = count; }
+
+ void compress()
+ {
+ if (m_capacity > m_count - shortListSize && m_count > shortListSize)
+ {
+ T* newBuffer = nullptr;
+ if (m_count > shortListSize)
+ {
+ newBuffer = _allocate(m_count - shortListSize);
+ for (Index i = shortListSize; i < m_count; i++)
+ newBuffer[i - shortListSize] = static_cast<T&&>(m_buffer[i - shortListSize]);
+ }
+ _deallocateBuffer();
+ m_buffer = newBuffer;
+ m_capacity = m_count - shortListSize;
+ }
+ }
+
+ SLANG_FORCE_INLINE const T& operator [](Index idx) const
+ {
+ SLANG_ASSERT(idx >= 0 && idx < m_count);
+ return (idx < shortListSize) ?
+ m_shortBuffer[idx] : m_buffer[idx - shortListSize];
+ }
+
+ SLANG_FORCE_INLINE T& operator [](Index idx)
+ {
+ SLANG_ASSERT(idx >= 0 && idx < m_count);
+ return (idx < shortListSize) ?
+ m_shortBuffer[idx] : m_buffer[idx - shortListSize];
+ }
+
+ template<typename Func>
+ Index findFirstIndex(const Func& predicate) const
+ {
+ for (Index i = 0; i < Math::Min(m_count, (Index)shortListSize); i++)
+ {
+ if (predicate(m_shortBuffer[i]))
+ return i;
+ }
+ for (Index i = shortListSize; i < m_count; i++)
+ {
+ if (predicate(m_buffer[i - shortListSize]))
+ return i;
+ }
+ return -1;
+ }
+
+ template<typename T2>
+ Index indexOf(const T2& val) const
+ {
+ for (Index i = 0; i < Math::Min(m_count, (Index)shortListSize); i++)
+ {
+ if (m_shortBuffer[i] == val)
+ return i;
+ }
+ for (Index i = shortListSize; i < m_count; i++)
+ {
+ if (m_buffer[i - shortListSize] == val)
+ return i;
+ }
+ return -1;
+ }
+
+ template<typename Func>
+ Index findLastIndex(const Func& predicate) const
+ {
+ for (Index i = m_count - 1; i >= shortListSize; i--)
+ {
+ if (predicate(m_buffer[i - shortListSize]))
+ return i;
+ }
+ for (Index i = Math::Min((Index)shortListSize, m_count) - 1; i >= 0; i--)
+ {
+ if (predicate(m_shortBuffer[i]))
+ return i;
+ }
+ return -1;
+ }
+
+ template<typename T2>
+ Index lastIndexOf(const T2& val) const
+ {
+ for (Index i = m_count - 1; i >= shortListSize; i--)
+ {
+ if (m_buffer[i - shortListSize] == val)
+ return i;
+ }
+ for (Index i = Math::Min((Index)shortListSize, m_count) - 1; i >= 0; i--)
+ {
+ if (m_shortBuffer[i] == val)
+ return i;
+ }
+ return -1;
+ }
+
+ bool contains(const T& val) const { return indexOf(val) != Index(-1); }
+
+ template <typename IterateFunc>
+ void forEach(IterateFunc f) const
+ {
+ for (Index i = 0; i < m_count; i++)
+ f(m_buffer[i]);
+ }
+
+ private:
+ T* m_buffer = nullptr; ///< A new T[N] allocated buffer. NOTE! All elements up to capacity are in some valid form for T.
+ Index m_capacity = 0; ///< The total capacity of elements in m_buffer
+ Index m_count = 0; ///< The amount of elements
+ T m_shortBuffer[shortListSize];
+
+ void _deallocateBuffer()
+ {
+ if (m_buffer)
+ {
+ AllocateMethod<T, TAllocator>::deallocateArray(m_buffer, m_capacity);
+ m_buffer = nullptr;
+ }
+ }
+ static inline T* _allocate(Index count)
+ {
+ return AllocateMethod<T, TAllocator>::allocateArray(count);
+ }
+ static inline void _free(T* ptr, Index count)
+ {
+ return AllocateMethod<T, TAllocator>::deallocateArray(ptr, count);
+ }
+
+ template<typename... Args>
+ void _init(const T& val, Args... args)
+ {
+ add(val);
+ _init(args...);
+ }
+
+ void _init() {}
+ };
+}
+
+#endif