From: Daniel Karbach Date: Thu, 5 Nov 2015 14:32:51 +0000 (+0100) Subject: let the server wait a little more efficiently X-Git-Url: http://git.localhorst.tv/?a=commitdiff_plain;h=fae1305b5783ce7a59ab1d4f44e199bd2bda1f45;p=blank.git let the server wait a little more efficiently --- diff --git a/src/app/IntervalTimer.hpp b/src/app/IntervalTimer.hpp index ee84c65..2f465ad 100644 --- a/src/app/IntervalTimer.hpp +++ b/src/app/IntervalTimer.hpp @@ -35,7 +35,7 @@ public: } /// true if an interval boundary was passed by the last call to Update() bool Hit() const noexcept { - return Running() && mod(value, intv) < last_dt; + return Running() && IntervalElapsed() < last_dt; } bool HitOnce() const noexcept { return Running() && value >= intv; @@ -46,6 +46,12 @@ public: Time Interval() const noexcept { return intv; } + Time IntervalElapsed() const noexcept { + return mod(value, intv); + } + Time IntervalRemain() const noexcept { + return intv - IntervalElapsed(); + } int Iteration() const noexcept { return value / intv; } diff --git a/src/server/Server.hpp b/src/server/Server.hpp index 3bffafc..40905c8 100644 --- a/src/server/Server.hpp +++ b/src/server/Server.hpp @@ -29,6 +29,10 @@ public: Server(const Config::Network &, World &, const World::Config &, const WorldSave &); ~Server(); + // wait for data to arrive for at most dt milliseconds + void Wait(int dt) noexcept; + // true if there's data waiting to be handled + bool Ready() noexcept; void Handle(); void Update(int dt); @@ -63,6 +67,7 @@ private: private: UDPsocket serv_sock; UDPpacket serv_pack; + SDLNet_SocketSet serv_set; std::list clients; World &world; diff --git a/src/server/ServerState.cpp b/src/server/ServerState.cpp index 0bec391..7e645ed 100644 --- a/src/server/ServerState.cpp +++ b/src/server/ServerState.cpp @@ -58,6 +58,15 @@ void ServerState::Handle(const SDL_Event &event) { void ServerState::Update(int dt) { loop_timer.Update(dt); + if (!loop_timer.HitOnce() && loop_timer.IntervalRemain() > 1) { + server.Wait(loop_timer.IntervalRemain() - 1); + return; + } + if (dt == 0 && !server.Ready()) { + // effectively wait in a spin loop + return; + } + server.Handle(); int world_dt = 0; while (loop_timer.HitOnce()) { diff --git a/src/server/net.cpp b/src/server/net.cpp index 47342ff..7947c22 100644 --- a/src/server/net.cpp +++ b/src/server/net.cpp @@ -633,28 +633,54 @@ Server::Server( const WorldSave &save) : serv_sock(nullptr) , serv_pack{ -1, nullptr, 0 } +, serv_set(SDLNet_AllocSocketSet(1)) , clients() , world(world) , spawn_index(world.Chunks().MakeIndex(wc.spawn, 3)) , save(save) , player_model(nullptr) , cli(world) { + if (!serv_set) { + throw NetError("SDLNet_AllocSocketSet"); + } + serv_sock = SDLNet_UDP_Open(conf.port); if (!serv_sock) { + SDLNet_FreeSocketSet(serv_set); throw NetError("SDLNet_UDP_Open"); } + if (SDLNet_UDP_AddSocket(serv_set, serv_sock) == -1) { + SDLNet_UDP_Close(serv_sock); + SDLNet_FreeSocketSet(serv_set); + throw NetError("SDLNet_UDP_AddSocket"); + } + serv_pack.data = new Uint8[sizeof(Packet)]; serv_pack.maxlen = sizeof(Packet); } Server::~Server() { + for (ClientConnection &client : clients) { + client.Disconnected(); + } + clients.clear(); world.Chunks().UnregisterIndex(spawn_index); delete[] serv_pack.data; + SDLNet_UDP_DelSocket(serv_set, serv_sock); SDLNet_UDP_Close(serv_sock); + SDLNet_FreeSocketSet(serv_set); } +void Server::Wait(int dt) noexcept { + SDLNet_CheckSockets(serv_set, dt); +} + +bool Server::Ready() noexcept { + return SDLNet_CheckSockets(serv_set, 0) > 0; +} + void Server::Handle() { int result = SDLNet_UDP_Recv(serv_sock, &serv_pack); while (result > 0) {