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