Skip to content

Commit

Permalink
Containers: initial growable arrays implementation.
Browse files Browse the repository at this point in the history
This was easy until I got to the benchmarks. Then it became a misery.
  • Loading branch information
mosra committed Dec 11, 2019
1 parent 2304ec2 commit 3cf41e3
Show file tree
Hide file tree
Showing 7 changed files with 2,522 additions and 10 deletions.
3 changes: 3 additions & 0 deletions doc/corrade-changelog.dox
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ namespace Corrade {

@subsubsection corrade-changelog-latest-new-containers Containers library

- New @ref Containers::arrayAppend(), @ref Containers::arrayReserve() family
of functions for opt-in growable arrays. See @ref Containers-Array-growable
for more information.
- Added @ref Containers::arrayCast() overloads for casting from the
@ref Containers::ArrayView<void> and @ref Containers::ArrayView<const void>
specializations
Expand Down
25 changes: 25 additions & 0 deletions doc/snippets/Containers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#endif

#include "Corrade/Containers/Array.h"
#include "Corrade/Containers/GrowableArray.h"
#include "Corrade/Containers/EnumSet.hpp"
#include "Corrade/Containers/LinkedList.h"
#include "Corrade/Containers/Optional.h"
Expand Down Expand Up @@ -227,6 +228,30 @@ Containers::Array<char, UnmapBuffer> array{data, bufferSize, UnmapBuffer{buffer}
#pragma GCC diagnostic pop
#endif

{
struct Face {
int vertexCount;
std::uint32_t vertices[4];
};

Containers::Array<Face> mesh;

/* [Array-growable] */
/* Optimistically reserve assuming the model consists of just triangles */
Containers::Array<std::uint32_t> triangles;
Containers::arrayReserve(triangles, mesh.size()*3);
for(const Face& face: mesh) {
/* If it's a quad, convert to two triangles */
if(face.vertexCount == 4) Containers::arrayAppend(triangles,
{face.vertices[0], face.vertices[1], face.vertices[2],
face.vertices[0], face.vertices[2], face.vertices[3]});
/* Otherwise add as-is */
else Containers::arrayAppend(triangles,
{face.vertices[0], face.vertices[1], face.vertices[2]});
}
/* [Array-growable] */
}

{
/* [Array-arrayView] */
Containers::Array<std::uint32_t> data;
Expand Down
62 changes: 52 additions & 10 deletions src/Corrade/Containers/Array.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,18 +82,16 @@ namespace Implementation {
/**
@brief Array wrapper with size information
@tparam T Element type
@tparam D Deleter type. Defaults to pointer to @cpp void(T*, std::size_t) @ce
@tparam D Deleter type. Defaults to pointer to a @cpp void(T*, std::size_t) @ce
function, where first is array pointer and second array size
Provides movable RAII wrapper around plain C array. Main use case is storing
binary data of unspecified type, where addition/removal of elements is not
needed or harmful.
However, the class is usable also as a lighter non-copyable alternative to
@ref std::vector; usable in STL algorithms in the same way as plain C array and
additionally also in range-for cycle.
Usage example:
Provides a RAII wrapper around a plain C array. A lighter alternative to
@ref std::vector that's deliberately move-only to avoid accidental copies of
large memory blocks. It's usable in STL algorithms in the same way as a plain C
array as well as in range-for cycles and other APIs operating with iterators.
By default the array has a non-changeable size by default and growing
functionality is opt-in, see @ref Containers-Array-growable below for more
information. Usage example:
@snippet Containers.cpp Array-usage
Expand Down Expand Up @@ -148,6 +146,50 @@ deleter type can be used:
@snippet Containers.cpp Array-deleter
@section Containers-Array-growable Growable arrays
The @ref Array class provides no reallocation or growing capabilities on its
own, and this functionality is opt-in via free functions from
@ref Corrade/Containers/GrowableArray.h instead. This is done in order to keep
the concept of an owning container decoupled from the extra baggage coming from
custom allocators, type constructibility and such.
As long as the type stored in the array is nothrow-move-constructible, any
@ref Array instance can be converted to a growing contaier by calling the
family of @ref arrayAppend(), @ref arrayReserve(), @ref arrayResize() ...
functions. A growable array behaves the same as a regular array to its
consumers --- its @ref size() returns the count of *real* elements, while
available capacity can be queried through @ref arrayCapacity(). Example of
populating an array with an undetermined amount of elements:
@snippet Containers.cpp Array-growable
A growable array can be turned back into a regular one using
@ref arrayShrink() if desired. That'll free all extra memory, moving the
elements to an array of exactly the size needed.
@m_class{m-block m-success}
@par Tip
To save typing, you can make use of ADL and call the @ref arrayAppend()
etc. functions unqualified, without having them explicitly prefixed with
@cpp Containers:: @ce.
@subsection Containers-Array-growable-allocators Growable allocators
Similarly to standard containers, growable arrays allow you to use a custom
allocator that matches the documented semantics of @ref ArrayAllocator. It's
also possible to switch between different allocators during the lifetime of an
@ref Array instance --- internally it's the same process as when a non-growable
array is converted to a growable version (or back, with @ref arrayShrink()).
The @ref ArrayAllocator is by default aliased to @ref ArrayNewAllocator, which
uses the standard C++ @cpp new[] @ce / @cpp delete[] @ce constructs and is
fully move-aware, requiring the types to be only nothrow-move-constructible at
the very least. If a type is trivially copyable, the @ref ArrayMallocAllocator
will get picked instead, make use of @ref std::realloc() to avoid unnecessary
memory copies when growing the array.
@section Containers-Array-views Conversion to array views
Arrays are implicitly convertible to @ref ArrayView as described in the
Expand Down
1 change: 1 addition & 0 deletions src/Corrade/Containers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ set(CorradeContainers_HEADERS
Containers.h
EnumSet.h
EnumSet.hpp
GrowableArray.h
LinkedList.h
Optional.h
OptionalStl.h
Expand Down
Loading

0 comments on commit 3cf41e3

Please sign in to comment.