17
17
#include " llvm/Support/Threading.h"
18
18
#include " llvm/Support/raw_ostream.h"
19
19
20
+ #include < atomic>
21
+ #include < chrono>
22
+
20
23
namespace llvm {
21
24
22
25
class raw_socket_stream ;
23
26
24
- // Make sure that calls to WSAStartup and WSACleanup are balanced.
25
27
#ifdef _WIN32
28
+ // / Ensures proper initialization and cleanup of winsock resources
29
+ // /
30
+ // / Make sure that calls to WSAStartup and WSACleanup are balanced.
26
31
class WSABalancer {
27
32
public:
28
33
WSABalancer ();
29
34
~WSABalancer ();
30
35
};
31
36
#endif // _WIN32
32
37
38
+ // / Manages a passive (i.e., listening) UNIX domain socket
39
+ // /
40
+ // / The ListeningSocket class encapsulates a UNIX domain socket that can listen
41
+ // / and accept incoming connections. ListeningSocket is portable and supports
42
+ // / Windows builds begining with Insider Build 17063. ListeningSocket is
43
+ // / designed for server-side operations, working alongside \p raw_socket_streams
44
+ // / that function as client connections.
45
+ // /
46
+ // / Usage example:
47
+ // / \code{.cpp}
48
+ // / std::string Path = "/path/to/socket"
49
+ // / Expected<ListeningSocket> S = ListeningSocket::createUnix(Path);
50
+ // /
51
+ // / if (S) {
52
+ // / Expected<std::unique_ptr<raw_socket_stream>> connection = S->accept();
53
+ // / if (connection) {
54
+ // / // Use the accepted raw_socket_stream for communication.
55
+ // / }
56
+ // / }
57
+ // / \endcode
58
+ // /
33
59
class ListeningSocket {
34
- int FD;
35
- std::string SocketPath;
36
- ListeningSocket (int SocketFD, StringRef SocketPath);
60
+
61
+ std::atomic<int > FD;
62
+ std::string SocketPath; // Not modified after construction
63
+
64
+ // / If a seperate thread calls ListeningSocket::shutdown, the ListeningSocket
65
+ // / file descriptor (FD) could be closed while ::poll is waiting for it to be
66
+ // / ready to perform a I/O operations. ::poll will continue to block even
67
+ // / after FD is closed so use a self-pipe mechanism to get ::poll to return
68
+ int PipeFD[2 ]; // Not modified after construction other then move constructor
69
+
70
+ ListeningSocket (int SocketFD, StringRef SocketPath, int PipeFD[2 ]);
71
+
37
72
#ifdef _WIN32
38
73
WSABalancer _;
39
74
#endif // _WIN32
40
75
41
76
public:
77
+ ~ListeningSocket ();
78
+ ListeningSocket (ListeningSocket &&LS);
79
+ ListeningSocket (const ListeningSocket &LS) = delete ;
80
+ ListeningSocket &operator =(const ListeningSocket &) = delete ;
81
+
82
+ // / Closes the FD, unlinks the socket file, and writes to PipeFD.
83
+ // /
84
+ // / After the construction of the ListeningSocket, shutdown is signal safe if
85
+ // / it is called during the lifetime of the object. shutdown can be called
86
+ // / concurrently with ListeningSocket::accept as writing to PipeFD will cause
87
+ // / a blocking call to ::poll to return.
88
+ // /
89
+ // / Once shutdown is called there is no way to reinitialize ListeningSocket.
90
+ void shutdown ();
91
+
92
+ // / Accepts an incoming connection on the listening socket. This method can
93
+ // / optionally either block until a connection is available or timeout after a
94
+ // / specified amount of time has passed. By default the method will block
95
+ // / until the socket has recieved a connection.
96
+ // /
97
+ // / \param Timeout An optional timeout duration in milliseconds. Setting
98
+ // / Timeout to -1 causes accept to block indefinitely
99
+ // /
100
+ Expected<std::unique_ptr<raw_socket_stream>>
101
+ accept (std::chrono::milliseconds Timeout = std::chrono::milliseconds(-1 ));
102
+
103
+ // / Creates a listening socket bound to the specified file system path.
104
+ // / Handles the socket creation, binding, and immediately starts listening for
105
+ // / incoming connections.
106
+ // /
107
+ // / \param SocketPath The file system path where the socket will be created
108
+ // / \param MaxBacklog The max number of connections in a socket's backlog
109
+ // /
42
110
static Expected<ListeningSocket> createUnix (
43
111
StringRef SocketPath,
44
112
int MaxBacklog = llvm::hardware_concurrency().compute_thread_count());
45
- Expected<std::unique_ptr<raw_socket_stream>> accept ();
46
- ListeningSocket (ListeningSocket &&LS);
47
- ~ListeningSocket ();
48
113
};
114
+
115
+ // ===----------------------------------------------------------------------===//
116
+ // raw_socket_stream
117
+ // ===----------------------------------------------------------------------===//
118
+
49
119
class raw_socket_stream : public raw_fd_stream {
50
120
uint64_t current_pos () const override { return 0 ; }
51
121
#ifdef _WIN32
@@ -54,7 +124,7 @@ class raw_socket_stream : public raw_fd_stream {
54
124
55
125
public:
56
126
raw_socket_stream (int SocketFD);
57
- // / Create a \p raw_socket_stream connected to the Unix domain socket at \p
127
+ // / Create a \p raw_socket_stream connected to the UNIX domain socket at \p
58
128
// / SocketPath.
59
129
static Expected<std::unique_ptr<raw_socket_stream>>
60
130
createConnectedUnix (StringRef SocketPath);
0 commit comments