HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

C++ Syncronous Poll Wrapper v2

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
syncronouswrapperpoll

Problem

I recently asked for some feedback on my design for a syncronous wrapper around linux sockets and poll

Based on the feedback, I created a new (hopefully more idiomatic) design.

socket.h

#pragma once
#include 
#include 

class Socket {
public:
    Socket(){}
    virtual ~Socket();

    Socket(Socket &&other);
    Socket& operator=(Socket &&other);

    int getsd() const {return sd;}
    bool has_error{false};

protected:
    explicit Socket(int sd);

    constexpr static int invalid_socket = -1;
    int sd{invalid_socket};
};

class DataSocket : public Socket {

public:
    DataSocket();
    explicit DataSocket(int sd);
    std::string get_peer_name() const;

    void send(const char* data, std::size_t len);
    void recv(char* data, std::size_t len);
};

class ConnectSocket : public DataSocket {

public:
    ConnectSocket(){}
    ConnectSocket(const char* ip_addr, std::uint16_t port);

protected:
    std::uint16_t port;
    std::uint32_t addr;
};

class ListenSocket : public Socket {

public:
    ListenSocket(std::uint16_t port);

    DataSocket accept();

protected:
    static constexpr int backlog = 128;
    std::uint16_t port;
};


socket.cpp

```
#include
#include
#include
#include
#include
#include
#include

#include "socket.h"

using std::size_t;
using std::strerror;
using std::string;
using std::runtime_error;

namespace {
using SaddrIn = struct sockaddr_in;
using Saddr = struct sockaddr;

string get_name_info(const Saddr *sa) {
char buf[128];
if(::getnameinfo(sa, sizeof(sockaddr), buf, 128, nullptr, 0, NI_NOFQDN | NI_NAMEREQD) != 0){
throw std::runtime_error(string("getnameinfo: ") + std::strerror(errno));
}
return string(buf);
}
}

Socket::Socket(int sd) :
sd(sd)
{
if (sd == invalid_socket){
throw std::logic_error("Socket created with invalid socket descriptor");
}
}

Socket::~Socket(){
if(sd != invalid_socket){
::close(sd);
}
}

Socket::Socket(S

Solution

Dynamic allocation inside the reactor loop should be avoided whenever possible (you allocate std::vector inside the PollSet). It would not only be very slow itself, but will slow the code around by increasing contention on the memory allocators and increasing heap fragmentation.

One possible option is to accept a functor instead of returning the container: void poll_sockets(auto& beg, auto& end, auto& fun) { ...; f(*itr); ... }

Context

StackExchange Code Review Q#135216, answer score: 4

Revisions (0)

No revisions yet.