<commit_before>
#include <nstd/Time.h>

#include "Server.h"

Server::~Server()
{
  for(List<ServerSocket*>::Iterator i = serverSockets.begin(), end = serverSockets.end(); i != end; ++i)
    delete *i;
  for(HashSet<ConnectSocket*>::Iterator i = connectSockets.begin(), end = connectSockets.end(); i != end; ++i)
    delete *i;
  for(HashSet<ClientSocket*>::Iterator i = clientSockets.begin(), end = clientSockets.end(); i != end; ++i)
    delete *i;
}

bool_t Server::listen(uint16_t port)
{
  ServerSocket* socket = new ServerSocket(*this, port);
  if(!socket->open() ||
      !socket->setReuseAddress() ||
      !socket->bind(Socket::anyAddr, port) ||
      !socket->listen())
  {
    delete socket;
    return false;
  }
  selector.set(*socket, Socket::Selector::acceptEvent);
  serverSockets.append(socket);
  return true;
}

Server::Client* Server::connect(uint32_t addr, uint16_t port)
{
  ConnectSocket* socket = new ConnectSocket(*this);
  if(!socket->open() ||
      !socket->setNonBlocking() ||
      !socket->connect(addr, port))
  {
    delete socket;
    return 0;
  }
  selector.set(*socket, Socket::Selector::connectEvent);
  connectSockets.append(socket);
  Client& client = socket->clientSocket->client;
  client.addr = addr;
  client.port = port;
  return &client;
}

Server::Timer& Server::addTimer(timestamp_t interval)
{
  timestamp_t timerTime = Time::time() + interval;
  Timer& timer = *timers.insert(timerTime, Timer(interval));
  return timer;
}

void_t Server::stop()
{
  stopped = true;
  for(List<ServerSocket*>::Iterator i = serverSockets.begin(), end = serverSockets.end(); i != end; ++i)
    (*i)->close();
}

bool_t Server::process()
{
  Socket* socket;
  uint_t selectEvent;
  while(!stopped)
  {
    timestamp_t timeout = timers.isEmpty() ? 10000 : (timers.begin().key() - Time::time());
    if(timeout > 0)
    {
      if(!selector.select(socket, selectEvent, timeout))
        return false;
      if(socket)
      {
        if(selectEvent & (Socket::Selector::writeEvent | Socket::Selector::connectEvent))
          ((CallbackSocket*)socket)->write();
        if(selectEvent & (Socket::Selector::readEvent | Socket::Selector::acceptEvent))
          ((CallbackSocket*)socket)->read();
      }
    }
    else
    {
      while(!timers.isEmpty())
      {
        timestamp_t timerTime = timers.begin().key();
        if(timerTime <= Time::time())
        {
          Timer& timer = timers.front();
          bool repeat = timer.listener && !timer.listener->execute();
          if(timer.listener != &cleanupTimer && listener)
            listener->executedTimer(timer);
          if(repeat)
            *timers.insert(timerTime + timer.interval, timer);
          timers.removeFront();
        }
        else
          break;
      }
    }
  }
  return true;
}

void_t Server::close(ClientSocket& socket)
{
  if(!socket.isOpen())
    return;
  selector.remove(socket);
  socket.close();
  if(socketsToDelete.isEmpty())
    addTimer(0).setListener(&cleanupTimer);
  socketsToDelete.append(&socket);
}<commit_msg>Minor server timer optimization<commit_after>
#include <nstd/Time.h>

#include "Server.h"

Server::~Server()
{
  for(List<ServerSocket*>::Iterator i = serverSockets.begin(), end = serverSockets.end(); i != end; ++i)
    delete *i;
  for(HashSet<ConnectSocket*>::Iterator i = connectSockets.begin(), end = connectSockets.end(); i != end; ++i)
    delete *i;
  for(HashSet<ClientSocket*>::Iterator i = clientSockets.begin(), end = clientSockets.end(); i != end; ++i)
    delete *i;
}

bool_t Server::listen(uint16_t port)
{
  ServerSocket* socket = new ServerSocket(*this, port);
  if(!socket->open() ||
      !socket->setReuseAddress() ||
      !socket->bind(Socket::anyAddr, port) ||
      !socket->listen())
  {
    delete socket;
    return false;
  }
  selector.set(*socket, Socket::Selector::acceptEvent);
  serverSockets.append(socket);
  return true;
}

Server::Client* Server::connect(uint32_t addr, uint16_t port)
{
  ConnectSocket* socket = new ConnectSocket(*this);
  if(!socket->open() ||
      !socket->setNonBlocking() ||
      !socket->connect(addr, port))
  {
    delete socket;
    return 0;
  }
  selector.set(*socket, Socket::Selector::connectEvent);
  connectSockets.append(socket);
  Client& client = socket->clientSocket->client;
  client.addr = addr;
  client.port = port;
  return &client;
}

Server::Timer& Server::addTimer(timestamp_t interval)
{
  timestamp_t timerTime = Time::time() + interval;
  Timer& timer = *timers.insert(timerTime, Timer(interval));
  return timer;
}

void_t Server::stop()
{
  stopped = true;
  for(List<ServerSocket*>::Iterator i = serverSockets.begin(), end = serverSockets.end(); i != end; ++i)
    (*i)->close();
}

bool_t Server::process()
{
  Socket* socket;
  uint_t selectEvent;
  while(!stopped)
  {
    timestamp_t timeout = timers.isEmpty() ? 10000 : (timers.begin().key() - Time::time());
    if(timeout > 0)
    {
      if(!selector.select(socket, selectEvent, timeout))
        return false;
      if(socket)
      {
        if(selectEvent & (Socket::Selector::writeEvent | Socket::Selector::connectEvent))
          ((CallbackSocket*)socket)->write();
        if(selectEvent & (Socket::Selector::readEvent | Socket::Selector::acceptEvent))
          ((CallbackSocket*)socket)->read();
      }
    }
    else
    {
      do
      {
        timestamp_t timerTime = timers.begin().key();
        if(timerTime <= Time::time())
        {
          Timer& timer = timers.front();
          bool repeat = timer.listener && !timer.listener->execute();
          if(timer.listener != &cleanupTimer && listener)
            listener->executedTimer(timer);
          if(repeat)
            timers.insert(timerTime + timer.interval, timer);
          timers.removeFront();
        }
        else
          break;
      } while(!timers.isEmpty());
    }
  }
  return true;
}

void_t Server::close(ClientSocket& socket)
{
  if(!socket.isOpen())
    return;
  selector.remove(socket);
  socket.close();
  if(socketsToDelete.isEmpty())
    addTimer(0).setListener(&cleanupTimer);
  socketsToDelete.append(&socket);
}
{'fraction_non_alphanumeric': 0.16456731555700965, 'fraction_numerical': 0.004580402421069851, 'mean_word_length': 3.4017278617710582, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5680317', 'n_tokens_mistral': 1951, 'n_tokens_neox': 1925, 'n_words': 362}