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