TreeFrogFramework  2.8
tfcore_unix.h
Go to the documentation of this file.
1 #pragma once
2 #include "tfcore.h"
3 #include <fcntl.h>
4 #include <poll.h>
5 #include <sys/file.h>
6 #include <sys/socket.h>
7 #include <sys/syscall.h>
8 #include <sys/types.h>
9 #include <sys/wait.h>
10 #include <netinet/in.h>
11 #include <unistd.h>
12 #include <thread>
13 #include <cstdint>
14 
15 #ifdef Q_OS_LINUX
16 #include <sys/epoll.h>
17 #endif
18 #ifdef Q_OS_DARWIN
19 #include <pthread.h>
20 #endif
21 #ifdef Q_OS_WASM
22 #include <sstream>
23 #endif
24 
25 #ifndef Q_OS_UNIX
26 #error "tfcore_unix.h included on a non-Unix system"
27 #endif
28 
29 namespace {
30 
31 #ifdef Q_OS_LINUX
32 
33 inline int tf_ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *ts)
34 {
35  TF_EAGAIN_LOOP(::ppoll(fds, nfds, ts, nullptr));
36 }
37 
38 
39 inline int tf_poll(struct pollfd *fds, nfds_t nfds, int timeout)
40 {
41  struct timespec ts = {timeout / 1000, (timeout % 1000) * 1000000L};
42  return tf_ppoll(fds, nfds, &ts);
43 }
44 
45 
46 inline int tf_epoll_wait(int epfd, struct epoll_event *events,
47  int maxevents, int timeout)
48 {
49  TF_EINTR_LOOP(::epoll_wait(epfd, events, maxevents, timeout));
50 }
51 
52 
53 inline int tf_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
54 {
55  TF_EINTR_LOOP(::epoll_ctl(epfd, op, fd, event));
56 }
57 
58 
59 inline int tf_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)
60 {
61  TF_EINTR_LOOP(::accept4(sockfd, addr, addrlen, flags));
62 }
63 
64 
65 inline int tf_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
66 {
67  TF_EINTR_LOOP(::connect(sockfd, addr, addrlen));
68 }
69 
70 
71 inline pid_t tf_gettid()
72 {
73  return syscall(SYS_gettid);
74 }
75 
76 
77 inline int tf_send(int sockfd, const void *buf, size_t len, int flags = 0)
78 {
79  flags |= MSG_NOSIGNAL;
80  TF_EINTR_LOOP(::send(sockfd, buf, len, flags));
81 }
82 
83 #endif // Q_OS_LINUX
84 
85 #ifdef Q_OS_DARWIN
86 
87 inline int tf_poll(struct pollfd *fds, nfds_t nfds, int timeout)
88 {
89  TF_EAGAIN_LOOP(::poll(fds, nfds, timeout));
90 }
91 
92 
93 inline pid_t tf_gettid()
94 {
95  uint64_t tid;
96  pthread_threadid_np(NULL, &tid);
97  return tid;
98 }
99 
100 
101 inline int tf_send(int sockfd, const void *buf, size_t len, int flags = 0)
102 {
103  TF_EINTR_LOOP(::send(sockfd, buf, len, flags));
104 }
105 
106 #endif // Q_OS_DARWIN
107 
108 #ifdef Q_OS_WASM
109 
110 inline int tf_poll(struct pollfd *fds, nfds_t nfds, int timeout)
111 {
112  TF_EAGAIN_LOOP(::poll(fds, nfds, timeout));
113 }
114 
115 
116 inline pid_t tf_gettid()
117 {
118  std::ostringstream ss;
119  ss << std::this_thread::get_id();
120  return std::stoull(ss.str());
121 }
122 
123 
124 inline int tf_send(int sockfd, const void *buf, size_t len, int flags = 0)
125 {
126  TF_EINTR_LOOP(::send(sockfd, buf, len, flags));
127 }
128 
129 #endif // Q_OS_WASM
130 
131 // inline int tf_aio_write(struct aiocb *aiocbp)
132 // {
133 // TF_EINTR_LOOP(::aio_write(aiocbp));
134 // }
135 
136 
137 inline int tf_close(int fd)
138 {
139  TF_EINTR_LOOP(::close(fd));
140 }
141 
142 
143 inline int tf_read(int fd, void *buf, size_t count)
144 {
145  TF_EINTR_LOOP(::read(fd, buf, count));
146 }
147 
148 
149 inline int tf_write(int fd, const void *buf, size_t count)
150 {
151  TF_EINTR_LOOP(::write(fd, buf, count));
152 }
153 
154 
155 inline int tf_recv(int sockfd, void *buf, size_t len, int flags = 0)
156 {
157  TF_EINTR_LOOP(::recv(sockfd, buf, len, flags));
158 }
159 
160 
161 inline int tf_close_socket(int sockfd)
162 {
163  TF_EINTR_LOOP(::close(sockfd));
164 }
165 
166 
167 inline int tf_dup(int fd)
168 {
169  return ::fcntl(fd, F_DUPFD, 0);
170 }
171 
172 
173 inline int tf_flock(int fd, int op)
174 {
175  TF_EINTR_LOOP(::flock(fd, op));
176 }
177 
178 // advisory lock. exclusive:true=exclusive lock, false=shared lock
179 inline int tf_lockfile(int fd, bool exclusive, bool blocking)
180 {
181  struct flock lck;
182 
183  std::memset(&lck, 0, sizeof(struct flock));
184  lck.l_type = (exclusive) ? F_WRLCK : F_RDLCK;
185  lck.l_whence = SEEK_SET;
186  auto cmd = (blocking) ? F_SETLKW : F_SETLK;
187  TF_EINTR_LOOP(::fcntl(fd, cmd, &lck));
188 }
189 
190 
191 inline int tf_unlink(const char *pathname)
192 {
193  return ::unlink(pathname);
194 }
195 
196 
197 inline int tf_fileno(FILE *stream)
198 {
199  return ::fileno(stream);
200 }
201 
206 inline int tf_poll_recv(int socket, int timeout)
207 {
208  struct pollfd pfd = {socket, POLLIN, 0};
209  int ret = tf_poll(&pfd, 1, timeout);
210  return ret;
211 }
212 
217 inline int tf_poll_send(int socket, int timeout)
218 {
219  struct pollfd pfd = {socket, POLLOUT, 0};
220  int ret = tf_poll(&pfd, 1, timeout);
221  return ret;
222 }
223 
224 } // namespace
#define TF_EAGAIN_LOOP(func)
Definition: tfcore.h:20
#define TF_EINTR_LOOP(func)
Definition: tfcore.h:12