Code Monkey home page Code Monkey logo

containers's Introduction

Containers CI status

Containers backed by std.experimental.allocator

Documentation

Documentation is available at http://dlang-community.github.io/containers/index.html

Example

/+dub.sdl:
dependency "emsi_containers" version="~>0.6"
+/
import std.stdio;
void main(string[] args)
{
    import containers;
    DynamicArray!int arr;
    arr ~= 1;
    foreach (e; arr)
        e.writeln;
}

Open on run.dlang.io

Insertion Speed Benchmark

Benchmark

Measurements taken on a Intel(R) Core(TM) i5-4250U CPU @ 1.30GHz with 8GB of memory. Compiled with dmd-2.068.0 using -O -release -inline flags.

Code

import containers.ttree;
import std.container.rbtree;
import containers.slist;
import std.container.slist;
import containers.unrolledlist;
import std.experimental.allocator;
import std.experimental.allocator.building_blocks.allocator_list;
import std.experimental.allocator.building_blocks.region;
import std.experimental.allocator.mallocator;
import std.datetime;
import std.stdio;

// For fun: change this number and watch the effect it has on the execution time
alias Allocator = AllocatorList!(a => Region!Mallocator(1024 * 16), Mallocator);

enum NUMBER_OF_ITEMS = 500_000;

void testEMSIContainer(alias Container, string ContainerName)()
{
	Allocator allocator;
	auto c = Container!(int, typeof(&allocator))(&allocator);
	StopWatch sw = StopWatch(AutoStart.yes);
	foreach (i; 0 .. NUMBER_OF_ITEMS)
		c.insert(i);
	sw.stop();
	writeln("Inserts for ", ContainerName, " finished in ",
		sw.peek().to!("msecs", float), " milliseconds.");
}

void testPhobosContainer(alias Container, string ContainerName)()
{
	static if (is(Container!int == class))
		auto c = new Container!int();
	else
		Container!int c;
	StopWatch sw = StopWatch(AutoStart.yes);
	foreach (i; 0 .. NUMBER_OF_ITEMS)
		c.insert(i);
	sw.stop();
	writeln("Inserts for ", ContainerName, " finished in ",
		sw.peek().to!("msecs", float), " milliseconds.");
}

void main()
{
	testEMSIContainer!(TTree, "TTree")();
	testPhobosContainer!(RedBlackTree, "RedBlackTree")();

	testPhobosContainer!(std.container.slist.SList, "Phobos SList")();
	testEMSIContainer!(containers.slist.SList, "EMSI SList")();

	testEMSIContainer!(UnrolledList, "UnrolledList")();
}

containers's People

Contributors

aminya avatar bbasile avatar burner avatar cybershadow avatar dayllenger avatar dlang-bot avatar dushibaiyu avatar eclipseo avatar geod24 avatar hackerpilot avatar jcrapuchettes avatar jinshil avatar kubo39 avatar ljmf00 avatar martinnowak avatar n8sh avatar p0nce avatar panke avatar petarkirov avatar sirnickolas avatar wilzbach avatar ximion avatar yorizuka avatar yshui avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

containers's Issues

Move aware containers

I currently have my own implementations of gc free containers, but it would be nice to switch to a more "widely" used library.

But I would need the containers to be move aware, so that you can have DynamicArray!(Unique!Foo) for example.

Thoughts?

Simplify Tests Example

Parameter ContainerName in

void testEMSIContainer(alias Container, string ContainerName)()
{
    Allocator allocator;
    auto c = Container!(int, typeof(&allocator))(&allocator);
    StopWatch sw = StopWatch(AutoStart.yes);
    foreach (i; 0 .. NUMBER_OF_ITEMS)
        c.insert(i);
    sw.stop();
    writeln("Inserts for ", ContainerName, " finished in ",
        sw.peek().to!("msecs", float), " milliseconds.");
}

and testPhobosContainer can be removed and its usage can be replaced by Container.stringof

as

void testEMSIContainer(alias Container)()
{
    Allocator allocator;
    auto c = Container!(int, typeof(&allocator))(&allocator);
    StopWatch sw = StopWatch(AutoStart.yes);
    foreach (i; 0 .. NUMBER_OF_ITEMS)
        c.insert(i);
    sw.stop();
    writeln("Inserts for ", Container.stringof, " finished in ",
        sw.peek().to!("msecs", float), " milliseconds.");
}

A DUB package for Phobos backports?

There is way to have allocators works with all compilers, we did it for logger here: burner/logger#22 to support multiple D front-ends.

  • create a DUB package with std.experimental.allocatorexcept renamed to std.historical.allocator (this avoid samey import conflicts with newer compilers)
  • instead of private import std.experimental.allocator.mallocator : Mallocator;, use
static if (front-end >= 2.069)
    import std.experimental.allocator;
else
    import std.historical.allocator;

I've checked and this isn't a problem for now but will be once a new DMD is out with allocators.
Such a package could be useful for other projects and would allow to compile allocators only once.

assign range to slice

something like this ?

   void opSliceAssign(T[] values, size_t i, size_t j) @nogc
    {
            assert(values.length==j-i);
            foreach(k,value;values)
                    arr[i+k]=value;
    }

which version of allocator should I use?

Using allocator branch of Andrei's Phobos fork:
https://github.com/andralex/phobos.git

and DMD v 2.068

just copying over the std.experimental code and using stock Phobos otherwise I have a problem compiling (arch linux 64):

Compiling using dmd...
phobos/std/experimental/allocator/building_blocks/allocator_list.d(307,20): Error: no property 'expand' for type 'shared(Mallocator)'
phobos/std/experimental/allocator/building_blocks/allocator_list.d(529,28): Error: template instance std.experimental.allocator.building_blocks.allocator_list.AllocatorList!(Factory, Mallocator) error instantiating
src/app.d(14,19): instantiated from here: AllocatorList!((a) => Region!Mallocator(1024 * 16), Mallocator)
FAIL .dub/build/application-debug-linux.posix-x86_64-dmd_2068-847B9437DBA5F4B7C25C9B215DF0D8E9/ containers executable
Error executing command build:
dmd failed with exit code 1.

any suggestions?

Concurrent containers?

How hard would it be to make these containers concurrent? A few locks here and there would do. A user defined lock could be used so only locking is needed, which also could be statically compiled in if the user defined lock is specified. (So no locking method specified = single threaded, else multi-threaded)

HashSet!(const(Object)) does not work

unittest
{
    static class Foo
    {
        string name;
    }

    hash_t stringToHash(string str) @safe pure nothrow @nogc
    {
        hash_t hash = 5381;
        return hash;
    }

    hash_t FooToHash(in Foo e) pure @safe nothrow @nogc
    {
        return stringToHash(e.name);
    }

    HashSet!(const(Foo), Mallocator, FooToHash) hs;
    const(Foo) f = new const Foo;
    hs.insert(f);
    assert(f in hs);
    auto r = hs.range();
}

not sure why this does not work. I test Rebindable separately and it work.

Can't use DynamicArray in @nogc code

struct HStorage
{
	import containers.dynamicarray: DynamicArray;

	DynamicArray!int storage;
}

@nogc
unittest
{
	auto hs = HStorage();	
}

fails with

Error: @nogc function 'hstorage.__unittestL11_10' cannot call non-@nogc destructor 'hstorage.HStorage.~this'

TreeMap.remove triggers assertion failure

When the TreeMap has only one entry (left), remove will trigger an assertion failure on ttree.d, line 48.

Code to reproduce:

import std.stdio;
import containers.treemap;

void main()
{
    TreeMap!(string, string) tm;

    // add two entries
    tm["test1"] = "hello";
    tm["test2"] = "world";

    // iterate: show two
    foreach(key, value; tm)
        writeln(key, " -> ", value);

    // remove one
    tm.remove("test1");

    // iterate: show one
    writeln("\niterating:");
    foreach(key, value; tm)
        writeln(key, " -> ", value);

    // remove the last one
    tm.remove("test2"); // this will crash with assertion failed, ttree.d (48)
}

HashSet compile error with 2.077.0

This example:

void main()
{
 static struct Foo {}
 import containers.hashset : HashSet;
 HashSet!Foo set; 
}

Fails to compile with:

......\Users\x\AppData\Roaming\dub\packages\emsi_containers-0.5.3\emsi_containers\src\containers\hashset.d(503): Error: cast(BucketNode*)current is not an lvalue
......\Users\x\AppData\Roaming\dub\packages\emsi_containers-0.5.3\emsi_containers\src\containers\hashset.d(337): Error: cast(Bucket[])oldBuckets is not an lvalue
..\source\app.d(76): Error: template instance containers.hashset.HashSet!(Foo, Mallocator, generateHash, false) error instantiating

Cannot Build with LDC 0.17.0

moveEmplaceAll is used in CyclicBuffer, which was introduced in 2.069, so now this cannot be built with LDC 0.17.0.

DynamicArray dtor problem

while working on remove for DynamicArray I ran into a problem.

class Cls {
    int* a;

    this(int* a) {
        this.a = a;
    }

    ~this() {
        ++(*a;)
    }
}

unittest {
    int a = 0;
    {
        DynamicArray!(Cls) arr;
        arr.insert(new Cls(&a));
    }
    assert(a == 1); // this fails
}

the dtor of the on cls is not called. Is this by design? I would say the typeof(T).destory in DynamicArray.dtor suggests otherwise.

DMD regression with the nightlies?

> dub test --compiler=/home/seb/dlang/dmd/generated/linux/release/64/dmd -v
/home/seb/dlang/dmd/generated/linux/release/64/dmd -c -of.dub/build/emsi_containers-test-library-unittest-linux.posix-x86_64-dmd_2075-8C76CBC0E842F261E6C615762480773B/emsi_containers-test-library.o -debug -g -unittest -w -version=VibeCustomMain -version=Have_emsi_containers -Isrc/ ../../../../tmp/dub_test_root-e9904ddf-e73e-4ac9-be2e-87e40e7135cf.d src/containers/cyclicbuffer.d src/containers/dynamicarray.d src/containers/hashmap.d src/containers/hashset.d src/containers/immutablehashset.d src/containers/internal/backwards.d src/containers/internal/element_type.d src/containers/internal/hash.d src/containers/internal/mixins.d src/containers/internal/node.d src/containers/internal/storage_type.d src/containers/openhashset.d src/containers/package.d src/containers/simdset.d src/containers/slist.d src/containers/treemap.d src/containers/ttree.d src/containers/unrolledlist.d -vcolumns
src/containers/treemap.d(33,3): Error: field tree must be initialized in constructor
src/containers/treemap.d(166,17): Error: template instance containers.treemap.TreeMap!(int, int, StatsCollector!(FreeList!(AllocatorList!(Factory, GCAllocator), 64LU, 64LU, cast(Flag)false), 262143LU, 0LU)*, "a < b", false, 64LU) error instantiating

minor enhancement request

for TreeMap (and others if applic) add .keys

so foreach(itemKey;container.keys)

Not a big deal since you can iterate by key/value pair.

foreach_reverse support

I have UnrolledList and I want to traverse this list in reverse order, but when I try to run this code:
foreach_reverse (Widget widget; widgetOrdering)
I get an error:

invalid foreach aggregate this.widgetOrdering, define opApply(), range primitives, or use .tupleof

Also container doesn't have method insertFront.

redundant const

containers/src/containers/ttree.d(193): Error: redundant attribute 'const'

Can Hashmap be used in @nogc code?

I thought that attribute inference would let HashMap be @nogc when using Mallocator?

Error: @nogc function 'dplug.gui.font.Font.getGlyphCoverage' cannot call non-@nogc function 'containers.hashmap.HashMap!(GlyphKey, Image!(Color!(ubyte, "l")), Mallocator, generateHash, true).HashMap.opBinaryRight!"in".opBinaryRight'

UnrolledList range value type

unittest
{
    UnrolledList!int list;
    list.insert(0);
    list.insert(0);
    list.insert(0);
    list.insert(0);
    list.insert(0);

    foreach(ref it; list.range) {
        it = 1;
    }

    foreach(it; list.range) {
        assert(it == 1);
    }
}

I think UnrolledList!int.Range.front needs to return ref int . But ref is sort of f*** up so I can't simple cast to ref int. @Hackerpilot ideas?

p.s. This only affects value types.
p.s.s HashMap is also affected

ttree.d doesn't build with 2.067.0-b2

containers/src/containers/ttree.d(491): Error: template instance sort!_less template 'sort' is not defined
containers/src/containers/ttree.d(528): Error: template instance sort!_less template 'sort' is not defined
containers/src/containers/ttree.d(491): Error: template instance sort!_less template 'sort' is not defined
containers/src/containers/ttree.d(528): Error: template instance sort!_less template 'sort' is not defined
src/autocomplete.d(167): Error: template instance containers.ttree.TTree!(SearchResult, false, "a < b", true, 64LU) error instantiating
src/autocomplete.d(131): Error: function autocomplete.symbolSearch no return exp; or assert(0); at end of function
containers/src/containers/ttree.d(491): Error: template instance sort!_less template 'sort' is not defined
containers/src/containers/ttree.d(528): Error: template instance sort!_less template 'sort' is not defined

Some common interfaces are missing

For example, HashMap doesn't have .byKey, .byValue, HashSet doesn't have opApply, etc.

Are those deliberately left out, or are there plans to implement them in the future? If it's the latter case, are you accepting pull requests? I really want to contribute to this project.

Duplicate items in HashSet

In HashSet.Bucket.insert. Not all BucketNodes are checked for duplication before insert.

i.e. the loop should look like this:

for (BucketNode* current = root; current !is null; current = current.next)
    if (current.get(n) !is null)
        return false;
for (BucketNode* current = root; current !is null; current = current.next)
    if (current.l < current.items.length)
    {
        current.insert(n);
        return true;
    }

HashMap opApply const key and const

HashMap!(string,string) hm;

foreach(ref string key, ref string value) {
    key = "WAT";  // this assignment should not be possible
}

also foreach (opApply) does not work for const(HashMap)

and opApply does not work with safe code

Disabled Copy Constructors

Returning a container from a function is currently not allowed because of

this(this) @disable;

Is there a reason for this?

HashSet with class nothrow

I'm trying to put a class into a HashSet but it keeps telling me something are not nothrow even though the code I created is nothrow. Maybe it's to late right now or I'm just stupid. Anyway, I could need some help.

import containers.hashset;

import std.experimental.allocator.mallocator : Mallocator;

private hash_t stringToHash(string str) @safe pure nothrow @nogc {
    hash_t hash = 5381;
    return hash;
}

hash_t FooToHash(Foo e) pure @safe nothrow @nogc {
    return stringToHash(e.name);
}

class Foo {
    string name;
}

void main() {
    HashSet!(Foo, Mallocator, FooToHash) hs;
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.