1 /**
2 Utility and ancillary artifacts of `stdx.collections`.
3 */
4 module stdx.collections.common;
5 import std.range: isInputRange;
6 
7 auto tail(Collection)(Collection collection)
8     if (isInputRange!Collection)
9 {
10     collection.popFront();
11     return collection;
12 }
13 
14 struct Mutable(T)
15 {
16     import std.experimental.allocator : RCIAllocator, RCISharedAllocator,
17            theAllocator, processAllocator, dispose, stateSize;
18     import std.experimental.allocator.building_blocks.affix_allocator;
19     import std.variant : Algebraic;
20     import core.atomic : atomicOp;
21     import std.algorithm.mutation : move;
22 
23     private static struct RefCountedMutable
24     {
25         DualAllocatorU!(RCIAllocator, RCISharedAllocator) _alloc;
26         T _payload;
27         size_t _rc;
28     }
29 
30     private void[] _mutableSupport;
31 
32     alias LocalAllocT = AffixAllocator!(RCIAllocator, RefCountedMutable);
33     alias SharedAllocT = shared AffixAllocator!(RCISharedAllocator, RefCountedMutable);
34     //alias AllocT = Algebraic!(LocalAllocT, SharedAllocT);
35     //alias AllocT = DualAllocatorU!(LocalAllocT, SharedAllocT);
36     //pragma(msg, AllocT.stringof);
37     //private AllocT _mutableAllocator;
38 
39     this(this Q)(T theMutable)
40     {
41         static if (is(Q == immutable) || is(Q == const))
42         {
43             this(processAllocator, theMutable);
44         }
45         else
46         {
47             this(theAllocator, theMutable);
48         }
49     }
50 
51     this(A, this Q)(A alloc, T theMutable)
52     if (((is(Q == immutable) || is(Q == const)) && is(A == RCISharedAllocator))
53         || (!(is(Q == immutable) || is(Q == const)) && is(A == RCIAllocator)))
54     {
55         static if (is(A == RCIAllocator))
56         {
57             auto t = LocalAllocT(alloc);
58         }
59         else
60         {
61             auto t = SharedAllocT(alloc);
62         }
63         auto tSupport = (() @trusted => t.allocate(1))();
64         () @trusted {
65             // TODO: this is opAssign
66             t.prefix(tSupport)._alloc = DualAllocatorU!(RCIAllocator, RCISharedAllocator)(alloc);
67             //move(DualAllocatorU!(RCIAllocator, RCISharedAllocator)(alloc), t.prefix(tSupport)._alloc);
68             t.prefix(tSupport)._payload = theMutable;
69         }();
70         _mutableSupport = (() @trusted => cast(typeof(_mutableSupport))(tSupport))();
71     }
72 
73     this(this) @trusted
74     {
75         if (_mutableSupport !is null)
76         {
77             addRef(_mutableSupport);
78         }
79     }
80 
81     @trusted void addRef(SupportQ, this Q)(SupportQ support)
82     {
83         assert(support !is null);
84         static if (is(Q == immutable) || is(Q == const))
85         {
86             auto p = cast(shared uint*)(&SharedAllocT.prefix(support)._rc);
87             atomicOp!"+="(*p, 1);
88         }
89         else
90         {
91             ++LocalAllocT.prefix(support)._rc;
92         }
93     }
94 
95     ~this() @trusted
96     {
97         if (_mutableSupport !is null)
98         {
99             if (LocalAllocT.prefix(_mutableSupport)._rc == 0)
100             {
101                 // Workaround for disabled postblit, though I think move is the
102                 // correct behaviour
103                 alias AT = typeof(LocalAllocT.prefix(_mutableSupport)._alloc);
104                 AT origAlloc;
105                 move(LocalAllocT.prefix(_mutableSupport)._alloc, origAlloc);
106                 if (!origAlloc.get!(RCISharedAllocator).isNull)
107                 {
108                     auto disposer = SharedAllocT(origAlloc.get!(RCISharedAllocator));
109                     disposer.dispose(_mutableSupport);
110                 }
111                 else
112                 {
113                     auto disposer = LocalAllocT(origAlloc.get!(RCIAllocator));
114                     disposer.dispose(_mutableSupport);
115                 }
116             }
117             else
118             {
119                 --LocalAllocT.prefix(_mutableSupport)._rc;
120             }
121         }
122     }
123 
124     auto ref opAssign()(auto ref typeof(this) rhs)
125     {
126         if (rhs._mutableSupport !is null
127             && _mutableSupport is rhs._mutableSupport)
128         {
129             return this;
130         }
131         if (rhs._mutableSupport !is null)
132         {
133             addRef(rhs._mutableSupport);
134         }
135         __dtor();
136         _mutableSupport = rhs._mutableSupport;
137         return this;
138     }
139 
140     bool isNull(this _)()
141     {
142         return _mutableSupport is null;
143     }
144 
145     auto ref get(this Q)()
146     {
147         static if (is(Q == immutable) || is(Q == const))
148         {
149             alias PayloadType = typeof(allocator.prefix(_mutableSupport)._payload);
150             //pragma(msg, "pld type is " ~ typeof(PayloadType).stringof);
151             return cast(shared PayloadType)(SharedAllocT.prefix(_mutableSupport)._payload);
152         }
153         else
154         {
155             return LocalAllocT.prefix(_mutableSupport)._payload;
156         }
157     }
158 
159     void set(T v)
160     {
161         LocalAllocT.prefix(_mutableSupport)._payload = v;
162     }
163 }
164 
165 @safe unittest
166 {
167     import std.experimental.allocator : RCIAllocator, RCISharedAllocator,
168            theAllocator, processAllocator, dispose;
169     import std.experimental.allocator.building_blocks.affix_allocator;
170     import std.variant : Algebraic;
171 
172     auto a = Mutable!(RCIAllocator)(theAllocator);
173     //auto a = immutable Mutable!(RCISharedAllocator)(processAllocator);
174     //auto a = shared Mutable!(RCIAllocator)(theAllocator, theAllocator);
175 }
176 
177 struct DualAllocatorU(LocalAllocT, SharedAllocT)
178 {
179     import std.experimental.allocator : RCIAllocator, RCISharedAllocator;
180     import std.traits : Unqual;
181 
182     private union LAllocator
183     {
184         LocalAllocT alloc;
185     }
186 
187     private union SAllocator
188     {
189         SharedAllocT alloc;
190     }
191 
192     bool _isShared = false;
193     LAllocator _localAlloc;
194     SAllocator _sharedAlloc;
195 
196     this(A, this Q)(A alloc) @trusted
197     {
198         static if (is(Q == immutable))
199         {
200             _isShared = true;
201             _sharedAlloc.alloc = cast(typeof(_sharedAlloc.alloc)) alloc;
202         }
203         else
204         {
205             _localAlloc.alloc = alloc;
206         }
207     }
208 
209     @disable this(this);
210     //this(this)
211     //{
212         //_localAlloc.alloc.__xpostblit();
213         //_sharedAlloc.alloc.__xpostblit();
214     //}
215 
216     @disable this(shared this) shared;
217     //this(this) shared
218     //{
219         //assert(_isShared);
220         //_localAlloc.alloc.__xpostblit();
221         //_sharedAlloc.alloc.__xpostblit();
222     //}
223 
224     ~this()
225     {
226         if(_isShared)
227         {
228             _sharedAlloc.alloc.__xdtor();
229         }
230         else
231         {
232             _localAlloc.alloc.__xdtor();
233         }
234     }
235 
236     auto ref get(T, this _)()
237     if (is(T == LocalAllocT) || is(T == SharedAllocT))
238     {
239         static if (is(T == SharedAllocT))
240         {
241             return _sharedAlloc.alloc;
242         }
243         else
244         {
245             return _localAlloc.alloc;
246         }
247     }
248 
249     //Forward to thread local allocator
250 
251     @property uint alignment()
252     {
253         return _localAlloc.alloc.alignment;
254     }
255 
256     //size_t goodAllocSize(size_t s)
257     //{
258         //return _localAlloc.alloc.goodAllocSize(s);
259     //}
260 
261     void[] allocate(size_t n)
262     {
263         return _localAlloc.alloc.allocate(n);
264     }
265 
266     //void[] alignedAllocate(size_t n, uint a)
267     //{
268         //return _localAlloc.alloc.alignedAllocate(n, a);
269     //}
270 
271     //void[] allocateAll()
272     //{
273         //return _localAlloc.alloc.allocateAll();
274     //}
275 
276     //bool expand(ref void[] b, size_t size)
277     //{
278         //return _localAlloc.alloc.expand(b, size);
279     //}
280 
281     //bool reallocate(ref void[] b, size_t size)
282     //{
283         //return _localAlloc.alloc.reallocate(b, size);
284     //}
285 
286     //bool alignedReallocate(ref void[] b, size_t size, uint alignment)
287     //{
288         //return _localAlloc.alloc.alignedReallocate(b, size, alignment);
289     //}
290 
291     //Ternary owns(void[] b)
292     //{
293         //return _localAlloc.alloc.owns(b);
294     //}
295 
296     //Ternary resolveInternalPointer(const void* p, ref void[] result)
297     //{
298         //return _localAlloc.alloc.resolveInternalPointer(p, result);
299     //}
300 
301     bool deallocate(void[] b)
302     {
303         return _localAlloc.alloc.deallocate(b);
304     }
305 
306     //bool deallocateAll()
307     //{
308         //return _localAlloc.alloc.deallocateAll();
309     //}
310 
311     //Ternary empty()
312     //{
313         //return _localAlloc.alloc.empty();
314     //}
315 
316 
317     // Forward to shared allocator
318 
319     @property uint alignment() shared
320     {
321         return _sharedAlloc.alloc.alignment;
322     }
323 
324     //size_t goodAllocSize(size_t s) shared
325     //{
326         //return _sharedAlloc.alloc.goodAllocSize(s);
327     //}
328 
329     void[] allocate(size_t n) shared
330     {
331         return _sharedAlloc.alloc.allocate(n);
332     }
333 
334     //void[] alignedAllocate(size_t n, uint a) shared
335     //{
336         //return _sharedAlloc.alloc.alignedAllocate(n, a);
337     //}
338 
339     //void[] allocateAll() shared
340     //{
341         //return _sharedAlloc.alloc.allocateAll();
342     //}
343 
344     //bool expand(ref void[] b, size_t size) shared
345     //{
346         //return _sharedAlloc.alloc.expand(b, size);
347     //}
348 
349     //bool reallocate(ref void[] b, size_t size) shared
350     //{
351         //return _sharedAlloc.alloc.reallocate(b, size);
352     //}
353 
354     //bool alignedReallocate(ref void[] b, size_t size, uint alignment) shared
355     //{
356         //return _sharedAlloc.alloc.alignedReallocate(b, size, alignment);
357     //}
358 
359     //Ternary owns(void[] b) shared
360     //{
361         //return _sharedAlloc.alloc.owns(b);
362     //}
363 
364     //Ternary resolveInternalPointer(const void* p, ref void[] result) shared
365     //{
366         //return _sharedAlloc.alloc.resolveInternalPointer(p, result);
367     //}
368 
369     bool deallocate(void[] b) shared
370     {
371         return _sharedAlloc.alloc.deallocate(b);
372     }
373 
374     //bool deallocateAll() shared
375     //{
376         //return _sharedAlloc.alloc.deallocateAll();
377     //}
378 
379     //Ternary empty() shared
380     //{
381         //return _sharedAlloc.alloc.empty();
382     //}
383 }
384 
385 @safe unittest
386 {
387     import std.experimental.allocator : RCIAllocator, RCISharedAllocator,
388            theAllocator, processAllocator, dispose;
389     import std.experimental.allocator.building_blocks.affix_allocator;
390 
391     struct RefCountedMutable(T)
392     {
393         DualAllocator!(RCIAllocator, RCISharedAllocator) _alloc;
394         T _payload;
395         size_t _rc;
396     }
397 
398     //alias SharedAllocT = shared AffixAllocator!(RCISharedAllocator, RefCountedMutable!RCISharedAllocator);
399     //pragma(msg, is(RCISharedAllocator == shared));
400     //SharedAllocT a = SharedAllocT(processAllocator);
401     //() @trusted shared {
402         //auto buf = a.allocate(10);
403         //assert(buf.length == 10);
404     //}();
405 
406     alias T = RCIAllocator;
407     alias LocalAllocT = AffixAllocator!(RCIAllocator, RefCountedMutable!T);
408     alias TT = RCISharedAllocator;
409     alias SharedAllocT = shared AffixAllocator!(RCISharedAllocator, RefCountedMutable!TT);
410     //alias AllocT = Algebraic!(LocalAllocT, SharedAllocT);
411     //alias AllocT = DualAllocator!(LocalAllocT, SharedAllocT);
412     alias AllocT = shared DualAllocatorU!(LocalAllocT, SharedAllocT);
413     AllocT _mutableAllocator;
414 
415     AffixAllocator!(AllocT, RefCountedMutable!T) a;
416     //AffixAllocator!(AllocT, int) a;
417 }
418 
419 @safe unittest
420 {
421     import std.experimental.allocator : RCIAllocator, RCISharedAllocator,
422            theAllocator, processAllocator, dispose;
423     import std.exception : enforce;
424 
425     auto a = DualAllocatorU!(RCIAllocator, RCISharedAllocator)(theAllocator);
426     assert(!a._isShared);
427     assert(a.get!(RCISharedAllocator).isNull);
428 
429     auto b = immutable DualAllocatorU!(RCIAllocator, RCISharedAllocator)(processAllocator);
430     assert(b._isShared);
431     assert(!b.get!(RCISharedAllocator).isNull);
432     assert(b.get!(RCIAllocator).isNull);
433 
434     DualAllocatorU!(RCIAllocator, RCISharedAllocator) c;
435     assert(c.get!(RCIAllocator).isNull);
436     assert(c.get!(RCISharedAllocator).isNull);
437 }
438 
439 struct DualAllocator(LocalAllocT, SharedAllocT)
440 {
441     import std.experimental.allocator : RCIAllocator, RCISharedAllocator;
442     import std.typecons : Ternary;
443     import std.traits : Unqual;
444 
445     private LocalAllocT localAlloc;
446     private SharedAllocT sharedAlloc;
447 
448     this(A, this Q)(A alloc) @trusted
449     {
450         static if (is(Q == immutable))
451         {
452             sharedAlloc = cast(typeof(sharedAlloc)) alloc;
453             //sharedAlloc = alloc;
454         }
455         else
456         {
457             localAlloc = alloc;
458         }
459     }
460 
461     this(this) inout {}
462 
463     auto ref opAssign(A)(A rhs)
464     if (is(A == LocalAllocT) || is(A == SharedAllocT))
465     {
466         static if (is(A == shared))
467         {
468             pragma(msg, "JAAAAA");
469             sharedAlloc = rhs;
470         }
471         else
472         {
473             localAlloc = rhs;
474         }
475         return this;
476     }
477 
478     // Only works for stateful allocators
479     inout(T)* peek(T)() inout @trusted
480     if (is(T == LocalAllocT) || is(T == SharedAllocT))
481     {
482         static if (is(T == SharedAllocT))
483         {
484             alias ST = typeof(sharedAlloc);
485             return sharedAlloc == ST.init ? null : &sharedAlloc;
486         }
487         else
488         {
489             alias LT = typeof(localAlloc);
490             return localAlloc == LT.init ? null : &localAlloc;
491         }
492     }
493 
494     auto ref get(T, this _)()
495     if (is(T == LocalAllocT) || is(T == SharedAllocT))
496     {
497         static if (is(T == SharedAllocT))
498         {
499             return sharedAlloc;
500         }
501         else
502         {
503             return localAlloc;
504         }
505     }
506 
507     //Forward to thread local allocator
508 
509     //@property uint alignment()
510     //{
511         //return localAlloc.alignment();
512     //}
513 
514     //size_t goodAllocSize(size_t s)
515     //{
516         //return localAlloc.goodAllocSize(s);
517     //}
518 
519     void[] allocate(size_t n)
520     {
521         return localAlloc.allocate(n);
522     }
523 
524     //void[] alignedAllocate(size_t n, uint a)
525     //{
526         //return localAlloc.alignedAllocate(n, a);
527     //}
528 
529     //void[] allocateAll()
530     //{
531         //return localAlloc.allocateAll();
532     //}
533 
534     //bool expand(ref void[] b, size_t size)
535     //{
536         //return localAlloc.expand(b, size);
537     //}
538 
539     //bool reallocate(ref void[] b, size_t size)
540     //{
541         //return localAlloc.reallocate(b, size);
542     //}
543 
544     //bool alignedReallocate(ref void[] b, size_t size, uint alignment)
545     //{
546         //return localAlloc.alignedReallocate(b, size, alignment);
547     //}
548 
549     //Ternary owns(void[] b)
550     //{
551         //return localAlloc.owns(b);
552     //}
553 
554     //Ternary resolveInternalPointer(const void* p, ref void[] result)
555     //{
556         //return localAlloc.resolveInternalPointer(p, result);
557     //}
558 
559     bool deallocate(void[] b)
560     {
561         return localAlloc.deallocate(b);
562     }
563 
564     //bool deallocateAll()
565     //{
566         //return localAlloc.deallocateAll();
567     //}
568 
569     //Ternary empty()
570     //{
571         //return localAlloc.empty();
572     //}
573 
574 
575     // Forward to shared allocator
576 
577     //@property uint alignment() shared
578     //{
579         //return sharedAlloc.alignment();
580     //}
581 
582     //size_t goodAllocSize(size_t s) shared
583     //{
584         //return sharedAlloc.goodAllocSize(s);
585     //}
586 
587     void[] allocate(size_t n) shared
588     {
589         return sharedAlloc.allocate(n);
590     }
591 
592     //void[] alignedAllocate(size_t n, uint a) shared
593     //{
594         //return sharedAlloc.alignedAllocate(n, a);
595     //}
596 
597     //void[] allocateAll() shared
598     //{
599         //return sharedAlloc.allocateAll();
600     //}
601 
602     //bool expand(ref void[] b, size_t size) shared
603     //{
604         //return sharedAlloc.expand(b, size);
605     //}
606 
607     //bool reallocate(ref void[] b, size_t size) shared
608     //{
609         //return sharedAlloc.reallocate(b, size);
610     //}
611 
612     //bool alignedReallocate(ref void[] b, size_t size, uint alignment) shared
613     //{
614         //return sharedAlloc.alignedReallocate(b, size, alignment);
615     //}
616 
617     //Ternary owns(void[] b) shared
618     //{
619         //return sharedAlloc.owns(b);
620     //}
621 
622     //Ternary resolveInternalPointer(const void* p, ref void[] result) shared
623     //{
624         //return sharedAlloc.resolveInternalPointer(p, result);
625     //}
626 
627     bool deallocate(void[] b) shared
628     {
629         return sharedAlloc.deallocate(b);
630     }
631 
632     //bool deallocateAll() shared
633     //{
634         //return sharedAlloc.deallocateAll();
635     //}
636 
637     //Ternary empty() shared
638     //{
639         //return sharedAlloc.empty();
640     //}
641 }
642 
643 @safe unittest
644 {
645     import std.experimental.allocator : RCIAllocator, RCISharedAllocator,
646            theAllocator, processAllocator, dispose;
647     import std.exception : enforce;
648 
649     auto a = DualAllocator!(RCIAllocator, RCISharedAllocator)(theAllocator);
650     assert(a.peek!(RCISharedAllocator) is null);
651     assert(a.peek!(RCIAllocator) !is null);
652     assert(a.get!(RCISharedAllocator).isNull);
653     assert(!a.get!(RCIAllocator).isNull);
654 
655     auto b = immutable DualAllocatorU!(RCIAllocator, RCISharedAllocator)(processAllocator);
656     assert(b._isShared);
657     assert(!b.get!(RCISharedAllocator).isNull);
658     assert(b.get!(RCIAllocator).isNull);
659 
660     DualAllocatorU!(RCIAllocator, RCISharedAllocator) c;
661     assert(c.get!(RCIAllocator).isNull);
662     assert(c.get!(RCISharedAllocator).isNull);
663 }
664 
665 struct MutableAlloc(Alloc)
666 {
667     import std.experimental.allocator : RCIAllocator, RCISharedAllocator,
668            theAllocator, processAllocator, dispose, stateSize;
669     import std.experimental.allocator.building_blocks.affix_allocator;
670     import std.variant : Algebraic;
671     import core.atomic : atomicOp;
672     import std.algorithm.mutation : move;
673 
674     private static struct RefCountedMutable
675     {
676         //DualAllocatorU!(RCIAllocator, RCISharedAllocator) _alloc;
677         Alloc _alloc;
678         //T _payload;
679         size_t _rc;
680     }
681 
682     private void[] _mutableSupport;
683 
684     static if (is(Alloc == shared)) {
685         alias LocalAllocT = shared AffixAllocator!(Alloc, RefCountedMutable);
686     } else {
687         alias LocalAllocT = AffixAllocator!(Alloc, RefCountedMutable);
688     }
689     //alias LocalAllocT = AffixAllocator!(Alloc, RefCountedMutable);
690     //alias SharedAllocT = shared AffixAllocator!(Alloc, RefCountedMutable);
691 
692     this(this Q)(Alloc alloc)
693     {
694         auto t = LocalAllocT(alloc);
695         auto tSupport = (() @trusted => t.allocate(1))();
696         () @trusted {
697             // TODO: this is opAssign
698             t.prefix(tSupport)._alloc = alloc;
699         }();
700         _mutableSupport = (() @trusted => cast(typeof(_mutableSupport))(tSupport))();
701     }
702 
703     this(this) @trusted
704     {
705         if (_mutableSupport !is null)
706         {
707             addRef(_mutableSupport);
708         }
709     }
710 
711     @trusted void addRef(SupportQ, this Q)(SupportQ support)
712     {
713         assert(support !is null);
714         static if (is(Q == immutable) || is(Q == const))
715         {
716             auto p = cast(shared uint*)(&LocalAllocT.prefix(support)._rc);
717             atomicOp!"+="(*p, 1);
718         }
719         else
720         {
721             ++LocalAllocT.prefix(support)._rc;
722         }
723     }
724 
725     ~this() @trusted
726     {
727         if (_mutableSupport !is null)
728         {
729             if (LocalAllocT.prefix(_mutableSupport)._rc == 0)
730             {
731                 // Workaround for disabled postblit, though I think move is the
732                 // correct behaviour
733                 alias AT = typeof(LocalAllocT.prefix(_mutableSupport)._alloc);
734                 //AT origAlloc;
735                 //move(LocalAllocT.prefix(_mutableSupport)._alloc, origAlloc);
736                 pragma(msg, is(AT == shared));
737 
738                 AT origAlloc = LocalAllocT.prefix(_mutableSupport)._alloc;
739                 //AT origAlloc;
740                 //move(LocalAllocT.prefix(_mutableSupport)._alloc, origAlloc);
741                 auto disposer = LocalAllocT(origAlloc);
742                 pragma(msg, typeof(disposer).stringof);
743                 pragma(msg, typeof(_mutableSupport).stringof);
744                 disposer.deallocate(_mutableSupport);
745             }
746             else
747             {
748                 --LocalAllocT.prefix(_mutableSupport)._rc;
749             }
750         }
751     }
752 
753     auto ref opAssign()(auto ref typeof(this) rhs)
754     {
755         if (rhs._mutableSupport !is null
756             && _mutableSupport is rhs._mutableSupport)
757         {
758             return this;
759         }
760         if (rhs._mutableSupport !is null)
761         {
762             addRef(rhs._mutableSupport);
763         }
764         __dtor();
765         _mutableSupport = rhs._mutableSupport;
766         return this;
767     }
768 
769     bool isNull(this _)()
770     {
771         return _mutableSupport is null;
772     }
773 
774     auto ref get(this Q)()
775     {
776         static if (is(Q == immutable) || is(Q == const))
777         {
778             alias PayloadType = typeof(allocator.prefix(_mutableSupport)._alloc);
779             //pragma(msg, "pld type is " ~ typeof(PayloadType).stringof);
780             return cast(shared PayloadType)(LocalAllocT.prefix(_mutableSupport)._alloc);
781         }
782         else
783         {
784             return LocalAllocT.prefix(_mutableSupport)._alloc;
785         }
786     }
787 
788     void set(Alloc v)
789     {
790         LocalAllocT.prefix(_mutableSupport)._alloc = v;
791     }
792 }
793 
794 @safe unittest
795 {
796     import std.experimental.allocator : RCIAllocator, RCISharedAllocator,
797            theAllocator, processAllocator, dispose;
798     import std.experimental.allocator.building_blocks.affix_allocator;
799     import std.variant : Algebraic;
800 
801     auto a = MutableAlloc!(RCIAllocator)(theAllocator);
802     auto a2 = immutable MutableAlloc!(RCISharedAllocator)(processAllocator);
803     auto a3 = MutableAlloc!(DualAllocatorU!(RCIAllocator, RCISharedAllocator))
804         (theAllocator);
805 }
806