1 module hio.common; 2 3 import std.exception; 4 import std.conv; 5 import std.format; 6 7 import core.stdc.string: strerror; 8 import std.experimental.logger; 9 10 import core.sys.posix.sys.socket; 11 import core.stdc.string; 12 import core.stdc.errno; 13 import core.sys.posix.unistd; 14 15 auto s_strerror(T)(T e) @trusted { 16 return to!string(strerror(e)); 17 } 18 19 SocketPair makeSocketPair() @safe { 20 import core.sys.posix.fcntl; 21 int[2] pair; 22 auto r = (() @trusted => socketpair(AF_UNIX, SOCK_DGRAM, 0, pair))(); 23 if ( r == -1 ) { 24 throw new Exception(s_strerror(errno())); 25 } 26 auto flags = (() @trusted => fcntl(pair[0], F_GETFL, 0) | O_NONBLOCK)(); 27 (() @trusted => fcntl(pair[0], F_SETFL, flags))(); 28 flags = (() @trusted => fcntl(pair[1], F_GETFL, 0) | O_NONBLOCK)(); 29 (() @trusted => fcntl(pair[1], F_SETFL, flags))(); 30 SocketPair result; 31 result._pair = pair; 32 return result; 33 } 34 35 36 struct SocketPair { 37 int[2] _pair = [-1, -1]; 38 ~this() @safe { 39 (() @trusted => close())(); 40 } 41 public void close() { 42 if ( _pair[0] >= 0 ) { 43 core.sys.posix.unistd.close(_pair[0]); 44 } 45 if ( _pair[1] >= 0 ) { 46 core.sys.posix.unistd.close(_pair[1]); 47 } 48 _pair = [-1, -1]; 49 } 50 auto opIndex(size_t i) const { 51 return _pair[i]; 52 } 53 auto read(uint i, size_t len) @safe 54 { 55 enforce!Exception(i <= 1, "Index in socketpair must be 0 or 1"); 56 if ( len <= 0 ) { 57 throw new Exception("read length must be > 0"); 58 } 59 ubyte[] b = new ubyte[](len); 60 auto s = (() @trusted => core.sys.posix.unistd.read(_pair[i], b.ptr, len))(); 61 enforce!Exception(s > 0, "failed to read from socketpair[%d], fd=%d".format(i, _pair[i])); 62 return b; 63 } 64 auto write(uint i, ubyte[] b) @safe { 65 return (() @trusted => core.sys.posix.unistd.write(_pair[i], b.ptr, b.length))(); 66 } 67 } 68 69 package 70 void safe_tracef(A...)(string f, scope A args, string file = __FILE__, int line = __LINE__) @safe @nogc nothrow 71 { 72 bool osx,ldc; 73 version(OSX) 74 { 75 osx = true; 76 } 77 version(LDC) 78 { 79 ldc = true; 80 } 81 debug (timingwheels) try 82 { 83 // this can fail on pair ldc2/osx, see https://github.com/ldc-developers/ldc/issues/3240 84 if (!osx || !ldc) 85 { 86 () @trusted @nogc {tracef("%s:%d " ~ f, file, line, args);}(); 87 } 88 } 89 catch(Exception e) 90 { 91 } 92 } 93 94 95 //class NotificationChannel { 96 // import containers; 97 98 // private enum NotificationType {Signal, Broadcast} 99 // 100 // private NotificationType _type = NotificationType.Signal; 101 // 102 // private SList!(void delegate() @safe) _subscribers; 103 // 104 // SocketPair _pipe; 105 // 106 // auto readEnd() const @safe @nogc { 107 // return _pipe[0]; 108 // } 109 // 110 // auto writeEnd() const @safe @nogc { 111 // return _pipe[1]; 112 // } 113 // 114 // void handler() @safe { 115 // with (NotificationType) final switch(_type) { 116 // case Signal: 117 // auto s = _subscribers.front; 118 // s(); 119 // break; 120 // case Broadcast: 121 // foreach(s; _subscribers) { 122 // s(); 123 // } 124 // break; 125 // } 126 // } 127 // 128 // this() @safe { 129 // _pipe = makeSocketPair(); 130 // } 131 // shared this() @safe { 132 // //_pipe = makeSocketPair(); 133 // } 134 // void subscribe(void delegate() @safe h) @safe { 135 // _subscribers ~= h; 136 // } 137 // void unsubscribe(void delegate() @safe h) @safe { 138 // _subscribers.remove(h); 139 // } 140 // 141 // auto signal() @property @safe @nogc { 142 // _type = NotificationType.Signal; 143 // ubyte[1] b = [0]; 144 // auto s = _pipe.write(1, b); 145 // return this; 146 // } 147 // auto broadcast() @property @safe @nogc { 148 // _type = NotificationType.Broadcast; 149 // ubyte[1] b = [0]; 150 // auto s = _pipe.write(1, b); 151 // return this; 152 // } 153 //} 154