Add algorithm package with move and moveEmplace

This commit is contained in:
Eugen Wissner 2017-10-29 07:51:00 +01:00
parent 414d7a11a8
commit 7a2768340e
9 changed files with 209 additions and 10 deletions

View File

@ -15,7 +15,6 @@ Garbage Collector heap. Everything in the library is usable in @nogc code.
Tanya extends Phobos functionality and provides alternative implementations for Tanya extends Phobos functionality and provides alternative implementations for
data structures and utilities that depend on the Garbage Collector in Phobos. data structures and utilities that depend on the Garbage Collector in Phobos.
* [Bug tracker](https://issues.caraus.io/projects/tanya/issues)
* [API Documentation](https://docs.caraus.io/tanya) * [API Documentation](https://docs.caraus.io/tanya)
* [Contribution guidelines](CONTRIBUTING.md) * [Contribution guidelines](CONTRIBUTING.md)
@ -24,6 +23,7 @@ data structures and utilities that depend on the Garbage Collector in Phobos.
Tanya consists of the following packages and (top-level) modules: Tanya consists of the following packages and (top-level) modules:
* `algorithm`: Collection of generic algorithms.
* `async`: Event loop (epoll, kqueue and IOCP). * `async`: Event loop (epoll, kqueue and IOCP).
* `container`: Queue, Array, Singly and doubly linked lists, Buffers, UTF-8 * `container`: Queue, Array, Singly and doubly linked lists, Buffers, UTF-8
string, Hash set. string, Hash set.

View File

@ -0,0 +1,164 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* Algorithms that modify its arguments.
*
* Copyright: Eugene Wissner 2017.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/algorithm/mutation.d,
* tanya/algorithm/mutation.d)
*/
module tanya.algorithm.mutation;
import tanya.memory.op;
import tanya.meta.trait;
/**
* Moves $(D_PARAM source) into $(D_PARAM target) assuming that
* $(D_PARAM target) isn't initialized.
*
* Moving the $(D_PARAM source) copies it into the $(D_PARAM target) and places
* the $(D_PARAM source) into a valid but unspecified state, which means that
* after moving $(D_PARAM source) can be destroyed or assigned a new value, but
* accessing it yields an unspecified value. No postblits or destructors are
* called. If the $(D_PARAM target) should be destroyed before, use
* $(D_PSYMBOL move).
*
* $(D_PARAM source) and $(D_PARAM target) must be different objects.
*
* Params:
* T = Object type.
* source = Source object.
* target = Target object.
*
* See_Also: $(D_PSYMBOL move),
* $(D_PSYMBOL hasElaborateCopyConstructor),
* $(D_PSYMBOL hasElaborateDestructor).
*
* Precondition: `&source !is &target`.
*/
void moveEmplace(T)(ref T source, ref T target) @system
in
{
assert(&source !is &target, "Source and target must be different");
}
body
{
static if (is(T == struct))
{
copy((&source)[0 .. 1], (&target)[0 .. 1]);
static if (hasElaborateCopyConstructor!T || hasElaborateDestructor!T)
{
static const T init = T.init;
static if (isNested!T)
{
// Don't override the context pointer.
enum size_t size = T.sizeof - (void*).sizeof;
copy((cast(void*) &init)[0 .. size], (&source)[0 .. 1]);
}
else
{
copy((&init)[0 .. 1], (&source)[0 .. 1]);
}
}
}
else
{
target = source;
}
}
///
@nogc nothrow pure @system unittest
{
static struct S
{
int member = 5;
this(this) @nogc nothrow pure @safe
{
assert(false);
}
}
S source, target = void;
moveEmplace(source, target);
assert(target.member == 5);
int x1 = 5, x2;
moveEmplace(x1, x2);
assert(x2 == 5);
}
/**
* Moves $(D_PARAM source) into $(D_PARAM target) assuming that
* $(D_PARAM target) isn't initialized.
*
* Moving the $(D_PARAM source) copies it into the $(D_PARAM target) and places
* the $(D_PARAM source) into a valid but unspecified state, which means that
* after moving $(D_PARAM source) can be destroyed or assigned a new value, but
* accessing it yields an unspecified value. $(D_PARAM target) is destroyed before
* the new value is assigned. If $(D_PARAM target) isn't initialized and
* therefore shouldn't be destroyed, $(D_PSYMBOL moveEmplace) can be used.
*
* If $(D_PARAM target) isn't specified, $(D_PSYMBOL move) returns the source
* as rvalue without calling its copy constructor or destructor.
*
* $(D_PARAM source) and $(D_PARAM target) are the same object,
* $(D_PSYMBOL move) does nothing.
*
* Params:
* T = Object type.
* source = Source object.
* target = Target object.
*
* See_Also: $(D_PSYMBOL moveEmplace).
*/
void move(T)(ref T source, ref T target)
{
if ((() @trusted => &source is &target)())
{
return;
}
static if (hasElaborateDestructor!T)
{
target.__xdtor();
}
(() @trusted => moveEmplace(source, target))();
}
/// ditto
T move(T)(ref T source)
{
T target = void;
(() @trusted => moveEmplace(source, target))();
return target;
}
///
@nogc nothrow pure @safe unittest
{
static struct S
{
int member = 5;
this(this) @nogc nothrow pure @safe
{
assert(false);
}
}
S source, target = void;
move(source, target);
assert(target.member == 5);
assert(move(target).member == 5);
int x1 = 5, x2;
move(x1, x2);
assert(x2 == 5);
assert(move(x2) == 5);
}

View File

@ -0,0 +1,17 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* Collection of generic algorithms.
*
* Copyright: Eugene Wissner 2017.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/algorithm/package.d,
* tanya/algorithm/package.d)
*/
module tanya.algorithm;
public import tanya.algorithm.mutation;

View File

@ -16,8 +16,16 @@ module tanya.container.array;
import core.checkedint; import core.checkedint;
import std.algorithm.comparison; import std.algorithm.comparison;
import std.algorithm.mutation; import std.algorithm.mutation : bringToFront,
copy,
fill,
initializeAll,
moveEmplaceAll,
moveAll,
swap,
uninitializedFill;
import std.meta; import std.meta;
import tanya.algorithm.mutation;
import tanya.exception; import tanya.exception;
import tanya.memory; import tanya.memory;
import tanya.meta.trait; import tanya.meta.trait;

View File

@ -15,11 +15,13 @@
module tanya.container.list; module tanya.container.list;
import std.algorithm.comparison; import std.algorithm.comparison;
import std.algorithm.mutation; import std.algorithm.mutation : swap;
import std.algorithm.searching; import std.algorithm.searching;
import tanya.algorithm.mutation;
import tanya.container.entry; import tanya.container.entry;
import tanya.memory; import tanya.memory;
import tanya.meta.trait; import tanya.meta.trait;
import tanya.meta.transform;
import tanya.range.array; import tanya.range.array;
import tanya.range.primitive; import tanya.range.primitive;

View File

@ -14,7 +14,7 @@
*/ */
module tanya.container.queue; module tanya.container.queue;
import std.algorithm.mutation; import tanya.algorithm.mutation;
import tanya.container.entry; import tanya.container.entry;
import tanya.exception; import tanya.exception;
import tanya.memory; import tanya.memory;

View File

@ -15,7 +15,8 @@
*/ */
module tanya.container.set; module tanya.container.set;
import std.algorithm.mutation; import std.algorithm.mutation : swap;
import tanya.algorithm.mutation;
import tanya.container; import tanya.container;
import tanya.container.entry; import tanya.container.entry;
import tanya.memory; import tanya.memory;

View File

@ -27,9 +27,10 @@
module tanya.container.string; module tanya.container.string;
import std.algorithm.comparison; import std.algorithm.comparison;
import std.algorithm.mutation; import std.algorithm.mutation : bringToFront, copy, swap;
import std.algorithm.searching; import std.algorithm.searching;
static import std.range; static import std.range;
import tanya.algorithm.mutation;
import tanya.memory; import tanya.memory;
import tanya.meta.trait; import tanya.meta.trait;
import tanya.meta.transform; import tanya.meta.transform;

View File

@ -14,11 +14,13 @@
*/ */
module tanya.math.mp; module tanya.math.mp;
import std.algorithm; import std.algorithm.comparison;
import std.algorithm.mutation;
import std.range; import std.range;
import tanya.container.array; import tanya.container.array;
import tanya.encoding.ascii; import tanya.encoding.ascii;
import tanya.memory; import tanya.memory;
static import tanya.memory.op;
import tanya.meta.trait; import tanya.meta.trait;
import tanya.meta.transform; import tanya.meta.transform;
@ -207,7 +209,7 @@ struct Integer
this(this) @nogc nothrow pure @safe this(this) @nogc nothrow pure @safe
{ {
auto tmp = allocator.resize!digit(null, this.size); auto tmp = allocator.resize!digit(null, this.size);
this.rep[0 .. this.size].copy(tmp); tanya.memory.op.copy(this.rep[0 .. this.size], tmp);
this.rep = tmp; this.rep = tmp;
} }
@ -340,7 +342,8 @@ struct Integer
if (is(Unqual!T == Integer)) if (is(Unqual!T == Integer))
{ {
this.rep = allocator.resize(this.rep, value.size); this.rep = allocator.resize(this.rep, value.size);
value.rep[0 .. value.size].copy(this.rep[0 .. value.size]); tanya.memory.op.copy(value.rep[0 .. value.size],
this.rep[0 .. value.size]);
this.size = value.size; this.size = value.size;
this.sign = value.sign; this.sign = value.sign;
@ -1023,7 +1026,10 @@ struct Integer
Integer opUnary(string op : "~")() const Integer opUnary(string op : "~")() const
{ {
auto ret = Integer(this, allocator); auto ret = Integer(this, allocator);
ret.rep[0 .. ret.size].each!((ref a) => a = ~a & mask); foreach (ref a; ret.rep[0 .. ret.size])
{
a = ~a & mask;
}
return ret; return ret;
} }