Fix reallocating the vector
This commit is contained in:
parent
d6514cb515
commit
87b74b2542
2
.gitignore
vendored
2
.gitignore
vendored
@ -5,4 +5,6 @@
|
|||||||
.dub
|
.dub
|
||||||
__test__*__
|
__test__*__
|
||||||
__test__*__.core
|
__test__*__.core
|
||||||
|
|
||||||
/docs/
|
/docs/
|
||||||
|
/docs.json
|
||||||
|
@ -5,8 +5,7 @@
|
|||||||
[![Dub downloads](https://img.shields.io/dub/dt/tanya.svg)](https://code.dlang.org/packages/tanya)
|
[![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)
|
[![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
|
Tanya is a general purpose library for D programming language.
|
||||||
rely on the Garbage Collector.
|
|
||||||
|
|
||||||
Its aim is to simplify the manual memory management in D and to provide a
|
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
|
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
|
The library is currently under development, but some parts of it can already be
|
||||||
used.
|
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
|
Containers were newly reworked and the API won't change significantly, but will
|
||||||
be only extended. The same is true for the `memory` package.
|
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
|
`math` package contains an arbitrary precision integer implementation that has
|
||||||
a stable API (that mostly consists of operator overloads), but still needs
|
a stable API (that mostly consists of operator overloads), but still needs
|
||||||
testing and work on its performance.
|
testing and work on its performance.
|
||||||
|
@ -10,9 +10,11 @@
|
|||||||
*/
|
*/
|
||||||
module tanya.container.vector;
|
module tanya.container.vector;
|
||||||
|
|
||||||
import core.stdc.string;
|
import core.checkedint;
|
||||||
import core.exception;
|
import core.exception;
|
||||||
|
import core.stdc.string;
|
||||||
import std.algorithm.comparison;
|
import std.algorithm.comparison;
|
||||||
|
import std.algorithm.mutation;
|
||||||
import std.conv;
|
import std.conv;
|
||||||
import std.range.primitives;
|
import std.range.primitives;
|
||||||
import std.meta;
|
import std.meta;
|
||||||
@ -297,30 +299,6 @@ struct Vector(T)
|
|||||||
assert(capacity_ == 0 || vector !is null);
|
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).
|
* Creates a new $(D_PSYMBOL Vector).
|
||||||
*
|
*
|
||||||
@ -364,7 +342,8 @@ struct Vector(T)
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
initialize(len);
|
reserve(len);
|
||||||
|
initializeAll(vector[0 .. len]);
|
||||||
capacity_ = length_ = len;
|
capacity_ = length_ = len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,9 +364,9 @@ struct Vector(T)
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
initialize(len);
|
reserve(len);
|
||||||
|
uninitializedFill(vector[0 .. len], init);
|
||||||
capacity_ = length_ = len;
|
capacity_ = length_ = len;
|
||||||
opSliceAssign(init, 0, length_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ditto.
|
/// Ditto.
|
||||||
@ -503,7 +482,8 @@ struct Vector(T)
|
|||||||
}
|
}
|
||||||
else if (len > length_)
|
else if (len > length_)
|
||||||
{
|
{
|
||||||
initialize(len);
|
reserve(len);
|
||||||
|
initializeAll(vector[length_ .. len]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -549,13 +529,41 @@ struct Vector(T)
|
|||||||
*/
|
*/
|
||||||
void reserve(in size_t size) @trusted
|
void reserve(in size_t size) @trusted
|
||||||
{
|
{
|
||||||
if (capacity_ < size)
|
if (capacity_ >= size)
|
||||||
{
|
{
|
||||||
void[] buf = vector[0 .. capacity_];
|
return;
|
||||||
allocator.reallocate(buf, size * T.sizeof);
|
|
||||||
vector = cast(T*) buf;
|
|
||||||
capacity_ = size;
|
|
||||||
}
|
}
|
||||||
|
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))
|
if (allSatisfy!(ApplyRight!(isImplicitlyConvertible, T), R))
|
||||||
{
|
{
|
||||||
reserve(length_ + el.length);
|
reserve(length_ + el.length);
|
||||||
if (capacity_ <= length_)
|
|
||||||
{
|
|
||||||
onOutOfMemoryError();
|
|
||||||
}
|
|
||||||
foreach (i; el)
|
foreach (i; el)
|
||||||
{
|
{
|
||||||
emplace(vector + length_, i);
|
emplace(vector + length_, i);
|
||||||
@ -737,8 +741,10 @@ struct Vector(T)
|
|||||||
&& isImplicitlyConvertible!(ElementType!R, T))
|
&& isImplicitlyConvertible!(ElementType!R, T))
|
||||||
{
|
{
|
||||||
immutable rLen = walkLength(el);
|
immutable rLen = walkLength(el);
|
||||||
|
immutable newLen = length_ + rLen;
|
||||||
|
|
||||||
initialize(length_ + rLen);
|
reserve(newLen);
|
||||||
|
initializeAll(vector[length_ .. newLen]);
|
||||||
T* pos = vector + length_;
|
T* pos = vector + length_;
|
||||||
foreach (e; el)
|
foreach (e; el)
|
||||||
{
|
{
|
||||||
@ -1270,11 +1276,7 @@ struct Vector(T)
|
|||||||
}
|
}
|
||||||
body
|
body
|
||||||
{
|
{
|
||||||
const T* end = vector + j;
|
fill(vector[i .. j], value);
|
||||||
for (T* v = vector + i; v != end; ++v)
|
|
||||||
{
|
|
||||||
*v = value;
|
|
||||||
}
|
|
||||||
return opSlice(i, j);
|
return opSlice(i, j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user