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

23
include/support/Base64.h Normal file
View File

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

View File

@@ -0,0 +1,83 @@
//
// 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 WPIUTIL_SUPPORT_CONCURRENT_QUEUE_H_
#define WPIUTIL_SUPPORT_CONCURRENT_QUEUE_H_
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
namespace wpi {
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_;
};
} // namespace wpi
#endif // WPIUTIL_SUPPORT_CONCURRENT_QUEUE_H_

82
include/support/Logger.h Normal file
View File

@@ -0,0 +1,82 @@
/*----------------------------------------------------------------------------*/
/* 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 WPIUTIL_SUPPORT_LOGGER_H_
#define WPIUTIL_SUPPORT_LOGGER_H_
#include <functional>
#include <sstream>
#include <string>
namespace wpi {
enum LogLevel {
WPI_LOG_CRITICAL = 50,
WPI_LOG_ERROR = 40,
WPI_LOG_WARNING = 30,
WPI_LOG_INFO = 20,
WPI_LOG_DEBUG = 10,
WPI_LOG_DEBUG1 = 9,
WPI_LOG_DEBUG2 = 8,
WPI_LOG_DEBUG3 = 7,
WPI_LOG_DEBUG4 = 6
};
class Logger {
public:
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:
LogFunc m_func;
unsigned int m_min_level = 20;
};
#define WPI_LOG(logger_inst, level, x) \
do { \
::wpi::Logger& WPI_logger_ = logger_inst; \
if (WPI_logger_.min_level() <= level && WPI_logger_.HasLogger()) { \
std::ostringstream oss; \
oss << x; \
WPI_logger_.Log(level, __FILE__, __LINE__, oss.str().c_str()); \
} \
} while (0)
#define WPI_ERROR(inst, x) WPI_LOG(inst, ::wpi::WPI_LOG_ERROR, x)
#define WPI_WARNING(inst, x) WPI_LOG(inst, ::wpi::WPI_LOG_WARNING, x)
#define WPI_INFO(inst, x) WPI_LOG(inst, ::wpi::WPI_LOG_INFO, x)
#ifdef NDEBUG
#define WPI_DEBUG(inst, x) do {} while (0)
#define WPI_DEBUG1(inst, x) do {} while (0)
#define WPI_DEBUG2(inst, x) do {} while (0)
#define WPI_DEBUG3(inst, x) do {} while (0)
#define WPI_DEBUG4(inst, x) do {} while (0)
#else
#define WPI_DEBUG(inst, x) WPI_LOG(inst, ::wpi::WPI_LOG_DEBUG, x)
#define WPI_DEBUG1(inst, x) WPI_LOG(inst, ::wpi::WPI_LOG_DEBUG1, x)
#define WPI_DEBUG2(inst, x) WPI_LOG(inst, ::wpi::WPI_LOG_DEBUG2, x)
#define WPI_DEBUG3(inst, x) WPI_LOG(inst, ::wpi::WPI_LOG_DEBUG3, x)
#define WPI_DEBUG4(inst, x) WPI_LOG(inst, ::wpi::WPI_LOG_DEBUG4, x)
#endif
} // namespace wpi
#endif // WPIUTIL_SUPPORT_LOGGER_H_

View File

@@ -0,0 +1,93 @@
/*----------------------------------------------------------------------------*/
/* 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 WPIUTIL_SUPPORT_SAFETHREAD_H_
#define WPIUTIL_SUPPORT_SAFETHREAD_H_
#include <atomic>
#include <condition_variable>
#include <mutex>
#include <thread>
namespace wpi {
// 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 wpi
#endif // WPIUTIL_SUPPORT_SAFETHREAD_H_

View File

@@ -0,0 +1,49 @@
/*----------------------------------------------------------------------------*/
/* 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 WPIUTIL_SUPPORT_ATOMIC_STATIC_H_
#define WPIUTIL_SUPPORT_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 // WPIUTIL_SUPPORT_ATOMIC_STATIC_H_

26
include/support/leb128.h Normal file
View File

@@ -0,0 +1,26 @@
/*----------------------------------------------------------------------------*/
/* 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 WPIUTIL_SUPPORT_LEB128_H_
#define WPIUTIL_SUPPORT_LEB128_H_
#include <cstddef>
#include "llvm/SmallVector.h"
namespace wpi {
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 wpi
#endif // WPIUTIL_SUPPORT_LEB128_H_

View File

@@ -0,0 +1,40 @@
/*----------------------------------------------------------------------------*/
/* 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 WPIUTIL_SUPPORT_RAW_ISTREAM_H_
#define WPIUTIL_SUPPORT_RAW_ISTREAM_H_
#include <cstddef>
namespace wpi {
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 wpi
#endif // WPIUTIL_SUPPORT_RAW_ISTREAM_H_

View File

@@ -0,0 +1,31 @@
/*----------------------------------------------------------------------------*/
/* 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 WPIUTIL_SUPPORT_RAW_SOCKET_ISTREAM_H_
#define WPIUTIL_SUPPORT_RAW_SOCKET_ISTREAM_H_
#include "support/raw_istream.h"
#include "tcpsockets/NetworkStream.h"
namespace wpi {
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 wpi
#endif // WPIUTIL_SUPPORT_RAW_SOCKET_ISTREAM_H_

View File

@@ -0,0 +1,28 @@
/*----------------------------------------------------------------------------*/
/* 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 WPIUTIL_SUPPORT_TIMESTAMP_H_
#define WPIUTIL_SUPPORT_TIMESTAMP_H_
#ifdef __cplusplus
extern "C" {
#endif
unsigned long long WPI_Now(void);
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
namespace wpi {
unsigned long long Now();
} // namespace wpi
#endif
#endif // WPIUTIL_SUPPORT_TIMESTAMP_H_