Sending/receiving data on a socket is roughly 5.5x faster, after removing data copies and buffer re-allocations.
66 lines
1.8 KiB
C++
66 lines
1.8 KiB
C++
//
|
|
// Created by fred on 09/12/16.
|
|
//
|
|
|
|
#include <thread>
|
|
#include <mutex>
|
|
#include "frnetlib/SocketSelector.h"
|
|
|
|
namespace fr
|
|
{
|
|
|
|
SocketSelector::SocketSelector() noexcept
|
|
{
|
|
//Zero out sets
|
|
FD_ZERO(&listen_set);
|
|
FD_ZERO(&listen_read);
|
|
|
|
max_descriptor = 0;
|
|
}
|
|
|
|
void SocketSelector::add(const Socket &socket)
|
|
{
|
|
//Add it to the set
|
|
FD_SET(socket.get_socket_descriptor(), &listen_set);
|
|
|
|
if(socket.get_socket_descriptor() > max_descriptor)
|
|
max_descriptor = socket.get_socket_descriptor();
|
|
}
|
|
|
|
bool SocketSelector::wait(std::chrono::milliseconds timeout)
|
|
{
|
|
//Windows will crash if we pass an empty set. Do a check.
|
|
#ifdef _WIN32
|
|
if(listen_set.fd_count == 0)
|
|
{
|
|
//It's empty. Emulate UNIX behaviour by sleeping for timeout.
|
|
std::this_thread::sleep_for(timeout);
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
timeval wait_time;
|
|
wait_time.tv_sec = 0;
|
|
wait_time.tv_usec = std::chrono::duration_cast<std::chrono::microseconds>(timeout).count();
|
|
|
|
listen_read = listen_set;
|
|
int select_result = select(max_descriptor + 1, &listen_read, NULL, NULL, timeout == std::chrono::milliseconds(0) ? NULL : &wait_time);
|
|
|
|
if(select_result == 0) //If it's timed out
|
|
return false;
|
|
else if(select_result == SOCKET_ERROR) //Else if error
|
|
throw std::logic_error("select() returned -1. Errno: " + std::to_string(errno));
|
|
|
|
return true;
|
|
}
|
|
|
|
void SocketSelector::remove(const Socket &socket)
|
|
{
|
|
FD_CLR(socket.get_socket_descriptor(), &listen_set);
|
|
}
|
|
|
|
bool SocketSelector::is_ready(const Socket &socket)
|
|
{
|
|
return (FD_ISSET(socket.get_socket_descriptor(), &listen_read));
|
|
}
|
|
} |