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
+ // / \brief 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
+ // / \class ListeningSocket
39
+ // / \brief Manages a passive (i.e., listening) UNIX domain socket
40
+ // /
41
+ // / The ListeningSocket class encapsulates a UNIX domain socket that can listen
42
+ // / and accept incoming connections. ListeningSocket is portable and supports
43
+ // / Windows builds begining with Insider Build 17063. ListeningSocket is
44
+ // / designed for server-side operations, working alongside \p raw_socket_streams
45
+ // / that function as client connections.
46
+ // /
47
+ // / Usage example:
48
+ // / \code{.cpp}
49
+ // / std::string Path = "/path/to/socket"
50
+ // / Expected<ListeningSocket> S = ListeningSocket::createListeningSocket(Path);
51
+ // /
52
+ // / if (S) {
53
+ // / Expected<std::unique_ptr<raw_socket_stream>> connection = S->accept();
54
+ // / if (connection) {
55
+ // / // Use the accepted raw_socket_stream for communication.
56
+ // / }
57
+ // / }
58
+ // / \endcode
59
+ // /
33
60
class ListeningSocket {
34
- int FD;
35
- std::string SocketPath;
36
- ListeningSocket (int SocketFD, StringRef SocketPath);
61
+
62
+ std::atomic<int > FD;
63
+ std::string SocketPath; // Never modified after construction
64
+
65
+ // / If a seperate thread calls ListeningSocket::shutdown, the ListeningSocket
66
+ // / file descriptor (FD) could be closed while ::poll is waiting for it to be
67
+ // / ready to performa I/O operations. ::poll with continue to block even after
68
+ // / FD is closed so use a self-pipe mechanism to get ::poll to return
69
+ int PipeFD[2 ]; // Never modified after construction
70
+
71
+ ListeningSocket (int SocketFD, StringRef SocketPath, int PipeFD[2 ]);
72
+
37
73
#ifdef _WIN32
38
74
WSABalancer _;
39
75
#endif // _WIN32
40
76
41
77
public:
42
- static Expected<ListeningSocket> createUnix (
78
+ ~ListeningSocket ();
79
+ ListeningSocket (ListeningSocket &&LS);
80
+ ListeningSocket (const ListeningSocket &LS) = delete ;
81
+ ListeningSocket &operator =(const ListeningSocket &) = delete ;
82
+
83
+ // / Closes the FD, unlinks the socket file, and writes to PipeFD.
84
+ // /
85
+ // / After the construction of the ListeningSocket, shutdown is signal safe if
86
+ // / it is called during the lifetime of the object. shutdown can be called
87
+ // / concurrently with ListeningSocket::accept as writing to PipeFD will cause
88
+ // / a blocking call to ::poll to return.
89
+ // /
90
+ // / Once shutdown is called there is no way to reinitialize ListeningSocket.
91
+ void shutdown ();
92
+
93
+ // / Accepts an incoming connection on the listening socket. This method can
94
+ // / optionally either block until a connection is available or timeout after a
95
+ // / specified amount of time has passed. By default the method will block
96
+ // / until the socket has recieved a connection.
97
+ // /
98
+ // / \param Timeout An optional timeout duration in milliseconds
99
+ // /
100
+ Expected<std::unique_ptr<raw_socket_stream>>
101
+ accept (std::optional<std::chrono::milliseconds> Timeout = std::nullopt);
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
+ // /
110
+ static Expected<ListeningSocket> createListeningUnixSocket (
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,10 +124,10 @@ 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
- createConnectedUnix (StringRef SocketPath);
130
+ createConnectedUnixSocket (StringRef SocketPath);
61
131
~raw_socket_stream ();
62
132
};
63
133
0 commit comments