Remove resizeArray alias
This commit is contained in:
		| @@ -8,7 +8,7 @@ | ||||
|  * Copyright: Eugene Wissner 2016. | ||||
|  * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, | ||||
|  *                  Mozilla Public License, v. 2.0). | ||||
|  * Authors: $(LINK2 mailto:belka@caraus.de, Eugene Wissner) | ||||
|  * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) | ||||
|  */ | ||||
| module tanya.math.random; | ||||
|  | ||||
| @@ -27,20 +27,20 @@ enum maxGather = 128; | ||||
|  */ | ||||
| class EntropyException : Exception | ||||
| { | ||||
| 	/** | ||||
| 	 * Params: | ||||
| 	 * 	msg  = Message to output. | ||||
| 	 * 	file = The file where the exception occurred. | ||||
| 	 * 	line = The line number where the exception occurred. | ||||
| 	 * 	next = The previous exception in the chain of exceptions, if any. | ||||
| 	 */ | ||||
| 	this(string msg, | ||||
| 	     string file = __FILE__, | ||||
| 	     size_t line = __LINE__, | ||||
| 	     Throwable next = null) pure @safe nothrow const @nogc | ||||
| 	{ | ||||
| 		super(msg, file, line, next); | ||||
| 	} | ||||
|     /** | ||||
|      * Params: | ||||
|      *  msg  = Message to output. | ||||
|      *  file = The file where the exception occurred. | ||||
|      *  line = The line number where the exception occurred. | ||||
|      *  next = The previous exception in the chain of exceptions, if any. | ||||
|      */ | ||||
|     this(string msg, | ||||
|          string file = __FILE__, | ||||
|          size_t line = __LINE__, | ||||
|          Throwable next = null) pure @safe nothrow const @nogc | ||||
|     { | ||||
|         super(msg, file, line, next); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -48,103 +48,103 @@ class EntropyException : Exception | ||||
|  */ | ||||
| abstract class EntropySource | ||||
| { | ||||
| 	/// Amount of already generated entropy. | ||||
| 	protected ushort size_; | ||||
|     /// Amount of already generated entropy. | ||||
|     protected ushort size_; | ||||
|  | ||||
| 	/** | ||||
| 	 * Returns: Minimum bytes required from the entropy source. | ||||
| 	 */ | ||||
| 	@property immutable(ubyte) threshold() const @safe pure nothrow; | ||||
|     /** | ||||
|      * Returns: Minimum bytes required from the entropy source. | ||||
|      */ | ||||
|     @property immutable(ubyte) threshold() const @safe pure nothrow; | ||||
|  | ||||
| 	/** | ||||
| 	 * Returns: Whether this entropy source is strong. | ||||
| 	 */ | ||||
| 	@property immutable(bool) strong() const @safe pure nothrow; | ||||
|     /** | ||||
|      * Returns: Whether this entropy source is strong. | ||||
|      */ | ||||
|     @property immutable(bool) strong() const @safe pure nothrow; | ||||
|  | ||||
| 	/** | ||||
| 	 * Returns: Amount of already generated entropy. | ||||
| 	 */ | ||||
| 	@property ushort size() const @safe pure nothrow | ||||
| 	{ | ||||
| 		return size_; | ||||
| 	} | ||||
|     /** | ||||
|      * Returns: Amount of already generated entropy. | ||||
|      */ | ||||
|     @property ushort size() const @safe pure nothrow | ||||
|     { | ||||
|         return size_; | ||||
|     } | ||||
|  | ||||
| 	/** | ||||
| 	 * Params: | ||||
| 	 * 	size = Amount of already generated entropy. Cannot be smaller than the | ||||
| 	 * 	       already set value. | ||||
| 	 */ | ||||
| 	@property void size(ushort size) @safe pure nothrow | ||||
| 	{ | ||||
| 		size_ = size; | ||||
| 	} | ||||
|     /** | ||||
|      * Params: | ||||
|      *  size = Amount of already generated entropy. Cannot be smaller than the | ||||
|      *         already set value. | ||||
|      */ | ||||
|     @property void size(ushort size) @safe pure nothrow | ||||
|     { | ||||
|         size_ = size; | ||||
|     } | ||||
|  | ||||
| 	/** | ||||
| 	 * Poll the entropy source. | ||||
| 	 * | ||||
| 	 * Params: | ||||
| 	 * 	output = Buffer to save the generate random sequence (the method will | ||||
| 	 * 	         to fill the buffer). | ||||
| 	 * | ||||
| 	 * Returns: Number of bytes that were copied to the $(D_PARAM output) | ||||
| 	 *          or $(D_PSYMBOL Nullable!ubyte.init) on error. | ||||
| 	 */ | ||||
| 	Nullable!ubyte poll(out ubyte[maxGather] output); | ||||
|     /** | ||||
|      * Poll the entropy source. | ||||
|      * | ||||
|      * Params: | ||||
|      *  output = Buffer to save the generate random sequence (the method will | ||||
|      *           to fill the buffer). | ||||
|      * | ||||
|      * Returns: Number of bytes that were copied to the $(D_PARAM output) | ||||
|      *          or $(D_PSYMBOL Nullable!ubyte.init) on error. | ||||
|      */ | ||||
|     Nullable!ubyte poll(out ubyte[maxGather] output); | ||||
| } | ||||
|  | ||||
| version (linux) | ||||
| { | ||||
| 	extern (C) long syscall(long number, ...) nothrow; | ||||
|     extern (C) long syscall(long number, ...) nothrow; | ||||
|  | ||||
| 	/** | ||||
| 	 * Uses getrandom system call. | ||||
| 	 */ | ||||
| 	class PlatformEntropySource : EntropySource | ||||
| 	{ | ||||
| 		/** | ||||
| 		 * Returns: Minimum bytes required from the entropy source. | ||||
| 		 */ | ||||
| 		override @property immutable(ubyte) threshold() const @safe pure nothrow | ||||
| 		{ | ||||
| 			return 32; | ||||
| 		} | ||||
|     /** | ||||
|      * Uses getrandom system call. | ||||
|      */ | ||||
|     class PlatformEntropySource : EntropySource | ||||
|     { | ||||
|         /** | ||||
|          * Returns: Minimum bytes required from the entropy source. | ||||
|          */ | ||||
|         override @property immutable(ubyte) threshold() const @safe pure nothrow | ||||
|         { | ||||
|             return 32; | ||||
|         } | ||||
|  | ||||
| 		/** | ||||
| 		 * Returns: Whether this entropy source is strong. | ||||
| 		 */ | ||||
| 		override @property immutable(bool) strong() const @safe pure nothrow | ||||
| 		{ | ||||
| 			return true; | ||||
| 		} | ||||
|         /** | ||||
|          * Returns: Whether this entropy source is strong. | ||||
|          */ | ||||
|         override @property immutable(bool) strong() const @safe pure nothrow | ||||
|         { | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
| 		/** | ||||
| 		 * Poll the entropy source. | ||||
| 		 * | ||||
| 		 * Params: | ||||
| 		 * 	output = Buffer to save the generate random sequence (the method will | ||||
| 		 * 	         to fill the buffer). | ||||
| 		 * | ||||
| 		 * Returns: Number of bytes that were copied to the $(D_PARAM output) | ||||
| 		 *          or $(D_PSYMBOL Nullable!ubyte.init) on error. | ||||
| 		 */ | ||||
| 		override Nullable!ubyte poll(out ubyte[maxGather] output) nothrow | ||||
| 		out (length) | ||||
| 		{ | ||||
| 			assert(length <= maxGather); | ||||
| 		} | ||||
| 		body | ||||
| 		{ | ||||
| 			// int getrandom(void *buf, size_t buflen, unsigned int flags); | ||||
| 			auto length = syscall(318, output.ptr, output.length, 0); | ||||
| 			Nullable!ubyte ret; | ||||
|         /** | ||||
|          * Poll the entropy source. | ||||
|          * | ||||
|          * Params: | ||||
|          *  output = Buffer to save the generate random sequence (the method will | ||||
|          *           to fill the buffer). | ||||
|          * | ||||
|          * Returns: Number of bytes that were copied to the $(D_PARAM output) | ||||
|          *          or $(D_PSYMBOL Nullable!ubyte.init) on error. | ||||
|          */ | ||||
|         override Nullable!ubyte poll(out ubyte[maxGather] output) nothrow | ||||
|         out (length) | ||||
|         { | ||||
|             assert(length <= maxGather); | ||||
|         } | ||||
|         body | ||||
|         { | ||||
|             // int getrandom(void *buf, size_t buflen, unsigned int flags); | ||||
|             auto length = syscall(318, output.ptr, output.length, 0); | ||||
|             Nullable!ubyte ret; | ||||
|  | ||||
| 			if (length >= 0) | ||||
| 			{ | ||||
| 				ret = cast(ubyte) length; | ||||
| 			} | ||||
| 			return ret; | ||||
| 		} | ||||
| 	} | ||||
|             if (length >= 0) | ||||
|             { | ||||
|                 ret = cast(ubyte) length; | ||||
|             } | ||||
|             return ret; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -156,165 +156,165 @@ version (linux) | ||||
|  * | ||||
|  * output = entropy.random; | ||||
|  * | ||||
|  * defaultAllocator.finalize(entropy); | ||||
|  * defaultAllocator.dispose(entropy); | ||||
|  * --- | ||||
|  */ | ||||
| class Entropy | ||||
| { | ||||
| 	/// Entropy sources. | ||||
| 	protected EntropySource[] sources; | ||||
|     /// Entropy sources. | ||||
|     protected EntropySource[] sources; | ||||
|  | ||||
| 	private ubyte sourceCount_; | ||||
|     private ubyte sourceCount_; | ||||
|  | ||||
| 	private shared Allocator allocator; | ||||
|     private shared Allocator allocator; | ||||
|  | ||||
| 	/// Entropy accumulator. | ||||
| 	protected SHA!(maxGather * 8, 512) accumulator; | ||||
|     /// Entropy accumulator. | ||||
|     protected SHA!(maxGather * 8, 512) accumulator; | ||||
|  | ||||
| 	/** | ||||
| 	 * Params: | ||||
| 	 *  maxSources = Maximum amount of entropy sources can be set. | ||||
| 	 * 	allocator  = Allocator to allocate entropy sources available on the | ||||
| 	 * 	             system. | ||||
| 	 */ | ||||
| 	this(size_t maxSources = 20, shared Allocator allocator = defaultAllocator) | ||||
| 	in | ||||
| 	{ | ||||
| 		assert(maxSources > 0 && maxSources <= ubyte.max); | ||||
| 		assert(allocator !is null); | ||||
| 	} | ||||
| 	body | ||||
| 	{ | ||||
| 		allocator.resizeArray(sources, maxSources); | ||||
|     /** | ||||
|      * Params: | ||||
|      *  maxSources = Maximum amount of entropy sources can be set. | ||||
|      *  allocator  = Allocator to allocate entropy sources available on the | ||||
|      *               system. | ||||
|      */ | ||||
|     this(size_t maxSources = 20, shared Allocator allocator = defaultAllocator) | ||||
|     in | ||||
|     { | ||||
|         assert(maxSources > 0 && maxSources <= ubyte.max); | ||||
|         assert(allocator !is null); | ||||
|     } | ||||
|     body | ||||
|     { | ||||
|         allocator.resize(sources, maxSources); | ||||
|  | ||||
| 		version (linux) | ||||
| 		{ | ||||
| 			this ~= allocator.make!PlatformEntropySource; | ||||
| 		} | ||||
| 	} | ||||
|         version (linux) | ||||
|         { | ||||
|             this ~= allocator.make!PlatformEntropySource; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	/** | ||||
| 	 * Returns: Amount of the registered entropy sources. | ||||
| 	 */ | ||||
| 	@property ubyte sourceCount() const @safe pure nothrow | ||||
| 	{ | ||||
| 		return sourceCount_; | ||||
| 	} | ||||
|     /** | ||||
|      * Returns: Amount of the registered entropy sources. | ||||
|      */ | ||||
|     @property ubyte sourceCount() const @safe pure nothrow | ||||
|     { | ||||
|         return sourceCount_; | ||||
|     } | ||||
|  | ||||
| 	/** | ||||
| 	 * Add an entropy source. | ||||
| 	 * | ||||
| 	 * Params: | ||||
| 	 * 	source = Entropy source. | ||||
| 	 * | ||||
| 	 * Returns: $(D_PSYMBOL this). | ||||
| 	 * | ||||
| 	 * See_Also: | ||||
| 	 * 	$(D_PSYMBOL EntropySource) | ||||
| 	 */ | ||||
| 	Entropy opOpAssign(string Op)(EntropySource source) @safe pure nothrow | ||||
| 		if (Op == "~") | ||||
| 	in | ||||
| 	{ | ||||
| 		assert(sourceCount_ <= sources.length); | ||||
| 	} | ||||
| 	body | ||||
| 	{ | ||||
| 		sources[sourceCount_++] = source; | ||||
| 		return this; | ||||
| 	} | ||||
|     /** | ||||
|      * Add an entropy source. | ||||
|      * | ||||
|      * Params: | ||||
|      *  source = Entropy source. | ||||
|      * | ||||
|      * Returns: $(D_PSYMBOL this). | ||||
|      * | ||||
|      * See_Also: | ||||
|      *  $(D_PSYMBOL EntropySource) | ||||
|      */ | ||||
|     Entropy opOpAssign(string Op)(EntropySource source) @safe pure nothrow | ||||
|         if (Op == "~") | ||||
|     in | ||||
|     { | ||||
|         assert(sourceCount_ <= sources.length); | ||||
|     } | ||||
|     body | ||||
|     { | ||||
|         sources[sourceCount_++] = source; | ||||
|         return this; | ||||
|     } | ||||
|  | ||||
| 	/** | ||||
| 	 * Returns: Generated random sequence. | ||||
| 	 * | ||||
| 	 * Throws: $(D_PSYMBOL EntropyException) if no strong entropy source was | ||||
| 	 *         registered or it failed. | ||||
| 	 */ | ||||
| 	@property ubyte[blockSize] random() | ||||
| 	in | ||||
| 	{ | ||||
| 		assert(sourceCount_ > 0, "No entropy sources defined."); | ||||
| 	} | ||||
| 	body | ||||
| 	{ | ||||
| 		bool haveStrong; | ||||
| 		ushort done; | ||||
| 		ubyte[blockSize] output; | ||||
|     /** | ||||
|      * Returns: Generated random sequence. | ||||
|      * | ||||
|      * Throws: $(D_PSYMBOL EntropyException) if no strong entropy source was | ||||
|      *         registered or it failed. | ||||
|      */ | ||||
|     @property ubyte[blockSize] random() | ||||
|     in | ||||
|     { | ||||
|         assert(sourceCount_ > 0, "No entropy sources defined."); | ||||
|     } | ||||
|     body | ||||
|     { | ||||
|         bool haveStrong; | ||||
|         ushort done; | ||||
|         ubyte[blockSize] output; | ||||
|  | ||||
| 		do | ||||
| 		{ | ||||
| 			ubyte[maxGather] buffer; | ||||
|         do | ||||
|         { | ||||
|             ubyte[maxGather] buffer; | ||||
|  | ||||
| 			// Run through our entropy sources | ||||
| 			for (ubyte i; i < sourceCount; ++i) | ||||
| 			{ | ||||
| 				auto outputLength = sources[i].poll(buffer); | ||||
|             // Run through our entropy sources | ||||
|             for (ubyte i; i < sourceCount; ++i) | ||||
|             { | ||||
|                 auto outputLength = sources[i].poll(buffer); | ||||
|  | ||||
| 				if (!outputLength.isNull) | ||||
| 				{ | ||||
| 					if (outputLength > 0) | ||||
| 					{ | ||||
| 						update(i, buffer, outputLength); | ||||
| 						sources[i].size = cast(ushort) (sources[i].size + outputLength); | ||||
| 					} | ||||
| 					if (sources[i].size < sources[i].threshold) | ||||
| 					{ | ||||
| 						continue; | ||||
| 					} | ||||
| 					else if (sources[i].strong) | ||||
| 					{ | ||||
| 						haveStrong = true; | ||||
| 					} | ||||
| 				} | ||||
| 				done = 257; | ||||
| 			} | ||||
| 		} | ||||
| 		while (++done < 256); | ||||
|                 if (!outputLength.isNull) | ||||
|                 { | ||||
|                     if (outputLength > 0) | ||||
|                     { | ||||
|                         update(i, buffer, outputLength); | ||||
|                         sources[i].size = cast(ushort) (sources[i].size + outputLength); | ||||
|                     } | ||||
|                     if (sources[i].size < sources[i].threshold) | ||||
|                     { | ||||
|                         continue; | ||||
|                     } | ||||
|                     else if (sources[i].strong) | ||||
|                     { | ||||
|                         haveStrong = true; | ||||
|                     } | ||||
|                 } | ||||
|                 done = 257; | ||||
|             } | ||||
|         } | ||||
|         while (++done < 256); | ||||
|  | ||||
| 		if (!haveStrong) | ||||
| 		{ | ||||
| 			throw allocator.make!EntropyException("No strong entropy source defined."); | ||||
| 		} | ||||
|         if (!haveStrong) | ||||
|         { | ||||
|             throw allocator.make!EntropyException("No strong entropy source defined."); | ||||
|         } | ||||
|  | ||||
| 		output = accumulator.finish(); | ||||
|         output = accumulator.finish(); | ||||
|  | ||||
| 		// Reset accumulator and counters and recycle existing entropy | ||||
| 		accumulator.start(); | ||||
|         // Reset accumulator and counters and recycle existing entropy | ||||
|         accumulator.start(); | ||||
|  | ||||
| 		// Perform second SHA-512 on entropy | ||||
| 		output = sha512Of(output); | ||||
|         // Perform second SHA-512 on entropy | ||||
|         output = sha512Of(output); | ||||
|  | ||||
| 		for (ubyte i = 0; i < sourceCount; ++i) | ||||
| 		{ | ||||
| 			sources[i].size = 0; | ||||
| 		} | ||||
| 		return output; | ||||
| 	} | ||||
|         for (ubyte i = 0; i < sourceCount; ++i) | ||||
|         { | ||||
|             sources[i].size = 0; | ||||
|         } | ||||
|         return output; | ||||
|     } | ||||
|  | ||||
| 	/** | ||||
| 	 * Update entropy accumulator. | ||||
| 	 * | ||||
| 	 * Params: | ||||
| 	 * 	sourceId = Entropy source index in $(D_PSYMBOL sources). | ||||
| 	 * 	data     = Data got from the entropy source. | ||||
| 	 * 	length   = Length of the received data. | ||||
| 	 */ | ||||
| 	protected void update(in ubyte sourceId, | ||||
| 	                      ref ubyte[maxGather] data, | ||||
| 	                      ubyte length) @safe pure nothrow | ||||
| 	{ | ||||
| 		ubyte[2] header; | ||||
|     /** | ||||
|      * Update entropy accumulator. | ||||
|      * | ||||
|      * Params: | ||||
|      *  sourceId = Entropy source index in $(D_PSYMBOL sources). | ||||
|      *  data     = Data got from the entropy source. | ||||
|      *  length   = Length of the received data. | ||||
|      */ | ||||
|     protected void update(in ubyte sourceId, | ||||
|                           ref ubyte[maxGather] data, | ||||
|                           ubyte length) @safe pure nothrow | ||||
|     { | ||||
|         ubyte[2] header; | ||||
|  | ||||
| 		if (length > blockSize) | ||||
| 		{ | ||||
| 			data[0..64] = sha512Of(data); | ||||
| 			length = blockSize; | ||||
| 		} | ||||
|         if (length > blockSize) | ||||
|         { | ||||
|             data[0..64] = sha512Of(data); | ||||
|             length = blockSize; | ||||
|         } | ||||
|  | ||||
| 		header[0] = sourceId; | ||||
| 		header[1] = length; | ||||
|         header[0] = sourceId; | ||||
|         header[1] = length; | ||||
|  | ||||
| 		accumulator.put(header); | ||||
| 		accumulator.put(data[0..length]); | ||||
| 	} | ||||
|         accumulator.put(header); | ||||
|         accumulator.put(data[0..length]); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -23,59 +23,61 @@ public import tanya.memory.allocator; | ||||
|  */ | ||||
| mixin template DefaultAllocator() | ||||
| { | ||||
| 	/// Allocator. | ||||
| 	protected shared Allocator allocator_; | ||||
|     /// Allocator. | ||||
|     protected shared Allocator allocator_; | ||||
|  | ||||
| 	/** | ||||
| 	 * Params: | ||||
| 	 * 	allocator = The allocator should be used. | ||||
| 	 */ | ||||
| 	this(shared Allocator allocator) | ||||
| 	in | ||||
| 	{ | ||||
| 		assert(allocator !is null); | ||||
| 	} | ||||
| 	body | ||||
| 	{ | ||||
| 		this.allocator_ = allocator; | ||||
| 	} | ||||
|     /** | ||||
|      * Params: | ||||
|      *  allocator = The allocator should be used. | ||||
|      * | ||||
|      * Precondition: $(D_INLINECODE allocator_ !is null) | ||||
|      */ | ||||
|     this(shared Allocator allocator) | ||||
|     in | ||||
|     { | ||||
|         assert(allocator !is null); | ||||
|     } | ||||
|     body | ||||
|     { | ||||
|         this.allocator_ = allocator; | ||||
|     } | ||||
|  | ||||
| 	/** | ||||
| 	 * This property checks if the allocator was set in the constructor | ||||
| 	 * and sets it to the default one, if not. | ||||
| 	 * | ||||
| 	 * Returns: Used allocator. | ||||
| 	 * | ||||
| 	 * Postcondition: $(D_INLINECODE allocator_ !is null) | ||||
| 	 */ | ||||
| 	protected @property shared(Allocator) allocator() nothrow @safe @nogc | ||||
| 	out (allocator) | ||||
| 	{ | ||||
| 		assert(allocator !is null); | ||||
| 	} | ||||
| 	body | ||||
| 	{ | ||||
| 		if (allocator_ is null) | ||||
| 		{ | ||||
| 			allocator_ = defaultAllocator; | ||||
| 		} | ||||
| 		return allocator_; | ||||
| 	} | ||||
|     /** | ||||
|      * This property checks if the allocator was set in the constructor | ||||
|      * and sets it to the default one, if not. | ||||
|      * | ||||
|      * Returns: Used allocator. | ||||
|      * | ||||
|      * Postcondition: $(D_INLINECODE allocator !is null) | ||||
|      */ | ||||
|     protected @property shared(Allocator) allocator() nothrow @safe @nogc | ||||
|     out (allocator) | ||||
|     { | ||||
|         assert(allocator !is null); | ||||
|     } | ||||
|     body | ||||
|     { | ||||
|         if (allocator_ is null) | ||||
|         { | ||||
|             allocator_ = defaultAllocator; | ||||
|         } | ||||
|         return allocator_; | ||||
|     } | ||||
|  | ||||
| 	/// Ditto. | ||||
| 	@property shared(Allocator) allocator() const nothrow @trusted @nogc | ||||
| 	out (allocator) | ||||
| 	{ | ||||
| 		assert(allocator !is null); | ||||
| 	} | ||||
| 	body | ||||
| 	{ | ||||
| 		if (allocator_ is null) | ||||
| 		{ | ||||
| 			return defaultAllocator; | ||||
| 		} | ||||
| 		return cast(shared Allocator) allocator_; | ||||
| 	} | ||||
|     /// Ditto. | ||||
|     @property shared(Allocator) allocator() const nothrow @trusted @nogc | ||||
|     out (allocator) | ||||
|     { | ||||
|         assert(allocator !is null); | ||||
|     } | ||||
|     body | ||||
|     { | ||||
|         if (allocator_ is null) | ||||
|         { | ||||
|             return defaultAllocator; | ||||
|         } | ||||
|         return cast(shared Allocator) allocator_; | ||||
|     } | ||||
| } | ||||
|  | ||||
| // From druntime | ||||
| @@ -85,28 +87,28 @@ shared Allocator allocator; | ||||
|  | ||||
| shared static this() nothrow @trusted @nogc | ||||
| { | ||||
| 	import tanya.memory.mmappool; | ||||
| 	allocator = MmapPool.instance; | ||||
|     import tanya.memory.mmappool; | ||||
|     allocator = MmapPool.instance; | ||||
| } | ||||
|  | ||||
| @property ref shared(Allocator) defaultAllocator() nothrow @safe @nogc | ||||
| out (allocator) | ||||
| { | ||||
| 	assert(allocator !is null); | ||||
|     assert(allocator !is null); | ||||
| } | ||||
| body | ||||
| { | ||||
| 	return allocator; | ||||
|     return allocator; | ||||
| } | ||||
|  | ||||
| @property void defaultAllocator(shared(Allocator) allocator) nothrow @safe @nogc | ||||
| in | ||||
| { | ||||
| 	assert(allocator !is null); | ||||
|     assert(allocator !is null); | ||||
| } | ||||
| body | ||||
| { | ||||
| 	.allocator = allocator; | ||||
|     .allocator = allocator; | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -114,101 +116,92 @@ body | ||||
|  * object of type $(D_PARAM T). | ||||
|  * | ||||
|  * Params: | ||||
|  * 	T = Object type. | ||||
|  *  T = Object type. | ||||
|  */ | ||||
| template stateSize(T) | ||||
| { | ||||
| 	static if (is(T == class) || is(T == interface)) | ||||
| 	{ | ||||
| 		enum stateSize = __traits(classInstanceSize, T); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		enum stateSize = T.sizeof; | ||||
| 	} | ||||
|     static if (is(T == class) || is(T == interface)) | ||||
|     { | ||||
|         enum stateSize = __traits(classInstanceSize, T); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         enum stateSize = T.sizeof; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Params: | ||||
|  * 	size      = Raw size. | ||||
|  * 	alignment = Alignment. | ||||
|  *  size      = Raw size. | ||||
|  *  alignment = Alignment. | ||||
|  * | ||||
|  * Returns: Aligned size. | ||||
|  */ | ||||
| size_t alignedSize(in size_t size, in size_t alignment = 8) pure nothrow @safe @nogc | ||||
| { | ||||
| 	return (size - 1) / alignment * alignment + alignment; | ||||
|     return (size - 1) / alignment * alignment + alignment; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Internal function used to create, resize or destroy a dynamic array. It | ||||
|  * throws $(D_PSYMBOL OutOfMemoryError) if $(D_PARAM Throws) is set. The new | ||||
|  * may throw $(D_PSYMBOL OutOfMemoryError). The new | ||||
|  * allocated part of the array is initialized only if $(D_PARAM Init)  | ||||
|  * is set. This function can be trusted only in the data structures that | ||||
|  * can ensure that the array is allocated/rellocated/deallocated with the | ||||
|  * same allocator. | ||||
|  * | ||||
|  * Params: | ||||
|  * 	T         = Element type of the array being created. | ||||
|  * 	Init      = If should be initialized. | ||||
|  * 	Throws    = If $(D_PSYMBOL OutOfMemoryError) should be throwsn. | ||||
|  * 	allocator = The allocator used for getting memory. | ||||
|  * 	array     = A reference to the array being changed. | ||||
|  * 	length    = New array length. | ||||
|  *  T         = Element type of the array being created. | ||||
|  *  Init      = If should be initialized. | ||||
|  *  allocator = The allocator used for getting memory. | ||||
|  *  array     = A reference to the array being changed. | ||||
|  *  length    = New array length. | ||||
|  * | ||||
|  * Returns: $(D_KEYWORD true) upon success, $(D_KEYWORD false) if memory could | ||||
|  *          not be reallocated. In the latter | ||||
|  * Returns: $(D_PARAM array). | ||||
|  */ | ||||
| package(tanya) bool resize(T, | ||||
|                            bool Init = true, | ||||
|                            bool Throws = true) | ||||
|                           (shared Allocator allocator, | ||||
|                            ref T[] array, | ||||
|                            in size_t length) @trusted | ||||
| package(tanya) T[] resize(T, | ||||
|                           bool Init = true) | ||||
|                          (shared Allocator allocator, | ||||
|                           auto ref T[] array, | ||||
|                           const size_t length) @trusted | ||||
| { | ||||
| 	void[] buf = array; | ||||
| 	static if (Init) | ||||
| 	{ | ||||
| 		immutable oldLength = array.length; | ||||
| 	} | ||||
| 	if (!allocator.reallocate(buf, length * T.sizeof)) | ||||
| 	{ | ||||
| 		static if (Throws) | ||||
| 		{ | ||||
| 			onOutOfMemoryError; | ||||
| 		} | ||||
| 		return false; | ||||
| 	} | ||||
| 	// Casting from void[] is unsafe, but we know we cast to the original type. | ||||
| 	array = cast(T[]) buf; | ||||
|     void[] buf = array; | ||||
|     static if (Init) | ||||
|     { | ||||
|         const oldLength = array.length; | ||||
|     } | ||||
|     if (!allocator.reallocate(buf, length * T.sizeof)) | ||||
|     { | ||||
|         onOutOfMemoryError; | ||||
|     } | ||||
|     // Casting from void[] is unsafe, but we know we cast to the original type. | ||||
|     array = cast(T[]) buf; | ||||
|  | ||||
| 	static if (Init) | ||||
| 	{ | ||||
| 		if (oldLength < length) | ||||
| 		{ | ||||
| 			array[oldLength .. $] = T.init; | ||||
| 		} | ||||
| 	} | ||||
| 	return true; | ||||
|     static if (Init) | ||||
|     { | ||||
|         if (oldLength < length) | ||||
|         { | ||||
|             array[oldLength .. $] = T.init; | ||||
|         } | ||||
|     } | ||||
|     return array; | ||||
| } | ||||
| package(tanya) alias resizeArray = resize; | ||||
|  | ||||
| /// | ||||
| unittest | ||||
| private unittest | ||||
| { | ||||
| 	int[] p; | ||||
|     int[] p; | ||||
|  | ||||
| 	defaultAllocator.resizeArray(p, 20); | ||||
| 	assert(p.length == 20); | ||||
|     p = defaultAllocator.resize(p, 20); | ||||
|     assert(p.length == 20); | ||||
|  | ||||
| 	defaultAllocator.resizeArray(p, 30); | ||||
| 	assert(p.length == 30); | ||||
|     p = defaultAllocator.resize(p, 30); | ||||
|     assert(p.length == 30); | ||||
|  | ||||
| 	defaultAllocator.resizeArray(p, 10); | ||||
| 	assert(p.length == 10); | ||||
|     p = defaultAllocator.resize(p, 10); | ||||
|     assert(p.length == 10); | ||||
|  | ||||
| 	defaultAllocator.resizeArray(p, 0); | ||||
| 	assert(p is null); | ||||
|     p = defaultAllocator.resize(p, 0); | ||||
|     assert(p is null); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -217,101 +210,101 @@ unittest | ||||
|  * allocator. | ||||
|  * | ||||
|  * Params: | ||||
|  * 	T         = Type of $(D_PARAM p). | ||||
|  * 	allocator = Allocator the $(D_PARAM p) was allocated with. | ||||
|  * 	p         = Object or array to be destroyed. | ||||
|  *  T         = Type of $(D_PARAM p). | ||||
|  *  allocator = Allocator the $(D_PARAM p) was allocated with. | ||||
|  *  p         = Object or array to be destroyed. | ||||
|  */ | ||||
| void dispose(T)(shared Allocator allocator, auto ref T* p) | ||||
| { | ||||
| 	static if (hasElaborateDestructor!T) | ||||
| 	{ | ||||
| 		destroy(*p); | ||||
| 	} | ||||
| 	() @trusted { allocator.deallocate((cast(void*) p)[0 .. T.sizeof]); }(); | ||||
| 	p = null; | ||||
|     static if (hasElaborateDestructor!T) | ||||
|     { | ||||
|         destroy(*p); | ||||
|     } | ||||
|     () @trusted { allocator.deallocate((cast(void*) p)[0 .. T.sizeof]); }(); | ||||
|     p = null; | ||||
| } | ||||
|  | ||||
| /// Ditto. | ||||
| void dispose(T)(shared Allocator allocator, auto ref T p) | ||||
| 	if (is(T == class) || is(T == interface)) | ||||
|     if (is(T == class) || is(T == interface)) | ||||
| { | ||||
| 	if (p is null) | ||||
| 	{ | ||||
| 		return; | ||||
| 	} | ||||
| 	static if (is(T == interface)) | ||||
| 	{ | ||||
| 		version(Windows) | ||||
| 		{ | ||||
| 			import core.sys.windows.unknwn : IUnknown; | ||||
| 			static assert(!is(T: IUnknown), "COM interfaces can't be destroyed in " | ||||
| 										 ~ __PRETTY_FUNCTION__); | ||||
| 		} | ||||
| 		auto ob = cast(Object) p; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		alias ob = p; | ||||
| 	} | ||||
| 	auto ptr = cast(void *) ob; | ||||
|     if (p is null) | ||||
|     { | ||||
|         return; | ||||
|     } | ||||
|     static if (is(T == interface)) | ||||
|     { | ||||
|         version(Windows) | ||||
|         { | ||||
|             import core.sys.windows.unknwn : IUnknown; | ||||
|             static assert(!is(T: IUnknown), "COM interfaces can't be destroyed in " | ||||
|                                          ~ __PRETTY_FUNCTION__); | ||||
|         } | ||||
|         auto ob = cast(Object) p; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         alias ob = p; | ||||
|     } | ||||
|     auto ptr = cast(void *) ob; | ||||
|  | ||||
| 	auto support = ptr[0 .. typeid(ob).initializer.length]; | ||||
| 	scope (success) | ||||
| 	{ | ||||
| 		() @trusted { allocator.deallocate(support); }(); | ||||
| 		p = null; | ||||
| 	} | ||||
|     auto support = ptr[0 .. typeid(ob).initializer.length]; | ||||
|     scope (success) | ||||
|     { | ||||
|         () @trusted { allocator.deallocate(support); }(); | ||||
|         p = null; | ||||
|     } | ||||
|  | ||||
| 	auto ppv = cast(void**) ptr; | ||||
| 	if (!*ppv) | ||||
| 	{ | ||||
| 		return; | ||||
| 	} | ||||
| 	auto pc = cast(ClassInfo*) *ppv; | ||||
| 	scope (exit) | ||||
| 	{ | ||||
| 		*ppv = null; | ||||
| 	} | ||||
|     auto ppv = cast(void**) ptr; | ||||
|     if (!*ppv) | ||||
|     { | ||||
|         return; | ||||
|     } | ||||
|     auto pc = cast(ClassInfo*) *ppv; | ||||
|     scope (exit) | ||||
|     { | ||||
|         *ppv = null; | ||||
|     } | ||||
|  | ||||
| 	auto c = *pc; | ||||
| 	do | ||||
| 	{ | ||||
| 		// Assume the destructor is @nogc. Leave it nothrow since the destructor | ||||
| 		// shouldn't throw and if it does, it is an error anyway. | ||||
| 		if (c.destructor) | ||||
| 		{ | ||||
| 			(cast(void function (Object) nothrow @safe @nogc) c.destructor)(ob); | ||||
| 		} | ||||
| 	} | ||||
| 	while ((c = c.base) !is null); | ||||
|     auto c = *pc; | ||||
|     do | ||||
|     { | ||||
|         // Assume the destructor is @nogc. Leave it nothrow since the destructor | ||||
|         // shouldn't throw and if it does, it is an error anyway. | ||||
|         if (c.destructor) | ||||
|         { | ||||
|             (cast(void function (Object) nothrow @safe @nogc) c.destructor)(ob); | ||||
|         } | ||||
|     } | ||||
|     while ((c = c.base) !is null); | ||||
|  | ||||
| 	if (ppv[1]) // if monitor is not null | ||||
| 	{ | ||||
| 		_d_monitordelete(cast(Object) ptr, true); | ||||
| 	} | ||||
|     if (ppv[1]) // if monitor is not null | ||||
|     { | ||||
|         _d_monitordelete(cast(Object) ptr, true); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// Ditto. | ||||
| void dispose(T)(shared Allocator allocator, auto ref T[] p) | ||||
| { | ||||
| 	static if (hasElaborateDestructor!(typeof(p[0]))) | ||||
| 	{ | ||||
| 		import std.algorithm.iteration; | ||||
| 		p.each!(e => destroy(e)); | ||||
| 	} | ||||
| 	() @trusted { allocator.deallocate(p); }(); | ||||
| 	p = null; | ||||
|     static if (hasElaborateDestructor!(typeof(p[0]))) | ||||
|     { | ||||
|         import std.algorithm.iteration; | ||||
|         p.each!(e => destroy(e)); | ||||
|     } | ||||
|     () @trusted { allocator.deallocate(p); }(); | ||||
|     p = null; | ||||
| } | ||||
|  | ||||
| unittest | ||||
| { | ||||
| 	struct S | ||||
| 	{ | ||||
| 		~this() | ||||
| 		{ | ||||
| 		} | ||||
| 	} | ||||
| 	auto p = cast(S[]) defaultAllocator.allocate(S.sizeof); | ||||
|     struct S | ||||
|     { | ||||
|         ~this() | ||||
|         { | ||||
|         } | ||||
|     } | ||||
|     auto p = cast(S[]) defaultAllocator.allocate(S.sizeof); | ||||
|  | ||||
| 	defaultAllocator.dispose(p); | ||||
|     defaultAllocator.dispose(p); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user