Files
allwpilib/ntcore/src/main/native/cpp/Dispatcher.h
Peter Johnson acfbb1a44a [ntcore] DispatcherBase::Flush: Use wpi::Now()
This is faster on some platforms than steady_clock, and will more
consistently support simulation timing.
2020-12-21 09:53:45 -08:00

152 lines
4.6 KiB
C++

/*----------------------------------------------------------------------------*/
/* Copyright (c) 2015-2020 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#ifndef NTCORE_DISPATCHER_H_
#define NTCORE_DISPATCHER_H_
#include <atomic>
#include <functional>
#include <memory>
#include <string>
#include <thread>
#include <utility>
#include <vector>
#include <wpi/StringRef.h>
#include <wpi/Twine.h>
#include <wpi/condition_variable.h>
#include <wpi/mutex.h>
#include "IDispatcher.h"
#include "INetworkConnection.h"
namespace wpi {
class Logger;
class NetworkAcceptor;
class NetworkStream;
} // namespace wpi
namespace nt {
class IConnectionNotifier;
class IStorage;
class NetworkConnection;
class DispatcherBase : public IDispatcher {
friend class DispatcherTest;
public:
typedef std::function<std::unique_ptr<wpi::NetworkStream>()> Connector;
DispatcherBase(IStorage& storage, IConnectionNotifier& notifier,
wpi::Logger& logger);
virtual ~DispatcherBase();
unsigned int GetNetworkMode() const;
void StartLocal();
void StartServer(const Twine& persist_filename,
std::unique_ptr<wpi::NetworkAcceptor> acceptor);
void StartClient();
void Stop();
void SetUpdateRate(double interval);
void SetIdentity(const Twine& name);
void Flush();
std::vector<ConnectionInfo> GetConnections() const;
bool IsConnected() const;
unsigned int AddListener(
std::function<void(const ConnectionNotification& event)> callback,
bool immediate_notify) const;
unsigned int AddPolledListener(unsigned int poller_uid,
bool immediate_notify) const;
void SetConnector(Connector connector);
void SetConnectorOverride(Connector connector);
void ClearConnectorOverride();
bool active() const { return m_active; }
DispatcherBase(const DispatcherBase&) = delete;
DispatcherBase& operator=(const DispatcherBase&) = delete;
private:
void DispatchThreadMain();
void ServerThreadMain();
void ClientThreadMain();
bool ClientHandshake(
NetworkConnection& conn,
std::function<std::shared_ptr<Message>()> get_msg,
std::function<void(wpi::ArrayRef<std::shared_ptr<Message>>)> send_msgs);
bool ServerHandshake(
NetworkConnection& conn,
std::function<std::shared_ptr<Message>()> get_msg,
std::function<void(wpi::ArrayRef<std::shared_ptr<Message>>)> send_msgs);
void ClientReconnect(unsigned int proto_rev = 0x0300);
void QueueOutgoing(std::shared_ptr<Message> msg, INetworkConnection* only,
INetworkConnection* except) override;
IStorage& m_storage;
IConnectionNotifier& m_notifier;
unsigned int m_networkMode = NT_NET_MODE_NONE;
std::string m_persist_filename;
std::thread m_dispatch_thread;
std::thread m_clientserver_thread;
std::unique_ptr<wpi::NetworkAcceptor> m_server_acceptor;
Connector m_client_connector_override;
Connector m_client_connector;
uint8_t m_connections_uid = 0;
// Mutex for user-accessible items
mutable wpi::mutex m_user_mutex;
std::vector<std::shared_ptr<INetworkConnection>> m_connections;
std::string m_identity;
std::atomic_bool m_active; // set to false to terminate threads
std::atomic_uint m_update_rate; // periodic dispatch update rate, in ms
// Condition variable for forced dispatch wakeup (flush)
wpi::mutex m_flush_mutex;
wpi::condition_variable m_flush_cv;
uint64_t m_last_flush;
bool m_do_flush = false;
// Condition variable for client reconnect (uses user mutex)
wpi::condition_variable m_reconnect_cv;
unsigned int m_reconnect_proto_rev = 0x0300;
bool m_do_reconnect = true;
protected:
wpi::Logger& m_logger;
};
class Dispatcher : public DispatcherBase {
friend class DispatcherTest;
public:
Dispatcher(IStorage& storage, IConnectionNotifier& notifier,
wpi::Logger& logger)
: DispatcherBase(storage, notifier, logger) {}
void StartServer(const Twine& persist_filename, const char* listen_address,
unsigned int port);
void SetServer(const char* server_name, unsigned int port);
void SetServer(ArrayRef<std::pair<StringRef, unsigned int>> servers);
void SetServerTeam(unsigned int team, unsigned int port);
void SetServerOverride(const char* server_name, unsigned int port);
void ClearServerOverride();
};
} // namespace nt
#endif // NTCORE_DISPATCHER_H_