Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:ClickHouse ClickHouse Poco Socket Impl

From Leeroopedia
Revision as of 14:38, 16 February 2026 by Admin (talk | contribs) (Auto-imported from implementations/ClickHouse_ClickHouse_Poco_Socket_Impl.md)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)


base/poco/Net/src/Socket.cpp:1-391 ClickHouse_ClickHouse ClickHouse_ClickHouse_Socket_Abstraction

Source File base/poco/Net/src/Socket.cpp
Lines of Code 391
Principle Principle:ClickHouse_ClickHouse_Socket_Abstraction
Domain Networking, Sockets
Language C++
Last Updated 2026-02-08 00:00 GMT

Purpose

Implements the `Socket` base class and its static `select` method. The `Socket` class is a lightweight handle that wraps a reference-counted `SocketImpl` pointer, providing value-semantic copy/assignment with shared underlying socket resources. The `select` method implements the classic BSD socket readiness check across three lists (read, write, except), using the best available platform mechanism (epoll, poll, or select).

Code Reference

Socket Handle (Value Semantics with Reference Counting)

Socket::Socket():
    _pImpl(new StreamSocketImpl)
{
}

Socket::Socket(SocketImpl* pImpl):
    _pImpl(pImpl)
{
    poco_check_ptr(_pImpl);
}

Socket::Socket(const Socket& socket):
    _pImpl(socket._pImpl)
{
    poco_check_ptr(_pImpl);
    _pImpl->duplicate();
}

Socket& Socket::operator = (const Socket& socket)
{
    if (&socket != this)
    {
        if (_pImpl) _pImpl->release();
        _pImpl = socket._pImpl;
        if (_pImpl) _pImpl->duplicate();
    }
    return *this;
}

Socket::~Socket()
{
    _pImpl->release();
}

Static select Method (Epoll Backend)

int Socket::select(SocketList& readList, SocketList& writeList,
                   SocketList& exceptList, const Poco::Timespan& timeout)
{
#if defined(POCO_HAVE_FD_EPOLL)
    int epollSize = readList.size() + writeList.size() + exceptList.size();
    if (epollSize == 0) return 0;

    // Build epoll_event array, merging duplicate fds
    std::vector<epoll_event> eventsIn(epollSize);
    struct epoll_event* eventLast = eventsIn.data();
    for (auto it = readList.begin(); it != readList.end(); ++it)
    {
        // Find existing entry or create new one
        // Set EPOLLIN flag
    }
    // Similar for writeList (EPOLLOUT) and exceptList (EPOLLERR)

    int epollfd = epoll_create(1);
    // Add all events via epoll_ctl
    // epoll_wait with EINTR retry loop
    ::close(epollfd);

    // Build ready lists from returned events
    std::swap(readList, readyReadList);
    std::swap(writeList, readyWriteList);
    std::swap(exceptList, readyExceptList);
    return readList.size() + writeList.size() + exceptList.size();
#endif
}

I/O Contract

Input Output Side Effects
`Socket()` default constructor A Socket wrapping a new `StreamSocketImpl` Allocates a new socket implementation
`Socket(const Socket& other)` copy constructor A new Socket handle sharing the same `SocketImpl` Increments the `SocketImpl` reference count via `duplicate`
`operator=(const Socket& other)` Reference to `*this` Releases old impl (may close socket if refcount reaches 0), duplicates new impl
`~Socket()` destructor None Releases the `SocketImpl` reference; if last reference, the socket is closed
`select(readList, writeList, exceptList, timeout)` Number of ready sockets Modifies input lists in-place: each list is replaced with only the sockets that are ready. Creates and destroys a temporary epoll fd (Linux) or pollfd array (BSD).

Usage Examples

// Copy semantics -- both sockets share the same underlying fd
Poco::Net::StreamSocket s1;
Poco::Net::Socket s2 = s1;  // reference count incremented

// Static select for readiness checking
Socket::SocketList readList, writeList, exceptList;
readList.push_back(serverSocket);
writeList.push_back(clientSocket);

Poco::Timespan timeout(5, 0);  // 5 seconds
int ready = Socket::select(readList, writeList, exceptList, timeout);

// After select, readList contains only readable sockets
for (auto& sock : readList)
{
    // Handle readable socket
}

Internal Details

Platform-Specific select Implementation

The `select` static method has three code paths:

  1. Epoll (Linux, `POCO_HAVE_FD_EPOLL`): Creates a temporary epoll instance, registers all sockets by scanning the three lists and merging duplicate file descriptors into combined event masks. After `epoll_wait`, maps events back to Socket objects using `data.ptr`. The epoll fd is closed after each call.
  1. Poll (BSD, `POCO_HAVE_FD_POLL`): Allocates a `pollfd` array, merging sockets appearing in multiple lists to avoid duplicate entries. After `::poll`, scans results and populates ready lists by matching file descriptors back to the original socket objects.
  1. Select (fallback): Uses classic `fd_set` with `FD_ZERO`/`FD_SET`/`FD_ISSET`. Limited by `FD_SETSIZE`. After `::select`, scans each original list and checks `FD_ISSET` to build the ready lists.

EINTR Retry with Timeout Adjustment

All three backends handle `EINTR` by measuring elapsed wall-clock time and subtracting it from the remaining timeout, then retrying the system call.

Reference Counting

`Socket` objects are copyable handles. The underlying `SocketImpl` (which inherits from `Poco::RefCountedObject`) is shared and automatically closed when the last `Socket` referencing it is destroyed.

Related Pages

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment