1 /** 2 * ae.sys.datamm 3 * 4 * License: 5 * This Source Code Form is subject to the terms of 6 * the Mozilla Public License, v. 2.0. If a copy of 7 * the MPL was not distributed with this file, You 8 * can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * Authors: 11 * Vladimir Panteleev <ae@cy.md> 12 */ 13 14 module ae.sys.datamm; 15 16 import core.stdc.errno; 17 18 import std.exception; 19 import std.mmfile; 20 import std.typecons; 21 22 debug(DATA_REFCOUNT) import std.stdio, core.stdc.stdio; 23 24 import ae.sys.data; 25 26 alias MmMode = MmFile.Mode; /// Convenience alias. 27 28 // ************************************************************************ 29 30 /// `Memory` implementation encapsulating a memory-mapped file. 31 /// When the last reference is released, the file is unmapped. 32 class MappedMemory : Memory 33 { 34 typeof(scoped!MmFile(null)) mmFile; /// The `MmFile` object. 35 ubyte[] mappedData; /// View of the mapped file data. 36 37 this(string name, MmMode mode, size_t from, size_t to) 38 { 39 mmFile = retryInterrupted({ 40 return scoped!MmFile(name, mode, 0, null); 41 }); 42 mappedData = cast(ubyte[])( 43 (from || to) 44 ? mmFile.Scoped_payload[from..(to ? to : mmFile.length)] 45 : mmFile.Scoped_payload[] 46 ); 47 48 debug(DATA_REFCOUNT) writefln("? -> %s [%s..%s]: Created MappedMemory", cast(void*)this, contents.ptr, contents.ptr + contents.length); 49 } /// 50 51 debug(DATA_REFCOUNT) 52 ~this() @nogc 53 { 54 printf("? -> %p: Deleted MappedMemory\n", cast(void*)this); 55 } 56 57 override @property inout(ubyte)[] contents() inout { return mappedData; } /// 58 override @property size_t size() const { return mappedData.length; } /// 59 override void setSize(size_t newSize) { assert(false, "Can't resize MappedMemory"); } /// 60 override @property size_t capacity() const { return mappedData.length; } /// 61 } 62 63 /// Returns a `Data` viewing a mapped file. 64 Data mapFile(string name, MmMode mode, size_t from = 0, size_t to = 0) 65 { 66 auto memory = unmanagedNew!MappedMemory(name, mode, from, to); 67 return Data(memory); 68 } 69 70 private T retryInterrupted(T)(scope T delegate() dg) 71 { 72 version (Posix) 73 { 74 while (true) 75 { 76 try 77 { 78 return dg(); 79 } 80 catch (ErrnoException e) 81 { 82 if (e.errno == EINTR) 83 continue; 84 throw e; 85 } 86 } 87 } 88 else 89 return dg(); 90 }