1 module carbon.memory;
2 
3 import carbon.functional;
4 
5 import core.exception;
6 import core.stdc.stdlib;
7 import core.memory;
8 
9 import std.algorithm;
10 import std.conv;
11 import std.stdio;
12 import std.exception;
13 import std.range;
14 import std.traits;
15 import std.typecons;
16 
17 
18 void callAllPostblit(T)(ref T obj)
19 if(is(T == struct))
20 {
21     foreach(ref e; obj.tupleof)
22         callAllPostblit(e);
23 
24     static if(is(typeof(obj.__postblit())))
25         obj.__postblit();
26 }
27 
28 
29 void callAllPostblit(T)(ref T obj)
30 if(!is(T == struct))
31 {}
32 
33 
34 void callAllDtor(T)(ref T obj)
35 if(is(T == struct))
36 {
37     static if(is(typeof(obj.__dtor())))
38         obj.__dtor();
39 
40     foreach(ref e; obj.tupleof)
41         callAllDtor(e);
42 }
43 
44 
45 void callAllDtor(T)(ref T obj)
46 if(!is(T == struct))
47 {}
48 
49 
50 
51 // copy from core.exception
52 extern (C) void onOutOfMemoryError(void* pretend_sideffect = null) @nogc @trusted pure nothrow /* dmd @@@BUG11461@@@ */
53 {
54     // NOTE: Since an out of memory condition exists, no allocation must occur
55     //       while generating this object.
56     throw cast(OutOfMemoryError) cast(void*) typeid(OutOfMemoryError).init;
57 }
58 
59 
60 private
61 E[] uninitializedCHeapArray(E)(size_t n) @trusted nothrow
62 {
63     if(n){
64         auto p = cast(E*)core.stdc.stdlib.malloc(n * E.sizeof);
65         if(p is null)
66             onOutOfMemoryError();
67 
68       static if(hasIndirections!E)
69       {
70         core.stdc..string.memset(p, 0, n * E.sizeof);
71         GC.addRange(p, n * E.sizeof);
72       }
73 
74         return p[0 .. n];
75     }else
76         return null;
77 }
78 
79 
80 private
81 void destroyCHeapArray(E)(ref E[] arr) nothrow @nogc
82 {
83     static if(hasElaborateDestructor!E)
84         foreach(ref e; arr)
85             callAllDtor(e);
86 
87     static if(hasIndirections!T)
88         GC.removeRange(arr.ptr);
89 
90     assumeTrusted!(core.stdc.stdlib.free)(arr.ptr);
91     arr = null;
92 }
93 
94 
95 private
96 void reallocCHeapArray(E)(ref E[] arr, size_t n)
97 {
98     if(n <= arr.length)     // n == 0 なら常に return される
99         return;
100 
101     immutable oldLen = arr.length;
102 
103   static if(hasIndirections!T)
104   {
105     auto newarr = uninitializedCHeapArray!E(n);
106     assumeTrusted!(core.stdc..string.memcpy)(newarr.ptr, arr.ptr, E.sizeof * oldLen);
107     assumeTrusted!(core.stdc..string.memset)(assumeTrusted!"a+b"(newarr.ptr + oldLen), 0, (n - oldLen) * E.sizeof);
108     GC.addRange(newarr.ptr, n * E.sizeof);
109     GC.removeRange(arr.ptr);
110     assumeTrusted!(core.stdc.stdlib.free)(arr.ptr);
111 
112     arr = newarr;
113   }
114   else
115   {
116     void* p = assumeTrusted!(core.stdc.stdlib.realloc)(arr.ptr, n * E.sizeof);
117     if(p is null)
118         onOutOfMemoryError();
119 
120     arr = assumeTrusted!((a, b) => (cast(E*)a)[0 .. b])(p, n);
121   }
122 }
123 
124 
125 auto onGCMemory(T)(T obj)
126 {
127     static struct Result {
128         alias _val this;
129         ref inout(T) _val() inout pure nothrow @safe @property { return *_v; }
130         T* _v;
131     }
132 
133     Result res = Result(new T);
134     *res._v = obj;
135     return res;
136 }
137 
138 unittest
139 {
140     auto r = [1, 2, 3, 4, 5].map!"a+2".onGCMemory;
141 
142     static void popN(R)(R r, size_t n)
143     {
144         foreach(i; 0 .. n) r.popFront();
145     }
146 
147     assert(equal(r.save, [3, 4, 5, 6, 7]));
148     popN(r, 2);
149     assert(equal(r.save, [5, 6, 7]));
150 }
151 
152 
153 /**
154 Defines a reference-counted object containing a $(D T) value as
155 payload. $(D RefCountedNoGC) keeps track of all references of an object,
156 and when the reference count goes down to zero, frees the underlying
157 store. $(D RefCountedNoGC) uses $(D malloc) and $(D free) for operation.
158 
159 $(D RefCountedNoGC) is unsafe and should be used with care. No references
160 to the payload should be escaped outside the $(D RefCountedNoGC) object.
161 
162 The $(D autoInit) option makes the object ensure the store is
163 automatically initialized. Leaving $(D autoInit ==
164 RefCountedAutoInitialize.yes) (the default option) is convenient but
165 has the cost of a test whenever the payload is accessed. If $(D
166 autoInit == RefCountedAutoInitialize.no), user code must call either
167 $(D refCountedStore.isInitialized) or $(D refCountedStore.ensureInitialized)
168 before attempting to access the payload. Not doing so results in null
169 pointer dereference.
170 
171 Example:
172 ----
173 // A pair of an $(D int) and a $(D size_t) - the latter being the
174 // reference count - will be dynamically allocated
175 auto rc1 = RefCountedNoGC!int(5);
176 assert(rc1 == 5);
177 // No more allocation, add just one extra reference count
178 auto rc2 = rc1;
179 // Reference semantics
180 rc2 = 42;
181 assert(rc1 == 42);
182 // the pair will be freed when rc1 and rc2 go out of scope
183 ----
184  */
185 struct RefCountedNoGC(T, RefCountedAutoInitialize autoInit =
186         RefCountedAutoInitialize.yes)
187 if (!is(T == class))
188 {
189     /// $(D RefCountedNoGC) storage implementation.
190     struct RefCountedStore
191     {
192         private struct Impl
193         {
194             T _payload;
195             size_t _count;
196         }
197 
198         private Impl* _store;
199 
200         private void initialize(A...)(auto ref A args)
201         {
202             import core.memory : GC;
203             import core.stdc.stdlib : malloc;
204             import std.conv : emplace;
205             import std.exception : enforce;
206 
207             _store = cast(Impl*)malloc(Impl.sizeof);
208             if(!_store)
209                 onOutOfMemoryError();
210 
211             static if (hasIndirections!T)
212                 GC.addRange(&_store._payload, T.sizeof);
213             emplace(&_store._payload, args);
214             _store._count = 1;
215         }
216 
217         /**
218            Returns $(D true) if and only if the underlying store has been
219            allocated and initialized.
220         */
221         @property nothrow @safe @nogc
222         bool isInitialized() const
223         {
224             return _store !is null;
225         }
226 
227         /**
228            Returns underlying reference count if it is allocated and initialized
229            (a positive integer), and $(D 0) otherwise.
230         */
231         @property nothrow @safe @nogc
232         size_t refCount() const
233         {
234             return isInitialized ? _store._count : 0;
235         }
236 
237         /**
238            Makes sure the payload was properly initialized. Such a
239            call is typically inserted before using the payload.
240         */
241         void ensureInitialized()
242         {
243             if (!isInitialized) initialize();
244         }
245 
246     }
247     RefCountedStore _refCounted;
248 
249     /// Returns storage implementation struct.
250     @property nothrow @safe
251     ref inout(RefCountedStore) refCountedStore() inout
252     {
253         return _refCounted;
254     }
255 
256 /**
257 Constructor that initializes the payload.
258 
259 Postcondition: $(D refCountedStore.isInitialized)
260  */
261     this(A...)(auto ref A args) if (A.length > 0)
262     {
263         _refCounted.initialize(args);
264     }
265 
266 /**
267 Constructor that tracks the reference count appropriately. If $(D
268 !refCountedStore.isInitialized), does nothing.
269  */
270     this(this)
271     {
272         if (!_refCounted.isInitialized) return;
273         ++_refCounted._store._count;
274     }
275 
276 /**
277 Destructor that tracks the reference count appropriately. If $(D
278 !refCountedStore.isInitialized), does nothing. When the reference count goes
279 down to zero, calls $(D destroy) agaist the payload and calls $(D free)
280 to deallocate the corresponding resource.
281  */
282     ~this()
283     {
284         if (!_refCounted.isInitialized) return;
285         assert(_refCounted._store._count > 0);
286         if (--_refCounted._store._count)
287             return;
288         // Done, deallocate
289         static if(hasElaborateDestructor!T)
290             callAllDtor(_refCounted._store._payload);
291 
292         static if (hasIndirections!T)
293         {
294             import core.memory : GC;
295             GC.removeRange(&_refCounted._store._payload);
296         }
297         import core.stdc.stdlib : free;
298         free(_refCounted._store);
299         _refCounted._store = null;
300     }
301 
302 /**
303 Assignment operators
304  */
305     void opAssign(typeof(this) rhs)
306     {
307         import std.algorithm : swap;
308 
309         swap(_refCounted._store, rhs._refCounted._store);
310     }
311 
312 /// Ditto
313     void opAssign(T rhs)
314     {
315         import std.algorithm : move;
316 
317         static if (autoInit == RefCountedAutoInitialize.yes)
318         {
319             _refCounted.ensureInitialized();
320         }
321         else
322         {
323             assert(_refCounted.isInitialized);
324         }
325         move(rhs, _refCounted._store._payload);
326     }
327 
328     //version to have a single properly ddoc'ed function (w/ correct sig)
329     version(StdDdoc)
330     {
331         /**
332         Returns a reference to the payload. If (autoInit ==
333         RefCountedAutoInitialize.yes), calls $(D
334         refCountedStore.ensureInitialized). Otherwise, just issues $(D
335         assert(refCountedStore.isInitialized)). Used with $(D alias
336         refCountedPayload this;), so callers can just use the $(D RefCountedNoGC)
337         object as a $(D T).
338 
339         $(BLUE The first overload exists only if $(D autoInit == RefCountedAutoInitialize.yes).)
340         So if $(D autoInit == RefCountedAutoInitialize.no)
341         or called for a constant or immutable object, then
342         $(D refCountedPayload) will also be qualified as safe and nothrow
343         (but will still assert if not initialized).
344          */
345         @property
346         ref T refCountedPayload();
347 
348         /// ditto
349         @property nothrow @safe
350         ref inout(T) refCountedPayload() inout;
351     }
352     else
353     {
354         static if (autoInit == RefCountedAutoInitialize.yes)
355         {
356             //Can't use inout here because of potential mutation
357             @property
358             ref T refCountedPayload()
359             {
360                 _refCounted.ensureInitialized();
361                 return _refCounted._store._payload;
362             }
363         }
364 
365         @property nothrow @safe
366         ref inout(T) refCountedPayload() inout
367         {
368             assert(_refCounted.isInitialized, "Attempted to access an uninitialized payload.");
369             return _refCounted._store._payload;
370         }
371     }
372 
373 /**
374 Returns a reference to the payload. If (autoInit ==
375 RefCountedAutoInitialize.yes), calls $(D
376 refCountedStore.ensureInitialized). Otherwise, just issues $(D
377 assert(refCountedStore.isInitialized)).
378  */
379     alias refCountedPayload this;
380 }
381 
382 
383 auto toRefCounted(T)(T obj)
384 {
385     return RefCountedNoGC!T(obj);
386 }
387 
388 
389 @nogc unittest
390 {
391     auto r = only(1, 2, 3, 4, 5).map!"a+2".toRefCounted;
392 
393     static void popN(R)(R r, size_t n)
394     {
395         foreach(i; 0 .. n) r.popFront();
396     }
397 
398     assert(equal(r.save, only(3, 4, 5, 6, 7)));
399     popN(r, 2);
400     assert(equal(r.save, only(5, 6, 7)));
401 }
402 
403 
404 __EOF__
405 
406 
407 struct UniqueArray(E, bool bMini = false)
408 {
409     private static
410     size_t allocateSize(size_t n) pure nothrow @safe @nogc
411     {
412       static if(bMini)
413         return n;
414       else
415         return 1 << (core.bitop.bsr(n) + 1);
416     }
417 
418 
419     /**
420     */
421     this(size_t n) nothrow @trusted
422     {
423         immutable elemN = allocateSize(n);
424 
425         auto arr = uninitializedCHeapArray!(Unqual!(E))(elemN);
426         foreach(ref e; arr)
427             .emplace(&e);
428 
429         _array = cast(E[])arr;
430         _s = 0;
431         _e = n;
432     }
433 
434 
435   static if(is(typeof((Unqual!E v){ E x = v; })))
436   {
437     this(bool b)(UniqueArray!(Unqual!E, b) unique) @trusted
438     {
439         _array = cast(E[])unique._array;
440         _s = unique._s;
441         _e = unique._e;
442 
443         unique._array = null;
444     }
445 
446 
447     void opAssign(bool b)(UniqueArray!(const(E), b) unique) @trusted
448     {
449         //.destroy(this);
450         callAllDtor(this);
451 
452         _array = cast(E[])unique._array;
453         _s = unique._s;
454         _e = unique._e;
455 
456         unique._array = null;
457     }
458   }
459 
460 
461   static if(is(typeof((const E v){ E x = v; })))
462   {
463     this(bool b)(UniqueArray!(const(E), b) unique) @trusted
464     {
465         _array = cast(E[])unique._array;
466         _s = unique._s;
467         _e = unique._e;
468 
469         unique._array = null;
470     }
471 
472 
473     void opAssign(bool b)(UniqueArray!(const(E), b) unique) @trusted
474     {
475         //.destroy(this);
476         callAllDtor(this);
477 
478         _array = cast(E[])unique._array;
479         _s = unique._s;
480         _e = unique._e;
481 
482         unique._array = null;
483     }
484   }
485 
486 
487   static if(is(typeof((immutable E v){ E x = v; })))
488   {
489     this(bool b)(UniqueArray!(immutable(E), b) unique) @trusted
490     {
491         _array = cast(E[])unique._array;
492         _s = unique._s;
493         _e = unique._e;
494 
495         unique._array = null;
496     }
497 
498 
499     void opAssign(bool b)(UniqueArray!(immutable(E), b) unique) @trusted
500     {
501         //.destroy(this);
502         callAllDtor(this);
503 
504         _array = cast(E[])unique._array;
505         _s = unique._s;
506         _e = unique._e;
507 
508         unique._array = null;
509     }
510   }
511 
512 
513     ~this()
514     {
515         if(_array !is null){
516           static if(hasElaborateDestructor!E)
517             foreach(ref e; _array)
518                 callAllDtor(e);
519                 //.destroy(e);
520 
521           static if(hasIndirections!E)
522             GC.removeRange(_array.ptr);
523 
524             core.stdc.stdlib.free(cast(void*)_array.ptr);
525             _array = null;
526         }
527     }
528 
529     // can copy
530   static if(is(typeof((E v){ E x = v; })))
531   {
532     this(this)
533     {
534         immutable elemN = (_s == 0 && _e == _array.length) ? _array.length : allocateSize(this.length);
535 
536         auto newarr = uninitializedCHeapArray!(Unqual!E)(elemN);
537         assumeTrusted!((p){
538             foreach(i, ref e; this.view)
539                 emplace(p + i, e);
540         })(newarr.ptr);
541 
542         _array = cast(E[])newarr;
543         _e -= _s;
544         _s = 0;
545     }
546 
547 
548     void opAssign(typeof(this) unique)
549     {
550         swap(this, unique);
551     }
552   }
553   else{
554     @disable this(this);
555     @disable void opAssign(typeof(this) unique);
556   }
557 
558 
559     size_t length() const pure nothrow @safe @nogc @property
560     {
561         return _e - _s;
562     }
563 
564 
565     size_t capacity() const pure nothrow @safe @nogc @property
566     {
567         return _array.length - _e;
568     }
569 
570 
571     size_t reserve(size_t n) @nogc
572     {
573         if(_array is null){
574             auto newArr = typeof(this)(n);
575             this._array = newArr._array;
576             this._s = newArr._s;
577             this._e = newArr._e;
578             newArr._array = null;
579 
580             return this.capacity;
581         }
582         else if(n <= _array.length - _s)
583             return this.capacity;
584         else{
585             immutable newElemN = allocateSize(n);
586             immutable newAllocN = newElemN * E.sizeof;
587 
588             auto p = cast(Unqual!E*)core.stdc.stdlib.malloc(newAllocN);
589             if(!p)
590                 onOutOfMemoryError();
591 
592             core.stdc..string.memcpy(p, _array.ptr + _s, this.length * E.sizeof);
593 
594           static if(hasIndirections!E)
595           {
596             core.stdc..string.memset(p + this.length, 0, (newElemN - this.length) * E.sizeof);
597             GC.addRange(p, newAllocN);
598             GC.removeRange(_array.ptr);
599           }
600 
601             core.stdc.stdlib.free(cast(Unqual!E*)_array.ptr);
602             _array = (cast(E*)p)[0 .. newElemN];
603             _e -= _s;
604             _s = 0;
605 
606             return this.capacity;
607         }
608     }
609 
610 
611     E[] view() pure nothrow @safe @nogc
612     {
613         return _array;
614     }
615 
616 
617   private:
618     E[] _array ;
619     size_t _s, _e;
620 }
621 
622 
623 unittest{
624     UniqueArray!int arr;
625 
626     auto rc = RefCountedNoGC!(UniqueArray!int)(3);
627 }
628 
629 
630 struct RefCountedArrayImpl(E)
631 {
632     this(size_t n) nothrow @trusted @nogc
633     {
634         _refCnt = uninitializedCHeapArray!size_t(1).ptr;
635         *_refCnt = 1;
636         _array = newCHeapArray!E(n);
637     }
638 
639 
640     bool isInitialized() const pure nothrow @safe @nogc @property
641     {
642         return _refCnt !is null;
643     }
644 
645 
646     size_t refCount() const pure nothrow @safe @nogc @property
647     {
648         return isInitialized ? *_refCnt : 0;
649     }
650 
651 
652     this(this) pure nothrow @safe @nogc
653     {
654         if(isInitialized)
655             ++*_refCnt;
656     }
657 
658 
659   static if(is(typeof(() @safe { E e; })))
660   {
661     ~this() @trusted
662     { dtorImpl(); }
663   }
664   else
665   {
666     ~this()
667     { dtorImpl(); }
668   }
669 
670 
671     void dtorImpl()
672     {
673         if(isInitialized){
674             --*_refCnt;
675             if(refCount == 0){
676                 size_t[] dummy = _refCnt[0 .. 1];
677 
678                 dummy.destroyCHeapArray();   // nothrow
679                 _refCnt = null;
680 
681                 _array.destroyCHeapArray();  // maybe throw
682             }
683         }
684     }
685 
686 
687     void reallocate(size_t n)
688     {
689         _array.reallocCHeapArray(n);
690     }
691 
692 
693   private:
694     size_t* _refCnt;
695     E[] _array;
696 }
697 
698 
699 /**
700 Cヒープ上に配列を作成し、その配列を参照カウント方式で管理します。
701 配列への追加は、スライスと同様にCopy On Write方式で管理されます。
702 つまり、複数のオブジェクトが一つの配列を参照している場合に配列への要素の追加を行うと、必ず配列は新たに確保されます。
703 */
704 struct RefCountedArray(E)
705 {
706     alias Impl = RefCountedArrayImpl;
707 
708 
709     /**
710     大きさを指定して配列を作成します。
711     */
712     this(size_t n)
713     {
714         _impl = Impl!E(allocateSize!E(n));
715         _s = 0;
716         _e = n;
717     }
718 
719 
720     /**
721     保持している参照を解除します。
722     よって、参照カウントは一つ減ります。
723     */
724     void release()
725     {
726         _impl = Impl!E.init;
727         _s = 0;
728         _e = 0;
729     }
730 
731 
732     /**
733     */
734     void clear()
735     {
736         if(_impl.refCount == 1){
737             _s = 0;
738             _e = 0;
739         }else
740             release();
741     }
742 
743 
744     /**
745     */
746     size_t capacity() const pure nothrow @safe @nogc @property
747     {
748         if(_impl.refCount == 1)
749             return _impl._array.length - _s;
750         else
751             return 0;
752     }
753 
754 
755     /**
756     */
757     size_t reserve(size_t n)
758     {
759         if(n <= this.length)
760             goto Lreturn;
761 
762         if(!_impl.isInitialized)
763             this = typeof(this)(n);
764         else if(_impl.refCount == 1 && _impl._array.length < n + _s){
765             immutable bool doesMoveToFront = (_s * 2 >= allocateSize!E(n) - _impl._array.length);
766 
767             if(!doesMoveToFront || _impl._array.length < n)
768                 _impl.reallocate(allocateSize!E(n));
769 
770             if(doesMoveToFront){
771                 foreach(i; 0 .. this.length){
772                   static if(is(E == struct) && !__traits(isPOD, E))
773                     _impl._array[i] = std.algorithm.move(_impl._array[_s + i]);
774                   else
775                     _impl._array[i] = _impl._array[_s + i];
776                 }
777 
778                 _e -= _s;
779                 _s = 0;
780             }
781         }
782         else if(_impl.refCount != 1){
783             auto newarr = typeof(this)(n);
784             newarr._impl._array[0 .. this.length] = this._impl._array[_s .. _e];
785             this = newarr;
786         }
787 
788       Lreturn:
789         return this.capacity;
790     }
791 
792 
793     /**
794     */
795     bool isNull() const pure nothrow @safe @nogc @property
796     {
797         return !_impl.isInitialized;
798     }
799 
800 
801     /**
802     代入演算子です。
803     このオブジェクトに&(D null)を代入すると、$(D release)を呼び出したことと等価になります。
804     */
805     void opAssign(typeof(null))
806     {
807         release();
808     }
809 
810 
811     /// array, range primitives
812     ref inout(E) front() inout pure nothrow @safe @nogc @property
813     {
814         return _impl._array[_s];
815     }
816 
817 
818     /// ditto
819     ref inout(E) back() inout pure nothrow @safe @nogc @property
820     {
821         return _impl._array[_e-1];
822     }
823 
824 
825     /// ditto
826     bool empty() const pure nothrow @safe @nogc @property
827     {
828         return !_impl.isInitialized || _s == _e;
829     }
830 
831 
832     /// ditto
833     void popFront()
834     {
835         ++_s;
836 
837         if(this.empty)
838             this.clear();
839     }
840 
841 
842     /// ditto
843     void popBack()
844     {
845         --_e;
846 
847         if(this.empty)
848             this.clear();
849     }
850 
851 
852     /// ditto
853     auto save() @property
854     {
855         return this;
856     }
857 
858 
859     /// ditto
860     ref inout(E) opIndex(size_t i) inout pure nothrow @safe @nogc
861     in{
862         assert(i < this.length);
863     }
864     body{
865         return _impl._array[_s + i];
866     }
867 
868 
869     /// ditto
870     auto opSlice()
871     {
872         return this;
873     }
874 
875 
876     /// ditto
877     size_t length() const pure nothrow @safe @nogc @property
878     {
879         return _e - _s;
880     }
881 
882 
883     /// ditto
884     alias opDollar = length;
885 
886 
887     /// ditto
888     void length(size_t n) @property
889     {
890         reserve(n);
891         _e = _s + n;
892     }
893 
894 
895     /// ditto
896     RefCountedArray!E dup() @property
897     {
898         auto dst = typeof(return)(this.length);
899         dst._impl._array[0 .. this.length] = this._impl._array[_s .. _e];
900         return dst;
901     }
902 
903 
904   static if(is(const(E) : E))
905   {
906     /// ditto
907     RefCountedArray!E dup() const @property
908     {
909         auto dst = typeof(return)(this.length);
910         dst._impl._array[0 .. this.length] = this._impl._array[_s .. _e];
911         return dst;
912     }
913   }
914 
915 
916     /// ditto
917     inout(E)[] view() inout pure nothrow @safe @nogc @property
918     {
919         return _impl._array[_s .. _e];
920     }
921 
922 
923     /// ditto
924     auto opSlice(size_t i, size_t j)
925     in{
926         immutable len = this.length;
927         assert(i <= len);
928         assert(j <= len);
929         assert(i <= j);
930     }
931     body{
932         auto dst = this;
933         dst._s += i;
934         dst._e = dst._s + (j - i);
935         return dst;
936     }
937 
938 
939     /// ditto
940     void opOpAssign(string op : "~")(E v)
941     {
942         this.length = this.length + 1;
943         this.back = v;
944     }
945 
946 
947     /// ditto
948     typeof(this) opBinary(string op : "~")(E v)
949     {
950         if(_impl.refCount == 1 && this.capacity != this.length){
951             auto dst = this;
952             dst._e += 1;
953             dst.back = v;
954             return dst;
955         }
956         else{
957             auto dst = this;
958             dst ~= v;
959             return dst;
960         }
961     }
962 
963 
964     /// ditto
965     typeof(this) opBinaryRight(string op : "~")(E v)
966     {
967         if(_impl.refCount == 1 && _s >= 1){
968             auto dst = this;
969             dst._s -= 1;
970             dst.front = v;
971             return dst;
972         }
973         else{
974             typeof(this) dst;
975             dst.reserve(1 + this.length);
976             dst ~= v;
977             dst ~= this.view;
978             return dst;
979         }
980     }
981 
982 
983     /// ditto
984     void opOpAssign(string op : "~")(E[] arr)
985     {
986         immutable oldLen = this.length;
987         this.length = oldLen + arr.length;
988         this._impl._array[oldLen .. this.length] = arr[0 .. $];
989     }
990 
991 
992     /// ditto
993     typeof(this) opBinary(string op : "~")(E[] arr)
994     {
995         immutable len = arr.length;
996         if(_impl.refCount <= 1 && this.capacity >= this.length + len){
997             auto dst = this;
998             dst._e += len;
999             dst._impl._array[this._e .. dst._e] = arr[0 .. $];
1000             return dst;
1001         }
1002         else{
1003             auto dst = this;
1004             dst ~= arr;
1005             return dst;
1006         }
1007     }
1008 
1009 
1010     /// ditto
1011     typeof(this) opBinaryRight(string op : "~")(E[] arr)
1012     {
1013         immutable len = arr.length;
1014         if(_impl.refCount == 1 && _s >= len){
1015             auto dst = this;
1016             dst._s -= len;
1017             dst._impl._array[dst._s .. this._s] = arr[0 .. $];
1018             return dst;
1019         }
1020         else{
1021             typeof(this) dst;
1022             dst.reserve(len + this.length);
1023             dst ~= arr;
1024             dst ~= this.view;
1025             return dst;
1026         }
1027     }
1028 
1029 
1030     /// ditto
1031     void opOpAssign(string op : "~")(typeof(this) src)
1032     {
1033         this ~= src.view;
1034     }
1035 
1036 
1037     /// ditto
1038     typeof(this) opBinary(string op : "~")(typeof(this) src)
1039     {
1040         return this ~ src.view;
1041     }
1042 
1043 
1044     /// ditto
1045     void opOpAssign(string op : "~", R)(R range)
1046     if(isInputRange!R && is(ElementType!R : E) && !isInfinite!R)
1047     {
1048       static if(hasLength!R)
1049       {
1050         immutable oldLen = this.length,
1051                   rangeLen = range.length;
1052         this.length = oldLen + rangeLen;
1053 
1054         foreach(i; 0 .. rangeLen){
1055             assert(!range.empty);
1056             _impl._array[_s + oldLen + i] = range.front;
1057             range.popFront();
1058         }
1059       }
1060       else
1061       {
1062         if(_impl.isInitialized)
1063             this = this.dup;
1064         else
1065             this = typeof(this)(0);
1066 
1067         assert(this._impl.refCount == 1);
1068         assert(this._s == 0);
1069 
1070         while(!range.empty){
1071             immutable remN = this._impl._array.length - _e;
1072 
1073             size_t cnt;
1074             foreach(i; 0 .. remN){
1075                 if(range.empty)
1076                     break;
1077 
1078                 this._impl._array[_e + i] = range.front;
1079                 ++cnt;
1080                 range.popFront();
1081             }
1082             _e += cnt;
1083 
1084             if(cnt == remN && !range.empty)
1085                 reserve(_e + 1);
1086         }
1087       }
1088     }
1089 
1090 
1091     /// ditto
1092     typeof(this) opBinary(string op : "~", R)(R range)
1093     if(isInputRange!R && is(ElementType!R : E) && !isInfinite!R)
1094     {
1095       static if(hasLength!R)
1096       {
1097         immutable len = range.length;
1098         if(_impl.refCount <= 1 && this.capacity >= this.length + len){
1099             auto dst = this;
1100             dst._e += len;
1101             foreach(i; 0 .. len){
1102                 dst._impl._array[this._e + i] = range.front;
1103                 range.popFront();
1104             }
1105             return dst;
1106         }
1107       }
1108       
1109         auto dst = this;
1110         dst ~= range;
1111         return this ~ dst;
1112     }
1113 
1114 
1115     /// ditto
1116     typeof(this) opBinaryRight(string op : "~", R)(R range)
1117     if(isInputRange!R && is(ElementType!R : E) && !isInfinite!R && !is(typeof(range.opBinary!"~"(this))))
1118     {
1119       static if(hasLength!R)
1120       {
1121         immutable len = range.length;
1122         if(_impl.refCount <= 1 && _s >= len){
1123             auto dst = this;
1124             dst._s -= len;
1125             foreach(i; 0 .. len){
1126                 dst._impl._array[dst._s + i] = range.front;
1127                 range.popFront();
1128             }
1129             return dst;
1130         }
1131 
1132         typeof(this) dst;
1133         dst.reserve(this.length + len);
1134         dst ~= range;
1135         dst ~= this.view;
1136         return dst;
1137       }
1138       else
1139       {
1140         typeof(this) dst;
1141         dst ~= range;
1142         return this ~ dst;
1143       }
1144     }
1145 
1146 
1147     /// ditto
1148     int opCmp(R)(auto ref R r)
1149     if(isForwardRange!R && is(typeof(r.front < this.front)))
1150     {
1151         return std.algorithm.cmp(this.view, r.save);
1152     }
1153 
1154 
1155     /// ditto
1156     bool opEquals(R)(auto ref R r)
1157     if(isForwardRange!R && is(typeof(r.front == this.front)))
1158     {
1159         return std.algorithm.equal(this.view, r.save);
1160     }
1161 
1162 
1163   private:
1164     Impl!E _impl;
1165     size_t _s, _e;
1166 }
1167 
1168 
1169 /*nothrow @safe @nogc*/ unittest{
1170     auto arr1 = RefCountedArray!int(0);
1171     static assert(isInputRange!(typeof(arr1)));
1172     static assert(isForwardRange!(typeof(arr1)));
1173     static assert(isRandomAccessRange!(typeof(arr1)));
1174     static assert(hasLength!(typeof(arr1)));
1175     static assert(hasSlicing!(typeof(arr1)));
1176 
1177     assert(arr1.length == 0);
1178     assert(equal(arr1, cast(int[])[]));
1179     assert(!arr1.isNull);
1180 
1181     arr1 ~= 1;
1182     assert(arr1.length == 1);
1183     assert(equal(arr1, only(1)));
1184     assert(!arr1.isNull);
1185 
1186     arr1 ~= only(2, 3);
1187     assert(arr1.length == 3);
1188     assert(equal(arr1, only(1, 2, 3)));
1189     assert(!arr1.isNull);
1190 
1191     arr1 ~= arr1;
1192     assert(arr1.length == 6);
1193     assert(equal(arr1, only(1, 2, 3, 1, 2, 3)));
1194     assert(!arr1.isNull);
1195 
1196     arr1 = arr1[2 .. $-1];
1197     assert(arr1.length == 3);
1198     assert(equal(arr1, only(3, 1, 2)));
1199     assert(!arr1.isNull);
1200 
1201     arr1 = arr1.dup;
1202     assert(arr1.length == 3);
1203     assert(equal(arr1, only(3, 1, 2)));
1204     assert(!arr1.isNull);
1205 
1206     arr1 = null;
1207     assert(arr1.isNull);
1208 
1209     arr1 ~= only(1, 2, 3, 4);
1210     assert(arr1.length == 4);
1211     assert(equal(arr1, only(1, 2, 3, 4)));
1212     assert(!arr1.isNull);
1213 
1214     assert(equal(arr1, arr1.retro.retro));
1215 
1216     {
1217         auto arr2 = arr1.retro;
1218         foreach_reverse(e; arr1){
1219             assert(e == arr2.front);
1220             arr2.popFront();
1221         }
1222     }
1223 
1224 
1225     static assert(isForwardRange!(typeof(only(1, 2, 3))));
1226 
1227 
1228     arr1.release();
1229     arr1 ~= only(1, 2, 3);
1230     assert(arr1 < only(2));
1231     assert(arr1 < only(1, 2, 3, 4));
1232     assert(arr1 < only(1, 2, 4));
1233 
1234     assert(arr1 <= arr1);
1235 
1236     assert(arr1 >= arr1);
1237     assert(arr1 == arr1);
1238 
1239     assert(arr1 > only(1));
1240     assert(arr1 > only(1, 2));
1241     assert(arr1 > only(1, 2, 2));
1242     assert(arr1 > only(1, 2, 2, 4));
1243 
1244     assert(arr1 == only(1, 2, 3));
1245     assert(arr1 != only(1, 2, 3, 4));
1246 
1247 
1248     // length, capacity, reserve test
1249     assert(arr1.length == 3);
1250     assert(arr1._impl.refCount == 1);
1251     assert(arr1.capacity == 4);
1252     foreach(i; 0 .. arr1.capacity - arr1.length)
1253         arr1 ~= i;
1254 
1255     assert(arr1.length == 4);
1256     assert(arr1.capacity - arr1.length == 0);
1257 
1258     foreach(i; 0 .. 3)
1259         arr1.popFront();
1260 
1261     assert(arr1.length == 1);
1262     assert(arr1.capacity - arr1.length == 0);
1263 
1264     arr1.reserve(arr1.length + 1);  //  all elements moved to front.
1265     assert(arr1._s == 0);
1266     assert(arr1._e == arr1.length);
1267     assert(arr1.capacity - arr1.length == 3);
1268 }
1269 
1270 
1271 unittest{
1272     import std.typecons;
1273 
1274     auto arr = RefCountedArray!(RefCountedNoGC!int)(0);
1275     assert(arr.length == 0);
1276 
1277     arr ~= RefCountedNoGC!int(1);
1278     assert(arr.length == 1);
1279     assert(arr.front == 1);
1280     assert(arr.front.refCountedStore.refCount == 1);
1281 
1282     auto e = arr.front;
1283     assert(arr.front.refCountedStore.refCount == 2);
1284     assert(e.refCountedStore.refCount == 2);
1285     arr.popFront();
1286     arr.release();
1287     assert(e.refCountedStore.refCount == 1);
1288 
1289     arr ~= RefCountedNoGC!int(1);
1290     e = arr.front;
1291     assert(arr.front.refCountedStore.refCount == 2);
1292     assert(e.refCountedStore.refCount == 2);
1293 
1294     arr[0] = RefCountedNoGC!int(2);
1295     assert(arr.front.refCountedStore.refCount == 1);
1296     assert(e.refCountedStore.refCount == 1);
1297 
1298     auto arr2 = arr.dup;
1299     assert(arr.front.refCountedStore.refCount == 2);
1300     assert(e.refCountedStore.refCount == 1);
1301 }
1302 
1303 
1304 /+
1305 unittest{
1306     static void func(T)()
1307     {
1308         T a;
1309 
1310         a ~= 1;
1311         foreach(i; 0 .. 15)
1312             a ~= a;
1313 
1314         T b;
1315         foreach(e; a[0 .. 1024 * 32])
1316             b ~= e;
1317     }
1318 
1319     static void funcAppender()
1320     {
1321         import std.array;
1322         auto b = appender!(int[])();
1323         foreach(e; recurrence!"a[n-1]+a[n-2]"(1, 1).take(32 * 1024))
1324             b ~= e;
1325     }
1326 
1327 
1328     import std.datetime;
1329     import std.container;
1330     auto ts = benchmark!(func!(int[]),
1331                          func!(RefCountedArray!int),
1332                          func!(Array!int),
1333                          funcAppender)(100);
1334 
1335     writeln(ts);
1336 
1337 
1338     RefCountedArray!int b;
1339     foreach(e; recurrence!"a[n-1]+a[n-2]"(1, 1).take(1024))
1340             b ~= e;
1341 }+/
1342 
1343 
1344 /**
1345 Cヒープ上に配列を作成します。
1346 この配列は、必ずオブジェクト一つに対してユニークな配列を割り当てます。
1347 つまり、ほとんどの場面で配列の確保とコピーが生じます。
1348 この方式は、C++のSTL std::vectorと同じです。
1349 */
1350 struct UniqueArray(E)
1351 {
1352     /**
1353     */
1354     this(size_t n) nothrow @safe @nogc
1355     {
1356         immutable allocLen = allocateSize(n);
1357 
1358         _array = newCHeapArray!E(allocLen);
1359         _s = 0;
1360         _e = n;
1361     }
1362 
1363 
1364     this(this)
1365     {
1366         if(_array.ptr !is null){
1367             immutable n = this.length;
1368 
1369             auto newarr = newCHeapArray!E(allocateSize(n));
1370             newarr[0 .. n] = _array[_s .. _e];
1371             _array = newarr;
1372             _s = 0;
1373             _e = n;
1374         }
1375     }
1376 
1377 
1378     ~this()
1379     {
1380         if(_array.ptr !is null){
1381             _array.destroyCHeapArray();
1382             _s = 0;
1383             _e = 0;
1384         }
1385     }
1386 
1387 
1388     /**
1389     */
1390     void release()
1391     {
1392         _array.destroyCHeapArray();
1393         _s = 0;
1394         _e = 0;
1395     }
1396 
1397 
1398     /**
1399     */
1400     void clear()
1401     {
1402       static if(is(E == struct) && !__traits(isPOD, E))
1403         foreach(ref e; _array[_s .. _e])
1404             e = E.init;
1405 
1406         _s = 0;
1407         _e = 0;
1408     }
1409 
1410 
1411     /**
1412     */
1413     size_t capacity() const pure nothrow @safe @nogc @property
1414     {
1415         return _array.length - _e;
1416     }
1417 
1418 
1419     /**
1420     */
1421     size_t reserve(size_t n)
1422     {
1423         if(n > this.length && _array.length < n + _s){
1424             if(_array.length < n)
1425                 _array.reallocCHeapArray(allocateSize!E(n));
1426 
1427             if(_s != 0){
1428                 foreach(i; 0 .. this.length)
1429                     _array[i] = _array[_s + i];
1430 
1431                 _e -= _s;
1432                 _s = 0;
1433             }
1434         }
1435     }
1436 
1437 
1438     bool isNull() const pure nothrow @safe @nogc @property
1439     {
1440         return _array is null;
1441     }
1442 
1443 
1444     void opAssign(typeof(null))
1445     {
1446         this.release();
1447     }
1448 
1449 
1450     /// array, range primitives
1451     ref inout(E) front() inout pure nothrow @safe @property @nogc
1452     {
1453         return _array[_s];
1454     }
1455 
1456 
1457     /// ditto
1458     ref inout(E) back() inout pure nothrow @safe @property @nogc
1459     {
1460         return _array[_e-1];
1461     }
1462 
1463 
1464     /// ditto
1465     ref inout(E) opIndex(size_t i) inout pure nothrow @safe @nogc
1466     {
1467         return _array[_s + i];
1468     }
1469 
1470 
1471     /// ditto
1472     bool empty() const pure nothrow @safe @nogc
1473     {
1474         return _array.ptr is null || _s == _e;
1475     }
1476 
1477 
1478     /// ditto
1479     void popFront()
1480     {
1481         _array[_s] = E.init;
1482         ++_s;
1483     }
1484 
1485 
1486     /// ditto
1487     void popBack()
1488     {
1489         _array[_e-1] = E.init;
1490         --_e;
1491     }
1492 
1493 
1494     /// ditto
1495     typeof(this) save() @property
1496     {
1497         return this;
1498     }
1499 
1500 
1501     /// ditto
1502     auto dup() const @property
1503     {
1504         return this;
1505     }
1506 
1507 
1508     /// ditto
1509     size_t length() const pure nothrow @safe @nogc @property
1510     {
1511         return _e - _s;
1512     }
1513 
1514 
1515     /// ditto
1516     alias opDollar = length;
1517 
1518 
1519     /// ditto
1520     void length(size_t n) @property
1521     {
1522         if(n < this.length){
1523             static if(is(E == struct) && !__traits(isPOD, E))
1524                 foreach(ref e; _array[_s + n .. _e])
1525                     e = E.init;
1526         }else
1527             reserve(n);
1528 
1529         _e = _s + n;
1530     }
1531 
1532 
1533     /// ditto
1534     inout(E)[] view() inout pure nothrow @safe @nogc @property
1535     {
1536         return _array[_s .. _e];
1537     }
1538 
1539 
1540     /// ditto
1541     void opOpAssign(string op : "~")(E v)
1542     {
1543         this.length = this.length + 1;
1544         this.back = v;
1545     }
1546 
1547 
1548     /// ditto
1549     void opOpAssign(string op : "~")(E[] arr)
1550     {
1551         immutable oldLen = this.length;
1552         this.length = oldLen + arr.length;
1553         this._array[oldLen .. this.length] = arr[0 .. $];
1554     }
1555 
1556 
1557     /// ditto
1558     void opOpAssign(string op : "~")(typeof(this) src)
1559     {
1560         opOpAssign!"~"(src._array[src._s .. src._e]);
1561     }
1562 
1563 
1564     /// ditto
1565     void opOpAssign(string op : "~", R)(R range)
1566     if(isInputRange!R && is(ElementType!R : E) && !is(R : U[], U) && !isInfinite!R)
1567     {
1568       static if(hasLength!R)
1569       {
1570         immutable oldLen = this.length,
1571                   rangeLen = range.length;
1572         this.length = oldLen + rangeLen;
1573 
1574         foreach(i; 0 .. rangeLen){
1575             assert(!range.empty);
1576             _array[_s + oldLen + i] = range.front;
1577             range.popFront();
1578         }
1579       }
1580       else
1581       {
1582         this = this.dup;
1583 
1584         while(!range.empty){
1585             immutable remN = this._impl._array.length - _e;
1586 
1587             size_t cnt;
1588             foreach(i; 0 .. remN){
1589                 if(range.empty)
1590                     break;
1591 
1592                 this._impl._array[_e + i] = range.front;
1593                 ++cnt;
1594                 range.popFront();
1595             }
1596             _e += cnt;
1597 
1598             if(cnt == remN && !range.empty)
1599                 reserve(_e + 1);
1600         }
1601       }
1602     }
1603 
1604 
1605     /// ditto
1606     int opCmp(R)(auto ref R r)
1607     if(isForwardRange!R && is(typeof(r.front < this.front)))
1608     {
1609         return std.algorithm.cmp(this.view, r.save);
1610     }
1611 
1612 
1613     /// ditto
1614     bool opEquals(R)(auto ref R r)
1615     if(isForwardRange!R && is(typeof(r.front == this.front)))
1616     {
1617         return std.algorithm.equal(this.view, r.save);
1618     }
1619 
1620 
1621   private:
1622     E[] _array;
1623     size_t _s, _e;
1624 }