项目作者: atilaneves

项目描述 :
C++-style automatic memory management smart pointers for D
高级语言: D
项目地址: git://github.com/atilaneves/automem.git
创建时间: 2017-03-13T01:51:21Z
项目社区:https://github.com/atilaneves/automem

开源协议:BSD 3-Clause "New" or "Revised" License

下载


automem - smart pointers for D

Build Status
Coverage
Open on run.dlang.io

C++-style automatic memory management smart pointers for D using std.experimental.allocator.

Unlike the C++ variants, the smart pointers themselves allocate the memory for the objects they contain.
That ensures the right allocator is used to dispose of the memory as well.

Allocators are template arguments instead of using theAllocator so
that these smart pointers can be used in @nogc code. However, they
will default to typeof(theAllocator) for simplicity. The examples
above will be explicit.

Another reason to have to pass in the type of allocator is to decide how it is to
be stored. Stateless allocators can be “stored” by value and imply zero-cost Unique pointers.
Singleton allocators such as Mallocator (that have an instance attribute/member function)
don’t need to be passed in to the constructor. This is detected at compile-time as an example
of design by instrospection.

RefCounted leverages D’s type system by doing atomic reference counting iff the type of the contained
object is shared. Otherwise it’s non-atomic.

Sample code:

  1. @safe unittest {
  2. import std.algorithm: move;
  3. static struct Point {
  4. int x;
  5. int y;
  6. }
  7. // set theAllocator as desired beforehand, e.g.
  8. // theAllocator = allocatorObject(Mallocator.instance)
  9. {
  10. // must pass arguments to initialise the contained object
  11. auto u1 = Unique!Point(2, 3);
  12. assert(*u1 == Point(2, 3));
  13. assert(u1.y == 3);
  14. // auto u2 = u1; // won't compile, can only move
  15. typeof(u1) u2 = () @trusted { return u1.move; }();
  16. assert(cast(bool)u1 == false); // u1 is now empty
  17. }
  18. // memory freed for the Point structure created in the block
  19. {
  20. auto s1 = RefCounted!Point(4, 5);
  21. assert(*s1 == Point(4, 5));
  22. assert(s1.x == 4);
  23. {
  24. auto s2 = s1; // can be copied
  25. } // ref count goes to 1 here
  26. } // ref count goes to 0 here, memory released
  27. {
  28. import std.algorithm: map;
  29. import std.range: iota;
  30. // `vector` is also known as `array`
  31. auto vec = vector(Point(1, 2), Point(3, 4), Point(5, 6));
  32. assert(equal(vec.range, [Point(1, 2), Point(3, 4), Point(5, 6)]));
  33. vec.length = 1;
  34. assert(equal(vec.range, [Point(1, 2)]));
  35. vec ~= Point(7, 8);
  36. assert(equal(vec.range, [Point(1, 2), Point(7, 8)]));
  37. vec ~= 2.iota.map!(i => Point(i + 10, i + 11));
  38. assert(equal(vec.range, [Point(1, 2), Point(7, 8), Point(10, 11), Point(11, 12)]));
  39. } // memory for the array released here
  40. }
  41. // @nogc test - must explicitly use the allocator for compile-time guarantees
  42. @system @nogc unittest {
  43. import stdx.allocator.mallocator: Mallocator;
  44. static struct Point {
  45. int x;
  46. int y;
  47. }
  48. {
  49. // must pass arguments to initialise the contained object
  50. auto u1 = Unique!(Point, Mallocator)(2, 3);
  51. assert(*u1 == Point(2, 3));
  52. assert(u1.y == 3);
  53. }
  54. // memory freed for the Point structure created in the block
  55. // similarly for the other types
  56. }