2018-08-22 12:24:55 -04:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#define WIN32_LEAN_AND_MEAN
|
|
|
|
#include <Windows.h>
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
2019-02-09 00:30:38 -05:00
|
|
|
#include <array>
|
2018-08-22 12:24:55 -04:00
|
|
|
#include <unordered_map>
|
2018-11-04 21:19:00 -05:00
|
|
|
#include <unordered_set>
|
2018-08-22 12:24:55 -04:00
|
|
|
#include <functional>
|
2018-10-31 01:20:44 -04:00
|
|
|
#include <algorithm>
|
2018-11-04 21:19:00 -05:00
|
|
|
#include <regex>
|
2018-10-31 01:20:44 -04:00
|
|
|
#include <memory>
|
2018-10-10 07:03:15 -04:00
|
|
|
#include <optional>
|
2018-08-22 12:24:55 -04:00
|
|
|
#include <thread>
|
2018-08-23 11:53:23 -04:00
|
|
|
#include <mutex>
|
2019-01-23 13:59:34 -05:00
|
|
|
#include <shared_mutex>
|
2019-02-09 00:30:38 -05:00
|
|
|
#include <atomic>
|
2018-09-20 21:59:07 -04:00
|
|
|
#include <cstdint>
|
2018-12-26 23:56:42 -05:00
|
|
|
#include <cassert>
|
2019-02-18 23:12:12 -05:00
|
|
|
|
|
|
|
template <typename T> using Array = T[];
|
|
|
|
|
|
|
|
template<typename E, typename M = std::mutex>
|
|
|
|
class ThreadSafe
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
template <typename... Args>
|
|
|
|
ThreadSafe(Args&&... args) : contents(std::forward<Args>(args)...) {}
|
|
|
|
auto operator->()
|
|
|
|
{
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
E* operator->() { return ptr; }
|
|
|
|
std::unique_lock<M> lock;
|
|
|
|
E* ptr;
|
|
|
|
} lockedProxy{ std::unique_lock(mtx), &contents };
|
|
|
|
return lockedProxy;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
E contents;
|
|
|
|
M mtx;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <auto F>
|
|
|
|
struct Functor
|
|
|
|
{
|
|
|
|
template <typename... Args>
|
|
|
|
auto operator()(Args&&... args) const { return std::invoke(F, std::forward<Args>(args)...); }
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename HandleCloser = Functor<CloseHandle>>
|
|
|
|
class AutoHandle
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
AutoHandle(HANDLE h) : h(h) {}
|
|
|
|
operator HANDLE() { return h.get(); }
|
|
|
|
PHANDLE operator&() { static_assert(sizeof(*this) == sizeof(HANDLE)); return (PHANDLE)this; }
|
|
|
|
operator bool() { return h.get() != NULL && h.get() != INVALID_HANDLE_VALUE; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
struct HandleCleaner { void operator()(void* h) { if (h != INVALID_HANDLE_VALUE) HandleCloser()(h); } };
|
|
|
|
std::unique_ptr<void, HandleCleaner> h;
|
|
|
|
};
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
2019-02-20 02:19:30 -05:00
|
|
|
#define TEST(...) inline auto TEST__RUNNER__DUMMY = CreateThread(nullptr, 0, [](auto) { __VA_ARGS__; return 0UL; }, NULL, 0, nullptr);
|
2019-02-18 23:12:12 -05:00
|
|
|
#else
|
|
|
|
#define TEST(...)
|
|
|
|
#endif
|
2019-02-28 01:40:40 -05:00
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
#define TEST_SYNC(...) inline auto TEST__RUNNER__DUMMY = std::invoke([] { __VA_ARGS__; return 0UL; });
|
|
|
|
#else
|
|
|
|
#define TEST_SYNC(...)
|
|
|
|
#endif
|