Make many more utility classes/headers public. (#76)

Moving these headers from src to include enables other libraries to use the
functionality provided.

* tcpsockets
* atomic_static
* raw_istream
* timestamp
* SafeThread
* Base64
* LEB128
* ConcurrentQueue

The classes have been moved into the wpi namespace as they're generic.
This commit is contained in:
Peter Johnson
2016-07-27 00:39:38 -07:00
committed by GitHub
parent d66f65e376
commit a73166a665
47 changed files with 361 additions and 259 deletions

View File

@@ -1,23 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2015. 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 NT_BASE64_H_
#define NT_BASE64_H_
#include <cstddef>
#include <string>
#include "llvm/StringRef.h"
namespace nt {
std::size_t Base64Decode(llvm::StringRef encoded, std::string* plain);
void Base64Encode(llvm::StringRef plain, std::string* encoded);
} // namespace nt
#endif // NT_BASE64_H_

View File

@@ -10,26 +10,28 @@
#include <algorithm>
#include <iterator>
#include "Log.h"
#include "tcpsockets/TCPAcceptor.h"
#include "tcpsockets/TCPConnector.h"
#include "Log.h"
using namespace nt;
ATOMIC_STATIC_INIT(Dispatcher)
void Dispatcher::StartServer(StringRef persist_filename,
void Dispatcher::StartServer(llvm::StringRef persist_filename,
const char* listen_address, unsigned int port) {
DispatcherBase::StartServer(persist_filename,
std::unique_ptr<NetworkAcceptor>(new TCPAcceptor(
static_cast<int>(port), listen_address)));
DispatcherBase::StartServer(
persist_filename,
std::unique_ptr<wpi::NetworkAcceptor>(new wpi::TCPAcceptor(
static_cast<int>(port), listen_address, Logger::GetInstance())));
}
void Dispatcher::StartClient(const char* server_name, unsigned int port) {
std::string server_name_copy(server_name);
DispatcherBase::StartClient([=]() -> std::unique_ptr<NetworkStream> {
return TCPConnector::connect(server_name_copy.c_str(),
static_cast<int>(port), 1);
DispatcherBase::StartClient([=]() -> std::unique_ptr<wpi::NetworkStream> {
return wpi::TCPConnector::connect(server_name_copy.c_str(),
static_cast<int>(port),
Logger::GetInstance(), 1);
});
}
@@ -39,9 +41,10 @@ void Dispatcher::StartClient(
for (const auto& server : servers) {
std::string server_name(server.first);
unsigned int port = server.second;
connectors.emplace_back([=]() -> std::unique_ptr<NetworkStream> {
return TCPConnector::connect(server_name.c_str(),
static_cast<int>(port), 1);
connectors.emplace_back([=]() -> std::unique_ptr<wpi::NetworkStream> {
return wpi::TCPConnector::connect(server_name.c_str(),
static_cast<int>(port),
Logger::GetInstance(), 1);
});
}
DispatcherBase::StartClient(std::move(connectors));
@@ -61,8 +64,9 @@ DispatcherBase::~DispatcherBase() {
Stop();
}
void DispatcherBase::StartServer(StringRef persist_filename,
std::unique_ptr<NetworkAcceptor> acceptor) {
void DispatcherBase::StartServer(
StringRef persist_filename,
std::unique_ptr<wpi::NetworkAcceptor> acceptor) {
{
std::lock_guard<std::mutex> lock(m_user_mutex);
if (m_active) return;

View File

@@ -19,25 +19,27 @@
#include "llvm/StringRef.h"
#include "atomic_static.h"
#include "support/atomic_static.h"
#include "NetworkConnection.h"
#include "Notifier.h"
#include "Storage.h"
namespace wpi {
class NetworkAcceptor;
class NetworkStream;
}
namespace nt {
class DispatcherBase {
friend class DispatcherTest;
public:
typedef std::function<std::unique_ptr<NetworkStream>()> Connector;
typedef std::function<std::unique_ptr<wpi::NetworkStream>()> Connector;
virtual ~DispatcherBase();
void StartServer(StringRef persist_filename,
std::unique_ptr<NetworkAcceptor> acceptor);
void StartServer(llvm::StringRef persist_filename,
std::unique_ptr<wpi::NetworkAcceptor> acceptor);
void StartClient(Connector connector);
void StartClient(std::vector<Connector>&& connectors);
void Stop();
@@ -81,7 +83,7 @@ class DispatcherBase {
std::thread m_dispatch_thread;
std::thread m_clientserver_thread;
std::unique_ptr<NetworkAcceptor> m_server_acceptor;
std::unique_ptr<wpi::NetworkAcceptor> m_server_acceptor;
std::vector<Connector> m_client_connectors;
// Mutex for user-accessible items

View File

@@ -61,6 +61,6 @@ static void def_log_func(unsigned int level, const char* file,
#endif
}
Logger::Logger() : m_func(def_log_func) {}
Logger::Logger() { SetLogger(def_log_func); }
Logger::~Logger() {}

View File

@@ -12,12 +12,12 @@
#include <sstream>
#include <string>
#include "atomic_static.h"
#include "ntcore_c.h"
#include "support/atomic_static.h"
#include "support/Logger.h"
namespace nt {
class Logger {
class Logger : public wpi::Logger {
public:
static Logger& GetInstance() {
ATOMIC_STATIC(Logger, instance);
@@ -25,59 +25,24 @@ class Logger {
}
~Logger();
typedef std::function<void(unsigned int level, const char* file,
unsigned int line, const char* msg)> LogFunc;
void SetLogger(LogFunc func) { m_func = func; }
void set_min_level(unsigned int level) { m_min_level = level; }
unsigned int min_level() const { return m_min_level; }
void Log(unsigned int level, const char* file, unsigned int line,
const char* msg) {
if (!m_func || level < m_min_level) return;
m_func(level, file, line, msg);
}
bool HasLogger() const { return m_func != nullptr; }
private:
Logger();
LogFunc m_func;
unsigned int m_min_level = 20;
ATOMIC_STATIC_DECL(Logger)
};
#define LOG(level, x) \
do { \
nt::Logger& logger = nt::Logger::GetInstance(); \
if (logger.min_level() <= level && logger.HasLogger()) { \
std::ostringstream oss; \
oss << x; \
logger.Log(level, __FILE__, __LINE__, oss.str().c_str()); \
} \
} while (0)
#define LOG(level, x) WPI_LOG(nt::Logger::GetInstance(), level, x)
#undef ERROR
#define ERROR(x) LOG(NT_LOG_ERROR, x)
#define WARNING(x) LOG(NT_LOG_WARNING, x)
#define INFO(x) LOG(NT_LOG_INFO, x)
#define ERROR(x) WPI_ERROR(nt::Logger::GetInstance(), x)
#define WARNING(x) WPI_WARNING(nt::Logger::GetInstance(), x)
#define INFO(x) WPI_INFO(nt::Logger::GetInstance(), x)
#ifdef NDEBUG
#define DEBUG(x) do {} while (0)
#define DEBUG1(x) do {} while (0)
#define DEBUG2(x) do {} while (0)
#define DEBUG3(x) do {} while (0)
#define DEBUG4(x) do {} while (0)
#else
#define DEBUG(x) LOG(NT_LOG_DEBUG, x)
#define DEBUG1(x) LOG(NT_LOG_DEBUG1, x)
#define DEBUG2(x) LOG(NT_LOG_DEBUG2, x)
#define DEBUG3(x) LOG(NT_LOG_DEBUG3, x)
#define DEBUG4(x) LOG(NT_LOG_DEBUG4, x)
#endif
#define DEBUG(x) WPI_DEBUG(nt::Logger::GetInstance(), x)
#define DEBUG1(x) WPI_DEBUG1(nt::Logger::GetInstance(), x)
#define DEBUG2(x) WPI_DEBUG2(nt::Logger::GetInstance(), x)
#define DEBUG3(x) WPI_DEBUG3(nt::Logger::GetInstance(), x)
#define DEBUG4(x) WPI_DEBUG4(nt::Logger::GetInstance(), x)
} // namespace nt

View File

@@ -7,11 +7,11 @@
#include "NetworkConnection.h"
#include "support/raw_socket_istream.h"
#include "support/timestamp.h"
#include "tcpsockets/NetworkStream.h"
#include "Log.h"
#include "Notifier.h"
#include "raw_socket_istream.h"
#include "WireDecoder.h"
#include "WireEncoder.h"
@@ -19,7 +19,7 @@ using namespace nt;
std::atomic_uint NetworkConnection::s_uid;
NetworkConnection::NetworkConnection(std::unique_ptr<NetworkStream> stream,
NetworkConnection::NetworkConnection(std::unique_ptr<wpi::NetworkStream> stream,
Notifier& notifier,
HandshakeFunc handshake,
Message::GetEntryTypeFunc get_entry_type)
@@ -106,7 +106,7 @@ void NetworkConnection::set_remote_id(StringRef remote_id) {
}
void NetworkConnection::ReadThreadMain() {
raw_socket_istream is(*m_stream);
wpi::raw_socket_istream is(*m_stream);
WireDecoder decoder(is, m_proto_rev);
m_state = static_cast<int>(kHandshake);
@@ -179,7 +179,7 @@ void NetworkConnection::WriteThreadMain() {
msg->Write(encoder);
}
}
NetworkStream::Error err;
wpi::NetworkStream::Error err;
if (!m_stream) break;
if (encoder.size() == 0) continue;
if (m_stream->send(encoder.data(), encoder.size(), &err) == 0) break;

View File

@@ -17,7 +17,9 @@
#include "Message.h"
#include "ntcore_cpp.h"
namespace wpi {
class NetworkStream;
}
namespace nt {
@@ -35,9 +37,9 @@ class NetworkConnection {
typedef std::function<void(std::shared_ptr<Message> msg,
NetworkConnection* conn)> ProcessIncomingFunc;
typedef std::vector<std::shared_ptr<Message>> Outgoing;
typedef ConcurrentQueue<Outgoing> OutgoingQueue;
typedef wpi::ConcurrentQueue<Outgoing> OutgoingQueue;
NetworkConnection(std::unique_ptr<NetworkStream> stream,
NetworkConnection(std::unique_ptr<wpi::NetworkStream> stream,
Notifier& notifier,
HandshakeFunc handshake,
Message::GetEntryTypeFunc get_entry_type);
@@ -54,7 +56,7 @@ class NetworkConnection {
ConnectionInfo info() const;
bool active() const { return m_active; }
NetworkStream& stream() { return *m_stream; }
wpi::NetworkStream& stream() { return *m_stream; }
void QueueOutgoing(std::shared_ptr<Message> msg);
void PostOutgoing(bool keep_alive);
@@ -82,7 +84,7 @@ class NetworkConnection {
static std::atomic_uint s_uid;
unsigned int m_uid;
std::unique_ptr<NetworkStream> m_stream;
std::unique_ptr<wpi::NetworkStream> m_stream;
Notifier& m_notifier;
OutgoingQueue m_outgoing;
HandshakeFunc m_handshake;

View File

@@ -60,7 +60,7 @@ class UidVector {
} // anonymous namespace
class Notifier::Thread : public SafeThread {
class Notifier::Thread : public wpi::SafeThread {
public:
Thread(std::function<void()> on_start, std::function<void()> on_exit)
: m_on_start(on_start), m_on_exit(on_exit) {}
@@ -83,7 +83,7 @@ class Notifier::Thread : public SafeThread {
UidVector<ConnectionListenerCallback> m_conn_listeners;
struct EntryNotification {
EntryNotification(StringRef name_, std::shared_ptr<Value> value_,
EntryNotification(llvm::StringRef name_, std::shared_ptr<Value> value_,
unsigned int flags_, EntryListenerCallback only_)
: name(name_),
value(value_),

View File

@@ -10,9 +10,9 @@
#include <functional>
#include "atomic_static.h"
#include "support/atomic_static.h"
#include "support/SafeThread.h"
#include "ntcore_cpp.h"
#include "SafeThread.h"
namespace nt {
@@ -34,7 +34,7 @@ class Notifier {
void SetOnStart(std::function<void()> on_start) { m_on_start = on_start; }
void SetOnExit(std::function<void()> on_exit) { m_on_exit = on_exit; }
unsigned int AddEntryListener(StringRef prefix,
unsigned int AddEntryListener(llvm::StringRef prefix,
EntryListenerCallback callback,
unsigned int flags);
void RemoveEntryListener(unsigned int entry_listener_uid);
@@ -52,7 +52,7 @@ class Notifier {
Notifier();
class Thread;
SafeThreadOwner<Thread> m_owner;
wpi::SafeThreadOwner<Thread> m_owner;
std::atomic_bool m_local_notifiers;

View File

@@ -15,7 +15,7 @@ using namespace nt;
ATOMIC_STATIC_INIT(RpcServer)
class RpcServer::Thread : public SafeThread {
class RpcServer::Thread : public wpi::SafeThread {
public:
Thread(std::function<void()> on_start, std::function<void()> on_exit)
: m_on_start(on_start), m_on_exit(on_exit) {}

View File

@@ -15,10 +15,10 @@
#include <utility>
#include "llvm/DenseMap.h"
#include "atomic_static.h"
#include "support/atomic_static.h"
#include "support/SafeThread.h"
#include "Message.h"
#include "ntcore_cpp.h"
#include "SafeThread.h"
namespace nt {
@@ -51,7 +51,7 @@ class RpcServer {
RpcServer();
class Thread;
SafeThreadOwner<Thread> m_owner;
wpi::SafeThreadOwner<Thread> m_owner;
struct RpcCall {
RpcCall(StringRef name_, std::shared_ptr<Message> msg_, RpcCallback func_,

View File

@@ -1,93 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2015. 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 NT_SAFETHREAD_H_
#define NT_SAFETHREAD_H_
#include <atomic>
#include <condition_variable>
#include <mutex>
#include <thread>
namespace nt {
// Base class for SafeThreadOwner threads.
class SafeThread {
public:
virtual ~SafeThread() = default;
virtual void Main() = 0;
std::mutex m_mutex;
bool m_active = true;
std::condition_variable m_cond;
};
namespace detail {
// Non-template proxy base class for common proxy code.
class SafeThreadProxyBase {
public:
SafeThreadProxyBase(SafeThread* thr) : m_thread(thr) {
if (!m_thread) return;
std::unique_lock<std::mutex>(m_thread->m_mutex).swap(m_lock);
if (!m_thread->m_active) {
m_lock.unlock();
m_thread = nullptr;
return;
}
}
explicit operator bool() const { return m_thread != nullptr; }
std::unique_lock<std::mutex>& GetLock() { return m_lock; }
protected:
SafeThread* m_thread;
std::unique_lock<std::mutex> m_lock;
};
// A proxy for SafeThread.
// Also serves as a scoped lock on SafeThread::m_mutex.
template <typename T>
class SafeThreadProxy : public SafeThreadProxyBase {
public:
SafeThreadProxy(SafeThread* thr) : SafeThreadProxyBase(thr) {}
T& operator*() const { return *static_cast<T*>(m_thread); }
T* operator->() const { return static_cast<T*>(m_thread); }
};
// Non-template owner base class for common owner code.
class SafeThreadOwnerBase {
public:
void Stop();
protected:
SafeThreadOwnerBase() { m_thread = nullptr; }
SafeThreadOwnerBase(const SafeThreadOwnerBase&) = delete;
SafeThreadOwnerBase& operator=(const SafeThreadOwnerBase&) = delete;
~SafeThreadOwnerBase() { Stop(); }
void Start(SafeThread* thr);
SafeThread* GetThread() { return m_thread.load(); }
private:
std::atomic<SafeThread*> m_thread;
};
} // namespace detail
template <typename T>
class SafeThreadOwner : public detail::SafeThreadOwnerBase {
public:
void Start() { Start(new T); }
void Start(T* thr) { detail::SafeThreadOwnerBase::Start(thr); }
using Proxy = typename detail::SafeThreadProxy<T>;
Proxy GetThread() { return Proxy(detail::SafeThreadOwnerBase::GetThread()); }
};
} // namespace nt
#endif // NT_SAFETHREAD_H_

View File

@@ -12,7 +12,7 @@
#include <tuple>
#include "llvm/StringExtras.h"
#include "Base64.h"
#include "support/Base64.h"
#include "Log.h"
#include "NetworkConnection.h"
@@ -853,7 +853,7 @@ static void SavePersistentImpl(
WriteString(os, v->GetString());
break;
case NT_RAW:
Base64Encode(v->GetRaw(), &base64_encoded);
wpi::Base64Encode(v->GetRaw(), &base64_encoded);
os << base64_encoded;
break;
case NT_BOOLEAN_ARRAY: {
@@ -1139,7 +1139,7 @@ bool Storage::LoadPersistent(
break;
}
case NT_RAW:
Base64Decode(line, &str);
wpi::Base64Decode(line, &str);
value = Value::MakeRaw(std::move(str));
break;
case NT_BOOLEAN_ARRAY: {

View File

@@ -19,7 +19,7 @@
#include "llvm/DenseMap.h"
#include "llvm/StringMap.h"
#include "atomic_static.h"
#include "support/atomic_static.h"
#include "Message.h"
#include "Notifier.h"
#include "ntcore_cpp.h"

View File

@@ -13,12 +13,12 @@ using namespace nt;
Value::Value() {
m_val.type = NT_UNASSIGNED;
m_val.last_change = Now();
m_val.last_change = wpi::Now();
}
Value::Value(NT_Type type, const private_init&) {
m_val.type = type;
m_val.last_change = Now();
m_val.last_change = wpi::Now();
if (m_val.type == NT_BOOLEAN_ARRAY)
m_val.data.arr_boolean.arr = nullptr;
else if (m_val.type == NT_DOUBLE_ARRAY)

View File

@@ -13,7 +13,7 @@
#include <cstring>
#include "llvm/MathExtras.h"
#include "leb128.h"
#include "support/leb128.h"
using namespace nt;
@@ -45,7 +45,8 @@ static double ReadDouble(const char*& buf) {
return llvm::BitsToDouble(val);
}
WireDecoder::WireDecoder(raw_istream& is, unsigned int proto_rev) : m_is(is) {
WireDecoder::WireDecoder(wpi::raw_istream& is, unsigned int proto_rev)
: m_is(is) {
// Start with a 1K temporary buffer. Use malloc instead of new so we can
// realloc.
m_allocated = 1024;

View File

@@ -11,9 +11,9 @@
#include <cstddef>
#include "nt_Value.h"
#include "leb128.h"
#include "support/leb128.h"
#include "support/raw_istream.h"
//#include "Log.h"
#include "raw_istream.h"
namespace nt {
@@ -26,7 +26,7 @@ namespace nt {
*/
class WireDecoder {
public:
explicit WireDecoder(raw_istream& is, unsigned int proto_rev);
explicit WireDecoder(wpi::raw_istream& is, unsigned int proto_rev);
~WireDecoder();
void set_proto_rev(unsigned int proto_rev) { m_proto_rev = proto_rev; }
@@ -113,7 +113,7 @@ class WireDecoder {
/* Reads an ULEB128-encoded unsigned integer. */
bool ReadUleb128(unsigned long* val) {
return nt::ReadUleb128(m_is, val);
return wpi::ReadUleb128(m_is, val);
}
bool ReadType(NT_Type* type);
@@ -135,7 +135,7 @@ class WireDecoder {
void Realloc(std::size_t len);
/* input stream */
raw_istream& m_is;
wpi::raw_istream& m_is;
/* temporary buffer */
char* m_buf;

View File

@@ -13,7 +13,7 @@
#include <cstring>
#include "llvm/MathExtras.h"
#include "leb128.h"
#include "support/leb128.h"
using namespace nt;
@@ -38,7 +38,7 @@ void WireEncoder::WriteDouble(double val) {
}
void WireEncoder::WriteUleb128(unsigned long val) {
nt::WriteUleb128(m_data, val);
wpi::WriteUleb128(m_data, val);
}
void WireEncoder::WriteType(NT_Type type) {
@@ -191,7 +191,7 @@ std::size_t WireEncoder::GetStringSize(llvm::StringRef str) const {
if (len > 0xffff) len = 0xffff; // Limited to 64K length; truncate
return 2 + len;
}
return SizeUleb128(str.size()) + str.size();
return wpi::SizeUleb128(str.size()) + str.size();
}
void WireEncoder::WriteString(llvm::StringRef str) {

View File

@@ -1,49 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2015. 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 NT_ATOMIC_STATIC_H_
#define NT_ATOMIC_STATIC_H_
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
// Just use a local static. This is thread-safe per
// http://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/
// Per https://msdn.microsoft.com/en-us/library/Hh567368.aspx "Magic Statics"
// are supported in Visual Studio 2015 but not in earlier versions.
#define ATOMIC_STATIC(cls, inst) static cls inst
#define ATOMIC_STATIC_DECL(cls)
#define ATOMIC_STATIC_INIT(cls)
#else
// From http://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/
#include <atomic>
#include <mutex>
#define ATOMIC_STATIC(cls, inst) \
cls* inst##tmp = m_instance.load(std::memory_order_acquire); \
if (inst##tmp == nullptr) { \
std::lock_guard<std::mutex> lock(m_instance_mutex); \
inst##tmp = m_instance.load(std::memory_order_relaxed); \
if (inst##tmp == nullptr) { \
inst##tmp = new cls; \
m_instance.store(inst##tmp, std::memory_order_release); \
} \
} \
cls& inst = *inst##tmp
#define ATOMIC_STATIC_DECL(cls) \
static std::atomic<cls*> m_instance; \
static std::mutex m_instance_mutex;
#define ATOMIC_STATIC_INIT(cls) \
std::atomic<cls*> cls::m_instance; \
std::mutex cls::m_instance_mutex;
#endif
#endif // NT_ATOMIC_STATIC_H_

View File

@@ -1,26 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2015. 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 NT_LEB128_H_
#define NT_LEB128_H_
#include <cstddef>
#include "llvm/SmallVector.h"
namespace nt {
class raw_istream;
std::size_t SizeUleb128(unsigned long val);
std::size_t WriteUleb128(llvm::SmallVectorImpl<char>& dest, unsigned long val);
std::size_t ReadUleb128(const char* addr, unsigned long* ret);
bool ReadUleb128(raw_istream& is, unsigned long* ret);
} // namespace nt
#endif // NT_LEB128_H_

View File

@@ -10,6 +10,7 @@
#include <cassert>
#include <cstdlib>
#include "support/timestamp.h"
#include "Value_internal.h"
using namespace nt;
@@ -405,6 +406,10 @@ const char *NT_LoadPersistent(const char *filename,
* Utility Functions
*/
unsigned long long NT_Now() {
return wpi::Now();
}
void NT_SetLogger(NT_LogFunc func, unsigned int min_level) {
nt::SetLogger(func, min_level);
}

View File

@@ -11,8 +11,9 @@
#include <cstdio>
#include <cstdlib>
#include "Dispatcher.h"
#include "support/timestamp.h"
#include "Log.h"
#include "Dispatcher.h"
#include "Notifier.h"
#include "RpcServer.h"
#include "Storage.h"
@@ -168,7 +169,7 @@ std::string PackRpcDefinition(const RpcDefinition& def) {
}
bool UnpackRpcDefinition(StringRef packed, RpcDefinition* def) {
raw_mem_istream is(packed.data(), packed.size());
wpi::raw_mem_istream is(packed.data(), packed.size());
WireDecoder dec(is, 0x0300);
if (!dec.Read8(&def->version)) return false;
if (!dec.ReadString(&def->name)) return false;
@@ -211,7 +212,7 @@ std::string PackRpcValues(ArrayRef<std::shared_ptr<Value>> values) {
std::vector<std::shared_ptr<Value>> UnpackRpcValues(StringRef packed,
ArrayRef<NT_Type> types) {
raw_mem_istream is(packed.data(), packed.size());
wpi::raw_mem_istream is(packed.data(), packed.size());
WireDecoder dec(is, 0x0300);
std::vector<std::shared_ptr<Value>> vec;
for (auto type : types) {
@@ -281,6 +282,10 @@ const char* LoadPersistent(
return Storage::GetInstance().LoadPersistent(filename, warn);
}
unsigned long long Now() {
return wpi::Now();
}
void SetLogger(LogFunc func, unsigned int min_level) {
Logger& logger = Logger::GetInstance();
logger.SetLogger(func);

View File

@@ -1,40 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2015. 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 NT_RAW_ISTREAM_H_
#define NT_RAW_ISTREAM_H_
#include <cstddef>
namespace nt {
class raw_istream {
public:
raw_istream() = default;
virtual ~raw_istream() = default;
virtual bool read(void* data, std::size_t len) = 0;
virtual void close() = 0;
raw_istream(const raw_istream&) = delete;
raw_istream& operator=(const raw_istream&) = delete;
};
class raw_mem_istream : public raw_istream {
public:
raw_mem_istream(const char* mem, std::size_t len) : m_cur(mem), m_left(len) {}
virtual ~raw_mem_istream() = default;
virtual bool read(void* data, std::size_t len);
virtual void close() {}
private:
const char* m_cur;
std::size_t m_left;
};
} // namespace nt
#endif // NT_RAW_ISTREAM_H_

View File

@@ -1,32 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2015. 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 NT_RAW_SOCKET_ISTREAM_H_
#define NT_RAW_SOCKET_ISTREAM_H_
#include "raw_istream.h"
#include "tcpsockets/NetworkStream.h"
namespace nt {
class raw_socket_istream : public raw_istream {
public:
raw_socket_istream(NetworkStream& stream, int timeout = 0)
: m_stream(stream), m_timeout(timeout) {}
virtual ~raw_socket_istream() = default;
virtual bool read(void* data, std::size_t len);
virtual void close();
private:
NetworkStream& m_stream;
int m_timeout;
};
} // namespace nt
#endif // NT_RAW_SOCKET_ISTREAM_H_

View File

@@ -62,9 +62,9 @@
*
*/
#include "Base64.h"
#include "support/Base64.h"
namespace nt {
namespace wpi {
// aaaack but it's fast and const should make it shared text page.
static const unsigned char pr2six[256] =
@@ -149,4 +149,4 @@ void Base64Encode(llvm::StringRef plain, std::string* encoded) {
}
}
} // namespace nt
} // namespace wpi

View File

@@ -1,79 +0,0 @@
//
// Copyright (c) 2013 Juan Palacios juan.palacios.puyana@gmail.com
// Subject to the BSD 2-Clause License
// - see < http://opensource.org/licenses/BSD-2-Clause>
//
#ifndef NT_SUPPORT_CONCURRENT_QUEUE_H_
#define NT_SUPPORT_CONCURRENT_QUEUE_H_
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
template <typename T>
class ConcurrentQueue {
public:
bool empty() const {
std::unique_lock<std::mutex> mlock(mutex_);
return queue_.empty();
}
typename std::queue<T>::size_type size() const {
std::unique_lock<std::mutex> mlock(mutex_);
return queue_.size();
}
T pop() {
std::unique_lock<std::mutex> mlock(mutex_);
while (queue_.empty()) {
cond_.wait(mlock);
}
auto item = std::move(queue_.front());
queue_.pop();
return item;
}
void pop(T& item) {
std::unique_lock<std::mutex> mlock(mutex_);
while (queue_.empty()) {
cond_.wait(mlock);
}
item = queue_.front();
queue_.pop();
}
void push(const T& item) {
std::unique_lock<std::mutex> mlock(mutex_);
queue_.push(item);
mlock.unlock();
cond_.notify_one();
}
void push(T&& item) {
std::unique_lock<std::mutex> mlock(mutex_);
queue_.push(std::forward<T>(item));
mlock.unlock();
cond_.notify_one();
}
template <typename... Args>
void emplace(Args&&... args) {
std::unique_lock<std::mutex> mlock(mutex_);
queue_.emplace(std::forward<Args>(args)...);
mlock.unlock();
cond_.notify_one();
}
ConcurrentQueue() = default;
ConcurrentQueue(const ConcurrentQueue&) = delete;
ConcurrentQueue& operator=(const ConcurrentQueue&) = delete;
private:
std::queue<T> queue_;
mutable std::mutex mutex_;
std::condition_variable cond_;
};
#endif // NT_SUPPORT_CONCURRENT_QUEUE_H_

View File

@@ -5,9 +5,9 @@
/* the project. */
/*----------------------------------------------------------------------------*/
#include "SafeThread.h"
#include "support/SafeThread.h"
using namespace nt;
using namespace wpi;
void detail::SafeThreadOwnerBase::Start(SafeThread* thr) {
SafeThread* curthr = nullptr;

View File

@@ -5,11 +5,11 @@
/* the project. */
/*----------------------------------------------------------------------------*/
#include "leb128.h"
#include "support/leb128.h"
#include "raw_istream.h"
#include "support/raw_istream.h"
namespace nt {
namespace wpi {
/**
* Get size of unsigned LEB128 data
@@ -116,4 +116,4 @@ bool ReadUleb128(raw_istream& is, unsigned long* ret) {
return true;
}
} // namespace nt
} // namespace wpi

View File

@@ -5,11 +5,11 @@
/* the project. */
/*----------------------------------------------------------------------------*/
#include "raw_istream.h"
#include "support/raw_istream.h"
#include <cstring>
using namespace nt;
using namespace wpi;
bool raw_mem_istream::read(void* data, std::size_t len) {
if (len > m_left) return false;

View File

@@ -5,9 +5,9 @@
/* the project. */
/*----------------------------------------------------------------------------*/
#include "raw_socket_istream.h"
#include "support/raw_socket_istream.h"
using namespace nt;
using namespace wpi;
bool raw_socket_istream::read(void* data, std::size_t len) {
char* cdata = static_cast<char*>(data);

View File

@@ -4,7 +4,7 @@
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include "timestamp.h"
#include "support/timestamp.h"
#ifdef _WIN32
#include <cassert>
@@ -70,7 +70,7 @@ static const unsigned long long offset_val = timestamp();
static const unsigned long long frequency_val = update_frequency();
#endif
unsigned long long nt::Now() {
unsigned long long wpi::Now() {
#ifdef _WIN32
assert(offset_val > 0u);
assert(frequency_val > 0u);
@@ -84,6 +84,6 @@ unsigned long long nt::Now() {
#endif
}
unsigned long long NT_Now() {
return nt::Now();
unsigned long long WPI_Now() {
return wpi::Now();
}

View File

@@ -1,28 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2015. 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 NT_SUPPORT_TIMESTAMP_H_
#define NT_SUPPORT_TIMESTAMP_H_
#ifdef __cplusplus
extern "C" {
#endif
unsigned long long NT_Now(void);
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
namespace nt {
unsigned long long Now();
} // namespace nt
#endif
#endif // NT_SUPPORT_TIMESTAMP_H_

View File

@@ -1,26 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2015. 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 TCPSOCKETS_NETWORKACCEPTOR_H_
#define TCPSOCKETS_NETWORKACCEPTOR_H_
#include "NetworkStream.h"
class NetworkAcceptor {
public:
NetworkAcceptor() = default;
virtual ~NetworkAcceptor() = default;
virtual int start() = 0;
virtual void shutdown() = 0;
virtual std::unique_ptr<NetworkStream> accept() = 0;
NetworkAcceptor(const NetworkAcceptor&) = delete;
NetworkAcceptor& operator=(const NetworkAcceptor&) = delete;
};
#endif // TCPSOCKETS_NETWORKACCEPTOR_H_

View File

@@ -1,39 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2015. 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 TCPSOCKETS_NETWORKSTREAM_H_
#define TCPSOCKETS_NETWORKSTREAM_H_
#include <cstddef>
#include "llvm/StringRef.h"
class NetworkStream {
public:
NetworkStream() = default;
virtual ~NetworkStream() = default;
enum Error {
kConnectionClosed = 0,
kConnectionReset = -1,
kConnectionTimedOut = -2
};
virtual std::size_t send(const char* buffer, std::size_t len, Error* err) = 0;
virtual std::size_t receive(char* buffer, std::size_t len, Error* err,
int timeout = 0) = 0;
virtual void close() = 0;
virtual llvm::StringRef getPeerIP() const = 0;
virtual int getPeerPort() const = 0;
virtual void setNoDelay() = 0;
NetworkStream(const NetworkStream&) = delete;
NetworkStream& operator=(const NetworkStream&) = delete;
};
#endif // TCPSOCKETS_NETWORKSTREAM_H_

View File

@@ -5,7 +5,7 @@
/* the project. */
/*----------------------------------------------------------------------------*/
#include "SocketError.h"
#include "tcpsockets/SocketError.h"
#ifdef _WIN32
#include <windows.h>
@@ -13,7 +13,7 @@
#include <string.h>
#endif
namespace tcpsockets {
namespace wpi {
std::string SocketStrerror(int code) {
#ifdef _WIN32
@@ -28,4 +28,4 @@ std::string SocketStrerror(int code) {
#endif
}
} // namespace tcpsockets
} // namespace wpi

View File

@@ -1,37 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2015. 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 TCPSOCKETS_SOCKETERROR_H_
#define TCPSOCKETS_SOCKETERROR_H_
#include <string>
#ifdef _WIN32
#include <WinSock2.h>
#else
#include <errno.h>
#endif
namespace tcpsockets {
static inline int SocketErrno() {
#ifdef _WIN32
return WSAGetLastError();
#else
return errno;
#endif
}
std::string SocketStrerror(int code);
static inline std::string SocketStrerror() {
return SocketStrerror(SocketErrno());
}
} // namespace tcpsockets
#endif // TCPSOCKETS_SOCKETERROR_H_

View File

@@ -21,7 +21,7 @@
limitations under the License.
*/
#include "TCPAcceptor.h"
#include "tcpsockets/TCPAcceptor.h"
#include <cstdio>
#include <cstring>
@@ -36,16 +36,17 @@
#endif
#include "llvm/SmallString.h"
#include "../Log.h"
#include "SocketError.h"
#include "support/Logger.h"
#include "tcpsockets/SocketError.h"
using namespace tcpsockets;
using namespace wpi;
TCPAcceptor::TCPAcceptor(int port, const char* address)
TCPAcceptor::TCPAcceptor(int port, const char* address, Logger& logger)
: m_lsd(0),
m_port(port),
m_address(address),
m_listening(false) {
m_listening(false),
m_logger(logger) {
m_shutdown = false;
#ifdef _WIN32
WSAData wsaData;
@@ -73,7 +74,7 @@ int TCPAcceptor::start() {
m_lsd = socket(PF_INET, SOCK_STREAM, 0);
if (m_lsd < 0) {
ERROR("could not create socket");
WPI_ERROR(m_logger, "could not create socket");
return -1;
}
struct sockaddr_in address;
@@ -99,13 +100,13 @@ int TCPAcceptor::start() {
int result = bind(m_lsd, (struct sockaddr*)&address, sizeof(address));
if (result != 0) {
ERROR("bind() failed: " << SocketStrerror());
WPI_ERROR(m_logger, "bind() failed: " << SocketStrerror());
return result;
}
result = listen(m_lsd, 5);
if (result != 0) {
ERROR("listen() failed: " << SocketStrerror());
WPI_ERROR(m_logger, "listen() failed: " << SocketStrerror());
return result;
}
m_listening = true;
@@ -172,7 +173,8 @@ std::unique_ptr<NetworkStream> TCPAcceptor::accept() {
std::memset(&address, 0, sizeof(address));
int sd = ::accept(m_lsd, (struct sockaddr*)&address, &len);
if (sd < 0) {
if (!m_shutdown) ERROR("accept() failed: " << SocketStrerror());
if (!m_shutdown)
WPI_ERROR(m_logger, "accept() failed: " << SocketStrerror());
return nullptr;
}
if (m_shutdown) {

View File

@@ -1,50 +0,0 @@
/*
TCPAcceptor.h
TCPAcceptor class interface. TCPAcceptor provides methods to passively
establish TCP/IP connections with clients.
------------------------------------------
Copyright © 2013 [Vic Hargrave - http://vichargrave.com]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef TCPSOCKETS_TCPACCEPTOR_H_
#define TCPSOCKETS_TCPACCEPTOR_H_
#include <atomic>
#include <memory>
#include <string>
#include "NetworkAcceptor.h"
#include "TCPStream.h"
class TCPAcceptor : public NetworkAcceptor {
int m_lsd;
int m_port;
std::string m_address;
bool m_listening;
std::atomic_bool m_shutdown;
public:
TCPAcceptor(int port, const char* address);
~TCPAcceptor();
int start() override;
void shutdown() override;
std::unique_ptr<NetworkStream> accept() override;
};
#endif

View File

@@ -21,7 +21,7 @@
limitations under the License
*/
#include "TCPConnector.h"
#include "tcpsockets/TCPConnector.h"
#include <errno.h>
#include <fcntl.h>
@@ -38,13 +38,13 @@
#include <unistd.h>
#endif
#include "TCPStream.h"
#include "tcpsockets/TCPStream.h"
#include "llvm/SmallString.h"
#include "../Log.h"
#include "SocketError.h"
#include "support/Logger.h"
#include "tcpsockets/SocketError.h"
using namespace tcpsockets;
using namespace wpi;
static int ResolveHostName(const char* hostname, struct in_addr* addr) {
struct addrinfo hints;
@@ -68,7 +68,8 @@ static int ResolveHostName(const char* hostname, struct in_addr* addr) {
}
std::unique_ptr<NetworkStream> TCPConnector::connect(const char* server,
int port, int timeout) {
int port, Logger& logger,
int timeout) {
#ifdef _WIN32
struct WSAHelper {
WSAHelper() {
@@ -90,7 +91,7 @@ std::unique_ptr<NetworkStream> TCPConnector::connect(const char* server,
addr_copy.push_back('\0');
int size = sizeof(address);
if (WSAStringToAddress(addr_copy.data(), PF_INET, nullptr, (struct sockaddr*)&address, &size) != 0) {
ERROR("could not resolve " << server << " address");
WPI_ERROR(logger, "could not resolve " << server << " address");
return nullptr;
}
#else
@@ -102,11 +103,11 @@ std::unique_ptr<NetworkStream> TCPConnector::connect(const char* server,
if (timeout == 0) {
int sd = socket(AF_INET, SOCK_STREAM, 0);
if (sd < 0) {
ERROR("could not create socket");
WPI_ERROR(logger, "could not create socket");
return nullptr;
}
if (::connect(sd, (struct sockaddr*)&address, sizeof(address)) != 0) {
ERROR("connect() to " << server << " port " << port << " failed: " << SocketStrerror());
WPI_ERROR(logger, "connect() to " << server << " port " << port << " failed: " << SocketStrerror());
#ifdef _WIN32
closesocket(sd);
#else
@@ -122,7 +123,7 @@ std::unique_ptr<NetworkStream> TCPConnector::connect(const char* server,
socklen_t len;
int result = -1, valopt, sd = socket(AF_INET, SOCK_STREAM, 0);
if (sd < 0) {
ERROR("could not create socket");
WPI_ERROR(logger, "could not create socket");
return nullptr;
}
@@ -154,15 +155,15 @@ std::unique_ptr<NetworkStream> TCPConnector::connect(const char* server,
len = sizeof(int);
getsockopt(sd, SOL_SOCKET, SO_ERROR, (char*)(&valopt), &len);
if (valopt) {
ERROR("select() to " << server << " port " << port << " error " << valopt << " - " << SocketStrerror(valopt));
WPI_ERROR(logger, "select() to " << server << " port " << port << " error " << valopt << " - " << SocketStrerror(valopt));
}
// connection established
else
result = 0;
} else
INFO("connect() to " << server << " port " << port << " timed out");
WPI_INFO(logger, "connect() to " << server << " port " << port << " timed out");
} else
ERROR("connect() to " << server << " port " << port << " error " << SocketErrno() << " - " << SocketStrerror());
WPI_ERROR(logger, "connect() to " << server << " port " << port << " error " << SocketErrno() << " - " << SocketStrerror());
}
// Return socket to blocking mode

View File

@@ -1,37 +0,0 @@
/*
TCPConnector.h
TCPConnector class interface. TCPConnector provides methods to actively
establish TCP/IP connections with a server.
------------------------------------------
Copyright © 2013 [Vic Hargrave - http://vichargrave.com]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License
*/
#ifndef TCPSOCKETS_TCPCONNECTOR_H_
#define TCPSOCKETS_TCPCONNECTOR_H_
#include <memory>
#include "NetworkStream.h"
class TCPConnector {
public:
static std::unique_ptr<NetworkStream> connect(const char* server, int port,
int timeout = 0);
};
#endif

View File

@@ -21,7 +21,7 @@
limitations under the License.
*/
#include "TCPStream.h"
#include "tcpsockets/TCPStream.h"
#ifdef _WIN32
#include <WinSock2.h>
@@ -31,13 +31,15 @@
#include <unistd.h>
#endif
TCPStream::TCPStream(int sd, struct sockaddr_in* address) : m_sd(sd) {
using namespace wpi;
TCPStream::TCPStream(int sd, sockaddr_in* address) : m_sd(sd) {
char ip[50];
#ifdef _WIN32
unsigned long size = sizeof(ip) - 1;
WSAAddressToString((struct sockaddr*)address, sizeof sockaddr_in, nullptr, ip, &size);
WSAAddressToString((sockaddr*)address, sizeof sockaddr_in, nullptr, ip, &size);
#else
inet_ntop(PF_INET, (struct in_addr*)&(address->sin_addr.s_addr), ip,
inet_ntop(PF_INET, (in_addr*)&(address->sin_addr.s_addr), ip,
sizeof(ip) - 1);
#endif
m_peerIP = ip;

View File

@@ -1,67 +0,0 @@
/*
TCPStream.h
TCPStream class interface. TCPStream provides methods to trasnfer
data between peers over a TCP/IP connection.
------------------------------------------
Copyright © 2013 [Vic Hargrave - http://vichargrave.com]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef TCPSOCKETS_TCPSTREAM_H_
#define TCPSOCKETS_TCPSTREAM_H_
#include <cstddef>
#include <string>
#ifdef _WIN32
#include <winsock2.h>
#else
#include <sys/socket.h>
#endif
#include "NetworkStream.h"
class TCPStream : public NetworkStream {
int m_sd;
std::string m_peerIP;
int m_peerPort;
public:
friend class TCPAcceptor;
friend class TCPConnector;
~TCPStream();
std::size_t send(const char* buffer, std::size_t len, Error* err) override;
std::size_t receive(char* buffer, std::size_t len, Error* err,
int timeout = 0) override;
void close() override;
llvm::StringRef getPeerIP() const override;
int getPeerPort() const override;
void setNoDelay() override;
TCPStream(const TCPStream& stream) = delete;
TCPStream& operator=(const TCPStream&) = delete;
private:
bool WaitForReadEvent(int timeout);
TCPStream(int sd, struct sockaddr_in* address);
TCPStream() = delete;
};
#endif