1 /**
2 License:
3     Boost Software License - Version 1.0 - August 17th, 2003
4 
5     Permission is hereby granted, free of charge, to any person or organization
6     obtaining a copy of the software and accompanying documentation covered by
7     this license (the "Software") to use, reproduce, display, distribute,
8     execute, and transmit the Software, and to prepare derivative works of the
9     Software, and to permit third-parties to whom the Software is furnished to
10     do so, all subject to the following:
11 
12     The copyright notices in the Software and this entire statement, including
13     the above license grant, this restriction and the following disclaimer,
14     must be included in all copies of the Software, in whole or in part, and
15     all derivative works of the Software, unless such copies or derivative
16     works are solely in the form of machine-executable object code generated by
17     a source language processor.
18 
19     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21     FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
22     SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
23     FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
24     ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25     DEALINGS IN THE SOFTWARE.
26 
27 Authors:
28     Alexandru Ermicioi
29 **/
30 module aermicioi.aedi.storage.allocator_aware;
31 
32 public import std.experimental.allocator : RCIAllocator, make, dispose, theAllocator;
33 import aermicioi.aedi.storage.decorator : MutableDecorator, Decorator;
34 
35 /**
36 Interface for components that are aware of a memory allocator and are using it for some purpose, such as allocating storage for other components, or data.
37 **/
38 @safe interface AllocatorAware(AllocatorType = RCIAllocator) {
39 
40     public {
41         @property {
42 
43             /**
44             Set allocator
45 
46             Params:
47                 allocator = ${param-description}
48 
49             Returns:
50                 typeof(this)
51             **/
52             typeof(this) allocator(AllocatorType allocator) @safe nothrow;
53         }
54     }
55 }
56 
57 /**
58 Convienience mixin that implmenets allocator aware interface by delegating it to decorated AllocatorAware component.
59 **/
60 @safe mixin template AllocatorAwareMixin(T : AllocatorAware!Z, Z) {
61     mixin AllocatorAwareMixin!Z;
62 }
63 
64 /**
65 ditto
66 **/
67 @safe mixin template AllocatorAwareMixin(Z) {
68     import std.experimental.allocator : RCIAllocator, make, theAllocator;
69     private {
70         Z allocator_;
71     }
72 
73     public {
74         @property {
75             /**
76             Set allocator
77 
78             Params:
79                 allocator = allocator used to create components
80 
81             Returns:
82                 typeof(this)
83             **/
84             typeof(this) allocator(Z allocator) @safe nothrow
85             in {
86                 static if (is(Z == class) || is(Z == interface)) {
87 
88                     assert(allocator !is null, "Expected an allocator, not null.");
89                 } else static if (is(Z == RCIAllocator)) {
90                     assert(!allocator.isNull, "Expected an allocator, not null.");
91                 }
92             }
93             body {
94                 this.allocator_ = allocator;
95 
96                 return this;
97             }
98 
99             /**
100             Get allocator
101 
102             Returns:
103                 Z
104             **/
105             inout(Z) allocator() @safe nothrow inout
106             out(allocator) {
107                 static if (is(typeof(allocator) == class) || is(typeof(allocator) == interface)) {
108                     assert(!allocator.isNull, "Allocator wasn't set yet. Please provide an allocator before it is queried for usage.");
109                 } else static if (is(typeof(allocator) == RCIAllocator)) {
110                     assert(!allocator.isNull, "Expected an allocator, not null.");
111                 }
112             }
113             do {
114                 return this.allocator_;
115             }
116         }
117     }
118 }
119 
120 /**
121 Mixin containing default forwarding allocator properties for decorating components.
122 **/
123 @safe mixin template AllocatorAwareDecoratorMixin(T : AllocatorAware!Z, Z)
124     if (is(T : Decorator!X, X)) {
125     import aermicioi.aedi.util.traits;
126     import std.meta;
127     import std.traits;
128 
129     public {
130         @property {
131             /**
132             Set allocator
133 
134             Params:
135                 allocator = allocator to pass to decorated.
136 
137             Returns:
138                 typeof(this)
139             **/
140             typeof(this) allocator(Z allocator) @safe nothrow
141             in (decorator !is null, "Cannot set allocator on decorated allocator aware object when it is not provided.")
142             {
143                 this.decorated.allocator = allocator;
144 
145                 return this;
146             }
147         }
148     }
149 }