-
Notifications
You must be signed in to change notification settings - Fork 613
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ntcore] Server round robin message processing (#7191)
Each client has an incoming queue of ClientMessage. In the read callback: - Parse and process only ping messages and a limited number of messages; anything else will get put into the queue and not processed - If we queued some messages, we tell the network we stopped reading; this will result in back-pressure if we are reading too slowly. We also start an idle handle to process the queued messages. In the idle handle callback: - For each client, process just a few pending messages. This is performed in round-robin fashion across all clients with pending messages - When a client's queue becomes empty, we re-enable the network read - When all client queues are empty, we stop the idle handle (so we don't spin) For local client processing, we use round-robin processing for most cases (including FlushLocal), but still do batch processing of all local changes for explicit network Flush() calls.
- Loading branch information
1 parent
8870d98
commit a621ceb
Showing
15 changed files
with
438 additions
and
246 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
// Copyright (c) FIRST and other WPILib contributors. | ||
// Open Source Software; you can modify and/or share it under the terms of | ||
// the WPILib BSD license file in the root directory of this project. | ||
|
||
#pragma once | ||
|
||
#include <span> | ||
#include <string> | ||
|
||
#include <wpi/FastQueue.h> | ||
#include <wpi/mutex.h> | ||
|
||
#include "Message.h" | ||
#include "MessageHandler.h" | ||
|
||
namespace wpi { | ||
class Logger; | ||
} // namespace wpi | ||
|
||
namespace nt::net { | ||
|
||
class ClientMessageQueue { | ||
public: | ||
virtual ~ClientMessageQueue() = default; | ||
|
||
virtual std::span<ClientMessage> ReadQueue(std::span<ClientMessage> out) = 0; | ||
virtual void ClearQueue() = 0; | ||
}; | ||
|
||
namespace detail { | ||
|
||
template <size_t MaxValueSize, bool IsMutexed> | ||
class ClientMessageQueueImpl final : public ClientMessageHandler, | ||
public ClientMessageQueue { | ||
public: | ||
static constexpr size_t kBlockSize = 64; | ||
|
||
explicit ClientMessageQueueImpl(wpi::Logger& logger) : m_logger{logger} {} | ||
|
||
bool empty() const { return m_queue.empty(); } | ||
|
||
// ClientMessageQueue - calls to these read the queue | ||
std::span<ClientMessage> ReadQueue(std::span<ClientMessage> out) final; | ||
void ClearQueue() final; | ||
|
||
// ClientMessageHandler - calls to these append to the queue | ||
void ClientPublish(int pubuid, std::string_view name, | ||
std::string_view typeStr, const wpi::json& properties, | ||
const PubSubOptionsImpl& options) final; | ||
void ClientUnpublish(int pubuid) final; | ||
void ClientSetProperties(std::string_view name, | ||
const wpi::json& update) final; | ||
void ClientSubscribe(int subuid, std::span<const std::string> topicNames, | ||
const PubSubOptionsImpl& options) final; | ||
void ClientUnsubscribe(int subuid) final; | ||
void ClientSetValue(int pubuid, const Value& value) final; | ||
|
||
private: | ||
wpi::FastQueue<ClientMessage, kBlockSize> m_queue{kBlockSize - 1}; | ||
wpi::Logger& m_logger; | ||
|
||
class NoMutex { | ||
public: | ||
void lock() {} | ||
void unlock() {} | ||
}; | ||
[[no_unique_address]] | ||
std::conditional_t<IsMutexed, wpi::mutex, NoMutex> m_mutex; | ||
|
||
struct ValueSize { | ||
size_t size{0}; | ||
bool errored{false}; | ||
}; | ||
struct Empty {}; | ||
[[no_unique_address]] | ||
std::conditional_t<MaxValueSize != 0, ValueSize, Empty> m_valueSize; | ||
}; | ||
|
||
} // namespace detail | ||
|
||
using LocalClientMessageQueue = | ||
detail::ClientMessageQueueImpl<2 * 1024 * 1024, true>; | ||
using NetworkIncomingClientQueue = detail::ClientMessageQueueImpl<0, false>; | ||
|
||
} // namespace nt::net | ||
|
||
#include "ClientMessageQueue.inc" |
Oops, something went wrong.