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 aermicioi 29 **/ 30 module aermicioi.aedi.container.gc_registering_container; 31 32 import aermicioi.aedi.container.container; 33 import aermicioi.aedi.storage.object_storage; 34 import aermicioi.aedi.storage.decorator; 35 import aermicioi.aedi.storage.locator : LocatorMixin; 36 import aermicioi.aedi.storage.alias_aware; 37 import aermicioi.aedi.storage.storage; 38 import aermicioi.aedi.factory.factory; 39 import aermicioi.aedi.exception.not_found_exception; 40 import aermicioi.aedi.util.traits; 41 import std.meta; 42 import std.traits; 43 44 import std.range.interfaces; 45 46 /** 47 Decorating container that will decorate all passed factories with gc registering factory. 48 This decorated will inherit following interfaces only and only if the 49 T also implements them: 50 $(OL 51 $(LI Storage!(ObjectFactory, string)) 52 $(LI Container) 53 $(LI AliasAware!string) 54 ) 55 Decorated container must implement following interfaces: 56 $(OL 57 $(LI Container) 58 $(LI MutableDecorator!T) 59 $(LI Subscribable!ContainerInstantiationEventType) 60 $(LI Decorator!Container) 61 ) 62 63 Params: 64 T = The decorated that switchable decorated will decorate. 65 **/ 66 template GcRegisteringContainer(T) 67 { 68 69 /** 70 Set which the switchable container will decorate for T. By default 71 Locator!() and Subscribable!ContainerInstantiationEventType is included. 72 **/ 73 alias InheritanceSet = NoDuplicates!(Filter!( 74 templateOr!( 75 partialSuffixed!( 76 isDerived, 77 Storage!(ObjectFactory, string) 78 ), 79 partialSuffixed!( 80 isDerived, 81 AliasAware!string 82 ), 83 partialSuffixed!( 84 isDerived, 85 FactoryLocator!ObjectFactory 86 ) 87 ), 88 InterfacesTuple!T), 89 Container, 90 Decorator!Container 91 ); 92 93 @safe class GcRegisteringContainer : InheritanceSet 94 { 95 96 public 97 { 98 99 /** 100 Default constructor for GcRegisteringContainer 101 **/ 102 this() 103 { 104 } 105 106 mixin MutableDecoratorMixin!(T); 107 mixin LocatorMixin!(typeof(this)); 108 mixin ContainerMixin!(typeof(this)); 109 110 static if (is(T : Storage!(ObjectFactory, string))) 111 { 112 113 /** 114 Set object factory 115 116 Params: 117 element = factory for a object that is to be managed by prototype container. 118 identity = identity of factory 119 Returns: 120 typeof(this) 121 **/ 122 GcRegisteringContainer!T set(ObjectFactory element, string identity) 123 { 124 decorated.set(new GcRegisteringFactoryDecorator(element), identity); 125 126 return this; 127 } 128 129 /** 130 Remove an object factory from container. 131 132 Params: 133 identity = identity of factory to be removed 134 Returns: 135 typeof(this) 136 **/ 137 GcRegisteringContainer!T remove(string identity) 138 { 139 decorated.remove(identity); 140 141 return this; 142 } 143 } 144 145 static if (is(T : AliasAware!string)) 146 { 147 148 mixin AliasAwareMixin!(typeof(this)); 149 } 150 151 static if (is(T : FactoryLocator!ObjectFactory)) 152 { 153 154 mixin FactoryLocatorMixin!(typeof(this)); 155 } 156 } 157 } 158 } 159 160 private @safe class GcRegisteringFactoryDecorator : Factory!Object { 161 import aermicioi.aedi.storage.locator_aware : LocatorAwareMixin; 162 import aermicioi.aedi.storage.allocator_aware : AllocatorAwareMixin; 163 164 mixin LocatorAwareMixin!GcRegisteringFactoryDecorator; 165 mixin AllocatorAwareMixin!GcRegisteringFactoryDecorator; 166 mixin MutableDecoratorMixin!(Factory!Object); 167 168 public { 169 this(Factory!Object decorated) { 170 this.decorated = decorated; 171 } 172 173 /** 174 Instantiates component of type Object. 175 176 Returns: 177 Object instantiated component. 178 **/ 179 Object factory() @trusted { 180 import core.memory : GC; 181 182 Object object = this.decorated.factory(); 183 GC.addRange(cast(void*) object, this.type.initializer.length, object.classinfo); 184 185 return object; 186 } 187 188 /** 189 Destructs a component of type T. 190 191 Params: 192 component = component that is to ve destroyed. 193 **/ 194 void destruct(ref Object component) @trusted { 195 import core.memory : GC; 196 GC.removeRange(cast(void*) component); 197 198 this.decorated.destruct(component); 199 } 200 201 @property { 202 203 /** 204 Get the type info of T that is created. 205 206 Returns: 207 TypeInfo object of created component. 208 **/ 209 TypeInfo type() @safe nothrow const { 210 return this.decorated.type(); 211 } 212 } 213 } 214 }