summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2017-01-09 17:03:09 +0100
committerEugen Wissner <belka@caraus.de>2017-01-09 17:03:09 +0100
commit87b74b2542131c5a7749e1a174d776aed2e7ddeb (patch)
treea78d7ff7797612231d4137f04bddf905f94033bc
parentd6514cb51595729fd78be593fe54b7ade4888b80 (diff)
downloadtanya-87b74b2542131c5a7749e1a174d776aed2e7ddeb.tar.gz
Fix reallocating the vector
-rw-r--r--.gitignore2
-rw-r--r--README.md9
-rw-r--r--source/tanya/container/vector.d88
3 files changed, 51 insertions, 48 deletions
diff --git a/.gitignore b/.gitignore
index 44d9c69..1b841d8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,4 +5,6 @@
.dub
__test__*__
__test__*__.core
+
/docs/
+/docs.json
diff --git a/README.md b/README.md
index 0666b27..77703f7 100644
--- a/README.md
+++ b/README.md
@@ -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.
diff --git a/source/tanya/container/vector.d b/source/tanya/container/vector.d
index 51c2e0b..3d138eb 100644
--- a/source/tanya/container/vector.d
+++ b/source/tanya/container/vector.d
@@ -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)
+ {
+ return;
+ }
+ bool overflow;
+ immutable byteSize = mulu(size, T.sizeof, overflow);
+ if (overflow)
+ {
+ onOutOfMemoryErrorNoGC();
+ }
+ void[] buf = vector[0 .. capacity_];
+ if (!allocator.expand(buf, byteSize))
{
- void[] buf = vector[0 .. capacity_];
- allocator.reallocate(buf, size * T.sizeof);
+ 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;
}
+ 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);
}