annotate foosdk/sdk/pfc/nix-objects.cpp @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
1 #include "pfc-lite.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
2
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
3
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
4 #ifndef _WIN32
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
5 #include <stdio.h>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
6 #include <unistd.h>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
7 #include <fcntl.h>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
8 #include <errno.h>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
9 #include <poll.h>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
10 #include <math.h>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
11
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
12 #ifdef __APPLE__
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
13 #include <mach-o/dyld.h>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
14 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
15
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
16 #include "nix-objects.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
17 #include "string_base.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
18 #include "array.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
19 #include "debug.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
20 #include "timers.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
21 #include "filehandle.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
22
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
23 namespace pfc {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
24 void nixFormatError( string_base & str, int code ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
25 char buffer[512] = {};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
26 strerror_r(code, buffer, sizeof(buffer));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
27 str = buffer;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
28 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
29
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
30 void setNonBlocking( int fd, bool bNonBlocking ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
31 int flags = fcntl(fd, F_GETFL, 0);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
32 int flags2 = flags;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
33 if (bNonBlocking) flags2 |= O_NONBLOCK;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
34 else flags2 &= ~O_NONBLOCK;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
35 if (flags2 != flags) fcntl(fd, F_SETFL, flags2);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
36 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
37
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
38 void setCloseOnExec( int fd, bool bCloseOnExec ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
39 int flags = fcntl(fd, F_GETFD);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
40 int flags2 = flags;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
41 if (bCloseOnExec) flags2 |= FD_CLOEXEC;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
42 else flags2 &= ~FD_CLOEXEC;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
43 if (flags != flags2) fcntl(fd, F_SETFD, flags2);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
44 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
45
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
46 void setInheritable( int fd, bool bInheritable ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
47 setCloseOnExec( fd, !bInheritable );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
48 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
49
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
50 void createPipe( int fd[2], bool bInheritable ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
51 #if defined(__linux__) && defined(O_CLOEXEC)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
52 if (pipe2(fd, bInheritable ? 0 : O_CLOEXEC) < 0) throw exception_nix();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
53 #else
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
54 if (pipe(fd) < 0) throw exception_nix();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
55 if (!bInheritable) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
56 setInheritable( fd[0], false );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
57 setInheritable( fd[1], false );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
58 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
59 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
60 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
61
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
62 exception_nix::exception_nix() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
63 _init(errno);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
64 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
65 exception_nix::exception_nix(int code) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
66 _init(code);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
67 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
68 void exception_nix::_init(int code) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
69 PFC_ASSERT( code != EINTR );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
70 m_code = code;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
71 nixFormatError(m_msg, code);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
72 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
73
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
74 timeval makeTimeVal( double timeSeconds ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
75 timeval tv = {};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
76 uint64_t temp = (uint64_t) floor( timeSeconds * 1000000.0 + 0.5);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
77 tv.tv_usec = (uint32_t) (temp % 1000000);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
78 tv.tv_sec = (uint32_t) (temp / 1000000);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
79 return tv;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
80 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
81 double importTimeval(const timeval & in) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
82 return (double)in.tv_sec + (double)in.tv_usec / 1000000.0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
83 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
84
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
85 void fdSet::operator+=( int fd ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
86 m_fds.insert( fd );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
87 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
88 void fdSet::operator-=( int fd ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
89 m_fds.erase(fd);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
90 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
91 bool fdSet::operator[] (int fd ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
92 return m_fds.find( fd ) != m_fds.end();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
93 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
94 void fdSet::clear() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
95 m_fds.clear();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
96 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
97
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
98 void fdSet::operator+=( fdSet const & other ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
99 for(auto i = other.m_fds.begin(); i != other.m_fds.end(); ++ i ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
100 (*this) += *i;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
101 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
102 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
103
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
104 int fdSelect::Select() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
105 return Select_( -1 );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
106 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
107 int fdSelect::Select( double timeOutSeconds ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
108 int ms;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
109 if (timeOutSeconds < 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
110 ms = -1;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
111 } else if (timeOutSeconds == 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
112 ms = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
113 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
114 ms = pfc::rint32( timeOutSeconds * 1000 );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
115 if (ms < 1) ms = 1;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
116 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
117 return Select_( ms );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
118 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
119
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
120 int fdSelect::Select_( int timeOutMS ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
121 fdSet total = Reads;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
122 total += Writes;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
123 total += Errors;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
124 const size_t count = total.m_fds.size();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
125 pfc::array_t< pollfd > v;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
126 v.set_size_discard( count );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
127 size_t walk = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
128 for( auto fd : total.m_fds) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
129 auto & f = v[walk++];
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
130 f.fd = fd;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
131 f.events = (Reads[fd] ? POLLIN : 0) | (Writes[fd] ? POLLOUT : 0);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
132 // POLLERR ignored in events, only used in revents
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
133 f.revents = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
134 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
135 hires_timer timer;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
136 int countdown = timeOutMS;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
137 if (countdown > 0) timer.start();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
138 int status;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
139 for ( ;; ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
140 status = poll(v.get_ptr(), (int)count, countdown);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
141 if (status >= 0) break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
142
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
143 int e = errno;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
144 if (e == EINTR) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
145 if (countdown < 0) continue; // infinite
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
146 if (countdown > 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
147 countdown = timeOutMS - rint32( timer.query() );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
148 if (countdown > 0) continue;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
149 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
150 // should not really get here
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
151 status = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
152 break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
153 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
154 throw exception_nix(e);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
155 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
156
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
157 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
158
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
159 Reads.clear(); Writes.clear(); Errors.clear();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
160
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
161 if (status > 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
162 for(walk = 0; walk < count; ++walk) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
163 auto & f = v[walk];
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
164 if (f.revents & POLLIN) Reads += f.fd;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
165 if (f.revents & POLLOUT) Writes += f.fd;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
166 if (f.revents & POLLERR) Errors += f.fd;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
167 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
168 PFC_ASSERT( !Reads.m_fds.empty() || !Writes.m_fds.empty() || !Errors.m_fds.empty() );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
169 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
170
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
171 return status;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
172 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
173
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
174 inline bool fdCanRead_select( int fdRead ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
175 PFC_ASSERT( fdRead < FD_SETSIZE );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
176 timeval tv = {};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
177 fd_set set;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
178 FD_ZERO(&set);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
179 FD_SET(fdRead, &set);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
180
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
181 return select(fdRead + 1, &set, nullptr, nullptr, &tv) > 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
182 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
183 inline bool fdCanRead_poll(int fdRead) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
184 pollfd arg = {fdRead, POLLIN };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
185 poll(&arg, 1, 0);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
186 return (arg.revents & POLLIN) != 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
187 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
188
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
189 bool fdCanRead( int fdRead ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
190 if ( fdRead < 0 ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
191 PFC_ASSERT( !"???" );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
192 return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
193 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
194 #ifdef __APPLE__
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
195 // BROKEN extremely inefficient implementation of poll() on Apple systems, avoid if possible
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
196 if ( fdRead < FD_SETSIZE ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
197 return fdCanRead_select( fdRead );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
198 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
199 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
200 return fdCanRead_poll(fdRead);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
201 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
202
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
203 bool fdCanWrite( int fd ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
204 return fdWaitWrite( fd, 0 );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
205 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
206
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
207 bool fdWaitRead( int fd, double timeOutSeconds ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
208 if ( timeOutSeconds == 0 ) return fdCanRead( fd );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
209 fdSelect sel; sel.Reads += fd;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
210 return sel.Select( timeOutSeconds ) > 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
211 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
212 bool fdWaitWrite( int fd, double timeOutSeconds ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
213 fdSelect sel; sel.Writes += fd;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
214 return sel.Select( timeOutSeconds ) > 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
215 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
216
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
217 nix_event::nix_event(bool state) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
218 createPipe( m_fd );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
219 setNonBlocking( m_fd[0] );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
220 setNonBlocking( m_fd[1] );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
221 if ( state ) set_state(true);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
222 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
223 nix_event::~nix_event() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
224 close( m_fd[0] );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
225 close( m_fd[1] );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
226 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
227
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
228 void nix_event::set_state( bool state ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
229 if (state) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
230 // Ensure that there is a byte in the pipe
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
231 if (!fdCanRead(m_fd[0] ) ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
232 uint8_t dummy = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
233 write( m_fd[1], &dummy, 1);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
234 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
235 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
236 // Keep reading until clear
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
237 for(;;) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
238 uint8_t dummy;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
239 if (read(m_fd[0], &dummy, 1 ) != 1) break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
240 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
241 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
242 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
243
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
244 bool nix_event::wait_for( double p_timeout_seconds ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
245 return fdWaitRead( m_fd[0], p_timeout_seconds );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
246 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
247 bool nix_event::is_set() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
248 return fdCanRead(m_fd[0]);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
249 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
250 bool nix_event::g_wait_for( int p_event, double p_timeout_seconds ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
251 return fdWaitRead( p_event, p_timeout_seconds );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
252 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
253 size_t nix_event::g_multiWait( const pfc::eventHandle_t * events, size_t count, double timeout ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
254 fdSelect sel;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
255 for( size_t i = 0; i < count; ++ i ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
256 sel.Reads += events[i];
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
257 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
258 int state = sel.Select( timeout );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
259 if (state < 0) throw exception_nix();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
260 if (state == 0) return SIZE_MAX;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
261 for( size_t i = 0; i < count; ++ i ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
262 if ( sel.Reads[ events[i] ] ) return i;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
263 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
264 crash(); // should not get here
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
265 return SIZE_MAX;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
266 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
267 size_t nix_event::g_multiWait(std::initializer_list<eventHandle_t> const & arg, double timeout) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
268 return g_multiWait(arg.begin(), arg.size(), timeout);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
269 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
270 int nix_event::g_twoEventWait( int h1, int h2, double timeout ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
271 fdSelect sel;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
272 sel.Reads += h1;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
273 sel.Reads += h2;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
274 int state = sel.Select( timeout );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
275 if (state < 0) throw exception_nix();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
276 if (state == 0) return 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
277 if (sel.Reads[ h1 ] ) return 1;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
278 if (sel.Reads[ h2 ] ) return 2;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
279 crash(); // should not get here
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
280 return 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
281 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
282 int nix_event::g_twoEventWait( nix_event & ev1, nix_event & ev2, double timeout ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
283 return g_twoEventWait( ev1.get_handle(), ev2.get_handle(), timeout );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
284 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
285
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
286 void nixSleep(double seconds) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
287 fdSelect sel; sel.Select( seconds );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
288 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
289 void sleepSeconds(double seconds) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
290 return nixSleep(seconds);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
291 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
292
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
293 void yield() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
294 return nixSleep(0.001);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
295 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
296
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
297 double nixGetTime() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
298 timeval tv = {};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
299 gettimeofday(&tv, NULL);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
300 return importTimeval(tv);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
301 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
302 tickcount_t getTickCount() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
303 return rint64(nixGetTime() * 1000.f);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
304 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
305
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
306 bool nixReadSymLink( string_base & strOut, const char * path ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
307 size_t l = 1024;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
308 for(;;) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
309 array_t<char> buffer; buffer.set_size( l + 1 );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
310 ssize_t rv = (size_t) readlink(path, buffer.get_ptr(), l);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
311 if (rv < 0) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
312 if ((size_t)rv <= l) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
313 buffer.get_ptr()[rv] = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
314 strOut = buffer.get_ptr();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
315 return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
316 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
317 l *= 2;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
318 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
319 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
320 bool nixSelfProcessPath( string_base & strOut ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
321 #ifdef __APPLE__
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
322 uint32_t len = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
323 _NSGetExecutablePath(NULL, &len);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
324 array_t<char> temp; temp.set_size( len + 1 ); temp.fill_null();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
325 _NSGetExecutablePath(temp.get_ptr(), &len);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
326 strOut = temp.get_ptr();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
327 return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
328 #else
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
329 return nixReadSymLink( strOut, PFC_string_formatter() << "/proc/" << (unsigned) getpid() << "/exe");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
330 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
331 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
332
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
333 static int openDevRand() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
334 int ret = open("/dev/urandom", O_RDONLY);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
335 if ( ret < 0 ) throw exception_nix();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
336 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
337 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
338 void nixGetRandomData( void * outPtr, size_t outBytes ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
339 try {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
340 static fileHandle randomData = openDevRand();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
341 if (read(randomData.h, outPtr, outBytes) != outBytes) throw exception_nix();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
342 } catch (std::exception const & e) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
343 throw std::runtime_error("getRandomData failure");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
344 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
345 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
346
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
347 #ifndef __APPLE__ // for Apple they are implemented in Obj-C
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
348 bool isShiftKeyPressed() {return false;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
349 bool isCtrlKeyPressed() {return false;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
350 bool isAltKeyPressed() {return false;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
351 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
352 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
353
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
354 void uSleepSeconds( double seconds, bool ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
355 pfc::nixSleep( seconds );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
356 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
357 #endif // _WIN32
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
358