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 /// `DataWrapper` implementation encapsulating a memory-mapped file. 31 /// When the last reference is released, the file is unmapped. 32 class MappedDataWrapper : DataWrapper 33 { 34 typeof(scoped!MmFile(null)) mmFile; /// The `MmFile` object. 35 void[] 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 = (from || to) ? mmFile.Scoped_payload[from..(to ? to : mmFile.length)] : mmFile.Scoped_payload[]; 43 44 debug(DATA_REFCOUNT) writefln("? -> %s [%s..%s]: Created MappedDataWrapper", cast(void*)this, contents.ptr, contents.ptr + contents.length); 45 } /// 46 47 debug(DATA_REFCOUNT) 48 ~this() @nogc 49 { 50 printf("? -> %p: Deleted MappedDataWrapper\n", cast(void*)this); 51 } 52 53 override @property inout(void)[] contents() inout { return mappedData; } /// 54 override @property size_t size() const { return mappedData.length; } /// 55 override void setSize(size_t newSize) { assert(false, "Can't resize MappedDataWrapper"); } /// 56 override @property size_t capacity() const { return mappedData.length; } /// 57 } 58 59 /// Returns a `Data` viewing a mapped file. 60 Data mapFile(string name, MmMode mode, size_t from = 0, size_t to = 0) 61 { 62 auto wrapper = unmanagedNew!MappedDataWrapper(name, mode, from, to); 63 return Data(wrapper, mode != MmMode.read); 64 } 65 66 private T retryInterrupted(T)(scope T delegate() dg) 67 { 68 version (Posix) 69 { 70 while (true) 71 { 72 try 73 { 74 return dg(); 75 } 76 catch (ErrnoException e) 77 { 78 if (e.errno == EINTR) 79 continue; 80 throw e; 81 } 82 } 83 } 84 else 85 return dg(); 86 }