Fix reallocating the vector

This commit is contained in:
Eugen Wissner 2017-01-09 17:03:09 +01:00
parent d6514cb515
commit 87b74b2542
3 changed files with 52 additions and 49 deletions

2
.gitignore vendored
View File

@ -5,4 +5,6 @@
.dub
__test__*__
__test__*__.core
/docs/
/docs.json

View File

@ -5,8 +5,7 @@
[![Dub downloads](https://img.shields.io/dub/dt/tanya.svg)](https://code.dlang.org/packages/tanya)
[![License](https://img.shields.io/badge/license-MPL_2.0-blue.svg)](https://raw.githubusercontent.com/caraus-ecms/tanya/master/LICENSE)
Tanya is a general purpose library for D programming language that doesn't
rely on the Garbage Collector.
Tanya is a general purpose library for D programming language.
Its aim is to simplify the manual memory management in D and to provide a
guarantee with @nogc attribute that there are no hidden allocations on the
@ -36,12 +35,12 @@ helper functions).
The library is currently under development, but some parts of it can already be
used.
`network` and `async` exist for quite some time and could be better tested than
other components.
Containers were newly reworked and the API won't change significantly, but will
be only extended. The same is true for the `memory` package.
`network` and `async` packages should be reviewed in the future and the API may
change.
`math` package contains an arbitrary precision integer implementation that has
a stable API (that mostly consists of operator overloads), but still needs
testing and work on its performance.

View File

@ -10,9 +10,11 @@
*/
module tanya.container.vector;
import core.stdc.string;
import core.checkedint;
import core.exception;
import core.stdc.string;
import std.algorithm.comparison;
import std.algorithm.mutation;
import std.conv;
import std.range.primitives;
import std.meta;
@ -297,30 +299,6 @@ struct Vector(T)
assert(capacity_ == 0 || vector !is null);
}
// Reserves memory to store len objects and initializes it.
// Doesn't change the length.
private void initialize(in size_t len)
{
reserve(len);
if (capacity_ < len)
{
onOutOfMemoryError();
}
const init = typeid(T).initializer();
if (init.ptr)
{
const T* end = vector + len;
for (void* v = vector + length_; v != end; v += init.length)
{
memcpy(v, init.ptr, init.length);
}
}
else
{
memset(vector + length_, 0, (len - length_) * T.sizeof);
}
}
/**
* Creates a new $(D_PSYMBOL Vector).
*
@ -364,7 +342,8 @@ struct Vector(T)
{
return;
}
initialize(len);
reserve(len);
initializeAll(vector[0 .. len]);
capacity_ = length_ = len;
}
@ -385,9 +364,9 @@ struct Vector(T)
{
return;
}
initialize(len);
reserve(len);
uninitializedFill(vector[0 .. len], init);
capacity_ = length_ = len;
opSliceAssign(init, 0, length_);
}
/// Ditto.
@ -503,7 +482,8 @@ struct Vector(T)
}
else if (len > length_)
{
initialize(len);
reserve(len);
initializeAll(vector[length_ .. len]);
}
else
{
@ -549,13 +529,41 @@ struct Vector(T)
*/
void reserve(in size_t size) @trusted
{
if (capacity_ < size)
if (capacity_ >= size)
{
void[] buf = vector[0 .. capacity_];
allocator.reallocate(buf, size * T.sizeof);
vector = cast(T*) buf;
capacity_ = size;
return;
}
bool overflow;
immutable byteSize = mulu(size, T.sizeof, overflow);
if (overflow)
{
onOutOfMemoryErrorNoGC();
}
void[] buf = vector[0 .. capacity_];
if (!allocator.expand(buf, byteSize))
{
buf = allocator.allocate(byteSize);
if (buf is null)
{
onOutOfMemoryErrorNoGC();
}
scope (failure)
{
allocator.deallocate(buf);
}
const T* end = vector + length_;
for (T* src = vector, dest = cast(T*) buf; src != end; ++src, ++dest)
{
moveEmplace(*src, *dest);
static if (hasElaborateDestructor!T)
{
destroy(*src);
}
}
allocator.deallocate(vector[0 .. capacity_]);
vector = cast(T*) buf;
}
capacity_ = size;
}
///
@ -718,10 +726,6 @@ struct Vector(T)
if (allSatisfy!(ApplyRight!(isImplicitlyConvertible, T), R))
{
reserve(length_ + el.length);
if (capacity_ <= length_)
{
onOutOfMemoryError();
}
foreach (i; el)
{
emplace(vector + length_, i);
@ -737,8 +741,10 @@ struct Vector(T)
&& isImplicitlyConvertible!(ElementType!R, T))
{
immutable rLen = walkLength(el);
immutable newLen = length_ + rLen;
initialize(length_ + rLen);
reserve(newLen);
initializeAll(vector[length_ .. newLen]);
T* pos = vector + length_;
foreach (e; el)
{
@ -1270,11 +1276,7 @@ struct Vector(T)
}
body
{
const T* end = vector + j;
for (T* v = vector + i; v != end; ++v)
{
*v = value;
}
fill(vector[i .. j], value);
return opSlice(i, j);
}