1717#include " llvm/Support/Threading.h"
1818#include " llvm/Support/raw_ostream.h"
1919
20+ #include < atomic>
21+ #include < chrono>
22+
2023namespace llvm {
2124
2225class raw_socket_stream ;
2326
24- // Make sure that calls to WSAStartup and WSACleanup are balanced.
2527#ifdef _WIN32
28+ // / Ensures proper initialization and cleanup of winsock resources
29+ // /
30+ // / Make sure that calls to WSAStartup and WSACleanup are balanced.
2631class WSABalancer {
2732public:
2833 WSABalancer ();
2934 ~WSABalancer ();
3035};
3136#endif // _WIN32
3237
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+ // /
3359class 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+
3772#ifdef _WIN32
3873 WSABalancer _;
3974#endif // _WIN32
4075
4176public:
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+ // /
42110 static Expected<ListeningSocket> createUnix (
43111 StringRef SocketPath,
44112 int MaxBacklog = llvm::hardware_concurrency().compute_thread_count());
45- Expected<std::unique_ptr<raw_socket_stream>> accept ();
46- ListeningSocket (ListeningSocket &&LS);
47- ~ListeningSocket ();
48113};
114+
115+ // ===----------------------------------------------------------------------===//
116+ // raw_socket_stream
117+ // ===----------------------------------------------------------------------===//
118+
49119class raw_socket_stream : public raw_fd_stream {
50120 uint64_t current_pos () const override { return 0 ; }
51121#ifdef _WIN32
@@ -54,7 +124,7 @@ class raw_socket_stream : public raw_fd_stream {
54124
55125public:
56126 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
58128 // / SocketPath.
59129 static Expected<std::unique_ptr<raw_socket_stream>>
60130 createConnectedUnix (StringRef SocketPath);
0 commit comments