Major patch [1/2]
This commit is contained in:
parent
3e33533276
commit
ffe4bc31fc
5
.gitignore
vendored
5
.gitignore
vendored
@ -19,4 +19,7 @@ Build_Develop/*
|
||||
.vs
|
||||
compile_flags.txt
|
||||
*.mk
|
||||
*.project
|
||||
*.project
|
||||
*cmake
|
||||
.intellij
|
||||
.clion
|
@ -6,9 +6,9 @@
|
||||
"impDefines": ["AURORA_ENGINE_KERNEL"],
|
||||
"staticImpDefines": "AURORA_ENGINE_KERNEL_STATIC",
|
||||
"defines": [],
|
||||
"soft-depends": ["wxwidgets"],
|
||||
"depends": ["glm", "asio", "mimalloc", "uuid", "fmt", "json", "bzip2", "ltc", "o1heap", "zstd", "zlib", "lz4", "mbedtls"],
|
||||
"features": ["remove-platform-code", "guess-platform-code"],
|
||||
"soft-depends": ["wxwidgets", "glm"],
|
||||
"depends": ["mimalloc", "uuid", "fmt", "json", "bzip2", "ltc", "o1heap", "zstd", "zlib", "lz4", "mbedtls"],
|
||||
"features": ["guess-platform-code"],
|
||||
"linkSources": "Source/Alloc.cpp",
|
||||
"actions": [
|
||||
{
|
||||
|
@ -2,7 +2,7 @@
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: Async.hpp
|
||||
Date: 2021-6-10
|
||||
Date: 2021-7-14
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
@ -19,8 +19,8 @@ namespace Aurora::Async
|
||||
using ThreadGroup_t = AuUInt8;
|
||||
using ThreadId_t = AuUInt16;
|
||||
|
||||
using WorkerId_t = std::pair<ThreadGroup_t, ThreadId_t>;
|
||||
using DispatchTarget_t = std::pair<ThreadGroup_t, std::optional<ThreadId_t>>;
|
||||
using WorkerId_t = AuPair<ThreadGroup_t, ThreadId_t>;
|
||||
using DispatchTarget_t = AuPair<ThreadGroup_t, AuOptional<ThreadId_t>>;
|
||||
|
||||
struct IWorkItemHandler
|
||||
{
|
||||
@ -50,7 +50,6 @@ namespace Aurora::Async
|
||||
virtual void Shutdown() = 0;
|
||||
};
|
||||
|
||||
|
||||
template<class Info_t = AVoid, class Result_t = AVoid>
|
||||
struct FJob
|
||||
{
|
||||
@ -68,13 +67,13 @@ namespace Aurora::Async
|
||||
template<class Info_t = AVoid, class Result_t = AVoid>
|
||||
struct FTask
|
||||
{
|
||||
std::function<std::optional<Result_t>(const Info_t &)> onFrame = 0;
|
||||
std::function<AuOptional<Result_t>(const Info_t &)> onFrame = 0;
|
||||
};
|
||||
|
||||
template<class Info_t = AVoid, class Result_t = AVoid>
|
||||
struct CTask
|
||||
{
|
||||
std::optional<Result_t>(* onFrame)(const Info_t &);
|
||||
AuOptional<Result_t>(* onFrame)(const Info_t &);
|
||||
};
|
||||
|
||||
class IWorkItem
|
||||
@ -116,7 +115,7 @@ namespace Aurora::Async
|
||||
{}
|
||||
|
||||
private:
|
||||
|
||||
#if !defined(_CPPSHARP)
|
||||
void DispatchFrame(ProcessInfo &info) override
|
||||
{
|
||||
try
|
||||
@ -143,8 +142,10 @@ namespace Aurora::Async
|
||||
Debug::PrintError();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#if !defined(_CPPSHARP)
|
||||
template<typename Info_t, typename Result_t, typename Task_t = FTask<Info_t, Result_t>, typename Job_t = FJob<Info_t, Result_t>>
|
||||
struct BasicWorkCallback : IWorkItemHandler, std::enable_shared_from_this<IWorkItemHandler>
|
||||
{
|
||||
@ -158,24 +159,43 @@ namespace Aurora::Async
|
||||
|
||||
Info_t input;
|
||||
|
||||
BasicWorkCallback<Info_t, Result_t, Task_t, Job_t> &SetTask(const Task_t &task)
|
||||
{
|
||||
this->task = task;
|
||||
return *this;
|
||||
}
|
||||
|
||||
BasicWorkCallback<Info_t, Result_t, Task_t, Job_t> &SetTask(const Job_t &callback)
|
||||
{
|
||||
this->callback = callback;
|
||||
return *this;
|
||||
}
|
||||
private:
|
||||
|
||||
static constexpr bool IsCallbackPtr = std::is_pointer_v<Job_t> || is_base_of_template<std::shared_ptr, Job_t>::value;
|
||||
static constexpr bool IsTaskPtr = std::is_pointer_v<Task_t> || is_base_of_template<std::shared_ptr, Task_t>::value;
|
||||
static constexpr bool IsCallbackPtr = std::is_pointer_v<Job_t> || AuIsBaseOfTemplate<std::shared_ptr, Job_t>::value;
|
||||
static constexpr bool IsTaskPtr = std::is_pointer_v<Task_t> || AuIsBaseOfTemplate<std::shared_ptr, Task_t>::value;
|
||||
|
||||
WorkerId_t caller;
|
||||
|
||||
void DispatchFrame(ProcessInfo &info) override
|
||||
{
|
||||
std::optional<Result_t> ret;
|
||||
AuOptional<Result_t> ret;
|
||||
|
||||
if constexpr (IsTaskPtr)
|
||||
try
|
||||
{
|
||||
ret = task->onFrame(input);
|
||||
if constexpr (IsTaskPtr)
|
||||
{
|
||||
ret = task->onFrame(input);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = task.onFrame(input);
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (...)
|
||||
{
|
||||
ret = task.onFrame(input);
|
||||
Debug::PrintError();
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
auto pin = std::static_pointer_cast<std::remove_pointer_t<decltype(this)>>(this->shared_from_this());
|
||||
@ -220,7 +240,7 @@ namespace Aurora::Async
|
||||
};
|
||||
|
||||
// TODO: this is somewhat evil. double alloc when we could reuse this
|
||||
NewWorkItem(caller, std::make_shared<BasicWorkStdFunc>(func, err))->Dispatch();
|
||||
NewWorkItem(caller, AuMakeShared<BasicWorkStdFunc>(func, err))->Dispatch();
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
@ -246,7 +266,7 @@ namespace Aurora::Async
|
||||
{
|
||||
if constexpr (IsCallbackPtr)
|
||||
{
|
||||
if constexpr (is_base_of_template<std::function, decltype(callback->onFailure)>::value)
|
||||
if constexpr (AuIsBaseOfTemplate<std::function, decltype(callback->onFailure)>::value)
|
||||
{
|
||||
if (!callback->onFailure)
|
||||
{
|
||||
@ -258,7 +278,7 @@ namespace Aurora::Async
|
||||
}
|
||||
else
|
||||
{
|
||||
if constexpr (is_base_of_template<std::function, decltype(callback.onFailure)>::value)
|
||||
if constexpr (AuIsBaseOfTemplate<std::function, decltype(callback.onFailure)>::value)
|
||||
{
|
||||
if (!callback.onFailure)
|
||||
{
|
||||
@ -295,7 +315,7 @@ namespace Aurora::Async
|
||||
auto cur = GetAsyncApp()->GetCurrentThread();
|
||||
return [=](Args... in) -> void
|
||||
{
|
||||
auto work = std::make_shared<BasicWorkStdFunc>([=]() -> void {
|
||||
auto work = AuMakeShared<BasicWorkStdFunc>([=]() -> void {
|
||||
func(in...);
|
||||
});
|
||||
auto workItem = NewWorkItem(cur, work);
|
||||
@ -310,8 +330,8 @@ namespace Aurora::Async
|
||||
auto cur = GetAsyncApp()->GetCurrentThread();
|
||||
return [=](std::function<void(const B&)> callback, Args... in) -> void
|
||||
{
|
||||
auto work = std::make_shared<BasicWorkCallback<AVoid, B>>();
|
||||
work.task.onProcess = [](const AVoid &) -> std::optional<B>
|
||||
auto work = AuMakeShared<BasicWorkCallback<AVoid, B>>();
|
||||
work.task.onProcess = [](const AVoid &) -> AuOptional<B>
|
||||
{
|
||||
return func(in...);
|
||||
};
|
||||
@ -325,6 +345,8 @@ namespace Aurora::Async
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
class IAsyncApp
|
||||
{
|
||||
public:
|
||||
|
@ -2,7 +2,7 @@
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: CompressionInfo.hpp
|
||||
Date: 2021-6-10
|
||||
Date: 2021-7-14
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
@ -2,7 +2,7 @@
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: ICompressionStream.hpp
|
||||
Date: 2021-6-10
|
||||
Date: 2021-7-14
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
@ -12,7 +12,9 @@ namespace Aurora::Compression
|
||||
class ICompressionStream
|
||||
{
|
||||
public:
|
||||
virtual std::pair<AuUInt32, AuUInt32> Ingest(AuUInt32 input) = 0;
|
||||
virtual bool Read(void * /*opt*/, AuUInt32 &len, bool ingestUntilEOS = true) = 0;
|
||||
virtual AuStreamReadWrittenPair_t Ingest(AuUInt32 bytesFromInputSource) = 0;
|
||||
virtual bool ReadByInflatedN(void * /*opt*/, AuUInt32 minimumInflated, AuStreamReadWrittenPair_t &pair, bool ingestUntilEOS = true) = 0;
|
||||
virtual bool GoBackByInflatedN(AuUInt32 offset) = 0;
|
||||
virtual bool GoForwardByInflatedN(AuUInt32 offset) = 0;
|
||||
};
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: StreamProcessor.hpp
|
||||
Date: 2021-6-9
|
||||
Date: 2021-7-14
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
@ -12,7 +12,22 @@
|
||||
|
||||
namespace Aurora::Console
|
||||
{
|
||||
/// Writes a log message to the console subscribers and telemetry outputs
|
||||
AUKN_SYM void WriteLine(const ConsoleMessage &msg);
|
||||
|
||||
/// nonblocking [!!!]
|
||||
/// you must disable the stdio console logger before using this api [!!!]
|
||||
/// you must not expect locale translation
|
||||
AUKN_SYM AuUInt32 ReadStdIn(void *buffer, AuUInt32 length);
|
||||
|
||||
/// nonblocking [!!!]
|
||||
/// you should disable the stdio console logger before using this api [!!!]
|
||||
/// expect system locale if the logger is not enabled
|
||||
/// edge case, utf8 if windows and logger is enabled
|
||||
AUKN_SYM AuUInt32 WriteStdIn(const void *buffer, AuUInt32 length);
|
||||
|
||||
AUKN_SYM void OpenLateStd();
|
||||
AUKN_SYM void OpenLateGUI();
|
||||
}
|
||||
|
||||
#include "Commands/Commands.hpp"
|
||||
|
@ -9,7 +9,18 @@
|
||||
|
||||
namespace Aurora::Console::Hooks
|
||||
{
|
||||
class IConsoleSubscriber
|
||||
{
|
||||
public:
|
||||
virtual void OnMessage(const ConsoleMessage &string) = 0;
|
||||
};
|
||||
|
||||
AUKN_SYM void AddSubscription(const AuSPtr<IConsoleSubscriber> &subscriber);
|
||||
AUKN_SYM void RemoveSubscription(const AuSPtr<IConsoleSubscriber> &subscriber);
|
||||
|
||||
using LineHook_cb = std::function<void(const ConsoleMessage &string)>;
|
||||
|
||||
AUKN_SYM void AddHook(LineHook_cb hook);
|
||||
/// @deprecated wont ever remove
|
||||
/// Most c++ styleguides would have you chuck an IConsoleSubscriber in your app somewhere
|
||||
AUKN_SYM void AddFunctionalHook(LineHook_cb hook);
|
||||
}
|
@ -9,6 +9,7 @@
|
||||
|
||||
namespace Aurora::Console::Logging
|
||||
{
|
||||
#if defined(_AUHAS_FMT)
|
||||
template<typename ... T>
|
||||
static inline void WriteLinef(const AuString &tag, const AuString &msg, T... args)
|
||||
{
|
||||
@ -44,4 +45,5 @@ namespace Aurora::Console::Logging
|
||||
{
|
||||
Aurora::Console::Logging::WriteLinef(EAnsiColor::eBlue, "Game", line, args...);
|
||||
}
|
||||
#endif
|
||||
}
|
@ -25,11 +25,11 @@ namespace Aurora::Crypto::AES
|
||||
const void* iv, void* outIv, AuUInt ivLength,
|
||||
const void* key, AuUInt keyLength,
|
||||
AuList<AuUInt8>& out,
|
||||
bool safe);
|
||||
bool auCoolCodePadding);
|
||||
|
||||
AUKN_SYM bool Decrypt(const void* cipherText, AuUInt cipherTextLength,
|
||||
const void* iv, void* outIv, AuUInt ivLength,
|
||||
const void* key, AuUInt keyLength,
|
||||
AuList<AuUInt8>& plainText,
|
||||
bool safe);
|
||||
bool auCoolCodePadding);
|
||||
}
|
@ -31,11 +31,16 @@ namespace Aurora::Data
|
||||
kTypeStructInt32,
|
||||
|
||||
kTypeSpecialComponent, // Special QST
|
||||
kTypeSpecialArray, //
|
||||
kTypeSpecialObject, //
|
||||
kTypeSpecialArray, //
|
||||
kTypeSpecialObject, //
|
||||
kTypeSpecialReserved1, //
|
||||
kTypeSpecialReserved2, //
|
||||
kTypeSpecialReserved3, //
|
||||
kTypeSpecialReserved4, //
|
||||
|
||||
kTypeEND,
|
||||
|
||||
// Out of order
|
||||
kTypeStructDouble = kTypeNumber, // overlap bin serial with human friendly aliases
|
||||
kTypeStructUInt64 = kTypeUInt, //
|
||||
kTypeStructInt64 = kTypeSInt, //
|
||||
@ -47,8 +52,8 @@ namespace Aurora::Data
|
||||
AuInt64 sint;
|
||||
double number;
|
||||
bool boolean;
|
||||
glm::vec3 vec3;
|
||||
glm::vec4 vec4;
|
||||
AuVec3 vec3;
|
||||
AuVec4 vec4;
|
||||
};
|
||||
|
||||
struct Value
|
||||
@ -58,8 +63,8 @@ namespace Aurora::Data
|
||||
{\
|
||||
primitive.member = val;\
|
||||
}
|
||||
CONSTRUCTOR(const glm::vec3 &, vec3);
|
||||
CONSTRUCTOR(const glm::vec4 &, vec4);
|
||||
CONSTRUCTOR(const AuVec3 &, vec3);
|
||||
CONSTRUCTOR(const AuVec4 &, vec4);
|
||||
CONSTRUCTOR(bool, boolean);
|
||||
CONSTRUCTOR(double, number);
|
||||
CONSTRUCTOR(AuInt64, sint);
|
||||
@ -97,6 +102,7 @@ namespace Aurora::Data
|
||||
Value value;
|
||||
};
|
||||
|
||||
#if !defined(_CPPSHARP)
|
||||
template<DataType type>
|
||||
static constexpr AuUInt GetDatatypeLength()
|
||||
{
|
||||
@ -139,4 +145,5 @@ namespace Aurora::Data
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
@ -51,6 +51,9 @@ namespace Aurora::Debug
|
||||
May attempt some hardened telemetry debug ops
|
||||
*/
|
||||
AUKN_SYM AU_NORETURN void Panic();
|
||||
|
||||
|
||||
AUKN_SYM void DebugBreak();
|
||||
}
|
||||
|
||||
#include "SysPanic.hpp"
|
||||
|
@ -11,10 +11,10 @@ namespace Aurora::Debug
|
||||
{
|
||||
struct StackTraceEntry
|
||||
{
|
||||
std::optional<AuString> label;
|
||||
AuOptional<AuString> label;
|
||||
AuUInt64 address;
|
||||
std::optional<AuString> module;
|
||||
std::optional<std::tuple<AuString, int, int>> file; // file, line, offset
|
||||
AuOptional<AuString> module;
|
||||
AuOptional<std::tuple<AuString, int, int>> file; // file, line, offset
|
||||
|
||||
AUKN_SYM AuString Stringify() const;
|
||||
};
|
||||
|
@ -2,7 +2,7 @@
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: SysAssertions.hpp
|
||||
Date: 2021-6-10
|
||||
Date: 2021-7-14
|
||||
Author: Reece
|
||||
***/
|
||||
|
||||
|
@ -30,6 +30,12 @@ namespace Aurora::Debug
|
||||
{
|
||||
_PushError(_DBG_RET_ADDR, FailureCategory::kFailureNested, nullptr);
|
||||
}
|
||||
|
||||
template<typename ... T>
|
||||
static AU_NOINLINE void ErrorMakeNested(const AuString &msg, T... args) _FREECOMPILER_OPTIMIZE_OFF
|
||||
{
|
||||
_PushError(_DBG_RET_ADDR, FailureCategory::kFailureNested, fmt::format(msg, args...).c_str());
|
||||
}
|
||||
|
||||
template<typename ... T>
|
||||
static AU_NOINLINE void SysPushError(FailureCategory category, const AuString &msg, T... args) _FREECOMPILER_OPTIMIZE_OFF
|
||||
@ -40,7 +46,11 @@ namespace Aurora::Debug
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(_AUHAS_FMT)
|
||||
_PushError(_DBG_RET_ADDR, category, fmt::format(msg, args...).c_str());
|
||||
#else
|
||||
_PushError(_DBG_RET_ADDR, category, "Missing dependency");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,9 +64,10 @@ namespace Aurora::Debug
|
||||
#endif
|
||||
}
|
||||
|
||||
#define SysCheckReturn(x, ...) if (!(x)) { Aurora::Debug::ErrorMakeNested(); return ##__VA_ARGS__; }
|
||||
#define SysCheckReturn(x, ...) if (!(static_cast<bool>(x))) { Aurora::Debug::ErrorMakeNested(); return __VA_ARGS__; }
|
||||
|
||||
#define SysPushErrorError(error, ...) Aurora::Debug::SysPushError(Aurora::Debug::error, ## __VA_ARGS__)
|
||||
#define SysPushErrorError(error, ...) Aurora::Debug::SysPushError(Aurora::Debug::error, ## __VA_ARGS__)
|
||||
#define SysPushUserError(exp, ...) Aurora::Debug::SysPushError((Aurora::Debug::FailureCategory)exp, ## __VA_ARGS__)
|
||||
|
||||
// legacy
|
||||
#define SysPushErrorArg(...) SysPushErrorError(kFailureParam, ## __VA_ARGS__)
|
||||
@ -66,7 +77,7 @@ namespace Aurora::Debug
|
||||
#define SysPushErrorMem(...) SysPushErrorError(kFailureMemory, ## __VA_ARGS__)
|
||||
|
||||
// edge case
|
||||
#define SysPushErrorNested() Aurora::Debug::ErrorMakeNested();
|
||||
#define SysPushErrorNested(...) Aurora::Debug::ErrorMakeNested(__VA_ARGS__);
|
||||
|
||||
// enums
|
||||
#define SysPushErrorGeneric(...) SysPushErrorError(kFailureGeneric, ## __VA_ARGS__)
|
||||
@ -86,39 +97,38 @@ namespace Aurora::Debug
|
||||
#define SysPushErrorWatchdogError(...) SysPushErrorError(kFailureWatchdogError, ## __VA_ARGS__)
|
||||
#define SysPushErrorServiceError(...) SysPushErrorError(kFailureServiceError, ## __VA_ARGS__)
|
||||
#define SysPushErrorPermissionError(...) SysPushErrorError(kFailurePermissionError, ## __VA_ARGS__)
|
||||
#define SysPushErrorOutOfRange(...) SysPushErrorError(kFailureOutOfRange, ## __VA_ARGS__)
|
||||
#define SysPushErrorSyntaxError(...) SysPushErrorError(kFailureSyntaxError, ## __VA_ARGS__)
|
||||
#define SysPushErrorDisconnected(...) SysPushErrorError(kFailureDisconnected, ## __VA_ARGS__)
|
||||
#define SysPushErrorUninitialized(...) SysPushErrorError(kFailureUninitialized, ## __VA_ARGS__)
|
||||
#define SysPushErrorOutOfRange(...) SysPushErrorError(kFailureOutOfRange, ## __VA_ARGS__)
|
||||
#define SysPushErrorSyntaxError(...) SysPushErrorError(kFailureSyntaxError, ## __VA_ARGS__)
|
||||
#define SysPushErrorDisconnected(...) SysPushErrorError(kFailureDisconnected, ## __VA_ARGS__)
|
||||
#define SysPushErrorUninitialized(...) SysPushErrorError(kFailureUninitialized, ## __VA_ARGS__)
|
||||
|
||||
|
||||
#if defined(DEBUG) || defined(STAGING)
|
||||
|
||||
|
||||
|
||||
#if defined(DEBUG) || defined(INTERNAL)
|
||||
|
||||
#define SysPushErrorArgDbg SysPushErrorArg
|
||||
#define SysPushErrorGenDbg SysPushErrorGen
|
||||
#define SysPushErrorCryptDbg SysPushErrorCrypt
|
||||
#define SysPushErrorNetDbg SysPushErrorNet
|
||||
#define SysPushErrorMemDbg SysPushErrorMem
|
||||
#define SysPushUserErrorDbg SysPushUserError
|
||||
|
||||
#define SysPushErrorArgDbg SysPushErrorArg
|
||||
#define SysPushErrorGenDbg SysPushErrorGen
|
||||
#define SysPushErrorCryptDbg SysPushErrorCrypt
|
||||
#define SysPushErrorNetDbg SysPushErrorNet
|
||||
#define SysPushErrorMemDbg SysPushErrorMem
|
||||
|
||||
#define SysPushErrorGenericDbg SysPushErrorGeneric
|
||||
#define SysPushErrorNestedDbg SysPushErrorNested
|
||||
#define SysPushErrorMemoryDbg SysPushErrorMemory
|
||||
#define SysPushErrorIODbg SysPushErrorIO
|
||||
#define SysPushErrorFIODbg SysPushErrorFIO
|
||||
#define SysPushErrorNetDbg SysPushErrorNet
|
||||
#define SysPushErrorAudioDbg SysPushErrorAudio
|
||||
#define SysPushErrorHALDbg SysPushErrorHAL
|
||||
#define SysPushErrorHALContextDbg SysPushErrorHALContext
|
||||
#define SysPushErrorCryptoDbg SysPushErrorCrypto
|
||||
#define SysPushErrorParamDbg SysPushErrorParam
|
||||
#define SysPushErrorLogicErrorDbg SysPushErrorLogicError
|
||||
#define SysPushErrorMathErrorDbg SysPushErrorMathError
|
||||
#define SysPushErrorUnavailableErrorDbg SysPushErrorUnavailableError
|
||||
#define SysPushErrorTimeoutErrorDbg SysPushErrorTimeoutError
|
||||
#define SysPushErrorWatchdogErrorDbg SysPushErrorWatchdogError
|
||||
#define SysPushErrorGenericDbg SysPushErrorGeneric
|
||||
#define SysPushErrorNestedDbg SysPushErrorNested
|
||||
#define SysPushErrorMemoryDbg SysPushErrorMemory
|
||||
#define SysPushErrorIODbg SysPushErrorIO
|
||||
#define SysPushErrorFIODbg SysPushErrorFIO
|
||||
#define SysPushErrorNetDbg SysPushErrorNet
|
||||
#define SysPushErrorAudioDbg SysPushErrorAudio
|
||||
#define SysPushErrorHALDbg SysPushErrorHAL
|
||||
#define SysPushErrorHALContextDbg SysPushErrorHALContext
|
||||
#define SysPushErrorCryptoDbg SysPushErrorCrypto
|
||||
#define SysPushErrorParamDbg SysPushErrorParam
|
||||
#define SysPushErrorLogicErrorDbg SysPushErrorLogicError
|
||||
#define SysPushErrorMathErrorDbg SysPushErrorMathError
|
||||
#define SysPushErrorUnavailableErrorDbg SysPushErrorUnavailableError
|
||||
#define SysPushErrorTimeoutErrorDbg SysPushErrorTimeoutError
|
||||
#define SysPushErrorWatchdogErrorDbg SysPushErrorWatchdogError
|
||||
#define SysPushErrorServiceErrorDbg SysPushErrorServiceError
|
||||
#define SysPushErrorPermissionErrorDbg SysPushErrorPermissionError
|
||||
#define SysPushErrorOutOfRangeDbg SysPushErrorOutOfRange
|
||||
@ -128,34 +138,34 @@ namespace Aurora::Debug
|
||||
|
||||
#else
|
||||
|
||||
#define SysPushErrorArgDbg(...)
|
||||
#define SysPushErrorGenDbg(...)
|
||||
#define SysPushErrorCryptDbg(...)
|
||||
#define SysPushErrorNetDbg(...)
|
||||
#define SysPushErrorMemDbg(...)
|
||||
#define SysPushUserErrorDbg(...)
|
||||
#define SysPushErrorArgDbg(...)
|
||||
#define SysPushErrorGenDbg(...)
|
||||
#define SysPushErrorCryptDbg(...)
|
||||
#define SysPushErrorNetDbg(...)
|
||||
#define SysPushErrorMemDbg(...)
|
||||
|
||||
#define SysPushErrorGenericDbg(...)
|
||||
#define SysPushErrorNestedDbg(...)
|
||||
#define SysPushErrorMemoryDbg(...)
|
||||
#define SysPushErrorIODbg(...)
|
||||
#define SysPushErrorFIODbg(...)
|
||||
#define SysPushErrorNetDbg(...)
|
||||
#define SysPushErrorAudioDbg(...)
|
||||
#define SysPushErrorHALDbg(...)
|
||||
#define SysPushErrorHALContextDbg(...)
|
||||
#define SysPushErrorCryptoDbg(...)
|
||||
#define SysPushErrorParamDbg(...)
|
||||
#define SysPushErrorLogicErrorDbg(...)
|
||||
#define SysPushErrorMathErrorDbg(...)
|
||||
#define SysPushErrorGenericDbg(...)
|
||||
#define SysPushErrorNestedDbg(...)
|
||||
#define SysPushErrorMemoryDbg(...)
|
||||
#define SysPushErrorIODbg(...)
|
||||
#define SysPushErrorFIODbg(...)
|
||||
#define SysPushErrorNetDbg(...)
|
||||
#define SysPushErrorAudioDbg(...)
|
||||
#define SysPushErrorHALDbg(...)
|
||||
#define SysPushErrorHALContextDbg(...)
|
||||
#define SysPushErrorCryptoDbg(...)
|
||||
#define SysPushErrorParamDbg(...)
|
||||
#define SysPushErrorLogicErrorDbg(...)
|
||||
#define SysPushErrorMathErrorDbg(...)
|
||||
#define SysPushErrorUnavailableErrorDbg(...)
|
||||
#define SysPushErrorTimeoutErrorDbg(...)
|
||||
#define SysPushErrorWatchdogErrorDbg(...)
|
||||
#define SysPushErrorServiceErrorDbg(...)
|
||||
#define SysPushErrorTimeoutErrorDbg(...)
|
||||
#define SysPushErrorWatchdogErrorDbg(...)
|
||||
#define SysPushErrorServiceErrorDbg(...)
|
||||
#define SysPushErrorPermissionErrorDbg(...)
|
||||
#define SysPushErrorOutOfRangeDbg(...)
|
||||
#define SysPushErrorSyntaxErrorDbg(...)
|
||||
#define SysPushErrorDisconnectedDbg(...)
|
||||
#define SysPushErrorUninitializedDbg(...)
|
||||
|
||||
|
||||
#endif
|
@ -7,9 +7,11 @@
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
#if defined(_AUHAS_FMT)
|
||||
template<typename ... T>
|
||||
static inline void __declspec(noreturn) SysPanic(T... args)
|
||||
{
|
||||
Aurora::Console::Logging::WriteLinef(Aurora::Console::EAnsiColor::eBoldRed, "Fatal", args...);
|
||||
Aurora::Debug::Panic();
|
||||
}
|
||||
}
|
||||
#endif
|
@ -11,12 +11,12 @@ namespace Aurora::Hashing
|
||||
{
|
||||
namespace CE
|
||||
{
|
||||
constexpr uint64_t val_64_const = 0xcbf29ce484222325;
|
||||
constexpr uint64_t prime_64_const = 0x100000001b3;
|
||||
constexpr uint64_t kFnv1MagicVal64 = 0xcbf29ce484222325;
|
||||
constexpr uint64_t kFnv1MagicPrime64 = 0x100000001b3;
|
||||
|
||||
inline constexpr uint64_t fnv1a(const char *const str, const uint64_t value = val_64_const) noexcept
|
||||
inline constexpr uint64_t fnv1a(const char *const str, const uint64_t value = kFnv1MagicVal64) noexcept
|
||||
{
|
||||
return (str[0] == '\0') ? value : fnv1a(&str[1], (value ^ uint64_t(str[0])) * prime_64_const);
|
||||
return (str[0] == '\0') ? value : fnv1a(&str[1], (value ^ uint64_t(str[0])) * kFnv1MagicPrime64);
|
||||
}
|
||||
|
||||
inline constexpr uint32_t fnv1a_trunc(const char *const str) noexcept
|
||||
@ -24,12 +24,12 @@ namespace Aurora::Hashing
|
||||
return static_cast<uint32_t>(fnv1a(str));
|
||||
}
|
||||
|
||||
constexpr uint64_t val_32_const = 0x811c9dc5;
|
||||
constexpr uint64_t prime_32_const = 0x01000193;
|
||||
constexpr uint64_t kFnv1MagicVal32 = 0x811c9dc5;
|
||||
constexpr uint64_t kFnv1MagicPrime32 = 0x01000193;
|
||||
|
||||
inline constexpr uint32_t fnv1a_32(const char *const str, const uint32_t value = val_32_const) noexcept
|
||||
inline constexpr uint32_t fnv1a_32(const char *const str, const uint32_t value = kFnv1MagicVal32) noexcept
|
||||
{
|
||||
return (str[0] == '\0') ? value : fnv1a_32(&str[1], (value ^ uint32_t(str[0])) * prime_32_const);
|
||||
return (str[0] == '\0') ? value : fnv1a_32(&str[1], (value ^ uint32_t(str[0])) * kFnv1MagicPrime32);
|
||||
}
|
||||
}
|
||||
}
|
@ -12,8 +12,15 @@ namespace Aurora::Hashing
|
||||
class IHashStream
|
||||
{
|
||||
public:
|
||||
virtual void Ingest(const void *, AuUInt32) = 0;
|
||||
virtual AuUInt8 *GetBytes(AuUInt32 &length) = 0;
|
||||
/*
|
||||
* Digest length of pBuf bytes
|
||||
*/
|
||||
virtual void Ingest(const void *pBuf, AuUInt32 length) = 0;
|
||||
|
||||
/**
|
||||
* Locks and returns the internal buffer
|
||||
*/
|
||||
virtual AuUInt8 const* GetBytes(AuUInt32 &length) = 0;
|
||||
};
|
||||
|
||||
AUKN_SHARED_API(HashStream, IHashStream, EHashType type);
|
||||
|
43
Include/Aurora/IO/AFIO/AFIO.hpp
Normal file
43
Include/Aurora/IO/AFIO/AFIO.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AFIO.hpp
|
||||
Date: 2021-8-21
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::IO::AFIO
|
||||
{
|
||||
class IAsyncTransaction;
|
||||
|
||||
class IAsyncFileStream
|
||||
{
|
||||
public:
|
||||
virtual AuSPtr<IAsyncTransaction> NewTransaction() = 0;
|
||||
};
|
||||
|
||||
class IAsyncFinishedSubscriber
|
||||
{
|
||||
public:
|
||||
virtual OnAsyncFileOpFinished(AuUInt64 offset, AuUInt32 length) = 0;
|
||||
};
|
||||
|
||||
class IAsyncTransaction
|
||||
{
|
||||
public:
|
||||
virtual void StartRead(AuUInt64 offset, void *, AuUInt32 length) = 0;
|
||||
virtual void StartWrite(AuUInt64 offset, const void *, AuUInt32 length) = 0;
|
||||
|
||||
virtual bool Complete() = 0;
|
||||
virtual AuUInt32 GetLastPacketLength() = 0;
|
||||
|
||||
virtual void SetCallback(const AuSPtr<IAsyncFinishedSubscriber> &sub) = 0;
|
||||
|
||||
virtual void Wait(AuUInt32 timeout) = 0;
|
||||
};
|
||||
|
||||
AUKN_SHARED_API(Open, IAsyncFileStream, const AuString &path, bool readOnly = true, bool directIO = false);
|
||||
|
||||
AUKN_SHARED bool WaitMultiple(const AuList<IAsyncTransaction> &files, AuUInt32 timeout);
|
||||
}
|
@ -26,11 +26,22 @@ namespace Aurora::IO
|
||||
|
||||
while ((ret = Read(temp, len)) == EStreamError::eErrorNone)
|
||||
{
|
||||
if (len == 0) break;
|
||||
if (len == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
buffer.insert(buffer.end(), temp, temp + len);
|
||||
|
||||
if (len != kBufferSize) break;
|
||||
if (len != kBufferSize)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == EStreamError::eErrorEndOfStream)
|
||||
{
|
||||
return EStreamError::eErrorNone;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -52,10 +52,101 @@ namespace Aurora::IO::Net
|
||||
class IBasicSocket;
|
||||
class IClientSocket;
|
||||
|
||||
using StreamHasData_cb = std::function<bool(AuSPtr<IClientSocket> socket)>; // DTLS/UDP/TCP/TLS -> TRUE = expects another frame or stream buffer, FALSE = end of socket life
|
||||
using InitializeSocket_cb = std::function<bool(AuSPtr<IClientSocket> socket)>;
|
||||
using ShutdownSocket_cb = std::function<void(AuSPtr<IBasicSocket> socket)>;
|
||||
/**
|
||||
* DTLS/UDP/TCP/TLS -> TRUE = expects another datagram or read pump
|
||||
* -> FALSE = end of socket life
|
||||
*/
|
||||
using StreamHasData_cb = std::function<bool(const AuSPtr<IClientSocket> &socket)>;
|
||||
|
||||
using InitializeSocket_cb = std::function<bool(const AuSPtr<IClientSocket> &socket)>;
|
||||
using ShutdownSocket_cb = std::function<void(const AuSPtr<IClientSocket> &socket)>;
|
||||
|
||||
class IClientHasData
|
||||
{
|
||||
public:
|
||||
// DTLS/UDP/TCP/TLS -> TRUE = expects another datagram or read pump
|
||||
// FALSE = end of socket life
|
||||
virtual bool OnSocketHasData(const AuSPtr<IClientSocket> &socket) = 0;
|
||||
};
|
||||
|
||||
class FunctionalClientHasData : public IClientHasData
|
||||
{
|
||||
private:
|
||||
StreamHasData_cb socket_;
|
||||
public:
|
||||
FunctionalClientHasData(const StreamHasData_cb &socket) : socket_(socket)
|
||||
{}
|
||||
FunctionalClientHasData(StreamHasData_cb &&socket) : socket_(std::move(socket))
|
||||
{}
|
||||
};
|
||||
|
||||
class IClientShutdown
|
||||
{
|
||||
public:
|
||||
virtual void OnSocketShutdown(const AuSPtr<IClientSocket> &socket) = 0;
|
||||
};
|
||||
|
||||
class FunctionalClientShutdown : public IClientShutdown
|
||||
{
|
||||
private:
|
||||
ShutdownSocket_cb socket_;
|
||||
public:
|
||||
FunctionalClientShutdown(const ShutdownSocket_cb &socket) : socket_(socket)
|
||||
{}
|
||||
FunctionalClientShutdown(ShutdownSocket_cb &&socket) : socket_(std::move(socket))
|
||||
{}
|
||||
};
|
||||
|
||||
class IClientDoS
|
||||
{
|
||||
public:
|
||||
virtual void OnSocketDoS(const AuSPtr<IClientSocket> &socket) = 0;
|
||||
};
|
||||
|
||||
class FunctionalClientDoS: public IClientDoS
|
||||
{
|
||||
private:
|
||||
ShutdownSocket_cb socket_;
|
||||
public:
|
||||
FunctionalClientDoS(const ShutdownSocket_cb &socket) : socket_(socket)
|
||||
{}
|
||||
FunctionalClientDoS(ShutdownSocket_cb &&socket) : socket_(std::move(socket))
|
||||
{}
|
||||
};
|
||||
|
||||
class IClientTLSBreakdown
|
||||
{
|
||||
public:
|
||||
virtual void OnSocketTLSBreakdown(const AuSPtr<IClientSocket> &socket) = 0;
|
||||
};
|
||||
|
||||
class FunctionalClientTLSBreakdown : public IClientTLSBreakdown
|
||||
{
|
||||
private:
|
||||
ShutdownSocket_cb socket_;
|
||||
public:
|
||||
FunctionalClientTLSBreakdown(const ShutdownSocket_cb &socket) : socket_(socket)
|
||||
{}
|
||||
FunctionalClientTLSBreakdown(ShutdownSocket_cb &&socket) : socket_(std::move(socket))
|
||||
{}
|
||||
};
|
||||
|
||||
class IClientEvents
|
||||
{
|
||||
public:
|
||||
virtual void AddSubscriptionHasData(const AuSPtr<IClientHasData> &iface) = 0;
|
||||
virtual void RemoveSubscriptionHasData(const AuSPtr<IClientHasData> &iface) = 0;
|
||||
|
||||
virtual void AddSubscriptionShutdown(const AuSPtr<IClientShutdown> &iface) = 0;
|
||||
virtual void RemoveSubscriptionShutdown(const AuSPtr<IClientShutdown> &iface) = 0;
|
||||
|
||||
virtual void AddSubscriptionDoS(const AuSPtr<IClientDoS> &iface) = 0;
|
||||
virtual void RemoveSubscriptionDoS(const AuSPtr<IClientDoS> &iface) = 0;
|
||||
|
||||
virtual void AddSubscriptionTlsBreakdown(const AuSPtr<IClientTLSBreakdown> &iface) = 0;
|
||||
virtual void RemoveSubscriptionTlsBreakdown(const AuSPtr<IClientTLSBreakdown> &iface) = 0;
|
||||
};
|
||||
|
||||
using Error_t = std::error_code;
|
||||
|
||||
class IBasicSocket
|
||||
@ -70,26 +161,43 @@ namespace Aurora::IO::Net
|
||||
class IClientSocket : public IBasicSocket
|
||||
{
|
||||
public:
|
||||
// called during loop pump
|
||||
struct ClientCallbacks
|
||||
{
|
||||
StreamHasData_cb hasData; // on data available
|
||||
ShutdownSocket_cb onShutdown; // Socket shutdown or otherwise dead
|
||||
ShutdownSocket_cb onStreamOverSaturation; // DoS?
|
||||
ShutdownSocket_cb onTLSHandshakeAbort;
|
||||
};
|
||||
|
||||
virtual IClientEvents *GetClientEvents() = 0;
|
||||
|
||||
virtual bool Initialize(const ClientCallbacks &callbacks) = 0;
|
||||
virtual bool Initialize() = 0;
|
||||
virtual bool Initialize() = 0;
|
||||
|
||||
virtual bool GetRemoteEndpoint(Endpoint &out) = 0;
|
||||
virtual bool GetRemoteEndpoint(Endpoint &out) = 0;
|
||||
|
||||
virtual bool ReadAsync(AuUInt8 *buffer, bool all, AuUInt32 &length) = 0;
|
||||
virtual bool WriteAsync(const AuUInt8 *buffer, AuUInt32 length) = 0;
|
||||
virtual bool WriteAsync(const AuUInt8 *buffer, AuUInt32 length, std::function<void(bool)>) = 0;
|
||||
virtual bool PumpRead() = 0;
|
||||
virtual bool PumpWrite() = 0;
|
||||
|
||||
virtual bool ReadAsync(AuUInt8 *buffer, AuUInt32 &length, bool all = false) = 0;
|
||||
virtual bool PeakAsync(AuUInt8 *buffer, AuUInt32 &length) = 0;
|
||||
virtual bool ReadSync(AuUInt8 *buffer, AuUInt32 &length, bool all = true) = 0;
|
||||
|
||||
virtual bool WriteAsync(const AuUInt8 *buffer, AuUInt32 length) = 0;
|
||||
virtual bool WriteAsync(const AuUInt8 *buffer, AuUInt32 length, std::function<void(bool)>) = 0;
|
||||
virtual bool WriteSync(const AuUInt8 *buffer, AuUInt32 length) = 0;
|
||||
|
||||
virtual AuUInt GetInternalRecvBuffer() = 0;
|
||||
virtual bool SetInternalRecvBuffer(AuUInt bytes) = 0;
|
||||
/**
|
||||
* Sets the internal application buffer size
|
||||
* Noting that Linux's default network buffer looks like this:
|
||||
* Minimum, Initial, Maximum: 10240 87380 12582912 | 10KB, 86KB, 12MB
|
||||
*/
|
||||
virtual AuUInt GetInternalRingBuffer() = 0;
|
||||
virtual bool SetInternalRingBuffer(AuUInt bytes) = 0;
|
||||
|
||||
/**
|
||||
* Defines the maximum amount of bytes each recieve frame can ingest
|
||||
*/
|
||||
virtual void SetRecvLength(AuOptional<AuUInt32> length) = 0;
|
||||
virtual AuUInt32 GetRecvLength() = 0;
|
||||
|
||||
/**
|
||||
* Enable ad-hoc input buffer ingestion into our internal buffer
|
||||
* Only use when PumpRead will not suffice by design (ie: sync apps)
|
||||
*/
|
||||
virtual void BufferAdhoc(AuOptional<bool> value) = 0;
|
||||
};
|
||||
|
||||
class ILocalClientSocket : public IClientSocket
|
||||
@ -135,7 +243,7 @@ namespace Aurora::IO::Net
|
||||
virtual bool AddAcceptCallback(const InitializeSocket_cb &accept) = 0; // on accept*
|
||||
virtual bool AddExitCallback(const ShutdownSocket_cb &accept) = 0; // server shutdown*
|
||||
|
||||
virtual void GetClients(AuList<AuSPtr<IClientSocket>> &soccies) = 0;
|
||||
virtual void GetClients(AuList<AuSPtr<IClientSocket>> &clients) = 0;
|
||||
virtual bool Listen() = 0;
|
||||
};
|
||||
|
||||
@ -147,12 +255,12 @@ namespace Aurora::IO::Net
|
||||
while (true)
|
||||
{
|
||||
// read from sockets pre-frame
|
||||
PumpSOL();
|
||||
PumpRead();
|
||||
|
||||
// process other async network logic here
|
||||
|
||||
// process writes and a few early reads before we sleep
|
||||
PumpEOL();
|
||||
PumpWrite();
|
||||
|
||||
// yield
|
||||
Yield();
|
||||
@ -162,22 +270,21 @@ namespace Aurora::IO::Net
|
||||
{
|
||||
// process other async network logic here
|
||||
|
||||
// run
|
||||
Run()
|
||||
// run once
|
||||
Pump()
|
||||
}
|
||||
|
||||
...and none with BufferAdhoc enabled
|
||||
*/
|
||||
virtual void PumpSOL() = 0;
|
||||
virtual void PumpEOL() = 0;
|
||||
virtual void PumpRead() = 0;
|
||||
virtual void PumpWrite() = 0;
|
||||
|
||||
virtual void Run() = 0;
|
||||
virtual void Pump() = 0;
|
||||
|
||||
virtual bool NewServer(const ServerInfo &listen, IServer *&out) = 0;
|
||||
virtual bool NewTlsServer(const TLSServerInfo &keys, IServer *&out) = 0;
|
||||
virtual void DeleteServer(IServer *socket) = 0;
|
||||
virtual bool NewServer(const ServerInfo &listen, AuSPtr<IServer> &out) = 0;
|
||||
virtual bool NewTlsServer(const TLSServerInfo &keys, AuSPtr<IServer> &out) = 0;
|
||||
|
||||
virtual bool NewClient(const ClientInfo &info, ILocalClientSocket *&out) = 0;
|
||||
virtual bool NewTlsClient(const TLSClientInfo &info, ILocalClientSocket *&out) = 0;
|
||||
virtual void DeleteClient(ILocalClientSocket *socket) = 0;
|
||||
virtual bool NewClient(const ClientInfo &info, AuSPtr<ILocalClientSocket> &out) = 0;
|
||||
virtual bool NewTlsClient(const TLSClientInfo &info, AuSPtr<ILocalClientSocket> &out) = 0;
|
||||
};
|
||||
}
|
@ -1,9 +1,7 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: FS.Win32.hpp
|
||||
Date: 2021-6-12
|
||||
File: IPCCV.hpp
|
||||
Date: 2021-8-27
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
7
Include/Aurora/IPC/IPCEvent.hpp
Normal file
7
Include/Aurora/IPC/IPCEvent.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: IPCEvent.hpp
|
||||
Date: 2021-8-28
|
||||
Author: Reece
|
||||
***/
|
7
Include/Aurora/IPC/IPCMemory.hpp
Normal file
7
Include/Aurora/IPC/IPCMemory.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: IPCMemory.hpp
|
||||
Date: 2021-8-27
|
||||
Author: Reece
|
||||
***/
|
7
Include/Aurora/IPC/IPCMutex.hpp
Normal file
7
Include/Aurora/IPC/IPCMutex.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: IPCMutex.hpp
|
||||
Date: 2021-8-27
|
||||
Author: Reece
|
||||
***/
|
7
Include/Aurora/IPC/IPCPipeClient.hpp
Normal file
7
Include/Aurora/IPC/IPCPipeClient.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: IPCPipeClient.hpp
|
||||
Date: 2021-8-28
|
||||
Author: Reece
|
||||
***/
|
7
Include/Aurora/IPC/IPCPipeServer.hpp
Normal file
7
Include/Aurora/IPC/IPCPipeServer.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: IPCPipeServer.hpp
|
||||
Date: 2021-8-28
|
||||
Author: Reece
|
||||
***/
|
7
Include/Aurora/IPC/IPCSemaphore.hpp
Normal file
7
Include/Aurora/IPC/IPCSemaphore.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: IPCSemaphore.hpp
|
||||
Date: 2021-8-27
|
||||
Author: Reece
|
||||
***/
|
29
Include/Aurora/Locale/ECodePage.hpp
Normal file
29
Include/Aurora/Locale/ECodePage.hpp
Normal file
@ -0,0 +1,29 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: ECodePage.hpp
|
||||
Date: 2021-8-20
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Locale
|
||||
{
|
||||
enum class ECodePage
|
||||
{
|
||||
eUTF32,
|
||||
eUTF32BE,
|
||||
eUTF16,
|
||||
eUTF16BE,
|
||||
eUTF8,
|
||||
eUTF7,
|
||||
e18030,
|
||||
e2312,
|
||||
eGBK,
|
||||
eSJIS,
|
||||
eLatin1,
|
||||
eSysUnk,
|
||||
eUnsupported,
|
||||
eMax = eUnsupported
|
||||
};
|
||||
}
|
25
Include/Aurora/Locale/Encoding/Encoding.hpp
Normal file
25
Include/Aurora/Locale/Encoding/Encoding.hpp
Normal file
@ -0,0 +1,25 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: Encoding.hpp
|
||||
Date: 2021-8-20
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Locale::Encoding
|
||||
{
|
||||
AUKN_SYM AuStreamReadWrittenPair_t EncodeUTF8(const void *utf8, AuUInt32 ut8Length, void *binary, AuUInt32 binaryLength, ECodePage page = ECodePage::eUnsupported);
|
||||
static inline AuStreamReadWrittenPair_t EncodeUTF8(const AuString &out, void *binary, AuUInt32 binaryLength, ECodePage page = ECodePage::eUnsupported)
|
||||
{
|
||||
return EncodeUTF8(out.data(), static_cast<AuUInt32>(out.size()), binary, binaryLength, page);
|
||||
}
|
||||
|
||||
AUKN_SYM std::optional<AuPair<ECodePage, AuUInt8>> DecodeBOM(const void *binary, AuUInt32 binaryLength);
|
||||
|
||||
/// Translates a buffer, possibly a slice of a stream, to UTF-8
|
||||
/// Returns a pair; bytes consumed, bytes written
|
||||
AUKN_SYM AuStreamReadWrittenPair_t DecodeUTF8(const void *binary, AuUInt32 binaryLength, void *utf8, AuUInt32 utf8Max, ECodePage page = ECodePage::eUnsupported);
|
||||
|
||||
AUKN_SYM AuStreamReadWrittenPair_t DecodeUTF8(const void *binary, AuUInt32 binaryLength, AuString &out, ECodePage page = ECodePage::eUnsupported);
|
||||
}
|
@ -7,15 +7,19 @@
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
#include "ECodePage.hpp"
|
||||
#include "Encoding/Encoding.hpp"
|
||||
|
||||
namespace Aurora::Locale
|
||||
{
|
||||
struct LocalizationInfo
|
||||
{
|
||||
LocalizationInfo(const AuString& language, const AuString& country, const AuString& codeset) : Language(language), Country(country), Codeset(codeset) {}
|
||||
LocalizationInfo(const AuString& language, const AuString& country, const AuString& codeset, const ECodePage codePage) : language(language), country(country), codeset(codeset), codepage(codePage) {}
|
||||
|
||||
const AuString& Language;
|
||||
const AuString& Country;
|
||||
const AuString& Codeset;
|
||||
const AuString& language;
|
||||
const AuString& country;
|
||||
const AuString& codeset;
|
||||
const ECodePage codepage;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -25,7 +29,6 @@ namespace Aurora::Locale
|
||||
*/
|
||||
AUKN_SYM LocalizationInfo GetLocale();
|
||||
|
||||
|
||||
#if defined(AURORA_PLATFORM_WIN32) || defined(I_REALLY_NEED_WIDECHAR_PUBAPI)
|
||||
AUKN_SYM std::wstring ConvertFromUTF8(const AuString &in);
|
||||
AUKN_SYM AuString ConvertFromWChar(const wchar_t *in, AuMach length);
|
||||
|
0
Include/Aurora/Loop/LSApple.hpp
Normal file
0
Include/Aurora/Loop/LSApple.hpp
Normal file
7
Include/Aurora/Loop/LSAsync.hpp
Normal file
7
Include/Aurora/Loop/LSAsync.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: LSAsync.hpp
|
||||
Date: 2021-8-21
|
||||
Author: Reece
|
||||
***/
|
7
Include/Aurora/Loop/LSCV.hpp
Normal file
7
Include/Aurora/Loop/LSCV.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: LSCV.hpp
|
||||
Date: 2021-8-28
|
||||
Author: Reece
|
||||
***/
|
7
Include/Aurora/Loop/LSEvent.hpp
Normal file
7
Include/Aurora/Loop/LSEvent.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: LSEvent.hpp
|
||||
Date: 2021-8-28
|
||||
Author: Reece
|
||||
***/
|
7
Include/Aurora/Loop/LSFd.hpp
Normal file
7
Include/Aurora/Loop/LSFd.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: LSFd.hpp
|
||||
Date: 2021-8-21
|
||||
Author: Reece
|
||||
***/
|
7
Include/Aurora/Loop/LSGlib.hpp
Normal file
7
Include/Aurora/Loop/LSGlib.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: LSGlib.hpp
|
||||
Date: 2021-8-21
|
||||
Author: Reece
|
||||
***/
|
7
Include/Aurora/Loop/LSMutex.hpp
Normal file
7
Include/Aurora/Loop/LSMutex.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: LSMutex.hpp
|
||||
Date: 2021-8-28
|
||||
Author: Reece
|
||||
***/
|
7
Include/Aurora/Loop/LSRWMutex.hpp
Normal file
7
Include/Aurora/Loop/LSRWMutex.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: LSRWMutex.hpp
|
||||
Date: 2021-8-21
|
||||
Author: Reece
|
||||
***/
|
7
Include/Aurora/Loop/LSSemaphore.hpp
Normal file
7
Include/Aurora/Loop/LSSemaphore.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: LSSemaphore.hpp
|
||||
Date: 2021-8-28
|
||||
Author: Reece
|
||||
***/
|
7
Include/Aurora/Loop/LSTimer.hpp
Normal file
7
Include/Aurora/Loop/LSTimer.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: LSTimer.hpp
|
||||
Date: 2021-8-21
|
||||
Author: Reece
|
||||
***/
|
7
Include/Aurora/Loop/LSWin32.hpp
Normal file
7
Include/Aurora/Loop/LSWin32.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: LSWin32.hpp
|
||||
Date: 2021-8-21
|
||||
Author: Reece
|
||||
***/
|
7
Include/Aurora/Loop/LSX11.hpp
Normal file
7
Include/Aurora/Loop/LSX11.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: LSX11.hpp
|
||||
Date: 2021-8-21
|
||||
Author: Reece
|
||||
***/
|
40
Include/Aurora/Loop/Loop.hpp
Normal file
40
Include/Aurora/Loop/Loop.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: Loop.hpp
|
||||
Date: 2021-8-21
|
||||
Author: Reece
|
||||
***/
|
||||
|
||||
enum class ELoopSource
|
||||
{
|
||||
eSourceInternalReserved1,
|
||||
eSourceInternalReserved2,
|
||||
eSourceInternalReserved3,
|
||||
eSourceInternalReserved4,
|
||||
|
||||
// unix only
|
||||
eSourceFileDescriptor,
|
||||
|
||||
// generic
|
||||
eSourceSemaphore,
|
||||
eSourceMutex,
|
||||
eSourceTimer,
|
||||
|
||||
// Specific to the runtime subsystem
|
||||
eSourceAsync,
|
||||
|
||||
// glib oses only
|
||||
eSourceGlib,
|
||||
|
||||
// window messge loops
|
||||
eSourceApple,
|
||||
eSourceX11,
|
||||
eSourceWin32
|
||||
};
|
||||
|
||||
class ILoopSource
|
||||
{
|
||||
|
||||
};
|
||||
|
7
Include/Aurora/Loop/Wait.hpp
Normal file
7
Include/Aurora/Loop/Wait.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: Wait.hpp
|
||||
Date: 2021-8-21
|
||||
Author: Reece
|
||||
***/
|
7
Include/Aurora/Memory/Array.hpp
Normal file
7
Include/Aurora/Memory/Array.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: Array.hpp
|
||||
Date: 2021-8-5
|
||||
Author: Reece
|
||||
***/
|
550
Include/Aurora/Memory/ByteBuffer.hpp
Normal file
550
Include/Aurora/Memory/ByteBuffer.hpp
Normal file
@ -0,0 +1,550 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: ByteBuffer.hpp
|
||||
Date: 2021-8-5
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Memory
|
||||
{
|
||||
static const auto kBufferPageSize = 512;
|
||||
|
||||
/***
|
||||
* A bytebuffer object represents a linear, partially-linear resizable, buffer **or** a ring buffer.
|
||||
*
|
||||
* Use cases for a ring buffer include wrapping specific streams whereby your use cases may include
|
||||
* arbitrarily seeking around wrapped blocks of a more limited block stream, a network stream, or other api
|
||||
* IE;
|
||||
* -> peaking a header in a datagram, or tcp stream; where instead of freeing the datagram or saving
|
||||
* the buffered tcp stream, a ring buffer is used to prevent reallocation on each frame
|
||||
* -> peaking, or seeking back after, a compression read transaction. A compression api could be fed on-
|
||||
* demand or ad hoc, writing to its write head pointer, while never running out of space so long as
|
||||
* the decompressed ring read head continues moving
|
||||
*
|
||||
* Small, linear, write/read-once [de]serialization use cases may elect to allocate a buffer and
|
||||
* follow the linear fast paths; perhaps even enabling flagExpandable for hopefully-smarter-than-stdvec-scaling
|
||||
*
|
||||
* Ring buffers scale from the write head, to the read head, potentially going-around in the process
|
||||
*
|
||||
* Linear flagExpandable buffers scale from [0, length]; reallocating at end of buffer if flagExpandable is enabled
|
||||
* if expanding is enabled,
|
||||
* realloc(max(size + offset, (offset / kBufferPageSize + 1) * kBufferPageSize))
|
||||
*
|
||||
* Deprecates INetworkStream, fixes allocation issues around compression backends
|
||||
* Superseeds abuse of AuList<AuUInt8> for binary blobs, alongside Memory::Array
|
||||
*/
|
||||
struct ByteBuffer
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Stable ByteBuffer ABI Header; length and read/write head pointers //
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Internal capacity to mitigate trivial reallocs
|
||||
AuUInt allocSize;
|
||||
|
||||
/// Abstract size
|
||||
AuUInt length;
|
||||
|
||||
/// Buffer pointer
|
||||
AuUInt8 *base;
|
||||
/// Stream pointer
|
||||
AuUInt8 *readPtr;
|
||||
/// Stream pointer
|
||||
AuUInt8 *writePtr;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Stable ByteBuffer ABI Header; u32 flags //
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
/// Is ring buffer?
|
||||
AuUInt32 flagCircular : 1;
|
||||
|
||||
/// Should resize linear buffer to accommodate additional writes
|
||||
AuUInt32 flagExpandable : 1;
|
||||
|
||||
AuUInt32 flagReadError : 1;
|
||||
AuUInt32 flagWriteError : 1;
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ByteBuffer(const ByteBuffer &buffer, bool preservePointers = true)
|
||||
{
|
||||
this->base = ZAlloc<AuUInt8 *>(buffer.length);
|
||||
this->length = buffer.length;
|
||||
this->allocSize = buffer.length;
|
||||
if (preservePointers)
|
||||
{
|
||||
this->writePtr = this->base + (buffer.writePtr - buffer.base);
|
||||
this->readPtr = this->base + (buffer.readPtr - buffer.base);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->writePtr = this->base;
|
||||
this->readPtr = this->base;
|
||||
}
|
||||
std::memcpy(this->base, buffer.base, this->length);
|
||||
this->flagCircular = buffer.flagCircular;
|
||||
this->flagExpandable = buffer.flagExpandable;
|
||||
}
|
||||
|
||||
ByteBuffer(const void *in, AuUInt length, bool circular = false, bool expandable = false) : flagCircular(circular), flagExpandable(expandable), flagReadError(0), flagWriteError(0)
|
||||
{
|
||||
this->base = ZAlloc<AuUInt8 *>(length);
|
||||
this->length = length;
|
||||
this->allocSize = length;
|
||||
this->readPtr = this->base;
|
||||
this->writePtr = this->readPtr + this->length;
|
||||
std::memcpy(this->base, in, this->length);
|
||||
}
|
||||
|
||||
ByteBuffer(const AuList<AuUInt8> &vector, bool circular = false, bool expandable = false) : flagCircular(circular), flagExpandable(expandable), flagReadError(0), flagWriteError(0)
|
||||
{
|
||||
this->base = ZAlloc<AuUInt8 *>(length);
|
||||
this->length = vector.size();
|
||||
this->allocSize = vector.size();
|
||||
this->readPtr = this->base;
|
||||
this->writePtr = this->readPtr + this->length;
|
||||
std::memcpy(this->base, vector.data(), this->length);
|
||||
}
|
||||
|
||||
ByteBuffer(AuUInt length, bool circular = false, bool expandable = false) : flagCircular(circular), flagExpandable(expandable), flagReadError(0), flagWriteError(0)
|
||||
{
|
||||
this->base = ZAlloc<AuUInt8 *>(length);
|
||||
this->length = length;
|
||||
this->allocSize = length;
|
||||
this->readPtr = this->base;
|
||||
this->writePtr = this->base;
|
||||
}
|
||||
|
||||
~ByteBuffer()
|
||||
{
|
||||
Free(this->base);
|
||||
}
|
||||
|
||||
inline void ResetPositions()
|
||||
{
|
||||
this->flagReadError = 0;
|
||||
this->flagWriteError = 0;
|
||||
this->readPtr = base;
|
||||
this->writePtr = base;
|
||||
}
|
||||
|
||||
// Iterator
|
||||
AUKN_SYM AuUInt8 *begin();
|
||||
AUKN_SYM AuUInt8 *end();
|
||||
|
||||
// To alternative types
|
||||
AUKN_SYM AuList<AuUInt8> ToVector();
|
||||
|
||||
// Seek
|
||||
AUKN_SYM bool ReaderTryGoForward(AuUInt32 offset);
|
||||
AUKN_SYM bool ReaderTryGoBack(AuUInt32 offset);
|
||||
|
||||
AUKN_SYM bool WriterTryGoForward(AuUInt32 offset);
|
||||
|
||||
|
||||
AUKN_SYM AuOptional<AuUInt8 *> WriterTryGetWriteHeadFor(AuUInt32 nBytes);
|
||||
|
||||
// Template implementation
|
||||
// TODO: remove to .inl
|
||||
|
||||
template<typename T>
|
||||
inline bool Read(T &out)
|
||||
{
|
||||
if constexpr (std::is_class_v<T>)
|
||||
{
|
||||
if constexpr (AuIsBaseOfTemplate<AURORA_RUNTIME_AU_LIST, std::remove_reference_t<T>>::value)
|
||||
{
|
||||
if (Read<AuUInt32>() != sizeof(typename T::value_type))
|
||||
{
|
||||
this->flagReadError = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto len = Read<AuUInt32>();
|
||||
out.resize(len);
|
||||
|
||||
for (auto i = 0u; i < len; i++)
|
||||
{
|
||||
Read<T::value_type>(out[i]);
|
||||
}
|
||||
|
||||
return !this->flagReadError;
|
||||
}
|
||||
else if constexpr (std::is_same_v<std::remove_reference_t<T>, AuString>)
|
||||
{
|
||||
out.resize(Read<AuUInt32>());
|
||||
Read(out.data(), out.size());
|
||||
return !this->flagReadError;
|
||||
}
|
||||
}
|
||||
|
||||
auto oldptr = readPtr;
|
||||
auto skipped = Read(&out, sizeof(T));
|
||||
if (skipped != sizeof(T))
|
||||
{
|
||||
this->flagReadError = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T Read()
|
||||
{
|
||||
T a{};
|
||||
Read(a);
|
||||
return a;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool Write(const T &in)
|
||||
{
|
||||
if constexpr (std::is_class_v<T>)
|
||||
{
|
||||
if constexpr (AuIsBaseOfTemplate<AURORA_RUNTIME_AU_LIST, std::remove_reference_t<T>>::value)
|
||||
{
|
||||
Write<AuUInt32>(sizeof(typename T::value_type));
|
||||
Write<AuUInt32>(AuUInt32(in.size()));
|
||||
|
||||
for (const auto &item : in)
|
||||
{
|
||||
Write<T::value_type>(item);
|
||||
}
|
||||
|
||||
return !this->flagWriteError;
|
||||
}
|
||||
else if constexpr (std::is_same_v<std::remove_reference_t<T>, AuString>)
|
||||
{
|
||||
Write<AuUInt32>(AuUInt32(in.size()));
|
||||
Write(in.data(), in.size());
|
||||
return !this->flagWriteError;
|
||||
}
|
||||
}
|
||||
|
||||
auto skipped = Write(&in, sizeof(T));
|
||||
if (skipped != sizeof(T))
|
||||
{
|
||||
this->flagWriteError = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool Resize(AuUInt length)
|
||||
{
|
||||
AuUInt oldWriteIdx, oldReadIdx, oldLength, newLength;
|
||||
AuUInt8 *nextRead, *nextWrite, *nextPtr;
|
||||
|
||||
if (this->allocSize > length)
|
||||
{
|
||||
this->length = length;
|
||||
|
||||
oldLength = this->length;
|
||||
newLength = length;
|
||||
nextPtr = this->base;
|
||||
oldWriteIdx = this->writePtr - this->base;
|
||||
oldReadIdx = this->readPtr - this->base;
|
||||
nextRead = nextPtr + oldReadIdx;
|
||||
nextWrite = nextPtr + oldWriteIdx;
|
||||
}
|
||||
else
|
||||
{
|
||||
oldLength = this->length;
|
||||
newLength = std::max(AuUInt(length), AuUInt(((this->allocSize / kBufferPageSize) + 1) * kBufferPageSize));
|
||||
|
||||
nextPtr = ZRealloc(this->base, newLength);
|
||||
if (!nextPtr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
oldWriteIdx = this->writePtr - this->base;
|
||||
oldReadIdx = this->readPtr - this->base;
|
||||
nextRead = nextPtr + oldReadIdx;
|
||||
nextWrite = nextPtr + oldWriteIdx;
|
||||
|
||||
this->allocSize = newLength;
|
||||
this->length = length;
|
||||
}
|
||||
|
||||
this->base = nextPtr;
|
||||
|
||||
if (!flagCircular)
|
||||
{
|
||||
this->readPtr = nextRead;
|
||||
this->writePtr = nextWrite;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->writePtr > this->readPtr)
|
||||
{
|
||||
this->readPtr = nextRead;
|
||||
this->writePtr = nextWrite;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto expansion = newLength - oldLength;
|
||||
auto movableTail = std::min(oldWriteIdx, expansion);
|
||||
|
||||
std::memcpy(nextPtr + oldLength, nextPtr, movableTail);
|
||||
|
||||
this->readPtr = nextRead;
|
||||
this->writePtr = nextPtr + oldLength + movableTail;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline AuUInt Write(const void *buffer, AuUInt requestLength)
|
||||
{
|
||||
AuUInt linearOverhead = 0, toReadOverhead = 0, linearWritable = 0, toReadWritable = 0, writable = 0;
|
||||
auto cptr = reinterpret_cast<const AuUInt8 *>(buffer);
|
||||
|
||||
if (flagCircular)
|
||||
{
|
||||
// 0 1 2 3 4 5
|
||||
// W R
|
||||
// 6 - (1) = 5 -> read bound; we have zero overhead not 5
|
||||
|
||||
if (writePtr < readPtr)
|
||||
{
|
||||
// Handle read-bound writes
|
||||
linearOverhead = readPtr - writePtr;
|
||||
toReadOverhead = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handle ordinary stream consume bound IO
|
||||
linearOverhead = length - (writePtr - base);
|
||||
toReadOverhead = readPtr - base;
|
||||
}
|
||||
|
||||
writable = std::min(linearOverhead + toReadOverhead, requestLength);
|
||||
|
||||
linearWritable = std::min(linearOverhead, requestLength);
|
||||
toReadWritable = writable - linearWritable;
|
||||
|
||||
if (cptr)
|
||||
{
|
||||
std::memcpy(writePtr, cptr, linearWritable);
|
||||
}
|
||||
writePtr += linearWritable;
|
||||
|
||||
if (toReadWritable)
|
||||
{
|
||||
writePtr = base;
|
||||
if (cptr)
|
||||
{
|
||||
std::memcpy(writePtr, cptr + linearOverhead, toReadWritable);
|
||||
}
|
||||
writePtr += toReadWritable;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (writePtr == base + length)
|
||||
{
|
||||
writePtr = base;
|
||||
}
|
||||
#endif
|
||||
|
||||
return linearWritable + toReadWritable;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto offset = writePtr - base;
|
||||
auto overhead = length - offset;
|
||||
|
||||
AuUInt len = std::min(overhead, requestLength);
|
||||
|
||||
if ((len != requestLength) && (flagExpandable))
|
||||
{
|
||||
if (!Resize(offset + requestLength))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
overhead = length - offset;
|
||||
len = std::min(overhead, requestLength);
|
||||
}
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
std::memcpy(writePtr, buffer, len);
|
||||
}
|
||||
|
||||
writePtr += len;
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
inline AuUInt RemainingBytes(bool endAtWrite = true)
|
||||
{
|
||||
if (flagCircular)
|
||||
{
|
||||
if ((readPtr < writePtr) && (endAtWrite))
|
||||
{
|
||||
return length - (writePtr - readPtr);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto linearOverhead = length - (readPtr - base);
|
||||
auto toWriteOverhead = writePtr - base;
|
||||
return linearOverhead + toWriteOverhead;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return endAtWrite ? (writePtr - readPtr) : (length - (readPtr - base));
|
||||
}
|
||||
}
|
||||
|
||||
inline AuList<AuUInt8> RemainingBytesToVector(bool endAtWrite = true)
|
||||
{
|
||||
AuList<AuUInt8> vec;
|
||||
|
||||
if (flagCircular)
|
||||
{
|
||||
if ((readPtr < writePtr) && (endAtWrite))
|
||||
{
|
||||
auto len = length - (writePtr - readPtr);
|
||||
|
||||
vec.resize(len);
|
||||
std::memcpy(vec.data(), readPtr, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto linearOverhead = length - (readPtr - base);
|
||||
auto toWriteOverhead = endAtWrite ? (writePtr - base) : (readPtr - base);
|
||||
|
||||
vec.resize(linearOverhead + toWriteOverhead);
|
||||
std::memcpy(vec.data(), readPtr, linearOverhead);
|
||||
std::memcpy(vec.data() + linearOverhead, base, linearOverhead);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AuUInt len;
|
||||
if (endAtWrite)
|
||||
{
|
||||
len = writePtr - readPtr;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = length - (readPtr - base);
|
||||
}
|
||||
|
||||
vec.resize(len);
|
||||
std::memcpy(vec.data(), readPtr, len);
|
||||
}
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
inline bool Skip(AuUInt count)
|
||||
{
|
||||
auto oldptr = readPtr;
|
||||
auto skipped = Read(nullptr, count);
|
||||
if (skipped != count)
|
||||
{
|
||||
readPtr = oldptr;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline AuUInt GetReadOffset()
|
||||
{
|
||||
if (flagCircular)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return readPtr - base;
|
||||
}
|
||||
}
|
||||
|
||||
inline AuUInt GetWriteOffset()
|
||||
{
|
||||
if (flagCircular)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return writePtr - base;
|
||||
}
|
||||
}
|
||||
|
||||
inline AuUInt Read(void *out, AuUInt requestedLength, bool peak = false)
|
||||
{
|
||||
AuUInt linearOverhead = 0, toWriteOverhead = 0, linearReadable = 0, toWriteReadable = 0;
|
||||
if (flagCircular)
|
||||
{
|
||||
if (readPtr < writePtr)
|
||||
{
|
||||
linearOverhead = writePtr - readPtr;
|
||||
toWriteOverhead = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
linearOverhead = length - (readPtr - base);
|
||||
toWriteOverhead = writePtr - base;
|
||||
}
|
||||
|
||||
auto readable = std::min(linearOverhead + toWriteOverhead, requestedLength);
|
||||
|
||||
linearReadable = std::min(linearOverhead, requestedLength);
|
||||
toWriteReadable = readable - linearReadable;
|
||||
|
||||
if (out)
|
||||
{
|
||||
std::memcpy(out, readPtr, linearOverhead);
|
||||
}
|
||||
|
||||
if (!peak)
|
||||
{
|
||||
readPtr += linearOverhead;
|
||||
}
|
||||
|
||||
if (toWriteOverhead)
|
||||
{
|
||||
std::memcpy(reinterpret_cast<AuUInt8 *>(out) + linearOverhead, base, toWriteReadable);
|
||||
|
||||
if (!peak)
|
||||
{
|
||||
readPtr = base + toWriteReadable;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (readPtr == base + length)
|
||||
{
|
||||
readPtr = base;
|
||||
}
|
||||
#endif
|
||||
|
||||
return linearReadable + toWriteReadable;
|
||||
}
|
||||
else
|
||||
{
|
||||
AuUInt len = std::min(AuUInt(writePtr - readPtr), requestedLength);
|
||||
|
||||
if (out)
|
||||
{
|
||||
std::memcpy(out, readPtr, len);
|
||||
}
|
||||
|
||||
if (!peak)
|
||||
{
|
||||
readPtr += len;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
@ -11,7 +11,6 @@
|
||||
|
||||
#include "MemRef.hpp"
|
||||
#include "Heap.hpp"
|
||||
#include "Handles.hpp"
|
||||
|
||||
namespace Aurora::Memory
|
||||
{
|
||||
@ -33,6 +32,8 @@ namespace Aurora::Memory
|
||||
// -> do not double init
|
||||
// TODO: ensure typeof(T) is not a pointer of a class
|
||||
|
||||
#if !defined(_CPPSHARP)
|
||||
|
||||
template<typename T>
|
||||
T ZAlloc(Types::size_t length)
|
||||
{
|
||||
@ -124,20 +125,24 @@ namespace Aurora::Memory
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T SRealloc(T in, Types::size_t length)
|
||||
T FRealloc(T in, Types::size_t length)
|
||||
{
|
||||
return reinterpret_cast<T>(_SRealloc(reinterpret_cast<void *>(in), length));
|
||||
return reinterpret_cast<T>(_FRealloc(reinterpret_cast<void *>(in), length));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T SRealloc(T in, Types::size_t length, Types::size_t alloc)
|
||||
T FRealloc(T in, Types::size_t length, Types::size_t alloc)
|
||||
{
|
||||
return reinterpret_cast<T>(_SRealloc(reinterpret_cast<void *>(in), length), alloc);
|
||||
return reinterpret_cast<T>(_FRealloc(reinterpret_cast<void *>(in), length), alloc);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
void Free(T in)
|
||||
{
|
||||
_Free(reinterpret_cast<void *>(in));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#include "Array.hpp"
|
||||
#include "ByteBuffer.hpp"
|
26
Include/Aurora/Parse/Hex.hpp
Normal file
26
Include/Aurora/Parse/Hex.hpp
Normal file
@ -0,0 +1,26 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: Hex.hpp
|
||||
Date: 2021-8-28
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Parse
|
||||
{
|
||||
enum class EHexDump
|
||||
{
|
||||
eString,
|
||||
eZeroXSpace,
|
||||
eHexEditor,
|
||||
eCLiteral,
|
||||
eJSLiteral
|
||||
};
|
||||
|
||||
AUKN_SYM void ByteToHex(AuUInt8 val, char(&hex)[2]);
|
||||
AUKN_SYM bool HexToInt (const char *hex, AuUInt32 length, AuUInt64 &val);
|
||||
|
||||
AUKN_SYM void EncodeHex(const void *pBuf, AuUInt32 length, EHexDump formatting, AuString &out);
|
||||
AUKN_SYM bool DecodeHex(const AuString &in, AuList<AuUInt8> &out);
|
||||
}
|
@ -24,8 +24,48 @@ namespace Aurora::Parse
|
||||
}
|
||||
|
||||
lineCallback(line);
|
||||
|
||||
if (startIdx >= in.size())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lineCallback(in.substr(startIdx));
|
||||
}
|
||||
|
||||
static AuList<AuString> SplitString(const AuString &in, AuUInt16 characters)
|
||||
{
|
||||
AuList<AuString> ret;
|
||||
for (auto i = 0u; i < in.size(); i += characters)
|
||||
{
|
||||
auto start = i;
|
||||
auto end = std::min(AuUInt32(in.size()), AuUInt32(i + characters));
|
||||
auto len = end - start;
|
||||
ret.push_back(in.substr(start, len));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static AuString SplitStringDelm(const AuString &in, const AuString &delm, AuUInt16 characters)
|
||||
{
|
||||
AuString ret;
|
||||
ret.reserve(in.size());
|
||||
for (auto i = 0u; i < in.size(); i += characters)
|
||||
{
|
||||
AuUInt32 start, end, len;
|
||||
|
||||
if (i != 0)
|
||||
{
|
||||
ret.insert(ret.size(), delm);
|
||||
}
|
||||
|
||||
start = i;
|
||||
end = std::min(AuUInt32(in.size()), AuUInt32(i + characters));
|
||||
len = end - start;
|
||||
|
||||
ret.insert(ret.size(), in.substr(start, len));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "Base32.hpp"
|
||||
#include "Base64.hpp"
|
||||
#include "Hex.hpp"
|
||||
|
||||
#include "LineParser.hpp"
|
||||
#include "Parser.hpp"
|
@ -40,24 +40,23 @@ namespace Aurora::Parse
|
||||
|
||||
struct ParseBit
|
||||
{
|
||||
ParseBit(ParsableTag _Tag, const AuString &_Label) : tag(_Tag), label(_Label)
|
||||
{
|
||||
}
|
||||
ParseBit(ParsableTag _Tag, const AuString &_Label, bool _Array, bool _Optional, bool _vararg) : tag(_Tag), label(_Label), array(_Array), optional(_Optional), vararg(_vararg)
|
||||
{
|
||||
}
|
||||
ParseBit(ParsableTag _Tag) : tag(_Tag)
|
||||
{
|
||||
}
|
||||
ParseBit(ParsableTag _Tag, bool _Array, bool _Optional, bool _vararg) : tag(_Tag), array(_Array), optional(_Optional), vararg(_vararg)
|
||||
{
|
||||
}
|
||||
ParseBit(ParsableTag tag, const AuString &label) : tag(tag), label(label)
|
||||
{}
|
||||
|
||||
ParseBit(ParsableTag tag, const AuString &label, bool array, bool optional, bool _vararg) : tag(tag), label(label), array(array), optional(optional), vararg(_vararg)
|
||||
{}
|
||||
|
||||
ParseBit(ParsableTag tag) : tag(tag)
|
||||
{}
|
||||
|
||||
ParseBit(ParsableTag tag, bool array, bool optional, bool _vararg) : tag(tag), array(array), optional(optional), vararg(_vararg)
|
||||
{}
|
||||
|
||||
ParseBit(ParseObject _ObjectParse) : tag(ParsableTag::kParseObject), objectParse(_ObjectParse)
|
||||
{
|
||||
}
|
||||
ParseBit(ParseObject _ObjectParse, const AuString &_Label) : tag(ParsableTag::kParseObject), objectParse(_ObjectParse), label(_Label)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
ParseBit(ParseObject _ObjectParse, const AuString &label) : tag(ParsableTag::kParseObject), objectParse(_ObjectParse), label(label)
|
||||
{}
|
||||
|
||||
// marks this "parse bit" and all following part bits optional
|
||||
bool optional = false;
|
||||
@ -90,11 +89,10 @@ namespace Aurora::Parse
|
||||
struct ParsedBit
|
||||
{
|
||||
ParsedBit()
|
||||
{
|
||||
}
|
||||
ParsedBit(ParsableTag _tag) : tag(_tag)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
ParsedBit(ParsableTag tag) : tag(tag)
|
||||
{}
|
||||
|
||||
AuMach count;
|
||||
ParsableTag tag;
|
||||
@ -131,6 +129,25 @@ namespace Aurora::Parse
|
||||
return getc;
|
||||
}
|
||||
|
||||
|
||||
struct ParseState
|
||||
{
|
||||
ParseState(ConsumeStream_cb &str) : stringstream(str)
|
||||
{}
|
||||
|
||||
ParseState(ConsumeStream_cb &&str) : stringstream(std::move(str))
|
||||
{}
|
||||
|
||||
ConsumeStream_cb stringstream;
|
||||
|
||||
AuUInt8 *additionalTokens {};
|
||||
AuUInt16 countOfTokens {};
|
||||
|
||||
bool hasLastToken {};
|
||||
AuUInt8 lastTokenCharacter {};
|
||||
AuMach lastTokenAdditional {};
|
||||
};
|
||||
|
||||
AUKN_SYM void VaildateStructure(const ParseObject &object);
|
||||
AUKN_SYM bool ConsumeToken(ParsableTag type, ConsumeStream_cb getc, ParseValue &out);
|
||||
|
||||
@ -145,17 +162,19 @@ namespace Aurora::Parse
|
||||
return ConsumeToken(type, StringToConsumable(str, index), out);
|
||||
}
|
||||
|
||||
AUKN_SYM bool Parse(ParseResult &result, const ParseObject &structure, ConsumeStream_cb getc);
|
||||
AUKN_SYM bool Parse(ParseState &state, const ParseObject &structure, ParseResult &result);
|
||||
|
||||
static bool Parse(ParseResult &result, const ParseObject &structure, const AuString &str, AuMach &index)
|
||||
{
|
||||
return Parse(result, structure, StringToConsumable(str, index));
|
||||
ParseState state(StringToConsumable(str, index));
|
||||
return Parse(state, structure, result);
|
||||
}
|
||||
|
||||
static bool Parse(ParseResult &result, const ParseObject &structure, const AuString &str)
|
||||
{
|
||||
AuMach index{};
|
||||
return Parse(result, structure, StringToConsumable(str, index));
|
||||
ParseState state(StringToConsumable(str, index));
|
||||
return Parse(state, structure, result);
|
||||
}
|
||||
|
||||
AUKN_SYM void SerializeToken(ParsableTag type, const ParseValue &value, AuString &str);
|
||||
|
@ -8,4 +8,36 @@
|
||||
#pragma once
|
||||
|
||||
#include "Paths.hpp"
|
||||
#include "ProcessMap.hpp"
|
||||
#include "ProcessMap.hpp"
|
||||
|
||||
namespace Aurora::Process
|
||||
{
|
||||
AUKN_SYM AU_NORETURN void Exit(AuUInt32 exitcode);
|
||||
|
||||
enum class EModulePath
|
||||
{
|
||||
eModulePathCWD,
|
||||
eModulePathSystemDir, /// /lib/, windir/system32
|
||||
eModulePathUserDir, /// /usr/lib/
|
||||
eProcessDirectory, ///
|
||||
eOSSpecified, /// LD_LIBRARY_PATH + /etc/ld.so.conf, AddDllDirectory
|
||||
eSpecified
|
||||
};
|
||||
|
||||
static AuList<EModulePath> kUserOverloadableSearchPath = {EModulePath::eSpecified, EModulePath::eModulePathCWD, EModulePath::eProcessDirectory, EModulePath::eModulePathUserDir, EModulePath::eModulePathSystemDir};
|
||||
static AuList<EModulePath> kAdminOverloadableSearchPath = {EModulePath::eSpecified, EModulePath::eModulePathSystemDir, EModulePath::eProcessDirectory, EModulePath::eModulePathCWD, EModulePath::eModulePathUserDir};
|
||||
|
||||
struct ModuleLoadRequest
|
||||
{
|
||||
AuString mod;
|
||||
AuOptional<AuString> version;
|
||||
AuOptional<AuString> extension;
|
||||
AuList<AuString> const *specifiedSearchPaths {};
|
||||
AuList<EModulePath> const *searchPath {};
|
||||
bool verifyOne {}; // always true if the executable is signed
|
||||
bool verifyAll {};
|
||||
};
|
||||
|
||||
AUKN_SYM bool LoadModule(const ModuleLoadRequest &request);
|
||||
AUKN_SYM AuMach GetProcAddress(AuString mod, AuString symbol);
|
||||
}
|
@ -18,7 +18,7 @@ namespace Aurora::Process
|
||||
};
|
||||
using Segments = AuList<Segment>;
|
||||
|
||||
AUKN_SYM std::optional<Segment> GetSegment(AuUInt pointer);
|
||||
AUKN_SYM AuOptional<Segment> GetSegment(AuUInt pointer);
|
||||
AUKN_SYM Segments DumpExecutableRoot();
|
||||
AUKN_SYM Segments DumpExecutableAll();
|
||||
}
|
@ -19,8 +19,8 @@ namespace Aurora::Processes
|
||||
public:
|
||||
///
|
||||
/// @return the waitable of a waitable child process or thread leader
|
||||
virtual Threading::IWaitable *AsWaitable() = 0;
|
||||
|
||||
virtual AuSPtr<Threading::IWaitable> AsWaitable() = 0;
|
||||
|
||||
/// Assuming AsWaitable()->TryLock() && Spawn != SpawnType::kSpawnAtomicOvermap,
|
||||
/// returns the true return value of the process
|
||||
/// otherwise returns zero
|
||||
|
22
Include/Aurora/RNG/ERngStringCharacters.hpp
Normal file
22
Include/Aurora/RNG/ERngStringCharacters.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: ERngStringCharacters.hpp
|
||||
Date: 2021-9-3
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::RNG
|
||||
{
|
||||
enum class ERngStringCharacters
|
||||
{
|
||||
eAlphaCharacters,
|
||||
eLowerCharacters,
|
||||
eUpperCharacters,
|
||||
eNumericCharacters,
|
||||
eAlphaNumericCharacters,
|
||||
eExtendedEntropy,
|
||||
eCount
|
||||
};
|
||||
}
|
82
Include/Aurora/RNG/IRandomDevice.hpp
Normal file
82
Include/Aurora/RNG/IRandomDevice.hpp
Normal file
@ -0,0 +1,82 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: IRandomDevice.hpp
|
||||
Date: 2021-9-3
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::RNG
|
||||
{
|
||||
class IRandomDevice
|
||||
{
|
||||
public:
|
||||
virtual void Read(void *in, AuUInt32 length) = 0;
|
||||
|
||||
virtual AuString NextString(AuUInt32 length, ERngStringCharacters type = ERngStringCharacters::eAlphaCharacters) = 0;
|
||||
virtual void NextString(char *string, AuUInt32 length, ERngStringCharacters type = ERngStringCharacters::eAlphaCharacters) = 0;
|
||||
virtual AuUInt8 NextByte() = 0;
|
||||
virtual bool NextBoolean() = 0;
|
||||
virtual AuUInt32 NextU32() = 0;
|
||||
virtual AuUInt32 NextU32(AuUInt32 min, AuUInt32 max) = 0;
|
||||
virtual AuUInt64 NextU64() = 0;
|
||||
virtual AuInt32 NextInt(AuInt32 min, AuInt32 max) = 0;
|
||||
virtual double NextDecimal() = 0;
|
||||
virtual float NextNumber(float min, float max) = 0;
|
||||
virtual AuUInt32 NextIndex(AuUInt32 count /* = max + 1*/) = 0;
|
||||
|
||||
|
||||
template<typename T, int N>
|
||||
inline void NextArray(T(&array)[N])
|
||||
{
|
||||
Read(array, N * sizeof(T));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void NextArray(T *array, AuUInt32 length)
|
||||
{
|
||||
Raed(array, length * sizeof(T));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T NextTmpl()
|
||||
{
|
||||
T ret {};
|
||||
Read(&ret, sizeof(T));
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T &NextArray(T *items, AuUInt32 count)
|
||||
{
|
||||
return items[NextIndex(count)];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T &NextVector(const AuList<T> &items)
|
||||
{
|
||||
return NextArray(items.data(), items.size());
|
||||
}
|
||||
};
|
||||
|
||||
struct RandomDef
|
||||
{
|
||||
bool secure;
|
||||
AuOptional<AuUInt32> seed;
|
||||
|
||||
inline void SetSeed(AuUInt32 seed)
|
||||
{
|
||||
this->seed = seed;
|
||||
this->secure = false;
|
||||
}
|
||||
|
||||
inline void SetCSRNG()
|
||||
{
|
||||
this->secure = true;
|
||||
this->seed.reset();
|
||||
}
|
||||
};
|
||||
|
||||
AUKN_SHARED_API(Random, IRandomDevice, const RandomDef &def);
|
||||
}
|
@ -2,18 +2,37 @@
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: RNG.hpp
|
||||
Date: 2021-6-10
|
||||
Date: 2021-7-14
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
#include "ERngStringCharacters.hpp"
|
||||
#include "IRandomDevice.hpp"
|
||||
|
||||
namespace Aurora::RNG
|
||||
{
|
||||
AUKN_SYM void ReadSecureRNG(void *in, AuUInt length);
|
||||
AUKN_SYM void ReadFastRNG(void *in, AuUInt length);
|
||||
AUKN_SYM void ReadSecureRNG(void *in, AuUInt32 length);
|
||||
AUKN_SYM void ReadFastRNG (void *in, AuUInt32 length);
|
||||
|
||||
AUKN_SYM AuString ReadString(AuUInt32 length, ERngStringCharacters type = ERngStringCharacters::eAlphaCharacters);
|
||||
AUKN_SYM void RngString(char *string, AuUInt32 length, ERngStringCharacters type = ERngStringCharacters::eAlphaCharacters);
|
||||
|
||||
AUKN_SYM AuUInt8 RngByte();
|
||||
AUKN_SYM bool RngBoolean();
|
||||
AUKN_SYM AuUInt32 RngU32();
|
||||
AUKN_SYM AuUInt32 RngU32(AuUInt32 min, AuUInt32 max);
|
||||
AUKN_SYM AuUInt64 RngU64();
|
||||
AUKN_SYM AuInt32 RngInt(AuInt32 min, AuInt32 max);
|
||||
AUKN_SYM double RngDecimal();
|
||||
AUKN_SYM float RngNumber(float min, float max);
|
||||
AUKN_SYM AuUInt32 RngIndex(AuUInt32 count /* = max + 1*/);
|
||||
|
||||
|
||||
// Note: it is conceivable that someone may want the following templates for some cryptographic purpose
|
||||
|
||||
template<bool fast = true, typename T, int N>
|
||||
static inline void Read(T(&array)[N])
|
||||
static inline void RngArray(T(&array)[N])
|
||||
{
|
||||
if constexpr (fast)
|
||||
{
|
||||
@ -26,7 +45,7 @@ namespace Aurora::RNG
|
||||
}
|
||||
|
||||
template<bool fast = true, typename T>
|
||||
static inline void Read(T *array, AuUInt length)
|
||||
static inline void RngArray(T *array, AuUInt32 length)
|
||||
{
|
||||
if constexpr (fast)
|
||||
{
|
||||
@ -38,50 +57,25 @@ namespace Aurora::RNG
|
||||
}
|
||||
}
|
||||
|
||||
enum class RngStringCharacters
|
||||
template<bool fast = true, typename T>
|
||||
static inline T RngTmpl()
|
||||
{
|
||||
eAlphaCharacters,
|
||||
eAlphaNumericCharacters,
|
||||
eExtendedEntropy,
|
||||
eCount
|
||||
};
|
||||
|
||||
static void RngString(char *string, AuUInt length, RngStringCharacters type = RngStringCharacters::eAlphaCharacters)
|
||||
{
|
||||
static std::pair<const char *, int> rngSequence[static_cast<int>(RngStringCharacters::eCount)] =
|
||||
T ret {};
|
||||
if constexpr (fast)
|
||||
{
|
||||
{"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 52},
|
||||
{"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", 62},
|
||||
{"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890=-+!$%^*.[];:", 75}
|
||||
};
|
||||
|
||||
ReadSecureRNG(string, length);
|
||||
|
||||
const auto &pair = rngSequence[static_cast<int>(type)];
|
||||
|
||||
for (auto i = 0; i < length; i++)
|
||||
{
|
||||
auto idx = std::floor(static_cast<float>(reinterpret_cast<AuUInt8 *>(string)[i]) / 255.f * static_cast<float>(pair.second - 1));
|
||||
string[i] = pair.first[static_cast<int>(idx)];
|
||||
ReadFastRNG(&ret, sizeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
static inline AuUInt8 RngByte()
|
||||
{
|
||||
AuUInt8 x[1];
|
||||
Read<true>(x);
|
||||
return x[0];
|
||||
}
|
||||
|
||||
static inline bool RngBoolean()
|
||||
{
|
||||
return RngByte() > 127;
|
||||
else
|
||||
{
|
||||
ReadSecureRNG(&ret, sizeof(T));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline T &RngArray(T *items, AuUInt count)
|
||||
static inline T &RngArray(T *items, AuUInt32 count)
|
||||
{
|
||||
return items[static_cast<int>(std::floor(static_cast<float>(RngByte()) / 255.f * static_cast<float>(count - 1)))];
|
||||
return items[RngIndex(count)];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
@ -9,15 +9,157 @@
|
||||
|
||||
namespace Aurora::Registry
|
||||
{
|
||||
using RegistryType = Aurora::Data::DataType;
|
||||
using RegistryValue = Aurora::Data::TypedValue;
|
||||
using RegistryType = Data::DataType;
|
||||
using RegistryValue = Data::TypedValue;
|
||||
|
||||
/**
|
||||
* This registry implementation is a fairly reliable, small scale, preference, and app variable database
|
||||
* Do not consider this as a replacement for a "real" high performance kvp database, it is not, it's a small cache backed document serializer for settings
|
||||
*
|
||||
* Basic use case:--------------------------------------------------------------
|
||||
* -> AllocRegistry()
|
||||
* -> Read("~/Registry/MyApp/DefSettings.dat")
|
||||
* -> Read("~/Registry/MyApp/UserSettings.dat")
|
||||
* -> menu.color = GetOrSetKey("theme-color", {.13, .13, .13})
|
||||
* -> menu.colorChanaged := SetKey("theme-color", color)
|
||||
* -> app:onExit := SaveAll({})
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* Arbitrary write use case:----------------------------------------------------
|
||||
* -> AllocRegistry()
|
||||
* -> OpenReadWriteback("~/Registry/MyApp/Settings.dat")
|
||||
* -> menu.color = GetOrSetKey("theme-color", {.13, .13, .13})
|
||||
* -> menu.colorChanaged := SetKey("theme-color", color)
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* Implementing a protected registry:-------------------------------------------
|
||||
* -> AllocRegistry()
|
||||
* -> Read("~/Registry/MyApp/PlayerProfile.dat") will read disk template to the cache, including one "genuine-player-setting"
|
||||
* -> SetWriteModeCache()
|
||||
* -> WriteKey("dev-secret-menu-enabled", {0})
|
||||
* -> LockKey("dev-secret-menu-enabled"), no user write may pass to 'dev-reserved'
|
||||
* -> SetWriteModeCache()
|
||||
* -> SetKey("dev-secret-menu-enabled", {1}) originating from an evil script will fail, returning false
|
||||
* -> SetKey("genuine-ux-setting", {2, 2}) will successfully write to cache
|
||||
* -> SetKey("genuine-player-setting", {2, 2}) will be assumed to be legitimate, write to cache
|
||||
* -> GetKey("genuine-ux-setting") will return {2, 2} from the cache
|
||||
* -> GetKey("genuine-player-setting") will return {2, 2} from the cache
|
||||
* -> SetKey("some-leftover-magic", {.3, .4, .3}) will successfully write to cache
|
||||
* -> GetKey("some-leftover-magic") will return {.3, .4, .3} from the cache
|
||||
* -> OpenSave({})
|
||||
* -> SetKey("genuine-ux-setting", GetKey("genuine-ux-setting")) will specifically write genuine-ux-setting to disk
|
||||
* -> var userSetting = GetKey("genuine-player-setting") will return genuine-player-setting from the cache
|
||||
* -> if (userSetting is inbounds of good constraints) then SetKey("genuine-player-setting", userSetting [=GetKey("genuine-ux-setting")]) will write the cached value back to disk
|
||||
* -> --
|
||||
* -> Unload(), some-leftover-magic will be lost
|
||||
*
|
||||
*
|
||||
* -> Prevent malicious usage of development variables while ensuring spurious references work with read only reference values
|
||||
* -> You may write to the registry the default safe [key:value]s; for instance, zeroing out debug options
|
||||
* -> You may call `LockKey(...)` to ensure spurious writes, like an unchecked server server command or user request, will not overload the protected variable
|
||||
*
|
||||
* -> Some developers may wish to validate the registry dataset before locking the registry,
|
||||
* -> A general purpose vaildator, schema vaildator, or similar may wish to reset values back to a known good state (`SetWriteModeCache` + `SetKey`) before locking (`SetWriteModeNone`) an otherwise read only database
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
class IRegistry
|
||||
{
|
||||
public:
|
||||
enum class EWriteMode
|
||||
{
|
||||
eWriteModeLocked, ///
|
||||
eWriteModeFileBuffer, /// Write to cache only
|
||||
eWriteModeFileStream, /// [Default] write database to disk on each set, saving to cache
|
||||
};
|
||||
|
||||
enum class EReadType
|
||||
{
|
||||
eClearCacheAndStore,
|
||||
eStoreNew,
|
||||
eStoreAll
|
||||
};
|
||||
|
||||
virtual bool Read(const AuString &path, EReadType read) = 0;
|
||||
|
||||
/**
|
||||
* Puts the registry in read only mode
|
||||
*/
|
||||
virtual void SetWriteModeNone() = 0; /// read only, eqiv of ForEach((key) => { LockKey(key) }; SetWriteModeCache();
|
||||
|
||||
/**
|
||||
* Puts the registry in an in memory only mode.
|
||||
* -> Permit local read/write updates
|
||||
* -> Never allows SetKeys to write manipulated sates to an IO buffer or stream until sanitized or otherwise explicitly written back
|
||||
*/
|
||||
virtual void SetWriteModeCache() = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Puts the registry in a live write mode
|
||||
*/
|
||||
virtual void SetWriteModeStream(const AuOptional<AuString> &path) = 0;
|
||||
|
||||
/**
|
||||
* Puts the registry in a write-back-like mode
|
||||
*/
|
||||
virtual void SetWriteModeBuffered(const AuOptional<AuString> &path) = 0;
|
||||
virtual void WriteAllCacheBack() = 0; /// eqiv of ForEach((key) => { WriteKey(key, GetKey(key)); }; writes all updated cache entries back to io buffer or stream
|
||||
virtual void SaveBuffered() = 0;
|
||||
|
||||
/**
|
||||
* Saves the current state of the registry
|
||||
*/
|
||||
virtual void SaveAll(const AuOptional<AuString> &path) = 0;
|
||||
|
||||
/**
|
||||
* Further calls to SetKeys will; update a database on write, if buffered; or write to a buffer and serialize on flush (`SaveBuffered`)
|
||||
*/
|
||||
virtual void OpenSave(const AuString &path, bool buffered = false) = 0;
|
||||
|
||||
/**
|
||||
* equiv Read(path, EReadType::eClearCacheAndStore)
|
||||
*/
|
||||
virtual void OpenRead(const AuString &path) = 0;
|
||||
|
||||
/**
|
||||
* equiv Read(path, EReadType::eClearCacheAndStore), OpenSave(path, false)
|
||||
*/
|
||||
virtual void OpenReadWriteback(const AuString &path) = 0;
|
||||
|
||||
virtual void CloseSave() = 0;
|
||||
|
||||
virtual bool KeyExists(const AuString &key, RegistryType &type) = 0;
|
||||
virtual bool GetOrCreateKey(const AuString &key, const RegistryValue &def, RegistryValue &value) = 0;
|
||||
|
||||
/**
|
||||
* Write a key, to cache or to disk
|
||||
*/
|
||||
virtual bool SetKey(const AuString &key, const RegistryValue &value) = 0;
|
||||
|
||||
/**
|
||||
* Read key from cache
|
||||
*/
|
||||
virtual bool GetKey(const AuString &key, RegistryValue &value) = 0;
|
||||
|
||||
virtual void LockKey(const AuString &str) = 0;
|
||||
virtual void UnlockKey(const AuString &str) = 0;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
inline void Lock()
|
||||
{
|
||||
SetWriteModeCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
inline void Unlock()
|
||||
{
|
||||
OpenSave({}, false);
|
||||
}
|
||||
};
|
||||
}
|
@ -14,5 +14,5 @@
|
||||
|
||||
namespace Aurora::Registry
|
||||
{
|
||||
AUKN_SHARED_API(Registry, IRegistry, ERegistrySource source, const AuString &name);
|
||||
AUKN_SHARED_API(Registry, IRegistry, ERegistrySource source);
|
||||
}
|
@ -19,19 +19,20 @@
|
||||
|
||||
#include "../AuroraMacros.hpp"
|
||||
|
||||
#if defined(_AUHAS_ASIO)
|
||||
#include <asio.hpp>
|
||||
#endif
|
||||
|
||||
#include <optional>
|
||||
#include <functional>
|
||||
|
||||
#include "../AuroraTypedefs.hpp"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#if defined(_AUHAS_FMT)
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/chrono.h>
|
||||
#endif
|
||||
|
||||
#if !defined(_AUHAS_UUID)
|
||||
#error Missing stduuid library
|
||||
#endif
|
||||
#include <uuid.h>
|
||||
|
||||
#define AUKN_SHARED_API(name, type, ...) AU_SHARED_API_EX(AUKN_SYM, name, type, ## __VA_ARGS__)
|
||||
@ -99,35 +100,66 @@ namespace Aurora
|
||||
|
||||
struct ConsoleConfig
|
||||
{
|
||||
LocalLogInfo logging;
|
||||
|
||||
bool disableAll {};
|
||||
/// Enables Aurora::Console::xxxStd functions; defer to enableStdXX for default logger behaviour
|
||||
bool enableStdPassthrough {};
|
||||
|
||||
/// Disables standard, debug, and GUI consoles
|
||||
bool disableAllConsoles {};
|
||||
|
||||
/// Attempt to force a terminal emulator host under graphical subsystems
|
||||
bool forceConsoleWindow {};
|
||||
|
||||
/// Attempt to force a GUI console under command line targets
|
||||
bool forceToolKitWindow {};
|
||||
|
||||
/// In conjunction with enableStdPassthrough, enables Aurora::Console::ReadStd to read binary
|
||||
/// In conjunction with !enableStdPassthrough, enables stdout logging
|
||||
bool enableStdIn {true};
|
||||
|
||||
bool attemptDarkTheme {true};
|
||||
/// In conjunction with enableStdPassthrough, enables Aurora::Console::WriteStd to write binary
|
||||
/// In conjunction with !enableStdPassthrough, enables stdin logger
|
||||
bool enableStdOut {true};
|
||||
|
||||
/// Use WxWidgets when possible
|
||||
bool enableWxWidgets {true};
|
||||
|
||||
/// FIO config
|
||||
LocalLogInfo fio;
|
||||
|
||||
AuString supportPublic {"https://jira.reece.sx"};
|
||||
AuString titleBrand = "Aurora SDK Sample";
|
||||
|
||||
AuString supportPublic {"https://git.reece.sx/AuroraSupport/AuroraRuntime/issues"};
|
||||
AuString supportInternal {"https://jira.reece.sx"};
|
||||
};
|
||||
|
||||
struct CryptoConfig
|
||||
{
|
||||
/// Defer to the rationales in the implementation
|
||||
bool allowChineseCerts {false};
|
||||
|
||||
/// Defer to the rationales in the implementation
|
||||
bool allowRussianCerts {true};
|
||||
|
||||
/// WIP
|
||||
bool allowHTTPRetrievalOfCerts {true};
|
||||
|
||||
///
|
||||
bool enablePinning {true};
|
||||
|
||||
bool allowHTTPRetrievalOfCerts {true};
|
||||
bool enablePinning {true};
|
||||
///
|
||||
AuList<AuString> blacklistedCerts{};
|
||||
AuList<AuString> whitelistedCerts{};
|
||||
};
|
||||
|
||||
struct AsyncConfig
|
||||
{
|
||||
AuUInt32 schedularFrequency {2}; // * 0.5 or 1 MS depending on the platform
|
||||
AuUInt32 sysPumpFrequency {10}; // x amount of schedularFrequencys
|
||||
AuUInt32 schedularFrequency {2}; // * 0.5 or 1 MS depending on the platform
|
||||
AuUInt32 sysPumpFrequency {25}; // x amount of schedularFrequencys
|
||||
};
|
||||
|
||||
struct FIOConfig
|
||||
{
|
||||
AuOptional<AuString> defaultBrand = "Aurora";
|
||||
};
|
||||
|
||||
struct RuntimeStartInfo
|
||||
@ -136,10 +168,11 @@ namespace Aurora
|
||||
CryptoConfig crypto;
|
||||
TelemetryConfig telemetry;
|
||||
AsyncConfig async;
|
||||
FIOConfig fio;
|
||||
};
|
||||
|
||||
AUKN_SYM void RuntimeStart(const RuntimeStartInfo &info);
|
||||
AUKN_SYM void RuntimeOverloadLocality(const AuPair<AuString, AuString> &locality);
|
||||
AUKN_SYM void RuntimeShutdown();
|
||||
|
||||
AUKN_SYM void RuntimeSysPump();
|
||||
}
|
@ -12,20 +12,68 @@ namespace Aurora::Threading
|
||||
template<typename T>
|
||||
class LockGuard
|
||||
{
|
||||
private:
|
||||
using Internal_t = std::remove_pointer_t<T>;
|
||||
|
||||
public:
|
||||
LockGuard(Aurora::Memory::MemRef<T> lock) : lockReference_(lock)
|
||||
|
||||
LockGuard(T &lock)
|
||||
{
|
||||
lockReference_->Lock();
|
||||
if constexpr (std::is_pointer_v<T>)
|
||||
{
|
||||
annoying_ = lock;
|
||||
}
|
||||
else
|
||||
{
|
||||
annoying_ = &lock;
|
||||
}
|
||||
|
||||
if constexpr (AuIsBaseOfTemplate<AURORA_RUNTIME_AU_SHARED_PTR, Internal_t>::value || AuIsBaseOfTemplate<AURORA_RUNTIME_AU_UNIQUE_PTR, Internal_t>::value)
|
||||
{
|
||||
annoying_->get()->Lock();
|
||||
}
|
||||
else
|
||||
{
|
||||
annoying_->Lock();
|
||||
}
|
||||
}
|
||||
|
||||
LockGuard(T &&lock)
|
||||
{
|
||||
if constexpr (std::is_pointer_v<T>)
|
||||
{
|
||||
annoying_ = lock;
|
||||
}
|
||||
else
|
||||
{
|
||||
annoying_ = &lock;
|
||||
}
|
||||
|
||||
if constexpr (AuIsBaseOfTemplate<AURORA_RUNTIME_AU_SHARED_PTR, Internal_t>::value || AuIsBaseOfTemplate<AURORA_RUNTIME_AU_UNIQUE_PTR, Internal_t>::value)
|
||||
{
|
||||
annoying_->get()->Lock();
|
||||
}
|
||||
else
|
||||
{
|
||||
annoying_->Lock();
|
||||
}
|
||||
}
|
||||
|
||||
~LockGuard()
|
||||
{
|
||||
lockReference_->Unlock();
|
||||
if constexpr (AuIsBaseOfTemplate<AURORA_RUNTIME_AU_SHARED_PTR, Internal_t>::value || AuIsBaseOfTemplate<AURORA_RUNTIME_AU_UNIQUE_PTR, Internal_t>::value)
|
||||
{
|
||||
annoying_->get()->Unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
annoying_->Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Aurora::Memory::MemRef<T> lockReference_;
|
||||
std::conditional_t<std::is_pointer_v<T>, T, T*> annoying_;
|
||||
};
|
||||
|
||||
using WaitableLockGuard = LockGuard<IWaitable>;
|
||||
|
||||
#define AU_LOCK_GUARD(variable) Aurora::Threading::LockGuard<decltype(variable)> AU_CONCAT(__stack_lock, __COUNTER__) (variable);
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: LockGuardPtr.hpp
|
||||
Date: 2021-6-10
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Threading
|
||||
{
|
||||
template<typename T>
|
||||
class LockGuardPtr
|
||||
{
|
||||
public:
|
||||
LockGuardPtr(T *lock) : annoying_(lock)
|
||||
{
|
||||
lock->Lock();
|
||||
}
|
||||
|
||||
LockGuardPtr(T &lock) : annoying_(&lock)
|
||||
{
|
||||
lock->Lock();
|
||||
}
|
||||
|
||||
~LockGuardPtr()
|
||||
{
|
||||
if constexpr (is_base_of_template<std::shared_ptr, T>::value || is_base_of_template<std::unique_ptr, T>::value)
|
||||
{
|
||||
annoying_->get()->Unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
annoying_->Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
T *annoying_;
|
||||
};
|
||||
}
|
@ -14,6 +14,27 @@ namespace Aurora::Threading::Primitives
|
||||
public:
|
||||
virtual IWaitable *AsReadable() = 0;
|
||||
virtual IWaitable *AsWritable() = 0;
|
||||
|
||||
/**
|
||||
* Solves the problem of atomic write racing
|
||||
* Consider: Thread 1 | Thread 2
|
||||
* ReadLock() |
|
||||
* cmp internal_x, 0|
|
||||
* jmp not eq +1 |
|
||||
* ret |
|
||||
* ReadUnlock() |
|
||||
* | WriteLock()
|
||||
* | internal_x = 1
|
||||
* | WriteUnlock()
|
||||
* WriteLock() |
|
||||
* internal_x = 0 |
|
||||
* WriteUnlock()
|
||||
*
|
||||
* where 1 and 0 should have been decided on mutually exclusively, losing the 1 state while assuming a decision in the locked state would remain true
|
||||
* workaround: [1] check for the race conditions, implmeneting slow and inefficient branching and spurious checks
|
||||
* workaround: [2] upgrade from read to write
|
||||
*/
|
||||
virtual bool UpgradeReadToWrite(AuUInt64 timeout) = 0;
|
||||
};
|
||||
|
||||
AUKN_SHARED_API(RWLock, RWLock);
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "Sleep.hpp"
|
||||
|
||||
#include "LockGuard.hpp"
|
||||
#include "LockGuardPtr.hpp"
|
||||
|
||||
#include "Threads/Threads.hpp"
|
||||
|
||||
|
41
Include/Aurora/Threading/Threads/IAuroraThread.hpp
Normal file
41
Include/Aurora/Threading/Threads/IAuroraThread.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: IAuroraThread.hpp
|
||||
Date: 2021-8-28
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Threading::Threads
|
||||
{
|
||||
class TLSView;
|
||||
|
||||
/// Threads may be reimplemented as fibers or under some other userland context switcher
|
||||
class IAuroraThread
|
||||
{
|
||||
public:
|
||||
virtual bool Run() = 0;
|
||||
virtual void Exit() = 0;
|
||||
virtual bool Exiting() = 0;
|
||||
virtual void SendExitSignal() = 0;
|
||||
|
||||
virtual void SetPrio(EThreadPrio prio) = 0;
|
||||
virtual void SetAffinity(AuUInt32 mask) = 0;
|
||||
virtual void SetName(const AuString &name) = 0;
|
||||
|
||||
virtual EThreadPrio GetPrio() = 0;
|
||||
virtual AuUInt32 GetMask() = 0;
|
||||
virtual AuString GetName() = 0;
|
||||
|
||||
/// Registers a thread feature _not_ calling on init
|
||||
/// It is not possible for this lower level thread object to schedule an init call (defer to async)
|
||||
/// Use this to register teardown functions
|
||||
virtual void AddLastHopeTlsHook(const AuSPtr<Threading::Threads::IThreadFeature> &feature) = 0;
|
||||
|
||||
virtual AuSPtr<TLSView> GetTlsView() = 0;
|
||||
|
||||
virtual void ExecuteInDeadThread(std::function<void()> callback) = 0;
|
||||
virtual AuSPtr<IWaitable> AsWaitable() = 0;
|
||||
};
|
||||
}
|
@ -7,41 +7,15 @@
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
#include "AbstractThreadVectors.hpp"
|
||||
|
||||
namespace Aurora::Threading::Threads
|
||||
{
|
||||
class TLSView;
|
||||
|
||||
|
||||
/// Threads may be reimplemented as fibers or under some other userland context switcher
|
||||
class IAuroraThread
|
||||
{
|
||||
public:
|
||||
virtual void Run() = 0;
|
||||
virtual void Exit() = 0;
|
||||
virtual bool Exiting() = 0;
|
||||
virtual void SendExitSignal() = 0;
|
||||
|
||||
virtual void SetPrio(EThreadPrio prio) = 0;
|
||||
virtual void SetAffinity(AuUInt32 mask) = 0;
|
||||
virtual void SetName(const AuString &name) = 0;
|
||||
|
||||
virtual EThreadPrio GetPrio() = 0;
|
||||
virtual AuUInt32 GetMask() = 0;
|
||||
virtual AuString GetName() = 0;
|
||||
|
||||
virtual AuSPtr<TLSView> GetTlsView() = 0;
|
||||
|
||||
virtual void ExecuteInDeadThread(std::function<void()> callback) = 0;
|
||||
virtual IWaitable * AsWaitable() = 0;
|
||||
};
|
||||
|
||||
AUKN_SYM IAuroraThread *GetThread();
|
||||
AUKN_SYM AuThreadId_t GetThreadId();
|
||||
AUKN_SYM AuThreadId_t GetThreadId();
|
||||
|
||||
AUKN_SYM void TerminateCurrent();
|
||||
|
||||
/**
|
||||
Constructs a thread instance given a set of callbacks
|
||||
*/
|
||||
AUKN_SHARED_API(Thread, IAuroraThread, const AbstractThreadVectors &vectors);
|
||||
AUKN_SHARED_API(Thread, IAuroraThread, const ThreadInfo &info);
|
||||
}
|
22
Include/Aurora/Threading/Threads/ThreadInfo.hpp
Normal file
22
Include/Aurora/Threading/Threads/ThreadInfo.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: ThreadInfo.hpp
|
||||
Date: 2021-8-28
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Threading::Threads
|
||||
{
|
||||
struct ThreadInfo
|
||||
{
|
||||
const AbstractThreadVectors &vectors;
|
||||
|
||||
ThreadInfo(const AbstractThreadVectors &vectors) : vectors(vectors)
|
||||
{}
|
||||
|
||||
AuOptional<AuUInt32> stackSize;
|
||||
AuOptional<AuString> name;
|
||||
};
|
||||
}
|
@ -10,6 +10,8 @@
|
||||
#include "IThreadFeature.hpp"
|
||||
#include "EThreadPrio.hpp"
|
||||
#include "AbstractThreadVectors.hpp"
|
||||
#include "IAuroraThread.hpp"
|
||||
#include "ThreadInfo.hpp"
|
||||
#include "Thread.hpp"
|
||||
#include "TLSView.hpp"
|
||||
#include "TLSVariable.hpp"
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
namespace Aurora::Time
|
||||
{
|
||||
#if ((defined(AU_FORCE_BENCHMARK) || defined(DEBUG) || defined(INTERNAL)) && (!defined(AU_FORCE_NOBENCHMARK)))
|
||||
#if ((defined(AU_FORCE_BENCHMARK) || defined(DEBUG) || defined(STAGING)) && (!defined(AU_FORCE_NOBENCHMARK)))
|
||||
|
||||
class DebugBenchmark
|
||||
{
|
||||
|
@ -7,16 +7,21 @@
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
#define AU_NO_COPY(type) type(type&) = delete;
|
||||
#define AU_NO_MOVE(type) type(type&&) = delete;
|
||||
#define AU_NO_COPY(type) type(type&) = delete;
|
||||
#define AU_NO_MOVE(type) type(type&&) = delete;
|
||||
#define AU_NO_COPY_NO_MOVE(type) AU_NO_COPY(type) AU_NO_MOVE(type)
|
||||
|
||||
#define AU_SHARED_FROM_THIS (std::static_pointer_cast<std::remove_pointer_t<decltype(this)>>(this->shared_from_this()))
|
||||
#define AU_WEAK_FROM_THIS (AuWPtr<std::remove_pointer_t<decltype(this)>>(std::static_pointer_cast<std::remove_pointer_t<decltype(this)>>(this->shared_from_this())))
|
||||
#define AU_SHARED_FROM_THIS (std::static_pointer_cast<std::remove_pointer_t<decltype(this)>>(this->shared_from_this()))
|
||||
#define AU_WEAK_FROM_THIS (AuWPtr<std::remove_pointer_t<decltype(this)>>(std::static_pointer_cast<std::remove_pointer_t<decltype(this)>>(this->shared_from_this())))
|
||||
|
||||
/// @hideinitializer
|
||||
#define AU_STRINGIFY_(in) #in
|
||||
#define AU_STRINGIFY(in) AU_STRINGIFY_(in)
|
||||
|
||||
/// @hideinitializer
|
||||
#define AU_CONCAT_(a, b) a ## b
|
||||
#define AU_CONCAT(a, b) AU_CONCAT_(a, b)
|
||||
|
||||
/// @hideinitializer
|
||||
#define _AUKCON_STRINGIFY_X(in) AU_STRINGIFY(in)
|
||||
|
||||
@ -37,7 +42,7 @@ struct CppDeleter ## name \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
using name ## Unique_t = std::unique_ptr<type, CppDeleter ## name>; \
|
||||
using name ## Unique_t = AURORA_RUNTIME_AU_UNIQUE_PTR<type, CppDeleter ## name>; \
|
||||
template<typename ... T> \
|
||||
name ## Unique_t name ## Unique(T... args) \
|
||||
{ \
|
||||
@ -59,6 +64,12 @@ name ## Shared_t name ## Shared(T... args) \
|
||||
#define AU_NOINLINE __attribute__((noinline))
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_COMPILER_MSVC)
|
||||
#define AU_INLINE __declspec(__forceinline)
|
||||
#else
|
||||
#define AU_INLINE __attribute__((always_inline))
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_COMPILER_MSVC)
|
||||
#define AU_NORETURN __declspec(noreturn)
|
||||
#else
|
||||
|
@ -5,4 +5,5 @@
|
||||
Date: 2021-6-9
|
||||
Author: Reece
|
||||
***/
|
||||
#include <AuroraCommon.hpp>
|
||||
#include "Aurora/Runtime.hpp"
|
@ -7,14 +7,31 @@
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#if !defined(AURORA_RUNTINE_TYPEDEFS_INCLUDE)
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#else
|
||||
#if defined(AURORA_RUNTINE_TYPEDEFS_INCLUDE_HEADER)
|
||||
#include <AURORA_RUNTINE_TYPEDEFS_INCLUDE_HEADER>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(AURORA_RUNTIME_AU_LIST)
|
||||
#define AURORA_RUNTIME_AU_LIST std::vector
|
||||
#endif
|
||||
|
||||
#if defined(_CPPSHARP)
|
||||
|
||||
template<typename T>
|
||||
using AuList = AURORA_RUNTIME_AU_LIST<T>;
|
||||
|
||||
#else
|
||||
|
||||
namespace Aurora::Memory
|
||||
{
|
||||
@ -22,27 +39,58 @@ namespace Aurora::Memory
|
||||
struct SpeedyArrayAllocator;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
using AuList = typename std::conditional<std::is_class<T>::value, AURORA_RUNTIME_AU_LIST<T>, AURORA_RUNTIME_AU_LIST<T, Aurora::Memory::SpeedyArrayAllocator<T>>>::type;
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(AURORA_RUNTIME_AU_HASH_MAP)
|
||||
#define AURORA_RUNTIME_AU_HASH_MAP std::unordered_map
|
||||
#endif
|
||||
|
||||
template<typename T, typename Z>
|
||||
using AuHashMap = AURORA_RUNTIME_AU_HASH_MAP<T, Z>;
|
||||
|
||||
template<typename T, typename Z, class Utility>
|
||||
using AuHashMapEx = AURORA_RUNTIME_AU_HASH_MAP<T, Z, Utility, Utility>;
|
||||
|
||||
#if !defined(AURORA_RUNTIME_AU_BST)
|
||||
#define AURORA_RUNTIME_AU_BST std::map
|
||||
#endif
|
||||
|
||||
template<typename T, typename Z>
|
||||
using AuBST = AURORA_RUNTIME_AU_BST<T, Z>;
|
||||
|
||||
template<typename T, typename Z, class Utility>
|
||||
using AuBSTEx = AURORA_RUNTIME_AU_BST<T, Z, Utility>;
|
||||
|
||||
#if !defined(AURORA_RUNTIME_AU_SHARED_PTR)
|
||||
#define AURORA_RUNTIME_AU_SHARED_PTR std::shared_ptr
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
using AuList = typename std::conditional<std::is_class<T>::value, std::vector<T>, std::vector<T, Aurora::Memory::SpeedyArrayAllocator<T>>>::type;
|
||||
using AuSPtr = AURORA_RUNTIME_AU_SHARED_PTR<T>;
|
||||
|
||||
template<class T, class Z>
|
||||
using AuHashMap = std::unordered_map<T, Z>;
|
||||
#if !defined(AURORA_RUNTIME_AU_WEAK_PTR)
|
||||
#define AURORA_RUNTIME_AU_WEAK_PTR std::weak_ptr
|
||||
#endif
|
||||
|
||||
template<class T, class Z, class Utility>
|
||||
using AuHashMapEx = std::unordered_map<T, Z, Utility, Utility>;
|
||||
template<typename T>
|
||||
using AuWPtr = AURORA_RUNTIME_AU_WEAK_PTR<T>;
|
||||
|
||||
template<class T, class Z>
|
||||
using AuBST = std::map<T, Z>;
|
||||
#if !defined(AURORA_RUNTIME_AU_UNIQUE_PTR)
|
||||
#define AURORA_RUNTIME_AU_UNIQUE_PTR std::unique_ptr
|
||||
#endif
|
||||
|
||||
template<class T, class Z, class Utility>
|
||||
using AuBSTEx = std::map<T, Z, Utility>;
|
||||
template<typename T, typename Deleter_t>
|
||||
using AuUPtr = AURORA_RUNTIME_AU_UNIQUE_PTR<T, Deleter_t>;
|
||||
|
||||
template<class T>
|
||||
using AuSPtr = std::shared_ptr<T>;
|
||||
#if !defined(AURORA_RUNTIME_AU_PAIR)
|
||||
#define AURORA_RUNTIME_AU_PAIR std::pair
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
using AuWPtr = std::weak_ptr<T>;
|
||||
template<typename A_t, typename B_t>
|
||||
using AuPair = AURORA_RUNTIME_AU_PAIR<A_t, B_t>;
|
||||
|
||||
#if defined(AURORA_COMPILER_MSVC)
|
||||
using AuAtomicInt = long;
|
||||
@ -50,10 +98,18 @@ using AuAtomicInt = long;
|
||||
using AuAtomicInt = int;
|
||||
#endif
|
||||
|
||||
#if !defined(AURORA_RUNTIME_AU_OPTIONAL)
|
||||
#define AURORA_RUNTIME_AU_OPTIONAL std::optional
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
using AuOptional = AURORA_RUNTIME_AU_OPTIONAL<T>;
|
||||
|
||||
//#include "tinyutf8.h"
|
||||
|
||||
using AuString = std::string;// tiny_utf8::utf8_string;
|
||||
|
||||
|
||||
using AuUInt64 = Aurora::Types::uint64_t;
|
||||
using AuUInt32 = Aurora::Types::uint32_t;
|
||||
using AuUInt16 = Aurora::Types::uint16_t;
|
||||
@ -61,11 +117,45 @@ using AuUInt8 = Aurora::Types::uint8_t;
|
||||
using AuInt64 = Aurora::Types::int64_t;
|
||||
using AuInt32 = Aurora::Types::int32_t;
|
||||
using AuInt16 = Aurora::Types::int16_t;
|
||||
|
||||
#if defined(_CPPSHARP)
|
||||
using AuInt8 = Aurora::Types::uint8_t;
|
||||
#else
|
||||
using AuInt8 = Aurora::Types::int8_t;
|
||||
#endif
|
||||
using AuMach = Aurora::Types::size_t;
|
||||
using AuSMach = Aurora::Types::ssize_t;
|
||||
using AuSInt = AuSMach;
|
||||
using AuUInt = AuMach;
|
||||
|
||||
using AuStreamReadWrittenPair_t = AuPair<AuUInt32, AuUInt32>;
|
||||
|
||||
using AuThreadId_t = AuUInt64;
|
||||
static const AuThreadId_t kThreadIdSpecialMask = AuThreadId_t(1) << AuThreadId_t(63);
|
||||
static const AuThreadId_t kThreadIdSpecialMask = AuThreadId_t(1) << AuThreadId_t(63);
|
||||
|
||||
#if defined(__has_include) && !defined(_AUHAS_GLM)
|
||||
#if __has_include(<glm/glm.hpp>)
|
||||
#define _AUHAS_GLM
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(_AUHAS_GLM)
|
||||
template<int N>
|
||||
struct AuFVec
|
||||
{
|
||||
float elements[N];
|
||||
|
||||
float &operator [](int idx) const
|
||||
{
|
||||
return elements[N];
|
||||
}
|
||||
};
|
||||
|
||||
using AuVec3 = AuFVec<3>;
|
||||
using AuVec4 = AuFVec<4>;
|
||||
#else
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
using AuVec3 = glm::vec3;
|
||||
using AuVec4 = glm::vec4;
|
||||
#endif
|
||||
|
@ -7,18 +7,56 @@
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
#if !defined(AURORA_RUNTIME_MAKE_SHARED)
|
||||
#define AURORA_RUNTIME_MAKE_SHARED std::make_shared
|
||||
#endif
|
||||
|
||||
template<typename T, typename... Args>
|
||||
static inline AuSPtr<T> AuMakeShared(Args... args)
|
||||
{
|
||||
return AURORA_RUNTIME_MAKE_SHARED<T>(args...);
|
||||
}
|
||||
|
||||
#if !defined(AURORA_RUNTIME_MAKE_PAIR)
|
||||
#define AURORA_RUNTIME_MAKE_PAIR std::make_pair
|
||||
#endif
|
||||
|
||||
template<typename... Args>
|
||||
static inline auto AuMakePair(Args... args)
|
||||
{
|
||||
return AURORA_RUNTIME_MAKE_PAIR(args...);
|
||||
}
|
||||
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
static inline void AuWin32CloseHandle(HANDLE &handle)
|
||||
{
|
||||
HANDLE local;
|
||||
|
||||
if ((local = std::exchange(handle, INVALID_HANDLE_VALUE)) != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle(local);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
static AuSPtr<T> AuUnsafeRaiiToShared(T *in)
|
||||
{
|
||||
return AuSPtr<T>(in, [](T *){});
|
||||
}
|
||||
|
||||
template<typename T, int Z>
|
||||
static constexpr int ArraySize(const T(&array)[Z])
|
||||
static constexpr int AuArraySize(const T(&array)[Z])
|
||||
{
|
||||
return Z;
|
||||
}
|
||||
|
||||
#if defined(DEBUG) || defined(INTERNAL)
|
||||
#if defined(DEBUG) || defined(STAGING)
|
||||
|
||||
template<typename Z, typename T>
|
||||
static void inline SafeDelete(T *in)
|
||||
{
|
||||
static_assert(std::is_base_of<T, std::remove_pointer<Z>::type>::value);
|
||||
static_assert(std::is_base_of<T, std::remove_pointer<Z>::type>::value, "Couldn't not safe delete from type T because it is not derived from Z");
|
||||
auto cast = dynamic_cast<Z>(in);
|
||||
if (cast == nullptr)
|
||||
{
|
||||
@ -33,49 +71,102 @@ static void inline SafeDelete(T *in)
|
||||
template<typename Z, typename T>
|
||||
static void inline SafeDelete(T *in)
|
||||
{
|
||||
static_assert(std::is_base_of<T, std::remove_pointer<Z>::type>::value);
|
||||
static_assert(std::is_base_of<T, std::remove_pointer<Z>::type>::value, "Couldn't not safe delete from type T because it is not derived from Z");
|
||||
delete static_cast<Z>(in);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static inline AuUInt64 ConvertMagicTag64(const char buffer[8])
|
||||
static constexpr inline AuUInt32 AuConvertMagicTag32(const char buffer[4])
|
||||
{
|
||||
return *reinterpret_cast<const AuUInt64 *>(buffer);
|
||||
AuUInt32 magic {};
|
||||
if (Aurora::Build::kCurrentEndian == Aurora::Build::ECPUEndian::eCPULittle)
|
||||
{
|
||||
magic |= AuUInt32(buffer[0]);
|
||||
magic |= AuUInt32(buffer[1]) << 8;
|
||||
magic |= AuUInt32(buffer[2]) << 16;
|
||||
magic |= AuUInt32(buffer[3]) << 24;
|
||||
// LE will look alright in memory dumps
|
||||
// MSFT uses tags that read back the initial string value when read back hex ints
|
||||
// I prefer binary streams and file headers contain a 4x or 8x ascii char headers (eg. LuaX)
|
||||
}
|
||||
else
|
||||
{
|
||||
// Lazy reinterpret cast reads will always be flipped
|
||||
// Assume byte buffers read/write machine endian
|
||||
// Assume *reinterpret_cast<T*> returns machine endian
|
||||
// BE needs to be flipped in memory
|
||||
// BE will look fine in memory dumps
|
||||
// BE will also look fine in stack/variable dumps when printed in hex
|
||||
magic |= AuUInt32(buffer[4]);
|
||||
magic |= AuUInt32(buffer[2]) << 8;
|
||||
magic |= AuUInt32(buffer[1]) << 16;
|
||||
magic |= AuUInt32(buffer[0]) << 24;
|
||||
}
|
||||
// Determinstic across platforms, perhaps unexpected by endian normalized streams
|
||||
// When asserting read(noEndian) against a tag, an endian swap would cause the
|
||||
// assertion to fail, thus providing you with the endian match check
|
||||
// This step is delegated to a de-facto machine endian buffer builder
|
||||
// ByteBuffers that normalize for endianness continue to work with tags
|
||||
// irrespective of reader/writer endianness
|
||||
return magic;
|
||||
}
|
||||
|
||||
static inline AuUInt32 ConvertMagicTag32(const char buffer[4])
|
||||
static constexpr inline AuUInt64 AuConvertMagicTag64(const char buffer[8])
|
||||
{
|
||||
return *reinterpret_cast<const AuUInt32 *>(buffer);
|
||||
AuUInt64 magic {};
|
||||
if (Aurora::Build::kCurrentEndian == Aurora::Build::ECPUEndian::eCPULittle)
|
||||
{
|
||||
magic |= AuUInt64(buffer[0]);
|
||||
magic |= AuUInt64(buffer[1]) << 8;
|
||||
magic |= AuUInt64(buffer[2]) << 16;
|
||||
magic |= AuUInt64(buffer[3]) << 24;
|
||||
magic |= AuUInt64(buffer[4]) << 32;
|
||||
magic |= AuUInt64(buffer[5]) << 40;
|
||||
magic |= AuUInt64(buffer[6]) << 48;
|
||||
magic |= AuUInt64(buffer[7]) << 56;
|
||||
}
|
||||
else
|
||||
{
|
||||
magic |= AuUInt64(buffer[7]);
|
||||
magic |= AuUInt64(buffer[6]) << 8;
|
||||
magic |= AuUInt64(buffer[5]) << 16;
|
||||
magic |= AuUInt64(buffer[4]) << 24;
|
||||
magic |= AuUInt64(buffer[3]) << 32;
|
||||
magic |= AuUInt64(buffer[2]) << 40;
|
||||
magic |= AuUInt64(buffer[1]) << 48;
|
||||
magic |= AuUInt64(buffer[0]) << 56;
|
||||
}
|
||||
return magic;
|
||||
}
|
||||
|
||||
template<typename T, typename Z>
|
||||
static inline std::optional<AuSPtr<T>> OptionalSharedDynamicCast(std::optional<AuSPtr<Z>> &in)
|
||||
static inline AuOptional<AuSPtr<T>> AuOptionalSharedDynamicCast(AuOptional<AuSPtr<Z>> &in)
|
||||
{
|
||||
if (!in.has_value()) return {};
|
||||
return std::dynamic_pointer_cast<T>(in.value());
|
||||
}
|
||||
|
||||
template<typename T, typename Z>
|
||||
static inline std::optional<AuSPtr<T>> OptionalSharedStaticCast(std::optional<AuSPtr<Z>> &in)
|
||||
static inline AuOptional<AuSPtr<T>> AuOptionalSharedStaticCast(AuOptional<AuSPtr<Z>> &in)
|
||||
{
|
||||
if (!in.has_value()) return {};
|
||||
return std::static_pointer_cast<T>(in.value());
|
||||
}
|
||||
|
||||
static inline bool EndsWith(std::string const &value, std::string const &ending)
|
||||
static inline bool AuEndsWith(std::string const &value, std::string const &ending)
|
||||
{
|
||||
if (ending.size() > value.size()) return false;
|
||||
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
|
||||
}
|
||||
|
||||
static inline bool StartsWith(std::string const &value, std::string const &starting)
|
||||
static inline bool AuStartsWith(std::string const &value, std::string const &starting)
|
||||
{
|
||||
return value.rfind(starting, 0) == 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline AuString ToStringASCIIOp(T op, const AuString &in)
|
||||
static inline AuString AuToStringASCIIOp(T op, const AuString &in)
|
||||
{
|
||||
AuString ret;
|
||||
ret.resize(in.size());
|
||||
@ -86,18 +177,18 @@ static inline AuString ToStringASCIIOp(T op, const AuString &in)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline AuString ToLower(const AuString &in)
|
||||
static inline AuString AuToLower(const AuString &in)
|
||||
{
|
||||
return ToStringASCIIOp<int(*)(int)>(std::tolower, in);
|
||||
return AuToStringASCIIOp<int(*)(int)>(std::tolower, in);
|
||||
}
|
||||
|
||||
static inline AuString ToUpper(const AuString &in)
|
||||
static inline AuString AuToUpper(const AuString &in)
|
||||
{
|
||||
return ToStringASCIIOp<int(*)(int)>(std::toupper, in);
|
||||
return AuToStringASCIIOp<int(*)(int)>(std::toupper, in);
|
||||
}
|
||||
|
||||
template<typename Map, class Key, typename Value>
|
||||
static inline bool TryFind(Map &map, const Key &key, Value *&ptr)
|
||||
static inline bool AuTryFind(Map &map, const Key &key, Value *&ptr)
|
||||
{
|
||||
auto itr = map.find(key);
|
||||
if (itr != map.end())
|
||||
@ -113,7 +204,7 @@ static inline bool TryFind(Map &map, const Key &key, Value *&ptr)
|
||||
}
|
||||
|
||||
template<typename Map, class Key, typename Value>
|
||||
static inline bool TryFind(Map *map, const Key &key, Value *&ptr)
|
||||
static inline bool AuTryFind(Map *map, const Key &key, Value *&ptr)
|
||||
{
|
||||
auto itr = map->find(key);
|
||||
if (itr != map->end())
|
||||
@ -129,7 +220,7 @@ static inline bool TryFind(Map *map, const Key &key, Value *&ptr)
|
||||
}
|
||||
|
||||
template<typename Map, class Key>
|
||||
static inline bool TryFind(Map &map, const Key &key)
|
||||
static inline bool AuTryFind(Map &map, const Key &key)
|
||||
{
|
||||
auto itr = map.find(key);
|
||||
if (itr != map.end())
|
||||
@ -143,7 +234,7 @@ static inline bool TryFind(Map &map, const Key &key)
|
||||
}
|
||||
|
||||
template<typename Map, class Key>
|
||||
static inline bool TryFind(Map *map, const Key &key)
|
||||
static inline bool AuTryFind(Map *map, const Key &key)
|
||||
{
|
||||
auto itr = map->find(key);
|
||||
if (itr != map->end())
|
||||
@ -155,8 +246,9 @@ static inline bool TryFind(Map *map, const Key &key)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Map, class Key, typename Value>
|
||||
static inline bool TryFindGeneric(Map &map, const Key &key, Value *&ptr)
|
||||
static inline bool AuTryFindGeneric(Map &map, const Key &key, Value *&ptr)
|
||||
{
|
||||
auto itr = map.find(key);
|
||||
if (itr != map.end())
|
||||
@ -172,7 +264,7 @@ static inline bool TryFindGeneric(Map &map, const Key &key, Value *&ptr)
|
||||
}
|
||||
|
||||
template<typename Map, class Key>
|
||||
static inline bool TryDelete(Map &map, const Key &key)
|
||||
static inline bool AuTryDelete(Map &map, const Key &key)
|
||||
{
|
||||
auto itr = map.find(key);
|
||||
if (itr != map.end())
|
||||
@ -187,7 +279,7 @@ static inline bool TryDelete(Map &map, const Key &key)
|
||||
}
|
||||
|
||||
template<typename List, class Key>
|
||||
static inline bool TryDeleteList(List &list, const Key &key)
|
||||
static inline bool AuTryDeleteList(List &list, const Key &key)
|
||||
{
|
||||
auto itr = std::find(list.begin(), list.end(), key);
|
||||
if (itr != list.end())
|
||||
@ -202,7 +294,7 @@ static inline bool TryDeleteList(List &list, const Key &key)
|
||||
}
|
||||
|
||||
template<typename Container, typename Type>
|
||||
static inline bool TryInsert(Container &container, const Type &value)
|
||||
static inline bool AuTryInsert(Container &container, const Type &value)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -216,7 +308,7 @@ static inline bool TryInsert(Container &container, const Type &value)
|
||||
}
|
||||
}
|
||||
template<typename Container, typename Type>
|
||||
static inline bool TryInsert(Container &container, Type &&value)
|
||||
static inline bool AuTryInsert(Container &container, Type &&value)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -231,7 +323,7 @@ static inline bool TryInsert(Container &container, Type &&value)
|
||||
}
|
||||
|
||||
template<typename Container, typename Type>
|
||||
static inline bool TryInsert(Container *container, const Type &value)
|
||||
static inline bool AuTryInsert(Container *container, const Type &value)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -246,7 +338,7 @@ static inline bool TryInsert(Container *container, const Type &value)
|
||||
}
|
||||
|
||||
template<typename Container, typename Type>
|
||||
static inline bool TryInsert(Container *container, Type &&value)
|
||||
static inline bool AuTryInsert(Container *container, Type &&value)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -261,7 +353,7 @@ static inline bool TryInsert(Container *container, Type &&value)
|
||||
}
|
||||
|
||||
template<typename Container, typename Type>
|
||||
static inline bool TryInsertNoEnd(Container &container, Type &&value) // move
|
||||
static inline bool AuTryInsertNoEnd(Container &container, Type &&value) // move
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -276,7 +368,7 @@ static inline bool TryInsertNoEnd(Container &container, Type &&value) // move
|
||||
}
|
||||
|
||||
template<typename Container, typename Type>
|
||||
static inline bool TryInsertNoEnd(Container &container, const Type &value) // copy
|
||||
static inline bool AuTryInsertNoEnd(Container &container, const Type &value) // copy
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -291,7 +383,7 @@ static inline bool TryInsertNoEnd(Container &container, const Type &value) // co
|
||||
}
|
||||
|
||||
template<typename Container, typename Type>
|
||||
static inline bool TryInsertNoEnd(Container *container, Type &&value) // move
|
||||
static inline bool AuTryInsertNoEnd(Container *container, Type &&value) // move
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -305,9 +397,8 @@ static inline bool TryInsertNoEnd(Container *container, Type &&value) // move
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename Container, typename Type>
|
||||
static inline bool TryInsertNoEnd(Container *container, const Type &value) // copy
|
||||
static inline bool AuTryInsertNoEnd(Container *container, const Type &value) // copy
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -322,7 +413,7 @@ static inline bool TryInsertNoEnd(Container *container, const Type &value) // co
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline bool TryResize(T &list, AuUInt length)
|
||||
static inline bool AuTryResize(T &list, AuUInt length)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -335,7 +426,7 @@ static inline bool TryResize(T &list, AuUInt length)
|
||||
}
|
||||
}
|
||||
|
||||
static inline std::string ReplaceAll(std::string &str, const std::string &from, const std::string &to)
|
||||
static inline std::string AuReplaceAll(std::string &str, const std::string &from, const std::string &to)
|
||||
{
|
||||
size_t start_pos = 0;
|
||||
while ((start_pos = str.find(from, start_pos)) != std::string::npos)
|
||||
@ -347,7 +438,7 @@ static inline std::string ReplaceAll(std::string &str, const std::string &from,
|
||||
}
|
||||
|
||||
// i told myself not to copy this, required a split function twice, now here we are :D
|
||||
static inline AuList<AuString> SplitString(const AuString& str, const AuString& delim, bool ignoreEmpty = true)
|
||||
static inline AuList<AuString> AuSplitString(const AuString& str, const AuString& delim, bool ignoreEmpty = true)
|
||||
{
|
||||
AuList<AuString> tokens;
|
||||
AuUInt prev = 0, pos = 0;
|
||||
@ -365,8 +456,8 @@ static inline AuList<AuString> SplitString(const AuString& str, const AuString&
|
||||
|
||||
// more copy/pasta. work smart, not hard.
|
||||
// i dont want to waste time working out template kinks between clang and msvc
|
||||
template < template <typename...> class base,typename derived>
|
||||
struct is_base_of_template_impl
|
||||
template<template<typename...> class base,typename derived>
|
||||
struct is_base_of_template_impl_au
|
||||
{
|
||||
template<typename... Ts>
|
||||
static constexpr std::true_type test(const base<Ts...> *);
|
||||
@ -375,4 +466,4 @@ struct is_base_of_template_impl
|
||||
};
|
||||
|
||||
template < template <typename...> class base,typename derived>
|
||||
using is_base_of_template = typename is_base_of_template_impl<base,derived>::type;
|
||||
using AuIsBaseOfTemplate = typename is_base_of_template_impl_au<base,derived>::type;
|
@ -28,12 +28,13 @@ namespace Aurora::Async
|
||||
{
|
||||
gAsyncApp.Shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//STATIC_TLS(WorkerId_t, tlsWorkerId);
|
||||
static Threading::Threads::TLSVariable<WorkerId_t, true> tlsWorkerId;
|
||||
|
||||
using WorkEntry_t = std::pair<std::optional<ThreadId_t>, AuSPtr<IAsyncRunnable>>;
|
||||
using WorkEntry_t = AuPair<AuOptional<ThreadId_t>, AuSPtr<IAsyncRunnable>>;
|
||||
|
||||
struct ThreadState
|
||||
{
|
||||
@ -111,7 +112,7 @@ namespace Aurora::Async
|
||||
auto & semaphore = GetThreadState()->syncSema;
|
||||
auto unsafeSemaphore = semaphore.get();
|
||||
|
||||
auto work = std::make_shared</*Async::BasicWorkStdFunc*/AsyncFuncRunnable>(([=]()
|
||||
auto work = AuMakeShared</*Async::BasicWorkStdFunc*/AsyncFuncRunnable>(([=]()
|
||||
{
|
||||
auto state = GetThreadState();
|
||||
|
||||
@ -150,10 +151,10 @@ namespace Aurora::Async
|
||||
IncRunningTasks();
|
||||
|
||||
{
|
||||
Threading::LockGuardPtr lol(state->cvWorkMutex);
|
||||
AU_LOCK_GUARD(state->cvWorkMutex);
|
||||
|
||||
#if defined(INTERNAL) || defined(DEBUG)
|
||||
Threading::LockGuardPtr lock(rwlock_->AsReadable());
|
||||
#if defined(STAGING) || defined(DEBUG)
|
||||
AU_LOCK_GUARD(rwlock_->AsReadable());
|
||||
|
||||
if (target.second.has_value())
|
||||
{
|
||||
@ -187,18 +188,18 @@ namespace Aurora::Async
|
||||
}
|
||||
#endif
|
||||
|
||||
state->workQueue.push_back(std::make_pair(target.second, runnable));
|
||||
state->workQueue.push_back(AuMakePair(target.second, runnable));
|
||||
}
|
||||
|
||||
if (target.second.has_value())
|
||||
{
|
||||
// sad :(
|
||||
state->cvVariable->Broadcast();
|
||||
}
|
||||
else
|
||||
{
|
||||
state->cvVariable->Signal();
|
||||
}
|
||||
if (target.second.has_value())
|
||||
{
|
||||
// sad :(
|
||||
state->cvVariable->Broadcast();
|
||||
}
|
||||
else
|
||||
{
|
||||
state->cvVariable->Signal();
|
||||
}
|
||||
}
|
||||
|
||||
bool AsyncApp::Poll(bool blocking)
|
||||
@ -206,10 +207,10 @@ namespace Aurora::Async
|
||||
auto state = GetThreadState();
|
||||
auto group = state->parent.lock();
|
||||
|
||||
state->pendingWorkItems.clear();
|
||||
//state->pendingWorkItems.clear();
|
||||
|
||||
{
|
||||
Threading::LockGuardPtr lol(group->cvWorkMutex);
|
||||
AU_LOCK_GUARD(group->cvWorkMutex);
|
||||
|
||||
do
|
||||
{
|
||||
@ -293,16 +294,17 @@ namespace Aurora::Async
|
||||
itr = state->pendingWorkItems.erase(itr);
|
||||
|
||||
// Atomically decrement global task counter
|
||||
runningTasks = --gRunningTasks;
|
||||
runningTasks = gRunningTasks.fetch_sub(1) - 1;
|
||||
}
|
||||
|
||||
// Return popped work back to the groups work pool when our -pump loops were preempted
|
||||
if (state->pendingWorkItems.size())
|
||||
{
|
||||
Threading::LockGuardPtr lol(group->cvWorkMutex);
|
||||
AU_LOCK_GUARD(group->cvWorkMutex);
|
||||
group->workQueue.insert(group->workQueue.end(), state->pendingWorkItems.begin(), state->pendingWorkItems.end());
|
||||
state->pendingWorkItems.clear();
|
||||
}
|
||||
|
||||
|
||||
if (runningTasks == 0)
|
||||
{
|
||||
ShutdownZero();
|
||||
@ -383,7 +385,7 @@ namespace Aurora::Async
|
||||
{
|
||||
// Nested shutdowns can happen a write lock
|
||||
{
|
||||
Threading::LockGuardPtr lock(rwlock_->AsReadable());
|
||||
AU_LOCK_GUARD(rwlock_->AsReadable());
|
||||
if (shuttingdown_)
|
||||
{
|
||||
return;
|
||||
@ -392,7 +394,7 @@ namespace Aurora::Async
|
||||
|
||||
// Set shutdown flag
|
||||
{
|
||||
Threading::LockGuardPtr lock(rwlock_->AsWritable());
|
||||
AU_LOCK_GUARD(rwlock_->AsWritable());
|
||||
if (std::exchange(shuttingdown_, true))
|
||||
{
|
||||
return;
|
||||
@ -406,7 +408,7 @@ namespace Aurora::Async
|
||||
//
|
||||
// Perform the following shutdown of the schedular and other available threads under a read lock
|
||||
{
|
||||
Threading::LockGuardPtr lock(rwlock_->AsReadable());
|
||||
AU_LOCK_GUARD(rwlock_->AsReadable());
|
||||
|
||||
StopSched();
|
||||
|
||||
@ -424,7 +426,7 @@ namespace Aurora::Async
|
||||
// then release all group contexts
|
||||
AuList<Threading::Threads::ThreadShared_t> threads;
|
||||
{
|
||||
Threading::LockGuardPtr lock(rwlock_->AsWritable());
|
||||
AU_LOCK_GUARD(rwlock_->AsWritable());
|
||||
|
||||
for (auto &[groupId, group] : this->threads_)
|
||||
{
|
||||
@ -447,7 +449,7 @@ namespace Aurora::Async
|
||||
|
||||
if (group->cvVariable)
|
||||
{
|
||||
Threading::LockGuardPtr lol(group->cvWorkMutex);
|
||||
AU_LOCK_GUARD(group->cvWorkMutex);
|
||||
group->cvVariable->Broadcast();
|
||||
}
|
||||
}
|
||||
@ -467,16 +469,16 @@ namespace Aurora::Async
|
||||
|
||||
bool AsyncApp::Spawn(WorkerId_t workerId)
|
||||
{
|
||||
Threading::LockGuardPtr lock(rwlock_->AsWritable());
|
||||
AU_LOCK_GUARD(rwlock_->AsWritable());
|
||||
|
||||
AuSPtr<GroupState> group;
|
||||
|
||||
// Try fetch or allocate group
|
||||
{
|
||||
AuSPtr<GroupState>* groupPtr;
|
||||
if (!TryFind(this->threads_, workerId.first, groupPtr))
|
||||
if (!AuTryFind(this->threads_, workerId.first, groupPtr))
|
||||
{
|
||||
group = std::make_shared<GroupState>();
|
||||
group = AuMakeShared<GroupState>();
|
||||
|
||||
if (!group->Init())
|
||||
{
|
||||
@ -484,7 +486,7 @@ namespace Aurora::Async
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TryInsert(this->threads_, std::make_pair(workerId.first, group)))
|
||||
if (!AuTryInsert(this->threads_, AuMakePair(workerId.first, group)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -499,14 +501,14 @@ namespace Aurora::Async
|
||||
{
|
||||
AuSPtr<ThreadState>* ret;
|
||||
|
||||
if (TryFind(group->workers, workerId.second, ret))
|
||||
if (AuTryFind(group->workers, workerId.second, ret))
|
||||
{
|
||||
SysPushErrorGen("Thread ID already exists");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto threadState = std::make_shared<ThreadState>();
|
||||
auto threadState = AuMakeShared<ThreadState>();
|
||||
threadState->parent = group;
|
||||
threadState->running = Threading::Primitives::EventUnique(true, false, true);
|
||||
threadState->syncSema = Threading::Primitives::SemaphoreUnique(0);
|
||||
@ -524,10 +526,10 @@ namespace Aurora::Async
|
||||
}
|
||||
else
|
||||
{
|
||||
threadState->threadObject = std::shared_ptr<Threading::Threads::IAuroraThread>(Threading::Threads::GetThread(), [](Threading::Threads::IAuroraThread *){});
|
||||
threadState->threadObject = AuSPtr<Threading::Threads::IAuroraThread>(Threading::Threads::GetThread(), [](Threading::Threads::IAuroraThread *){});
|
||||
}
|
||||
|
||||
group->workers.insert(std::make_pair(workerId.second, threadState));
|
||||
group->workers.insert(AuMakePair(workerId.second, threadState));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -540,7 +542,7 @@ namespace Aurora::Async
|
||||
}
|
||||
|
||||
AuSPtr<ThreadState>* ret;
|
||||
if (!TryFind(group->workers, id.second, ret))
|
||||
if (!AuTryFind(group->workers, id.second, ret))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
@ -550,7 +552,7 @@ namespace Aurora::Async
|
||||
|
||||
AuBST<ThreadGroup_t, AuList<ThreadId_t>> AsyncApp::GetThreads()
|
||||
{
|
||||
Threading::LockGuardPtr lock(rwlock_->AsReadable());
|
||||
AU_LOCK_GUARD(rwlock_->AsReadable());
|
||||
|
||||
AuBST<ThreadGroup_t, AuList<ThreadId_t>> ret;
|
||||
|
||||
@ -576,7 +578,7 @@ namespace Aurora::Async
|
||||
|
||||
bool AsyncApp::Sync(ThreadGroup_t groupId, bool requireSignal, AuUInt32 timeoutMs)
|
||||
{
|
||||
Threading::LockGuardPtr lock(rwlock_->AsReadable());
|
||||
AU_LOCK_GUARD(rwlock_->AsReadable());
|
||||
auto group = GetGroup(groupId);
|
||||
|
||||
for (auto &jobWorker : group->workers)
|
||||
@ -592,7 +594,7 @@ namespace Aurora::Async
|
||||
|
||||
void AsyncApp::Signal(ThreadGroup_t groupId)
|
||||
{
|
||||
Threading::LockGuardPtr lock(rwlock_->AsReadable());
|
||||
AU_LOCK_GUARD(rwlock_->AsReadable());
|
||||
|
||||
auto group = GetGroup(groupId);
|
||||
|
||||
@ -609,7 +611,7 @@ namespace Aurora::Async
|
||||
|
||||
void AsyncApp::SyncAllSafe()
|
||||
{
|
||||
Threading::LockGuardPtr lock(rwlock_->AsReadable());
|
||||
AU_LOCK_GUARD(rwlock_->AsReadable());
|
||||
|
||||
for (const auto &re : this->threads_)
|
||||
{
|
||||
@ -622,10 +624,10 @@ namespace Aurora::Async
|
||||
|
||||
AuSPtr<GroupState> AsyncApp::GetGroup(ThreadGroup_t type)
|
||||
{
|
||||
Threading::LockGuardPtr lock(rwlock_->AsReadable());
|
||||
AU_LOCK_GUARD(rwlock_->AsReadable());
|
||||
|
||||
AuSPtr<GroupState>* ret;
|
||||
if (!TryFind(this->threads_, type, ret))
|
||||
if (!AuTryFind(this->threads_, type, ret))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
@ -635,13 +637,13 @@ namespace Aurora::Async
|
||||
|
||||
size_t AsyncApp::GetThreadWorkersCount(ThreadGroup_t group)
|
||||
{
|
||||
Threading::LockGuardPtr lock(rwlock_->AsReadable());
|
||||
AU_LOCK_GUARD(rwlock_->AsReadable());
|
||||
return GetGroup(group)->workers.size();
|
||||
}
|
||||
|
||||
AuSPtr<ThreadState> AsyncApp::GetThreadState()
|
||||
{
|
||||
Threading::LockGuardPtr lock(rwlock_->AsReadable());
|
||||
AU_LOCK_GUARD(rwlock_->AsReadable());
|
||||
auto id = GetCurrentThread();
|
||||
auto state = GetGroup(id.first);
|
||||
return state->workers[id.second];
|
||||
@ -662,7 +664,7 @@ namespace Aurora::Async
|
||||
|
||||
if (id != WorkerId_t {0, 0})
|
||||
{
|
||||
Threading::LockGuardPtr lock(rwlock_->AsReadable());
|
||||
AU_LOCK_GUARD(rwlock_->AsReadable());
|
||||
|
||||
if (!shuttingdown_ && !job->rejecting)
|
||||
{
|
||||
@ -691,7 +693,7 @@ namespace Aurora::Async
|
||||
auto state = GetGroup(id.first);
|
||||
|
||||
{
|
||||
Threading::LockGuardPtr lock(rwlock_->AsWritable());
|
||||
AU_LOCK_GUARD(rwlock_->AsWritable());
|
||||
|
||||
auto itr = state->workers.find(id.second);
|
||||
auto &jobWorker = itr->second;
|
||||
@ -732,7 +734,7 @@ namespace Aurora::Async
|
||||
|
||||
void AsyncApp::AddFeature(WorkerId_t id, AuSPtr<Threading::Threads::IThreadFeature> feature, bool async)
|
||||
{
|
||||
auto work = std::make_shared<BasicWorkStdFunc>(([=]()
|
||||
auto work = AuMakeShared<BasicWorkStdFunc>(([=]()
|
||||
{
|
||||
GetThreadState()->features.push_back(feature);
|
||||
feature->Init();
|
||||
|
@ -78,6 +78,6 @@ namespace Aurora::Async
|
||||
|
||||
ThreadDb_t threads_;
|
||||
bool shuttingdown_ {};
|
||||
std::optional<WorkerId_t> commandDispatcher_;
|
||||
AuOptional<WorkerId_t> commandDispatcher_;
|
||||
};
|
||||
}
|
@ -25,7 +25,7 @@ namespace Aurora::Async
|
||||
|
||||
static void GetDispatchableTasks(AuList<SchedEntry> &pending)
|
||||
{
|
||||
Threading::LockGuardPtr lock(gSchedLock.get());
|
||||
AU_LOCK_GUARD(gSchedLock);
|
||||
|
||||
auto time = Time::CurrentClockNS();
|
||||
|
||||
@ -43,6 +43,13 @@ namespace Aurora::Async
|
||||
}
|
||||
}
|
||||
|
||||
static bool gLockedPump = false;
|
||||
|
||||
static void PumpSysThread()
|
||||
{
|
||||
RuntimeSysPump();
|
||||
gLockedPump = false;
|
||||
}
|
||||
|
||||
static void SchedThread()
|
||||
{
|
||||
@ -75,11 +82,14 @@ namespace Aurora::Async
|
||||
}
|
||||
|
||||
counter++;
|
||||
if ((gRuntimeConfig.async.schedularFrequency != 1) || ((gRuntimeConfig.async.sysPumpFrequency) && (counter % gRuntimeConfig.async.sysPumpFrequency) == 0))
|
||||
if ((!gRuntimeConfig.async.sysPumpFrequency) || ((gRuntimeConfig.async.sysPumpFrequency) && (counter % gRuntimeConfig.async.sysPumpFrequency) == 0))
|
||||
{
|
||||
try
|
||||
{
|
||||
NewWorkItem({0, 0}, std::make_shared<BasicWorkStdFunc>(RuntimeSysPump))->Dispatch();
|
||||
if (!std::exchange(gLockedPump, true))
|
||||
{
|
||||
NewWorkItem({0, 0}, AuMakeShared<BasicWorkStdFunc>(PumpSysThread))->Dispatch();
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@ -120,14 +130,14 @@ namespace Aurora::Async
|
||||
|
||||
void Schedule(AuUInt64 ns, DispatchTarget_t target, AuSPtr<IAsyncRunnable> runnable)
|
||||
{
|
||||
Threading::LockGuardPtr lock(gSchedLock.get());
|
||||
AU_LOCK_GUARD(gSchedLock);
|
||||
IncRunningTasks();
|
||||
gEntries.push_back({ns, target, runnable});
|
||||
}
|
||||
|
||||
void TerminateSceduledTasks(DispatchTarget_t target)
|
||||
{
|
||||
Threading::LockGuardPtr lock(gSchedLock.get());
|
||||
AU_LOCK_GUARD(gSchedLock);
|
||||
|
||||
for (auto itr = gEntries.begin(); itr != gEntries.end(); )
|
||||
{
|
||||
|
@ -34,8 +34,8 @@ namespace Aurora::Async
|
||||
{
|
||||
auto dependency = std::reinterpret_pointer_cast<WorkItem>(workItem);
|
||||
|
||||
Threading::LockGuard<Threading::Primitives::SpinLock> l(lock);
|
||||
Threading::LockGuard<Threading::Primitives::SpinLock> l2(dependency->lock);
|
||||
AU_LOCK_GUARD(lock);
|
||||
AU_LOCK_GUARD(dependency->lock);
|
||||
|
||||
if (dependency->HasFailed())
|
||||
{
|
||||
@ -60,12 +60,12 @@ namespace Aurora::Async
|
||||
bool status {};
|
||||
|
||||
{
|
||||
Threading::LockGuard<Threading::Primitives::SpinLock> l(lock);
|
||||
AU_LOCK_GUARD(lock);
|
||||
|
||||
for (auto &workItem : workItems)
|
||||
{
|
||||
auto dependency = std::reinterpret_pointer_cast<WorkItem>(workItem);
|
||||
Threading::LockGuard<Threading::Primitives::SpinLock> l2(dependency->lock);
|
||||
AU_LOCK_GUARD(dependency->lock);
|
||||
|
||||
if (dependency->HasFailed())
|
||||
{
|
||||
@ -125,19 +125,15 @@ namespace Aurora::Async
|
||||
|
||||
void WorkItem::DispatchEx(bool check)
|
||||
{
|
||||
Threading::LockGuard<Threading::Primitives::SpinLock> l(lock);
|
||||
AU_LOCK_GUARD(lock);
|
||||
|
||||
if (check)
|
||||
{
|
||||
if (!dispatchPending_)
|
||||
if (dispatchPending_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dispatchPending_ = true;
|
||||
}
|
||||
|
||||
if (HasFailed())
|
||||
{
|
||||
@ -156,6 +152,8 @@ namespace Aurora::Async
|
||||
itr = waitOn_.erase(itr);
|
||||
}
|
||||
|
||||
dispatchPending_ = true;
|
||||
|
||||
if (Time::CurrentClockNS() < dispatchTimeNs_)
|
||||
{
|
||||
Schedule();
|
||||
@ -164,7 +162,7 @@ namespace Aurora::Async
|
||||
|
||||
if (auto delay = std::exchange(delayTimeNs_, {}))
|
||||
{
|
||||
dispatchTimeNs_ = delay;
|
||||
dispatchTimeNs_ = delay + Time::CurrentClockNS();
|
||||
Schedule();
|
||||
return;
|
||||
}
|
||||
@ -174,16 +172,20 @@ namespace Aurora::Async
|
||||
|
||||
void WorkItem::CancelAsync()
|
||||
{
|
||||
Threading::LockGuard<Threading::Primitives::SpinLock> l(lock);
|
||||
AU_LOCK_GUARD(lock);
|
||||
Fail();
|
||||
}
|
||||
|
||||
void WorkItem::RunAsync()
|
||||
{
|
||||
Threading::LockGuard<Threading::Primitives::SpinLock> l(lock);
|
||||
AU_LOCK_GUARD(lock);
|
||||
|
||||
IWorkItemHandler::ProcessInfo info(true);
|
||||
task_->DispatchFrame(info);
|
||||
|
||||
if (task_)
|
||||
{
|
||||
task_->DispatchFrame(info);
|
||||
}
|
||||
|
||||
switch (info.type)
|
||||
{
|
||||
@ -223,16 +225,16 @@ namespace Aurora::Async
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &waiter : waiters_)
|
||||
{
|
||||
std::reinterpret_pointer_cast<WorkItem>(waiter)->DispatchEx(true);
|
||||
}
|
||||
|
||||
finished = true;
|
||||
if (finishedEvent_)
|
||||
{
|
||||
finishedEvent_->Set();
|
||||
}
|
||||
|
||||
for (auto &waiter : waiters_)
|
||||
{
|
||||
std::reinterpret_pointer_cast<WorkItem>(waiter)->DispatchEx(true);
|
||||
}
|
||||
}
|
||||
|
||||
void WorkItem::Fail()
|
||||
@ -286,6 +288,6 @@ namespace Aurora::Async
|
||||
|
||||
AUKN_SYM AuSPtr<IWorkItem> NewWorkItem(const DispatchTarget_t &worker, const AuSPtr<IWorkItemHandler> &task, bool supportsBlocking)
|
||||
{
|
||||
return std::make_shared<WorkItem>(worker, task, supportsBlocking);
|
||||
return AuMakeShared<WorkItem>(worker, task, supportsBlocking);
|
||||
}
|
||||
}
|
@ -16,7 +16,8 @@
|
||||
|
||||
namespace Aurora::Compression
|
||||
{
|
||||
std::pair<AuUInt32, AuUInt32> BaseStreamDeflate::Ingest(AuUInt32 input)
|
||||
#if 0
|
||||
AuStreamReadWrittenPair_t BaseStreamDeflate::Ingest(AuUInt32 input)
|
||||
{
|
||||
auto ingest = IngestImpl(input);
|
||||
_count += ingest.first;
|
||||
@ -58,4 +59,5 @@ namespace Aurora::Compression
|
||||
{
|
||||
SafeDelete<BaseStreamDeflate *>(stream);
|
||||
}
|
||||
#endif
|
||||
}
|
@ -9,22 +9,24 @@
|
||||
|
||||
namespace Aurora::Compression
|
||||
{
|
||||
#if 0
|
||||
class BaseStreamDeflate : public ICompressionStream
|
||||
{
|
||||
public:
|
||||
virtual ~BaseStreamDeflate() { }
|
||||
|
||||
|
||||
virtual std::pair<AuUInt32, AuUInt32> IngestImpl(AuUInt32 input);
|
||||
virtual AuStreamReadWrittenPair_t IngestImpl(AuUInt32 input);
|
||||
virtual void Flush() = 0;
|
||||
|
||||
virtual bool Init(Aurora::IO::IStreamReader *reader, const CompressionInfo &info) = 0;
|
||||
bool Read(void * /*opt*/ buffer, AuUInt32 &len, bool ingestUntilError) override;
|
||||
std::pair<AuUInt32, AuUInt32> Ingest(AuUInt32 input) override;
|
||||
AuStreamReadWrittenPair_t Ingest(AuUInt32 input) override;
|
||||
|
||||
protected:
|
||||
AuUInt32 _count {};
|
||||
AuUInt32 _lastCount {};
|
||||
AuList<AuUInt8> _outbuffer;
|
||||
};
|
||||
#endif
|
||||
}
|
@ -16,29 +16,51 @@
|
||||
|
||||
namespace Aurora::Compression
|
||||
{
|
||||
bool BaseStream::Read(void * /*opt*/ buffer, AuUInt32 &len, bool ingestUntilError)
|
||||
bool BaseStream::ReadByInflatedN(void * buffer, AuUInt32 minimumInflated, AuStreamReadWrittenPair_t &pair, bool ingestUntilEOS)
|
||||
{
|
||||
if (ingestUntilError)
|
||||
AuUInt32 read {}, len {};
|
||||
|
||||
if (ingestUntilEOS)
|
||||
{
|
||||
while (this->_outbuffer.size() < len)
|
||||
while (this->_outbuffer.RemainingBytes() < minimumInflated)
|
||||
{
|
||||
if (Ingest(4096).second == 0)
|
||||
{
|
||||
if (this->_outbuffer.size())
|
||||
if (!this->_outbuffer.RemainingBytes())
|
||||
{
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
read += 4096;
|
||||
}
|
||||
}
|
||||
|
||||
return StreamRead(buffer, len, this->_outbuffer);
|
||||
len = this->_outbuffer.Read(buffer, len, buffer == nullptr);
|
||||
pair = {read, len};
|
||||
return len != 0;
|
||||
}
|
||||
|
||||
bool BaseStream::GoBackByInflatedN(AuUInt32 offset)
|
||||
{
|
||||
return this->_outbuffer.ReaderTryGoBack(offset);
|
||||
}
|
||||
|
||||
bool BaseStream::GoForwardByInflatedN(AuUInt32 offset)
|
||||
{
|
||||
return this->_outbuffer.ReaderTryGoForward(offset);
|
||||
}
|
||||
|
||||
class ZSTDInflate : public BaseStream
|
||||
{
|
||||
public:
|
||||
ZSTDInflate() : BaseStream()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
~ZSTDInflate()
|
||||
{
|
||||
if (auto dctx = std::exchange(dctx_, {}))
|
||||
@ -58,12 +80,10 @@ namespace Aurora::Compression
|
||||
return false;
|
||||
}
|
||||
|
||||
this->_outbuffer.reserve(10 * 1024);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::pair<AuUInt32, AuUInt32> Ingest(AuUInt32 input) override
|
||||
AuStreamReadWrittenPair_t Ingest(AuUInt32 input) override
|
||||
{
|
||||
AuUInt32 length = ZSTD_DStreamInSize();
|
||||
void *din = alloca(length);
|
||||
@ -76,7 +96,7 @@ namespace Aurora::Compression
|
||||
AuUInt32 request = std::min(input, length);
|
||||
if (this->reader_->Read(din, request) != IO::EStreamError::eErrorNone)
|
||||
{
|
||||
return std::make_pair(read, done);
|
||||
return AuMakePair(read, done);
|
||||
}
|
||||
read += request;
|
||||
|
||||
@ -89,17 +109,16 @@ namespace Aurora::Compression
|
||||
if (ZSTD_isError(ret))
|
||||
{
|
||||
SysPushErrorIO("Compression error: {}", ret);
|
||||
return std::make_pair(read, 0);
|
||||
return AuMakePair(read, 0);
|
||||
}
|
||||
|
||||
done += output.pos;
|
||||
this->_outbuffer.insert(this->_outbuffer.end(),
|
||||
reinterpret_cast<const AuUInt8 *>(output.dst),
|
||||
reinterpret_cast<const AuUInt8 *>(output.dst) + output.pos);
|
||||
this->_outbuffer.Write(reinterpret_cast<const AuUInt8 *>(output.dst),
|
||||
output.pos);
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_pair(read, done);
|
||||
return AuMakePair(read, done);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -130,23 +149,22 @@ namespace Aurora::Compression
|
||||
return false;
|
||||
}
|
||||
|
||||
this->_outbuffer.reserve(10 * 1024);
|
||||
this->init_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::pair<AuUInt32, AuUInt32> Ingest(AuUInt32 input) override
|
||||
AuStreamReadWrittenPair_t Ingest(AuUInt32 input) override
|
||||
{
|
||||
int ret;
|
||||
|
||||
AuUInt32 done{}, read{};
|
||||
|
||||
while (read != input)
|
||||
while (read < input)
|
||||
{
|
||||
AuUInt32 request = std::min(input, AuUInt32(ArraySize(din_)));
|
||||
AuUInt32 request = std::min(input, AuUInt32(AuArraySize(din_)));
|
||||
if (this->reader_->Read(din_, request) != IO::EStreamError::eErrorNone)
|
||||
{
|
||||
return std::make_pair(read, done);
|
||||
return AuMakePair(read, done);
|
||||
}
|
||||
|
||||
read += request;
|
||||
@ -156,7 +174,7 @@ namespace Aurora::Compression
|
||||
|
||||
do
|
||||
{
|
||||
this->ctx_.avail_out = ArraySize(dout_);
|
||||
this->ctx_.avail_out = AuArraySize(dout_);
|
||||
this->ctx_.next_out = dout_;
|
||||
|
||||
if (!this->ctx_.avail_out)
|
||||
@ -168,21 +186,20 @@ namespace Aurora::Compression
|
||||
if (ret != Z_OK)
|
||||
{
|
||||
SysPushErrorIO("Error: {}", ret);
|
||||
return std::make_pair(read, 0);
|
||||
return AuMakePair(read, 0);
|
||||
}
|
||||
|
||||
auto have = ArraySize(dout_) - this->ctx_.avail_out;
|
||||
auto have = AuArraySize(dout_) - this->ctx_.avail_out;
|
||||
done += have;
|
||||
|
||||
this->_outbuffer.insert(this->_outbuffer.end(),
|
||||
reinterpret_cast<const AuUInt8 *>(dout_),
|
||||
reinterpret_cast<const AuUInt8 *>(dout_) + have);
|
||||
this->_outbuffer.Write(reinterpret_cast<const AuUInt8 *>(dout_),
|
||||
have);
|
||||
|
||||
} while (this->ctx_.avail_out == 0);
|
||||
SysAssert(this->ctx_.avail_in == 0);
|
||||
}
|
||||
|
||||
return std::make_pair(read, done);
|
||||
return AuMakePair(read, done);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -216,22 +233,21 @@ namespace Aurora::Compression
|
||||
return false;
|
||||
}
|
||||
|
||||
this->_outbuffer.reserve(10 * 1024);
|
||||
this->init_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::pair<AuUInt32, AuUInt32> Ingest(AuUInt32 input) override
|
||||
AuStreamReadWrittenPair_t Ingest(AuUInt32 input) override
|
||||
{
|
||||
int ret;
|
||||
|
||||
AuUInt32 done{}, read{};
|
||||
while (read != input)
|
||||
while (read < input)
|
||||
{
|
||||
AuUInt32 request = std::min(input, AuUInt32(ArraySize(din_)));
|
||||
AuUInt32 request = std::min(input, AuUInt32(AuArraySize(din_)));
|
||||
if (this->reader_->Read(din_, request) != IO::EStreamError::eErrorNone)
|
||||
{
|
||||
return std::make_pair(read, done);
|
||||
return AuMakePair(read, done);
|
||||
}
|
||||
read += request;
|
||||
|
||||
@ -240,29 +256,28 @@ namespace Aurora::Compression
|
||||
|
||||
do
|
||||
{
|
||||
this->ctx_.avail_out = ArraySize(dout_);
|
||||
this->ctx_.avail_out = AuArraySize(dout_);
|
||||
this->ctx_.next_out = dout_;
|
||||
|
||||
ret = BZ2_bzDecompress(&this->ctx_);
|
||||
if (ret != Z_OK)
|
||||
{
|
||||
SysPushErrorIO("Error: {}", ret);
|
||||
return std::make_pair(read, 0);
|
||||
return AuMakePair(read, 0);
|
||||
}
|
||||
|
||||
auto have = ArraySize(dout_) - this->ctx_.avail_out;
|
||||
auto have = AuArraySize(dout_) - this->ctx_.avail_out;
|
||||
done += have;
|
||||
|
||||
this->_outbuffer.insert(this->_outbuffer.end(),
|
||||
reinterpret_cast<const AuUInt8 *>(dout_),
|
||||
reinterpret_cast<const AuUInt8 *>(dout_) + have);
|
||||
this->_outbuffer.Write(reinterpret_cast<const AuUInt8 *>(dout_),
|
||||
have);
|
||||
|
||||
|
||||
} while (this->ctx_.avail_out == 0);
|
||||
SysAssert(this->ctx_.avail_in == 0);
|
||||
}
|
||||
|
||||
return std::make_pair(read, done);
|
||||
return AuMakePair(read, done);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -277,12 +292,12 @@ namespace Aurora::Compression
|
||||
class LZ4Inflate : public BaseStream
|
||||
{
|
||||
public:
|
||||
|
||||
LZ4Inflate() : BaseStream(64 * 1024 * 2)
|
||||
{}
|
||||
|
||||
~LZ4Inflate()
|
||||
{
|
||||
if (auto ctx = std::exchange(this->lz4Stream_, {}))
|
||||
{
|
||||
LZ4_freeStreamDecode(this->lz4Stream_);
|
||||
}
|
||||
}
|
||||
|
||||
bool Init(Aurora::IO::IStreamReader *reader)
|
||||
@ -296,61 +311,13 @@ namespace Aurora::Compression
|
||||
return false;
|
||||
}
|
||||
|
||||
this->_outbuffer.reserve(10 * 1024);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::pair<AuUInt32, AuUInt32> Ingest(AuUInt32 input) override
|
||||
|
||||
AuStreamReadWrittenPair_t Ingest(AuUInt32 input) override
|
||||
{
|
||||
AuUInt32 done {}, read {}, lastFrameSize {};
|
||||
std::shared_ptr<char> inFrame;
|
||||
std::shared_ptr<char> outFrames[2];
|
||||
bool outFrame {};
|
||||
|
||||
while (read != input)
|
||||
{
|
||||
AuUInt32 frameSize;
|
||||
AuUInt32 request = sizeof(frameSize);
|
||||
|
||||
if (this->reader_->Read(&frameSize, request) != IO::EStreamError::eErrorNone)
|
||||
{
|
||||
return std::make_pair(read, done);
|
||||
}
|
||||
read += request;
|
||||
|
||||
if ((lastFrameSize < frameSize) || (!outFrames[outFrame]))
|
||||
{
|
||||
inFrame = std::shared_ptr<char>(new char[frameSize], std::default_delete<char[]>());
|
||||
outFrames[outFrame] = std::shared_ptr<char>(new char[frameSize], std::default_delete<char[]>());
|
||||
lastFrameSize = frameSize;
|
||||
}
|
||||
|
||||
request = frameSize;
|
||||
if (this->reader_->Read(inFrame.get(), request) != IO::EStreamError::eErrorNone)
|
||||
{
|
||||
return std::make_pair(read, done);
|
||||
}
|
||||
read += request;
|
||||
|
||||
auto outPtr = outFrames[outFrame].get();
|
||||
|
||||
auto bytes = LZ4_decompress_safe_continue(lz4Stream_, inFrame.get(), outPtr, frameSize, frameSize);
|
||||
if (bytes <= 0)
|
||||
{
|
||||
return std::make_pair(read, 0);
|
||||
}
|
||||
|
||||
done += bytes;
|
||||
|
||||
this->_outbuffer.insert(this->_outbuffer.end(),
|
||||
reinterpret_cast<const AuUInt8 *>(outPtr),
|
||||
reinterpret_cast<const AuUInt8 *>(outPtr) + bytes);
|
||||
|
||||
outFrames[!outFrame] = std::move(outFrames[outFrame]);
|
||||
outFrame = !outFrame;
|
||||
}
|
||||
|
||||
return std::make_pair(read, done);
|
||||
return {};
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -12,12 +12,18 @@ namespace Aurora::Compression
|
||||
class BaseStream : public ICompressionStream
|
||||
{
|
||||
public:
|
||||
virtual ~BaseStream() {}
|
||||
BaseStream(int bufferSize = 4096 * 4) : _outbuffer(bufferSize, true) {}
|
||||
|
||||
virtual ~BaseStream() {}
|
||||
|
||||
virtual bool Init(Aurora::IO::IStreamReader *reader) = 0;
|
||||
bool Read(void * /*opt*/ buffer, AuUInt32 &len, bool ingestUntilError) override;
|
||||
|
||||
|
||||
virtual bool ReadByInflatedN(void * /*opt*/, AuUInt32 minimumInflated, AuStreamReadWrittenPair_t &pair, bool ingestUntilEOS = true) override;
|
||||
virtual bool GoBackByInflatedN(AuUInt32 offset) override;
|
||||
virtual bool GoForwardByInflatedN(AuUInt32 offset) override;
|
||||
|
||||
protected:
|
||||
AuList<AuUInt8> _outbuffer;
|
||||
Aurora::Memory::ByteBuffer _outbuffer;
|
||||
};
|
||||
}
|
@ -14,7 +14,7 @@ namespace Aurora::Compression
|
||||
{
|
||||
AUKN_SYM bool Compress(const void *buffer, AuUInt32 length, AuList<AuUInt8> &out, int compressionLevel )
|
||||
{
|
||||
if (!TryResize(out, length))
|
||||
if (!AuTryResize(out, length))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -36,35 +36,47 @@ namespace Aurora::Compression
|
||||
|
||||
AUKN_SYM bool Decompress(const void *buffer, AuUInt32 length, AuList<AuUInt8> &out)
|
||||
{
|
||||
auto inflatedLength = ZSTD_getFrameContentSize(buffer, length);
|
||||
AuUInt32 read = 0;
|
||||
|
||||
if (inflatedLength == ZSTD_CONTENTSIZE_ERROR)
|
||||
while (read != length)
|
||||
{
|
||||
return false;
|
||||
auto startPtr = reinterpret_cast<const AuUInt8 *>(buffer) + read;
|
||||
auto deflatedLength = ZSTD_findFrameCompressedSize(startPtr, length - read);
|
||||
auto inflatedLength = ZSTD_getFrameContentSize(startPtr, length - read);
|
||||
|
||||
if (inflatedLength == ZSTD_CONTENTSIZE_ERROR)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (inflatedLength == ZSTD_CONTENTSIZE_UNKNOWN)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ZSTD_isError(inflatedLength))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto startingSize = out.size();
|
||||
|
||||
if (!AuTryResize(out, inflatedLength))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto ret = ZSTD_decompress(&out[0], out.size(), buffer, length);
|
||||
if (ZSTD_isError(ret))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
out.resize(startingSize + ret);
|
||||
|
||||
read += deflatedLength;
|
||||
}
|
||||
|
||||
if (inflatedLength == ZSTD_CONTENTSIZE_UNKNOWN)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ZSTD_isError(inflatedLength))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TryResize(out, inflatedLength))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto ret = ZSTD_decompress(&out[0], out.size(), buffer, length);
|
||||
if (ZSTD_isError(ret))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
out.resize(ret);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -10,17 +10,4 @@
|
||||
namespace Aurora::Compression
|
||||
{
|
||||
static const AuUInt64 kChunkSize = 4096;
|
||||
|
||||
// This is acommon prolog required by BlockCompressors and BlockDecompressors. dw about it.
|
||||
static inline bool StreamRead(void * buffer, AuUInt32 &len, AuList<AuUInt8> &vec)
|
||||
{
|
||||
len = std::min(AuUInt32(vec.size()), len);
|
||||
if (len == 0) return false;
|
||||
if (!buffer) return true;
|
||||
std::memcpy(buffer, vec.data(), len);
|
||||
auto rem = vec.size() - len;
|
||||
std::memmove(vec.data(), vec.data() + len, rem);
|
||||
vec.resize(rem);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -13,6 +13,7 @@
|
||||
#include "zstd.h"
|
||||
#include "zlib.h"
|
||||
#include "lz4.h"
|
||||
#include "lz4frame.h"
|
||||
|
||||
namespace Aurora::Compression
|
||||
{
|
||||
@ -21,7 +22,7 @@ namespace Aurora::Compression
|
||||
auto length = ZSTD_DStreamInSize();
|
||||
|
||||
AuList<AuUInt8> buffer;
|
||||
auto ok = TryResize(buffer, length);
|
||||
auto ok = AuTryResize(buffer, length);
|
||||
if (!ok)
|
||||
{
|
||||
SysPushErrorMem("Couldn't reserve inflation buffers");
|
||||
@ -30,7 +31,7 @@ namespace Aurora::Compression
|
||||
|
||||
auto outFrameLength = ZSTD_DStreamOutSize();
|
||||
AuList<AuUInt8> inflatedBuffer;
|
||||
ok = TryResize(inflatedBuffer, outFrameLength);
|
||||
ok = AuTryResize(inflatedBuffer, outFrameLength);
|
||||
if (!ok)
|
||||
{
|
||||
SysPushErrorMem("Couldn't reserve inflation buffers");
|
||||
@ -83,7 +84,7 @@ namespace Aurora::Compression
|
||||
const auto buffOutSize = ZSTD_CStreamOutSize();
|
||||
|
||||
AuList<AuUInt8> inflatedBuffer;
|
||||
auto ok = TryResize(inflatedBuffer, buffInSize);
|
||||
auto ok = AuTryResize(inflatedBuffer, buffInSize);
|
||||
if (!ok)
|
||||
{
|
||||
SysPushErrorMem("Couldn't reserve deflation buffers");
|
||||
@ -91,7 +92,7 @@ namespace Aurora::Compression
|
||||
}
|
||||
|
||||
AuList<AuUInt8> deflatedBuffer;
|
||||
ok = TryResize(deflatedBuffer, buffOutSize);
|
||||
ok = AuTryResize(deflatedBuffer, buffOutSize);
|
||||
if (!ok)
|
||||
{
|
||||
SysPushErrorMem("Couldn't reserve deflation buffers. Out of memory");
|
||||
@ -209,7 +210,7 @@ namespace Aurora::Compression
|
||||
|
||||
do
|
||||
{
|
||||
auto read = stream.inPipe(in, ArraySize(in));
|
||||
auto read = stream.inPipe(in, AuArraySize(in));
|
||||
strm.avail_in = read;
|
||||
|
||||
inputStat += read;
|
||||
@ -219,7 +220,7 @@ namespace Aurora::Compression
|
||||
|
||||
do
|
||||
{
|
||||
strm.avail_out = ArraySize(out);
|
||||
strm.avail_out = AuArraySize(out);
|
||||
strm.next_out = out;
|
||||
|
||||
ret = deflate(&strm, flush);
|
||||
@ -229,7 +230,7 @@ namespace Aurora::Compression
|
||||
return false;
|
||||
}
|
||||
|
||||
auto have = ArraySize(out) - strm.avail_out;
|
||||
auto have = AuArraySize(out) - strm.avail_out;
|
||||
|
||||
stream.writePipe(out, have);
|
||||
|
||||
@ -267,7 +268,7 @@ namespace Aurora::Compression
|
||||
|
||||
do
|
||||
{
|
||||
auto read = stream.inPipe(in, ArraySize(in));
|
||||
auto read = stream.inPipe(in, AuArraySize(in));
|
||||
inputStat += read;
|
||||
if (!read)
|
||||
{
|
||||
@ -279,7 +280,7 @@ namespace Aurora::Compression
|
||||
|
||||
do
|
||||
{
|
||||
strm.avail_out = ArraySize(out);
|
||||
strm.avail_out = AuArraySize(out);
|
||||
strm.next_out = out;
|
||||
|
||||
ret = inflate(&strm, Z_NO_FLUSH);
|
||||
@ -289,7 +290,7 @@ namespace Aurora::Compression
|
||||
return false;
|
||||
}
|
||||
|
||||
auto have = ArraySize(out) - strm.avail_out;
|
||||
auto have = AuArraySize(out) - strm.avail_out;
|
||||
|
||||
stream.writePipe(out, have);
|
||||
|
||||
@ -327,7 +328,7 @@ namespace Aurora::Compression
|
||||
|
||||
do
|
||||
{
|
||||
auto read = stream.inPipe(in, ArraySize(in));
|
||||
auto read = stream.inPipe(in, AuArraySize(in));
|
||||
strm.avail_in = read;
|
||||
|
||||
inputStat += read;
|
||||
@ -337,7 +338,7 @@ namespace Aurora::Compression
|
||||
|
||||
do
|
||||
{
|
||||
strm.avail_out = ArraySize(out);
|
||||
strm.avail_out = AuArraySize(out);
|
||||
strm.next_out = out;
|
||||
|
||||
ret = BZ2_bzCompress(&strm, flush);
|
||||
@ -347,7 +348,7 @@ namespace Aurora::Compression
|
||||
return false;
|
||||
}
|
||||
|
||||
auto have = ArraySize(out) - strm.avail_out;
|
||||
auto have = AuArraySize(out) - strm.avail_out;
|
||||
|
||||
stream.writePipe(out, have);
|
||||
|
||||
@ -385,7 +386,7 @@ namespace Aurora::Compression
|
||||
|
||||
do
|
||||
{
|
||||
auto read = stream.inPipe(in, ArraySize(in));
|
||||
auto read = stream.inPipe(in, AuArraySize(in));
|
||||
inputStat += read;
|
||||
if (!read)
|
||||
{
|
||||
@ -397,7 +398,7 @@ namespace Aurora::Compression
|
||||
|
||||
do
|
||||
{
|
||||
strm.avail_out = ArraySize(out);
|
||||
strm.avail_out = AuArraySize(out);
|
||||
strm.next_out = out;
|
||||
|
||||
ret = BZ2_bzDecompress(&strm);
|
||||
@ -407,7 +408,7 @@ namespace Aurora::Compression
|
||||
return false;
|
||||
}
|
||||
|
||||
auto have = ArraySize(out) - strm.avail_out;
|
||||
auto have = AuArraySize(out) - strm.avail_out;
|
||||
|
||||
stream.writePipe(out, have);
|
||||
|
||||
@ -429,27 +430,39 @@ namespace Aurora::Compression
|
||||
|
||||
static bool CompressLZ4(const CompressionPipe &stream, const CompressionInfo &info)
|
||||
{
|
||||
bool ret = true;
|
||||
LZ4_stream_t* const lz4Stream = LZ4_createStream();
|
||||
|
||||
int size = info.lz4BlockSize ? info.lz4BlockSize : 64 * 1024;
|
||||
|
||||
std::shared_ptr<char> in1Buf(new char[size], std::default_delete<char[]>());
|
||||
std::shared_ptr<char> in2Buf(new char[size], std::default_delete<char[]>());
|
||||
std::shared_ptr<char> outBuf(new char[size], std::default_delete<char[]>());
|
||||
std::shared_ptr<char> inBuffers[2] = {in1Buf, in2Buf};
|
||||
bool inBufState = false;
|
||||
|
||||
bool ret;
|
||||
LZ4F_cctx *cctxPtr;
|
||||
LZ4F_preferences_t pref {};
|
||||
AuUInt32 inputStat = 0, outputStat = 0;
|
||||
LZ4F_compressOptions_t options {};
|
||||
char header[512];
|
||||
|
||||
ret = true;
|
||||
pref.compressionLevel = info.compressionLevel;
|
||||
|
||||
auto maxFrameSize = info.lz4BlockSize ? info.lz4BlockSize : 64 * 1024;
|
||||
auto buffer = AuSPtr<char>(new char[maxFrameSize], std::default_delete<char[]>());
|
||||
auto maxOut = LZ4F_compressBound(maxFrameSize, &pref);
|
||||
auto outBuffer = AuSPtr<char>(new char[maxOut], std::default_delete<char[]>());;
|
||||
|
||||
auto err = LZ4F_createCompressionContext(&cctxPtr, LZ4F_getVersion());
|
||||
if (LZ4F_isError(err))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write header
|
||||
{
|
||||
auto written = LZ4F_compressBegin(cctxPtr, header, AuArraySize(header), &pref);
|
||||
stream.writePipe(header, written);
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
auto &inBuf = inBuffers[inBufState = !inBufState];
|
||||
|
||||
auto read = stream.inPipe(inBuf.get(), size);
|
||||
auto read = stream.inPipe(buffer.get(), maxFrameSize);
|
||||
if (!read) break;
|
||||
|
||||
AuUInt32 bufferedBytes = LZ4_compress_fast_continue(lz4Stream, inBuf.get(), outBuf.get(), read, size, 1);
|
||||
AuUInt32 bufferedBytes = LZ4F_compressUpdate(cctxPtr, outBuffer.get(), maxOut, buffer.get(), read, &options);
|
||||
|
||||
if (bufferedBytes <= 0)
|
||||
{
|
||||
@ -457,79 +470,113 @@ namespace Aurora::Compression
|
||||
break;
|
||||
}
|
||||
|
||||
stream.writePipe(&bufferedBytes, sizeof(bufferedBytes));
|
||||
stream.writePipe(outBuf.get(), bufferedBytes);
|
||||
stream.writePipe(outBuffer.get(), bufferedBytes);
|
||||
|
||||
inputStat += read;
|
||||
outputStat += bufferedBytes;
|
||||
|
||||
if (!stream.reportProgress(inputStat, outputStat)) break;
|
||||
if (!stream.reportProgress(inputStat, outputStat))
|
||||
{
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LZ4_freeStream(lz4Stream);
|
||||
LZ4F_freeCompressionContext(cctxPtr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool DecompressLZ4(const CompressionPipe &pipe)
|
||||
{
|
||||
bool ret = true;
|
||||
LZ4_streamDecode_t* lz4Stream = LZ4_createStreamDecode();
|
||||
|
||||
AuUInt32 inputStat {}, outputStat {}, lastFrameSize {};
|
||||
std::shared_ptr<char> inFrame;
|
||||
std::shared_ptr<char> outFrames[2];
|
||||
bool outFrame {};
|
||||
LZ4F_dctx *dctxPtr;
|
||||
AuUInt32 inputStat = 0, outputStat = 0;
|
||||
LZ4F_decompressOptions_t opts {};
|
||||
AuUInt32 lastFrameMaxSize {};
|
||||
AuSPtr<char> bufferIn, bufferOut;
|
||||
|
||||
auto err = LZ4F_createDecompressionContext(&dctxPtr, LZ4F_getVersion());
|
||||
if (LZ4F_isError(err))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
AuUInt32 frameSize;
|
||||
AuUInt32 request = sizeof(frameSize);
|
||||
auto read = pipe.inPipe(&frameSize, sizeof(frameSize));
|
||||
if (read != request)
|
||||
{
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
inputStat += request;
|
||||
|
||||
if ((lastFrameSize < frameSize) || (!outFrames[outFrame]))
|
||||
{
|
||||
inFrame = std::shared_ptr<char>(new char[frameSize], std::default_delete<char[]>());
|
||||
outFrames[outFrame] = std::shared_ptr<char>(new char[frameSize], std::default_delete<char[]>());
|
||||
lastFrameSize = frameSize;
|
||||
}
|
||||
|
||||
request = frameSize;
|
||||
read = pipe.inPipe(inFrame.get(), request);
|
||||
if (read != request)
|
||||
{
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
inputStat += request;
|
||||
char header[LZ4F_HEADER_SIZE_MAX];
|
||||
|
||||
auto outPtr = outFrames[outFrame].get();
|
||||
|
||||
auto bytes = LZ4_decompress_safe_continue(lz4Stream, inFrame.get(), outPtr, frameSize, frameSize);
|
||||
if (bytes <= 0)
|
||||
LZ4F_frameInfo_t info {};
|
||||
|
||||
// Read header
|
||||
if (pipe.inPipe(header, LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH) != LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH)
|
||||
{
|
||||
ret = false;
|
||||
break;
|
||||
return {};
|
||||
}
|
||||
|
||||
pipe.writePipe(outPtr, bytes);
|
||||
inputStat += bytes;
|
||||
|
||||
outFrames[!outFrame] = std::move(outFrames[outFrame]);
|
||||
outFrame = !outFrame;
|
||||
|
||||
if (!pipe.reportProgress(inputStat, outputStat))
|
||||
//
|
||||
auto sizeOfheader = LZ4F_headerSize(header, LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH);
|
||||
if (LZ4F_isError(sizeOfheader))
|
||||
{
|
||||
break;
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto req = sizeOfheader - LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH;
|
||||
if (pipe.inPipe(header + LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH, req) != req)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
inputStat += sizeOfheader;
|
||||
|
||||
size_t sizePtr = sizeOfheader;
|
||||
auto status = LZ4F_getFrameInfo(dctxPtr, &info, header, &sizePtr);
|
||||
if (sizePtr != sizeOfheader)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
auto frameSize = status;
|
||||
auto min = std::max(info.contentSize, frameSize);
|
||||
|
||||
if (min > lastFrameMaxSize)
|
||||
{
|
||||
lastFrameMaxSize = min;
|
||||
if (lastFrameMaxSize > 64 * 1024 * 1024)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
bufferIn = AuSPtr<char>(new char[lastFrameMaxSize], std::default_delete<char[]>());
|
||||
bufferOut = AuSPtr<char>(new char[lastFrameMaxSize], std::default_delete<char[]>());
|
||||
}
|
||||
|
||||
if (pipe.inPipe(bufferIn.get(), frameSize) != frameSize)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
inputStat += frameSize;
|
||||
|
||||
if (info.contentSize)
|
||||
{
|
||||
size_t frameSPtr = frameSize;
|
||||
size_t frameS2Ptr = info.contentSize;
|
||||
LZ4F_decompress(dctxPtr, bufferIn.get(), &frameSPtr, bufferOut.get(), &frameS2Ptr, &opts);
|
||||
|
||||
if (frameS2Ptr)
|
||||
{
|
||||
pipe.writePipe(bufferOut.get(), frameS2Ptr);
|
||||
}
|
||||
|
||||
outputStat += frameS2Ptr;
|
||||
|
||||
if (!pipe.reportProgress(inputStat, outputStat))
|
||||
{
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LZ4_freeStreamDecode(lz4Stream);
|
||||
LZ4F_freeDecompressionContext(dctxPtr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -552,7 +599,6 @@ namespace Aurora::Compression
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AUKN_SYM bool Decompress(const CompressionPipe &pipe)
|
||||
{
|
||||
switch (pipe.type)
|
||||
|
@ -13,33 +13,34 @@ namespace Aurora::Console::Commands
|
||||
struct Command;
|
||||
struct CommandDispatch;
|
||||
|
||||
static AuHashMap<AuString, Command> gCommands;
|
||||
static AuList<Hooks::LineHook_cb> gLineCallbacks;
|
||||
static AuList<CommandDispatch> gPendingCommands;
|
||||
static auto gMutex = Threading::Primitives::MutexUnique();
|
||||
static auto gPendingCommandsMutex = Threading::Primitives::MutexUnique();
|
||||
static std::optional<Async::DispatchTarget_t> gCommandDispatcher;
|
||||
static AuHashMap<AuString, Command> gCommands;
|
||||
static AuList<Hooks::LineHook_cb> gLineCallbacks;
|
||||
static AuList<CommandDispatch> gPendingCommands;
|
||||
static auto gMutex = Threading::Primitives::MutexUnique();
|
||||
static auto gPendingCommandsMutex = Threading::Primitives::MutexUnique();
|
||||
static AuOptional<Async::DispatchTarget_t> gCommandDispatcher;
|
||||
|
||||
struct Command
|
||||
{
|
||||
AuString tag;
|
||||
Parse::ParseObject commandStructure;
|
||||
const CommandCallback_cb &callback;
|
||||
CommandCallback_cb callback;
|
||||
|
||||
Command(AuString tag, Parse::ParseObject commandStructure, const CommandCallback_cb &callback) : tag(tag), commandStructure(commandStructure), callback(callback) {}
|
||||
Command(AuString tag, Parse::ParseObject commandStructure, CommandCallback_cb &&callback) : tag(tag), commandStructure(commandStructure), callback(std::move(callback)) {}
|
||||
};
|
||||
|
||||
struct CommandDispatch
|
||||
{
|
||||
Parse::ParsedObject arguments;
|
||||
const CommandCallback_cb &callback;
|
||||
CommandCallback_cb callback;
|
||||
|
||||
CommandDispatch(const Parse::ParsedObject &arguments, const CommandCallback_cb &callback) : arguments(arguments), callback(callback) {}
|
||||
};
|
||||
|
||||
static bool Dispatch(const AuString &string)
|
||||
{
|
||||
Threading::WaitableLockGuard guard(gPendingCommandsMutex.get());
|
||||
AU_LOCK_GUARD(gPendingCommandsMutex);
|
||||
AuString tag;
|
||||
AuString cmdParse;
|
||||
AuMach offset;
|
||||
@ -66,8 +67,8 @@ namespace Aurora::Console::Commands
|
||||
auto const &cmdEntry = cmdItr->second;
|
||||
|
||||
offset = 0;
|
||||
auto consumable = Parse::StringToConsumable(cmdParse, offset);
|
||||
auto status = Parse::Parse(res, cmdEntry.commandStructure, consumable);
|
||||
Parse::ParseState consumable(Parse::StringToConsumable(cmdParse, offset));
|
||||
auto status = Parse::Parse(consumable, cmdEntry.commandStructure, res);
|
||||
|
||||
if (!status)
|
||||
{
|
||||
@ -79,21 +80,21 @@ namespace Aurora::Console::Commands
|
||||
return true;
|
||||
}
|
||||
|
||||
void AddCommand(const AuString &tag, const Parse::ParseObject &commandStructure, const CommandCallback_cb &callback)
|
||||
AUKN_SYM void AddCommand(const AuString &tag, const Parse::ParseObject &commandStructure, const CommandCallback_cb &callback)
|
||||
{
|
||||
Threading::WaitableLockGuard guard(gPendingCommandsMutex.get());
|
||||
gCommands.insert(std::make_pair(tag, Command(tag, commandStructure, callback)));
|
||||
AU_LOCK_GUARD(gPendingCommandsMutex);
|
||||
gCommands.insert(AuMakePair(tag, Command(tag, commandStructure, callback)));
|
||||
}
|
||||
|
||||
bool DispatchCommand(const AuString &string)
|
||||
AUKN_SYM bool DispatchCommand(const AuString &string)
|
||||
{
|
||||
return Dispatch(string);
|
||||
}
|
||||
|
||||
void UpdateDispatcher(std::optional<Async::DispatchTarget_t> target)
|
||||
void UpdateDispatcher(AuOptional<Async::DispatchTarget_t> target)
|
||||
{
|
||||
gMutex->Lock();
|
||||
gPendingCommandsMutex->Lock();
|
||||
AU_LOCK_GUARD(gMutex);
|
||||
AU_LOCK_GUARD(gPendingCommandsMutex);
|
||||
|
||||
if ((!target.has_value()) && (gCommandDispatcher == target))
|
||||
{
|
||||
@ -105,9 +106,6 @@ namespace Aurora::Console::Commands
|
||||
}
|
||||
|
||||
gCommandDispatcher = target;
|
||||
|
||||
gPendingCommandsMutex->Unlock();
|
||||
gMutex->Unlock();
|
||||
}
|
||||
|
||||
static void DispatchCommandsFromThis(const AuList<CommandDispatch> &commands)
|
||||
@ -132,13 +130,12 @@ namespace Aurora::Console::Commands
|
||||
}
|
||||
else
|
||||
{
|
||||
Async::NewWorkItem(gCommandDispatcher.value(),
|
||||
std::make_shared<Async::BasicWorkStdFunc>([&commands]()
|
||||
Async::NewWorkItem(gCommandDispatcher.value(),
|
||||
AuMakeShared<Async::BasicWorkStdFunc>([&commands]()
|
||||
{
|
||||
DispatchCommandsFromThis(commands);
|
||||
}),
|
||||
}),
|
||||
true)->Dispatch()->BlockUntilComplete();
|
||||
|
||||
}
|
||||
|
||||
gMutex->Unlock();
|
||||
|
@ -9,6 +9,6 @@
|
||||
|
||||
namespace Aurora::Console::Commands
|
||||
{
|
||||
void UpdateDispatcher(std::optional<Async::DispatchTarget_t> target);
|
||||
void UpdateDispatcher(AuOptional<Async::DispatchTarget_t> target);
|
||||
void PumpCommands();
|
||||
}
|
@ -9,40 +9,66 @@
|
||||
#include "Console.hpp"
|
||||
#include "Commands/Commands.hpp"
|
||||
#include "Hooks/Hooks.hpp"
|
||||
#include "ConsoleAsioStd/ConsoleAsioStd.hpp"
|
||||
#include "ConsoleStd/ConsoleStd.hpp"
|
||||
#include "ConsoleWxWidgets/ConsoleWxWidgets.hpp"
|
||||
#include "ConsoleLogger/ConsoleLogger.hpp"
|
||||
#include "ConsoleFIO/ConsoleFIO.hpp"
|
||||
#include "Flusher.hpp"
|
||||
|
||||
namespace Aurora::Console
|
||||
{
|
||||
void WriteLine(const ConsoleMessage &msg)
|
||||
AUKN_SYM void WriteLine(const ConsoleMessage &msg)
|
||||
{
|
||||
Hooks::WriteLine(msg);
|
||||
}
|
||||
|
||||
AUKN_SYM AuUInt32 ReadStdIn(void *buffer, AuUInt32 length)
|
||||
{
|
||||
return ConsoleStd::ReadStdIn(buffer, length);
|
||||
}
|
||||
|
||||
AUKN_SYM AuUInt32 WriteStdIn(const void *buffer, AuUInt32 length)
|
||||
{
|
||||
return ConsoleStd::WriteStdOut(buffer, length);
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
ConsoleAsioStd::Init();
|
||||
Hooks::Init();
|
||||
ConsoleStd::Init();
|
||||
ConsoleWxWidgets::Init();
|
||||
}
|
||||
|
||||
void Init2()
|
||||
{
|
||||
ConsoleLogger::Init();
|
||||
ConsoleFIO::Init();
|
||||
InitFlusher();
|
||||
}
|
||||
|
||||
void Pump()
|
||||
{
|
||||
Commands::PumpCommands();
|
||||
ConsoleAsioStd::Pump();
|
||||
ConsoleStd::Pump();
|
||||
ConsoleWxWidgets::Pump();
|
||||
ConsoleLogger::Pump();
|
||||
ConsoleFIO::Pump();
|
||||
}
|
||||
|
||||
void Exit()
|
||||
{
|
||||
ConsoleAsioStd::Exit();
|
||||
DeinitFlusher();
|
||||
ConsoleStd::Exit();
|
||||
ConsoleWxWidgets::Exit();
|
||||
ConsoleLogger::Exit();
|
||||
ConsoleFIO::Exit();
|
||||
Hooks::Deinit();
|
||||
}
|
||||
|
||||
|
||||
AUKN_SYM void OpenLateStd()
|
||||
{
|
||||
ConsoleStd::Start();
|
||||
}
|
||||
|
||||
AUKN_SYM void OpenLateGUI()
|
||||
{
|
||||
ConsoleWxWidgets::Start();
|
||||
}
|
||||
}
|
@ -1,196 +0,0 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: ConsoleAsioStd.cpp
|
||||
Date: 2021-6-8
|
||||
Author: Reece
|
||||
***/
|
||||
#include <RuntimeInternal.hpp>
|
||||
#include "ConsoleAsioStd.hpp"
|
||||
|
||||
namespace Aurora::Console::ConsoleAsioStd
|
||||
{
|
||||
#if defined(AURORA_PLATFORM_WIN32) || defined(AURORA_PLATFORM_LINUX) || defined(AURORA_PLATFORM_APPLE)
|
||||
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
using StreamDescriptor_t = asio::windows::stream_handle;
|
||||
#else
|
||||
using StreamDescriptor_t = asio::posix::stream_descriptor;
|
||||
#endif
|
||||
|
||||
static const AuMach kLineBufferMax = 2048;
|
||||
|
||||
static AuUInt8 gLineBuffer[kLineBufferMax] = { 0 };
|
||||
static AuString gLineString = "";
|
||||
|
||||
static StreamDescriptor_t *gInputStream = {};
|
||||
static StreamDescriptor_t *gOutputStream = {};
|
||||
|
||||
static asio::io_context gIOC;
|
||||
|
||||
void Init()
|
||||
{
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
|
||||
if (GetConsoleWindow() == NULL)
|
||||
{
|
||||
if (!gRuntimeConfig.console.forceConsoleWindow)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (gRuntimeConfig.console.disableAll)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto ok = AllocConsole();
|
||||
SysAssert(ok, "Request of a Win32 console yielded nada, forceConsole wasn't respected");
|
||||
}
|
||||
else
|
||||
{
|
||||
// no always means no under UNIX targets; but on windows, if you're compiling a console app, dont be surprised to find console output
|
||||
// instead of attempting to detach from conhost, link as a WindowedApp and do not setup any windows, if you're looking for windowless
|
||||
// ignore gRuntimeConfig.console.disableAll
|
||||
}
|
||||
|
||||
DWORD dwMode;
|
||||
bool ok;
|
||||
auto hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
SysAssert(hOutput != INVALID_HANDLE_VALUE, "Couldn't open STDOUT");
|
||||
|
||||
ok = GetConsoleMode(hOutput, &dwMode);
|
||||
SysAssert(ok, "Couldn't get console mode");
|
||||
|
||||
dwMode |= ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
ok = SetConsoleMode(hOutput, dwMode);
|
||||
SysAssert(ok, "Couldn't set console mode");
|
||||
|
||||
auto fileHandle = CreateFileA("CONIN$",
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING,
|
||||
NULL);
|
||||
|
||||
SysAssert(fileHandle != INVALID_HANDLE_VALUE, "Couldn't open CONIN");
|
||||
gInputStream = _new StreamDescriptor_t(gIOC, fileHandle);
|
||||
|
||||
fileHandle = CreateFileA("CONOUT$",
|
||||
GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING,
|
||||
NULL);
|
||||
|
||||
SysAssert(fileHandle != INVALID_HANDLE_VALUE, "Couldn't open CONOUT");
|
||||
gOutputStream = _new StreamDescriptor_t(gIOC, fileHandle);
|
||||
|
||||
#else
|
||||
|
||||
// no always means no under UNIX targets
|
||||
// we *know* stdin/out should be available under these standards
|
||||
if (gRuntimeConfig.console.disableAll)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gInputStream = _new StreamDescriptor_t(gIOC, STDIN_FILENO);
|
||||
gOutputStream = _new StreamDescriptor_t(gIOC, STDOUT_FILENO);
|
||||
|
||||
#endif
|
||||
|
||||
SysAssert(gInputStream, "Couldn't allocate input stream handler");
|
||||
SysAssert(gOutputStream, "Couldn't allocate output stream handler");
|
||||
|
||||
Aurora::Console::Hooks::AddHook([](const Aurora::Console::ConsoleMessage &string) -> void
|
||||
{
|
||||
#if defined(DEBUG) && defined(AURORA_PLATFORM_WIN32)
|
||||
auto debugLine = string.ToSimplified() + "\r\n";
|
||||
OutputDebugStringA(debugLine.c_str());
|
||||
#endif
|
||||
|
||||
auto writeLine = string.ToConsole();
|
||||
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
writeLine += '\r';
|
||||
#endif
|
||||
writeLine += '\n';
|
||||
|
||||
asio::write(*gOutputStream, asio::buffer(writeLine));
|
||||
});
|
||||
}
|
||||
|
||||
static void ProcessLines()
|
||||
{
|
||||
AuMach index = 0;
|
||||
|
||||
while ((index = gLineString.find("\n")) != AuString::npos)
|
||||
{
|
||||
auto line = gLineString.substr(0, index);
|
||||
gLineString = gLineString.substr(index + 1);
|
||||
|
||||
if (line[line.size() - 1] == '\r')
|
||||
{
|
||||
line.pop_back();
|
||||
}
|
||||
|
||||
if (line.size())
|
||||
{
|
||||
Aurora::Console::Commands::DispatchCommand(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void StdInHandler(const asio::error_code &code, std::size_t bytesCopied)
|
||||
{
|
||||
if (bytesCopied == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gLineString.append(reinterpret_cast<const char *>(gLineBuffer), bytesCopied);
|
||||
|
||||
ProcessLines();
|
||||
}
|
||||
|
||||
void Pump()
|
||||
{
|
||||
if (!gInputStream) return;
|
||||
|
||||
gInputStream->async_read_some(asio::buffer(gLineBuffer, kLineBufferMax), StdInHandler);
|
||||
|
||||
gIOC.poll_one();
|
||||
}
|
||||
|
||||
void Exit()
|
||||
{
|
||||
if (gInputStream)
|
||||
{
|
||||
delete gInputStream;
|
||||
}
|
||||
|
||||
if (gOutputStream)
|
||||
{
|
||||
delete gOutputStream;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void Pump()
|
||||
{
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
}
|
||||
|
||||
void Exit()
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: ConsoleAsioStd.hpp
|
||||
Date: 2021-6-8
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Console::ConsoleAsioStd
|
||||
{
|
||||
void Init();
|
||||
void Pump();
|
||||
void Exit();
|
||||
}
|
@ -1,21 +1,41 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: ConsoleLogger.cpp
|
||||
File: ConsoleFIO.cpp
|
||||
Date: 2021-6-22
|
||||
Author: Reece
|
||||
***/
|
||||
#include <RuntimeInternal.hpp>
|
||||
#include "ConsoleLogger.hpp"
|
||||
#include "ConsoleFIO.hpp"
|
||||
|
||||
namespace Aurora::Console::ConsoleLogger
|
||||
namespace Aurora::Console::ConsoleFIO
|
||||
{
|
||||
static Threading::Threads::ThreadUnique_t gFileWriterThread;
|
||||
static AuList<AuUInt8> gLogBuffer;
|
||||
static Threading::Primitives::RWLockUnique_t gLogMutex;
|
||||
static IO::FS::OpenWriteUnique_t gFileHandle;
|
||||
|
||||
static const auto & gLogConfig = gRuntimeConfig.console.logging;
|
||||
|
||||
static const auto & gLogConfig = gRuntimeConfig.console.fio;
|
||||
|
||||
static AuString GetLogDirectory()
|
||||
{
|
||||
AuString path;
|
||||
AuString procName;
|
||||
|
||||
if (!IO::FS::GetProfileDomain(path))
|
||||
{
|
||||
path = ".";
|
||||
}
|
||||
|
||||
if (!Process::GetProcName(procName))
|
||||
{
|
||||
procName = "Unknown";
|
||||
}
|
||||
|
||||
path += "/Logs/";
|
||||
path += procName;
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
static void EraseFilesByTimestamp(const AuString &path, /*const its not worth reallocation*/ AuList<AuString> &files)
|
||||
{
|
||||
@ -47,47 +67,40 @@ namespace Aurora::Console::ConsoleLogger
|
||||
|
||||
static void CleanupOldLogs()
|
||||
{
|
||||
AuString path;
|
||||
AuString procName;
|
||||
|
||||
if (!Process::GetProcName(procName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IO::FS::GetProfileDomain(path))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
path += "/Logs/";
|
||||
path += procName;
|
||||
|
||||
AuList<AuString> files;
|
||||
AuBST<AuString, IO::FS::Stat> fileMeta;
|
||||
AuUInt32 size {};
|
||||
IO::FS::FilesInDirectory(path, files);
|
||||
|
||||
auto baseLogPath = GetLogDirectory();
|
||||
|
||||
IO::FS::FilesInDirectory(baseLogPath, files);
|
||||
|
||||
for (const auto &file : files)
|
||||
{
|
||||
IO::FS::Stat stat;
|
||||
IO::FS::StatFile(path + "/" + file, stat);
|
||||
IO::FS::StatFile(baseLogPath + "/" + file, stat);
|
||||
fileMeta[file] = stat;
|
||||
size += stat.size;
|
||||
}
|
||||
|
||||
EraseFilesByTimestamp(path, files);
|
||||
EraseFilesByTimestamp(baseLogPath, files);
|
||||
// TODO: erase when size >= gLogConfig.maxSizeMb * 1024
|
||||
}
|
||||
|
||||
static void CompressLogs()
|
||||
{
|
||||
|
||||
// TODO: write XZ's
|
||||
}
|
||||
|
||||
void Flush()
|
||||
{
|
||||
Threading::WaitableLockGuard a(gLogMutex->AsReadable());
|
||||
/// It should be expected that the TLS teardown emergency flush to dispatch after deinit
|
||||
if (!gLogMutex)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AU_LOCK_GUARD(gLogMutex->AsReadable());
|
||||
|
||||
if (gFileHandle)
|
||||
{
|
||||
@ -100,39 +113,22 @@ namespace Aurora::Console::ConsoleLogger
|
||||
static bool OpenLogFile()
|
||||
{
|
||||
AuString path;
|
||||
AuString procName;
|
||||
|
||||
if (!Process::GetProcName(procName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IO::FS::GetProfileDomain(path))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto tm = Time::ToCivilTime(Time::CurrentClockMS());
|
||||
|
||||
path += fmt::format("/Logs/{}/{:04}-{:02}-{:02}T{:02}-{:02}-{:02}Z.txt",
|
||||
procName,
|
||||
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec);
|
||||
path = fmt::format("{}/{:04}-{:02}-{:02}T{:02}-{:02}-{:02}Z.txt",
|
||||
GetLogDirectory(),
|
||||
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec);
|
||||
|
||||
gFileHandle = IO::FS::OpenWriteUnique(path);
|
||||
return gFileHandle ? true : false;
|
||||
return static_cast<bool>(gFileHandle);
|
||||
}
|
||||
|
||||
static void LogThreadInit()
|
||||
void FIOCleanup()
|
||||
{
|
||||
CleanupOldLogs();
|
||||
|
||||
auto thread = Threading::Threads::GetThread();
|
||||
while (!thread->Exiting())
|
||||
{
|
||||
Sleep(500);
|
||||
Flush();
|
||||
}
|
||||
CompressLogs();
|
||||
}
|
||||
|
||||
void Init()
|
||||
@ -152,32 +148,17 @@ namespace Aurora::Console::ConsoleLogger
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Threading::Threads::AbstractThreadVectors handler;
|
||||
handler.DoRun = [](Threading::Threads::IAuroraThread *)
|
||||
{
|
||||
LogThreadInit();
|
||||
};
|
||||
|
||||
gFileWriterThread = Threading::Threads::ThreadUnique(handler);
|
||||
if (!gFileWriterThread)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gFileWriterThread->SetName("ConsoleFIO");
|
||||
gFileWriterThread->Run();
|
||||
|
||||
Console::Hooks::AddHook([&](const Console::ConsoleMessage &string) -> void
|
||||
Console::Hooks::AddFunctionalHook([&](const Console::ConsoleMessage &string) -> void
|
||||
{
|
||||
Threading::WaitableLockGuard a(gLogMutex->AsWritable());
|
||||
AU_LOCK_GUARD(gLogMutex->AsWritable());
|
||||
auto str = string.ToSimplified();
|
||||
|
||||
gLogBuffer.reserve(gLogBuffer.size() + str.size() + 2);
|
||||
|
||||
gLogBuffer.insert(gLogBuffer.end(), reinterpret_cast<AuUInt8*>(str.data()), reinterpret_cast<AuUInt8*>(str.data()) + str.size());
|
||||
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
gLogBuffer.insert(gLogBuffer.end(), AuUInt8('\r'));
|
||||
#endif
|
||||
gLogBuffer.insert(gLogBuffer.end(), AuUInt8('\n'));
|
||||
@ -192,10 +173,7 @@ namespace Aurora::Console::ConsoleLogger
|
||||
void Exit()
|
||||
{
|
||||
Flush();
|
||||
gFileWriterThread.reset();
|
||||
gLogMutex.reset();
|
||||
gFileHandle.reset();
|
||||
|
||||
CompressLogs();
|
||||
}
|
||||
}
|
@ -1,16 +1,17 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: ConsoleLogger.hpp
|
||||
File: ConsoleFIO.hpp
|
||||
Date: 2021-6-22
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Console::ConsoleLogger
|
||||
namespace Aurora::Console::ConsoleFIO
|
||||
{
|
||||
void Init();
|
||||
void Pump();
|
||||
void Exit();
|
||||
void Flush();
|
||||
void FIOCleanup();
|
||||
}
|
@ -10,7 +10,8 @@
|
||||
|
||||
namespace Aurora::Console
|
||||
{
|
||||
static std::array<std::string, static_cast<size_t>(EAnsiColor::eCount)> AnsiCheats{
|
||||
static std::array<std::string, static_cast<size_t>(EAnsiColor::eCount)> AnsiCheats
|
||||
{
|
||||
"\033[0;31m",
|
||||
"\033[1;31m",
|
||||
"\033[0;32m",
|
||||
|
516
Source/Console/ConsoleStd/ConsoleStd.cpp
Normal file
516
Source/Console/ConsoleStd/ConsoleStd.cpp
Normal file
@ -0,0 +1,516 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: ConsoleStd.cpp
|
||||
Date: 2021-6-8
|
||||
Author: Reece
|
||||
***/
|
||||
#include <RuntimeInternal.hpp>
|
||||
#include "ConsoleStd.hpp"
|
||||
#include "Locale/Locale.hpp"
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED) || defined(AURORA_IS_POSIX_DERIVED)
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
// nothing yet
|
||||
#elif defined(AURORA_IS_POSIX_DERIVED)
|
||||
#define IO_POSIX_STREAMS
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/select.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
// compile time preprocessor definition to strip std stream based IO
|
||||
#if !(defined(AURORA_DISABLE_STD_CONSOLE))
|
||||
#define ENABLE_STD_CONSOLE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace Aurora::Console::ConsoleStd
|
||||
{
|
||||
#if defined(ENABLE_STD_CONSOLE)
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
using StreamHandle_t = HANDLE;
|
||||
#define IS_STREAM_HANDLE_VALID(h) (h != INVALID_HANDLE_VALUE)
|
||||
#define DEFAULT_HANDLE_VAL INVALID_HANDLE_VALUE
|
||||
|
||||
static StreamHandle_t gWin32Thread = INVALID_HANDLE_VALUE;
|
||||
#elif defined(IO_POSIX_STREAMS)
|
||||
#define IS_STREAM_HANDLE_VALID(h) (h != 0)
|
||||
#define DEFAULT_HANDLE_VAL 0
|
||||
using StreamHandle_t = int;
|
||||
#endif
|
||||
static bool AsyncReadAnyOrReadStreamBlock();
|
||||
|
||||
static const AuMach kLineBufferMax = 2048;
|
||||
static AuUInt8 gLineEncodedBuffer[kLineBufferMax];
|
||||
static AuUInt gEncodedIndex = 0;
|
||||
static AuString gLineBuffer(kLineBufferMax, 0);
|
||||
static AuUInt gLineIndex = 0;
|
||||
static StreamHandle_t gTerminateConsole;
|
||||
static StreamHandle_t gInputStream = DEFAULT_HANDLE_VAL;
|
||||
static StreamHandle_t gOutputStream = DEFAULT_HANDLE_VAL;
|
||||
|
||||
static Threading::Primitives::SpinLock gRingLock;
|
||||
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
static DWORD WINAPI StdInWin32Thread(void*)
|
||||
{
|
||||
HANDLE a[2] = {gInputStream, gTerminateConsole};
|
||||
|
||||
while (true)
|
||||
{
|
||||
WaitForMultipleObjectsEx(2, a, false, 25, 0);
|
||||
|
||||
if (WaitForSingleObject(gTerminateConsole, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
AsyncReadAnyOrReadStreamBlock();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
void Start()
|
||||
{
|
||||
static bool gConsoleStarted = false;
|
||||
if (std::exchange(gConsoleStarted, true)) return;
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
|
||||
DWORD dwMode;
|
||||
bool ok;
|
||||
// Obtain a win32 file HANDLE of STDIN
|
||||
auto fileHandle = CreateFileA("CONIN$",
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
|
||||
SysAssert(fileHandle != INVALID_HANDLE_VALUE, "Couldn't open CONIN");
|
||||
gInputStream = fileHandle;
|
||||
|
||||
// Obtain a win32 file HANDLE of STDOUT
|
||||
fileHandle = CreateFileA("CONOUT$",
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
|
||||
SysAssert(fileHandle != INVALID_HANDLE_VALUE, "Couldn't open CONOUT");
|
||||
gOutputStream = fileHandle;
|
||||
|
||||
// Get current console flags
|
||||
if (GetConsoleMode(gOutputStream, &dwMode))
|
||||
{
|
||||
if (gRuntimeConfig.console.enableStdPassthrough ^ gRuntimeConfig.console.enableStdOut)
|
||||
{
|
||||
// Enable escape processing; enable colored output
|
||||
dwMode |= ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
ok = SetConsoleMode(gOutputStream, dwMode);
|
||||
SysAssert(ok, "Couldn't set console mode");
|
||||
|
||||
// Set the output stream to use UTF-8
|
||||
ok = SetConsoleOutputCP(CP_UTF8);
|
||||
SysAssert(ok, "Couldn't maintain UTF-8 stdout stream");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (gRuntimeConfig.console.enableStdPassthrough && gRuntimeConfig.console.enableStdOut)
|
||||
{
|
||||
SetConsoleMode(gOutputStream, 0);
|
||||
}
|
||||
|
||||
if (gRuntimeConfig.console.enableStdPassthrough ^ gRuntimeConfig.console.enableStdIn)
|
||||
{
|
||||
ok = SetConsoleCP(CP_UTF8);
|
||||
#if 0
|
||||
SysAssert(ok, "Couldn't maintain UTF-8 stdin stream");
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
if (gRuntimeConfig.console.enableStdPassthrough && gRuntimeConfig.console.enableStdIn)
|
||||
{
|
||||
if (!GetConsoleMode(gInputStream, &dwMode))
|
||||
{
|
||||
ok = SetConsoleMode(gInputStream, dwMode & ~(ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT));
|
||||
SysAssert(ok, "Couldn't maintain binary stdin stream");
|
||||
}
|
||||
}
|
||||
|
||||
gTerminateConsole = CreateEvent(nullptr, true, false, nullptr);
|
||||
|
||||
gWin32Thread = CreateThread(nullptr, 0, StdInWin32Thread, nullptr, 0, nullptr);
|
||||
|
||||
#elif defined(AURORA_IS_POSIX_DERIVED)
|
||||
|
||||
gInputStream = STDIN_FILENO;
|
||||
gOutputStream = STDOUT_FILENO;
|
||||
|
||||
#endif
|
||||
|
||||
SysAssert(gInputStream, "Couldn't allocate input stream handler");
|
||||
SysAssert(gOutputStream, "Couldn't allocate output stream handler");
|
||||
|
||||
Console::Hooks::AddFunctionalHook([](const Aurora::Console::ConsoleMessage &string) -> void
|
||||
{
|
||||
#if (defined(DEBUG) || defined(STAGING)) && defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
auto debugLine = string.ToSimplified() + "\r\n";
|
||||
OutputDebugStringW(Locale::ConvertFromUTF8(debugLine).c_str());
|
||||
#endif
|
||||
|
||||
if (!gRuntimeConfig.console.enableStdOut)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto writeLine = string.ToConsole();
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
writeLine += '\r';
|
||||
#endif
|
||||
writeLine += '\n';
|
||||
|
||||
#if defined(IO_POSIX_STREAMS)
|
||||
if (Locale::GetInternalCodePage() == Locale::ECodePage::eUTF8)
|
||||
{
|
||||
WriteStdOut(writeLine.data(), writeLine.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
AuString slow;
|
||||
slow.resize(writeLine.size() * 4);
|
||||
auto len = Locale::Encoding::EncodeUTF8(writeLine, reinterpret_cast<AuUInt8 *>(slow.data()), slow.size(), Locale::ECodePage::eSysUnk);
|
||||
if (len.first != 0)
|
||||
{
|
||||
WriteStdOut(slow.data(), len.second);
|
||||
}
|
||||
else
|
||||
{
|
||||
// better write this than nothing
|
||||
WriteStdOut(writeLine.data(), writeLine.size());
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
WriteStdOut(writeLine.data(), writeLine.size());
|
||||
#endif
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
|
||||
if (GetConsoleWindow() == NULL)
|
||||
{
|
||||
if (!gRuntimeConfig.console.forceConsoleWindow)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (gRuntimeConfig.console.disableAllConsoles)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto ok = AllocConsole();
|
||||
SysAssert(ok, "Request of a Win32 console yielded nada, forceConsole wasn't respected");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Under windows, applications linked with the console subsystem flag should have output no matter what disableAll/forceConsoleWindow says
|
||||
// The amount of effort it takes to link as console app for a conhost window far exceeds whatever 'forceConsoleWindow' is defined as
|
||||
// One does not simply switch over to conapp for the fun of it. We can't or at least shouldn't destroy or hide conhost with hacks
|
||||
// Assuming stdconsole is wanted - DO NOT RETURN - LINK AS A WINDOWED APP IF YOU DO NOT WANT A CONSOLE WINDOW
|
||||
}
|
||||
|
||||
#elif defined(AURORA_IS_POSIX_DERIVED)
|
||||
|
||||
// no always means no under UNIX targets
|
||||
// we *know* stdin/out will be available under these standards
|
||||
if (gRuntimeConfig.console.disableAllConsoles)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Start();
|
||||
}
|
||||
|
||||
AuUInt32 WriteStdOut(const void *data, AuUInt32 length)
|
||||
{
|
||||
if (!IS_STREAM_HANDLE_VALID(gOutputStream))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(IO_POSIX_STREAMS)
|
||||
AuInt32 written = write(gOutputStream, data, length);
|
||||
if (written < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#elif defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
DWORD written;
|
||||
if (!WriteFile(gOutputStream, data, length, &written, NULL))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
static bool InputStreamAvailable()
|
||||
{
|
||||
#if defined(IO_POSIX_STREAMS)
|
||||
timeval tv {};
|
||||
fd_set fds {};
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(gInputStream, &fds);
|
||||
select(gInputStream + 1, &fds, NULL, NULL, &tv);
|
||||
return (FD_ISSET(0, &fds));
|
||||
#elif defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
// Inline non-blocking is not legal on windows.
|
||||
// One can force it with the overlapped flag, seemingly vaid since win8, but defined as illegal since the 90s
|
||||
return false;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
AuUInt32 ReadStdIn(void *data, AuUInt32 length)
|
||||
{
|
||||
Pump();
|
||||
|
||||
gRingLock.Lock();
|
||||
auto readable = std::min(AuUInt32(length), AuUInt32(gEncodedIndex));
|
||||
|
||||
std::memcpy(data, gLineEncodedBuffer, readable);
|
||||
|
||||
const auto remainingBytes = gEncodedIndex - readable;
|
||||
if (remainingBytes)
|
||||
{
|
||||
std::memmove(gLineEncodedBuffer, &gLineEncodedBuffer[readable], remainingBytes);
|
||||
}
|
||||
|
||||
gEncodedIndex = remainingBytes;
|
||||
gRingLock.Unlock();
|
||||
return readable;
|
||||
}
|
||||
|
||||
static void ProcessLines()
|
||||
{
|
||||
AuMach index = 0, startIdx = 0;
|
||||
|
||||
if (gLineIndex == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto end = gLineBuffer.data() + gLineIndex;
|
||||
|
||||
while (true)
|
||||
{
|
||||
auto a = std::find(gLineBuffer.data() + startIdx, end, '\n');
|
||||
if (a == end) break;
|
||||
index = a - gLineBuffer.data();
|
||||
|
||||
auto line = gLineBuffer.substr(startIdx, index - startIdx);
|
||||
startIdx = index + 1;
|
||||
|
||||
if (line[line.size() - 1] == '\r')
|
||||
{
|
||||
line.pop_back();
|
||||
}
|
||||
|
||||
if (line.size())
|
||||
{
|
||||
Console::Commands::DispatchCommand(line);
|
||||
}
|
||||
}
|
||||
|
||||
if (index != 0)
|
||||
{
|
||||
const auto remainingBytes = gLineIndex - startIdx;
|
||||
if (remainingBytes)
|
||||
{
|
||||
std::memmove(gLineBuffer.data(), &gLineBuffer.data()[startIdx], remainingBytes);
|
||||
gLineIndex -= startIdx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ProcessLinesSysCP()
|
||||
{
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
static Locale::Encoding::TextStreamEncoder stream(Locale::ECodePage::eUTF8);
|
||||
#else
|
||||
static Locale::Encoding::TextStreamEncoder stream(Locale::GetInternalCodePage());
|
||||
#endif
|
||||
|
||||
AU_LOCK_GUARD(&gRingLock);
|
||||
|
||||
auto ret = stream.DecodeUTF8(gLineEncodedBuffer, gEncodedIndex, gLineBuffer.data() + gLineIndex, gLineBuffer.size() - gLineIndex);
|
||||
|
||||
// increment backline buffer
|
||||
{
|
||||
const auto remainingBytes = gEncodedIndex - ret.first;
|
||||
if (remainingBytes)
|
||||
{
|
||||
std::memmove(gLineEncodedBuffer, &gLineEncodedBuffer[ret.first], remainingBytes);
|
||||
}
|
||||
|
||||
gEncodedIndex = remainingBytes;
|
||||
}
|
||||
|
||||
// increment frontline buffer
|
||||
{
|
||||
gLineIndex += ret.second;
|
||||
}
|
||||
|
||||
ProcessLines();
|
||||
}
|
||||
|
||||
static AuUInt32 SyncReadConsole()
|
||||
{
|
||||
void *data = &gLineEncodedBuffer[gEncodedIndex];
|
||||
auto length = kLineBufferMax - gEncodedIndex;
|
||||
|
||||
if (!IS_STREAM_HANDLE_VALID(gInputStream))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
|
||||
DWORD read = length;
|
||||
if (!ReadFile(gInputStream, data, read, &read, NULL))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
gRingLock.Lock();
|
||||
gEncodedIndex += read;
|
||||
gRingLock.Unlock();
|
||||
|
||||
return read;
|
||||
|
||||
#elif defined(IO_POSIX_STREAMS)
|
||||
|
||||
auto bread = ::read(gInputStream, data, length);
|
||||
if (bread < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
gRingLock.Lock();
|
||||
gEncodedIndex += bread;
|
||||
gRingLock.Unlock();
|
||||
|
||||
return bread;
|
||||
|
||||
#else
|
||||
|
||||
return 0;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool AsyncReadAnyOrReadStreamBlock()
|
||||
{
|
||||
if (SyncReadConsole())
|
||||
{
|
||||
ProcessLinesSysCP();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Pump()
|
||||
{
|
||||
if (!gRuntimeConfig.console.enableStdIn)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IS_STREAM_HANDLE_VALID(gInputStream))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!InputStreamAvailable())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AsyncReadAnyOrReadStreamBlock();
|
||||
}
|
||||
|
||||
void Exit()
|
||||
{
|
||||
if (IS_STREAM_HANDLE_VALID(gTerminateConsole))
|
||||
{
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
SetEvent(gTerminateConsole);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Note: CloseHandle in the middle of a ReadFile blocks & we can't legally preempt without the support of docs
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
if (gWin32Thread != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
WaitForSingleObject(gWin32Thread, 200);
|
||||
TerminateThread(gWin32Thread, 0);
|
||||
}
|
||||
|
||||
AuWin32CloseHandle(gWin32Thread);
|
||||
AuWin32CloseHandle(gTerminateConsole);
|
||||
AuWin32CloseHandle(gInputStream);
|
||||
AuWin32CloseHandle(gOutputStream);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void Pump()
|
||||
{
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
}
|
||||
|
||||
void Exit()
|
||||
{
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
}
|
20
Source/Console/ConsoleStd/ConsoleStd.hpp
Normal file
20
Source/Console/ConsoleStd/ConsoleStd.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: ConsoleStd.hpp
|
||||
Date: 2021-6-8
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Console::ConsoleStd
|
||||
{
|
||||
void Init();
|
||||
void Pump();
|
||||
void Exit();
|
||||
|
||||
void Start();
|
||||
|
||||
AuUInt32 ReadStdIn(void *data, AuUInt32 length);
|
||||
AuUInt32 WriteStdOut(const void *data, AuUInt32 length);
|
||||
}
|
@ -9,7 +9,6 @@
|
||||
#include "ConsoleWxWidgets.hpp"
|
||||
|
||||
#if defined(_AUHAS_WXWIDGETS)
|
||||
#include <asio.hpp>
|
||||
#include <wx/wxprec.h>
|
||||
#include <wx/wx.h>
|
||||
|
||||
@ -24,6 +23,7 @@ class ConsoleFrame;
|
||||
static AuList<Aurora::Console::ConsoleMessage> gPendingLines;
|
||||
static Aurora::Threading::Primitives::MutexUnique_t gMutex;
|
||||
static bool gWxConsoleReady;
|
||||
static bool gConsoleStarted = false;
|
||||
static ConsoleFrame *gWxFrame;
|
||||
|
||||
|
||||
@ -31,7 +31,7 @@ class WxSplitterLine : public wxWindow
|
||||
{
|
||||
public:
|
||||
WxSplitterLine() {}
|
||||
WxSplitterLine(wxSize splitter, wxColor color, wxWindow *parent, wxWindowID winid) : wxWindow(parent, winid), _color(color)
|
||||
WxSplitterLine(wxSize splitter, std::optional<wxColor> color, wxWindow *parent, wxWindowID winid) : wxWindow(parent, winid), _color(color)
|
||||
{
|
||||
SetMinSize(splitter);
|
||||
}
|
||||
@ -39,15 +39,16 @@ public:
|
||||
void OnPaint(wxPaintEvent &paint)
|
||||
{
|
||||
wxPaintDC re(this);
|
||||
re.SetBrush(_color);
|
||||
re.SetBackground(_color);
|
||||
|
||||
re.SetBrush(_color.value_or(this->GetParent()->GetBackgroundColour()));
|
||||
re.SetBackground(_color.value_or(this->GetParent()->GetBackgroundColour()));
|
||||
re.Clear();
|
||||
}
|
||||
|
||||
private:
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
wxColor _color;
|
||||
std::optional<wxColor> _color;
|
||||
};
|
||||
wxBEGIN_EVENT_TABLE(WxSplitterLine, wxPanel)
|
||||
EVT_PAINT(WxSplitterLine::OnPaint)
|
||||
@ -66,7 +67,6 @@ ConsoleApp::~ConsoleApp()
|
||||
|
||||
}
|
||||
|
||||
|
||||
class ConsoleFrame : public wxFrame
|
||||
{
|
||||
public:
|
||||
@ -90,8 +90,9 @@ private:
|
||||
void OnShow(wxWindowCreateEvent &event);
|
||||
void OnCmd(wxCommandEvent &event);
|
||||
void OnPump(wxTimerEvent& event);
|
||||
|
||||
|
||||
WxSplitterLine *NewSplitter(wxSize splitter, wxColor color);
|
||||
WxSplitterLine *NewSplitter(wxSize splitter);
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
wxRichTextCtrl *richtextbox_;
|
||||
@ -121,7 +122,8 @@ wxEND_EVENT_TABLE()
|
||||
|
||||
bool ConsoleApp::OnInit()
|
||||
{
|
||||
ConsoleFrame *frame = _new ConsoleFrame("Aurora Engine Console", wxPoint(50, 50), wxSize(1080, 550));
|
||||
//gRuntimeConfig.console.
|
||||
ConsoleFrame *frame = _new ConsoleFrame("Aurora SDK Sample", wxPoint(50, 50), wxSize(1080, 550));
|
||||
frame->Show(true);
|
||||
gWxFrame = frame;
|
||||
return true;
|
||||
@ -150,6 +152,13 @@ WxSplitterLine *ConsoleFrame::NewSplitter(wxSize splitter, wxColor color)
|
||||
return re;
|
||||
}
|
||||
|
||||
WxSplitterLine *ConsoleFrame::NewSplitter(wxSize splitter)
|
||||
{
|
||||
auto re = new WxSplitterLine(splitter, {}, this, -1);
|
||||
_splitters.push_back(re);
|
||||
return re;
|
||||
}
|
||||
|
||||
void ConsoleFrame::WriteLine(const Aurora::Console::ConsoleMessage &string)
|
||||
{
|
||||
static std::array<const wxColour, static_cast<size_t>(Aurora::Console::EAnsiColor::eCount)> ColorMap
|
||||
@ -209,7 +218,7 @@ void ConsoleFrame::WriteLine(const Aurora::Console::ConsoleMessage &string)
|
||||
if (bold)
|
||||
richtextbox_->BeginBold();
|
||||
|
||||
richtextbox_->WriteText(writeLine);
|
||||
richtextbox_->WriteText(wxString::FromUTF8(writeLine));
|
||||
richtextbox_->Newline();
|
||||
|
||||
if (bold)
|
||||
@ -234,6 +243,8 @@ void ConsoleFrame::WriteLine(const Aurora::Console::ConsoleMessage &string)
|
||||
//richtextbox_->Disable
|
||||
//richtextbox_->EndParagraphSpacing();
|
||||
}
|
||||
#include <wx/gbsizer.h>
|
||||
|
||||
|
||||
ConsoleFrame::ConsoleFrame(const wxString &title, const wxPoint &pos, const wxSize &size)
|
||||
: wxFrame(NULL, wxID_ANY, title, pos, size)
|
||||
@ -244,14 +255,42 @@ ConsoleFrame::ConsoleFrame(const wxString &title, const wxPoint &pos, const wxSi
|
||||
bool useWin32DarkHack = false;
|
||||
#endif
|
||||
|
||||
// _ _ _ _ _ _ _
|
||||
// (_) | | | | | | | | | | | |
|
||||
// __ ____ _ _ __ ___ _ __ _ _ __ ___ ___ ___ __ _| |__ ___ __ _ __| | | | | | | | | |
|
||||
// \ \ /\ / / _` | '__| / __| '__| | '_ ` _ \ / _ \/ __| / _` | '_ \ / _ \/ _` |/ _` | | | | | | | | |
|
||||
// \ V V / (_| | | | (__| | | | | | | | | __/\__ \ | (_| | | | | __/ (_| | (_| | |_| |_| |_| |_|
|
||||
// \_/\_/ \__,_|_| \___|_| |_|_| |_| |_|\___||___/ \__,_|_| |_|\___|\__,_|\__,_| (_) (_) (_) (_)
|
||||
//
|
||||
|
||||
|
||||
static const auto kEnableDark = (useWin32DarkHack) ||
|
||||
(Aurora::Build::kCurrentPlatform != Aurora::Build::EPlatform::ePlatformWin32);
|
||||
|
||||
static const auto kIsBgColorDefault = !kEnableDark;
|
||||
static const auto kBackgroundColor = kIsBgColorDefault ? this->GetBackgroundColour() : wxColour(38, 38, 38);
|
||||
static const auto kTextBoxColor = kIsBgColorDefault ? this->GetForegroundColour() : wxColour(255, 255, 255);
|
||||
static const auto kTextBoxOutter = wxColour(0x15, 0x15, 0x15);
|
||||
static const auto kTextBoxInner = wxColour(0x38, 0x38, 0x38);
|
||||
static const auto kHeaderPadUpDown = 14;
|
||||
static const auto kHeaderPadLeftRight = 15;
|
||||
static const auto kTextboxWin32PadInner = 2;
|
||||
static const auto kTextboxWin32PadOutter = 1;
|
||||
static const auto kTitleContentSplitterDepth = 2;
|
||||
static const auto kTextboxHeight = 20;
|
||||
static const auto kTextBoxHandlePad = kEnableDark;
|
||||
static const auto kTextBoxHandleColor = kEnableDark;
|
||||
static const auto kDrawOwnCheckboxes = kEnableDark;
|
||||
|
||||
|
||||
// 1080, 550
|
||||
this->SetClientSize(this->FromDIP(wxSize(903, 434)));
|
||||
|
||||
menuBar_ = _new wxMenuBar;
|
||||
menuBar_ = _new wxMenuBar();
|
||||
if (!menuBar_) return;
|
||||
|
||||
{
|
||||
wxMenu *menuFile = _new wxMenu;
|
||||
auto menuFile = _new wxMenu();
|
||||
if (!menuFile) return;
|
||||
|
||||
menuFile->Append(wxID_SAVE, "Export text log");
|
||||
@ -263,7 +302,7 @@ ConsoleFrame::ConsoleFrame(const wxString &title, const wxPoint &pos, const wxSi
|
||||
}
|
||||
|
||||
{
|
||||
wxMenu *menuHelp = _new wxMenu;
|
||||
auto menuHelp = _new wxMenu();
|
||||
if (!menuHelp) return;
|
||||
|
||||
menuHelp->Append(ID_BLACKBOX, "&Report application state to the black box");
|
||||
@ -272,51 +311,242 @@ ConsoleFrame::ConsoleFrame(const wxString &title, const wxPoint &pos, const wxSi
|
||||
menuBar_->Append(menuHelp, "&Bugs");
|
||||
}
|
||||
|
||||
richtextbox_ = _new wxRichTextCtrl(this, -1, wxEmptyString,
|
||||
wxDefaultPosition, wxDefaultSize,
|
||||
(useWin32DarkHack ? wxBORDER_NONE : 0) | wxTE_MULTILINE | wxRE_READONLY | wxRE_CENTER_CARET);
|
||||
if (!richtextbox_) return;
|
||||
|
||||
commandbox_ = _new wxTextCtrl(this, -1, wxEmptyString,
|
||||
wxDefaultPosition, wxDefaultSize,
|
||||
(useWin32DarkHack ? wxBORDER_NONE : 0) | wxTE_PROCESS_ENTER);
|
||||
if (!commandbox_) return;
|
||||
|
||||
if (useWin32DarkHack)
|
||||
{
|
||||
this->SetBackgroundColour(wxColour(0, 0, 0));
|
||||
|
||||
richtextbox_->SetBackgroundColour(wxColour(0, 0, 0));
|
||||
richtextbox_->SetForegroundColour(wxColour(255, 255, 255));
|
||||
|
||||
commandbox_->SetBackgroundColour(wxColour(0, 0, 0));
|
||||
commandbox_->SetForegroundColour(wxColour(255, 255, 255));
|
||||
|
||||
//this->Connect(wxEVT_SHOW, wxWindowCreateEventHandler(ConsoleFrame::OnShow));
|
||||
this->Connect(wxEVT_SHOW, wxWindowCreateEventHandler(ConsoleFrame::OnShow));
|
||||
}
|
||||
|
||||
commandbox_->SetHint("Type a command here");
|
||||
commandbox_->Connect(wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(ConsoleFrame::OnCmd));
|
||||
//commandbox_->Bind(wxEVT_COMMAND_TEXT_ENTER, &ConsoleFrame::OnCmd, commandbox_);
|
||||
|
||||
sizer_ = _new wxBoxSizer(wxVERTICAL);
|
||||
if (!sizer_) return;
|
||||
|
||||
auto font = this->GetFont();
|
||||
font.SetPointSize(9);
|
||||
font.MakeBold();
|
||||
|
||||
auto font2 = this->GetFont();
|
||||
font2.SetPointSize(9);
|
||||
|
||||
sizer_->Add(richtextbox_, 3, wxEXPAND);
|
||||
if (useWin32DarkHack)
|
||||
auto addTextbox = [&](wxBoxSizer *parent, int minx, int miny, bool alt = false) -> wxTextCtrl *
|
||||
{
|
||||
sizer_->Add(NewSplitter(wxSize(4, 2), wxColour(0x38, 0x38, 0x38)), 0, wxEXPAND);
|
||||
sizer_->Add(NewSplitter(wxSize(4, 1), wxColour(0, 0, 0)), 0, wxEXPAND);
|
||||
}
|
||||
sizer_->Add(commandbox_, 0, wxEXPAND | wxBOTTOM);
|
||||
if (useWin32DarkHack)
|
||||
|
||||
auto filterBarContainer = _new wxBoxSizer(wxVERTICAL);
|
||||
if (!filterBarContainer) return {};
|
||||
|
||||
auto filterBar = _new wxBoxSizer(wxHORIZONTAL);
|
||||
if (!filterBar) return{};
|
||||
|
||||
auto filterBox = _new wxTextCtrl(this, -1, wxEmptyString,
|
||||
wxDefaultPosition, alt ? wxDefaultSize : wxSize(400, 20),
|
||||
(kTextBoxHandlePad ? wxBORDER_NONE : 0) | wxTE_PROCESS_ENTER | wxEXPAND);
|
||||
if (!filterBox) return{};
|
||||
|
||||
filterBox->SetMinSize({minx, miny});
|
||||
|
||||
if (kTextBoxHandlePad)
|
||||
{
|
||||
filterBarContainer->Add(NewSplitter(wxSize(kTextboxWin32PadOutter, kTextboxWin32PadOutter), kTextBoxOutter), 0, wxEXPAND);
|
||||
filterBarContainer->Add(NewSplitter(wxSize(kTextboxWin32PadInner, kTextboxWin32PadInner), kTextBoxInner), 0, wxEXPAND);
|
||||
}
|
||||
|
||||
filterBarContainer->Add(filterBox, wxSizerFlags().Proportion(1).Expand());
|
||||
|
||||
if (kTextBoxHandleColor)
|
||||
{
|
||||
filterBox->SetBackgroundColour(kBackgroundColor);
|
||||
filterBox->SetForegroundColour(kTextBoxColor);
|
||||
}
|
||||
|
||||
if (kTextBoxHandlePad)
|
||||
{
|
||||
filterBarContainer->Add(NewSplitter(wxSize(kTextboxWin32PadInner, kTextboxWin32PadInner), kTextBoxInner), 0, wxEXPAND);
|
||||
filterBarContainer->Add(NewSplitter(wxSize(kTextboxWin32PadOutter, kTextboxWin32PadOutter), kTextBoxOutter), 0, wxEXPAND);
|
||||
}
|
||||
|
||||
if (kTextBoxHandlePad)
|
||||
{
|
||||
filterBar->Add(NewSplitter(wxSize(kTextboxWin32PadOutter, kTextboxWin32PadOutter), kTextBoxOutter) , 0, wxEXPAND | wxTOP | wxBOTTOM, 1);
|
||||
filterBar->Add(NewSplitter(wxSize(kTextboxWin32PadInner, kTextboxWin32PadInner), kTextBoxInner), 0, wxEXPAND | wxTOP | wxBOTTOM, 1);
|
||||
}
|
||||
|
||||
filterBar->Add(filterBarContainer, wxSizerFlags().Proportion(1).Expand());
|
||||
|
||||
if (kTextBoxHandlePad)
|
||||
{
|
||||
filterBar->Add(NewSplitter(wxSize(kTextboxWin32PadInner, kTextboxWin32PadInner), kTextBoxInner), 0, wxEXPAND | wxTOP | wxBOTTOM, 1);
|
||||
filterBar->Add(NewSplitter(wxSize(kTextboxWin32PadOutter, kTextboxWin32PadOutter), kTextBoxOutter), 0, wxEXPAND | wxTOP | wxBOTTOM, 1);
|
||||
}
|
||||
|
||||
parent->Add(filterBar, wxSizerFlags().Expand());
|
||||
return filterBox;
|
||||
};
|
||||
|
||||
auto header = _new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
auto addHeaderPanel = [&](wxBoxSizer *parent, wxBoxSizer *inner, bool up, bool down, bool left, bool right, int top, int sides)
|
||||
{
|
||||
sizer_->Add(NewSplitter(wxSize(4, 1), wxColour(0, 0, 0)), 0, wxEXPAND);
|
||||
sizer_->Add(NewSplitter(wxSize(4, 2), wxColour(0x38, 0x38, 0x38)), 0, wxEXPAND);
|
||||
auto filterBar = _new wxBoxSizer(wxVERTICAL);
|
||||
if (!filterBar) return;
|
||||
|
||||
auto innerBar = _new wxBoxSizer(wxHORIZONTAL);
|
||||
if (!innerBar) return;
|
||||
|
||||
// PAD FILTER REGION UP
|
||||
if (up)
|
||||
{
|
||||
filterBar->Add(NewSplitter(wxSize(top, top)), wxSizerFlags().Expand());
|
||||
}
|
||||
|
||||
{
|
||||
// PAD FILTER REGION LEFT
|
||||
if (left)
|
||||
{
|
||||
innerBar->Add(NewSplitter(wxSize(sides, sides)), wxSizerFlags().Expand());
|
||||
}
|
||||
|
||||
innerBar->Add(inner, wxSizerFlags().Expand());
|
||||
|
||||
// PAD FILTER REGION RIGHT
|
||||
if (right)
|
||||
{
|
||||
innerBar->Add(NewSplitter(wxSize(sides, sides)), wxSizerFlags().Expand());
|
||||
}
|
||||
}
|
||||
filterBar->Add(innerBar, wxSizerFlags().Expand());
|
||||
|
||||
// PAD FILTER REGION DOWN
|
||||
if (down)
|
||||
{
|
||||
filterBar->Add(NewSplitter(wxSize(top, top)), wxSizerFlags().Expand());
|
||||
}
|
||||
|
||||
parent->Add(filterBar, wxSizerFlags().Expand());
|
||||
};
|
||||
|
||||
this->SetBackgroundColour(kBackgroundColor);
|
||||
|
||||
// HEADER PANEL 1# filter
|
||||
{
|
||||
auto filterBarContainer = _new wxBoxSizer(wxVERTICAL);
|
||||
if (!filterBarContainer) return;
|
||||
|
||||
auto filterLabel = _new wxStaticText(this, -1, "FILTER");
|
||||
if (!filterLabel) return;
|
||||
|
||||
filterLabel->SetFont(font);
|
||||
filterLabel->SetBackgroundColour(kBackgroundColor);
|
||||
filterLabel->SetForegroundColour(kTextBoxColor);
|
||||
|
||||
filterBarContainer->Add(filterLabel);
|
||||
filterBarContainer->Add(NewSplitter(wxSize(kTitleContentSplitterDepth, kTitleContentSplitterDepth)), wxSizerFlags().Expand());
|
||||
|
||||
addTextbox(filterBarContainer, 400, kTextboxHeight);
|
||||
addHeaderPanel(header, filterBarContainer, true, true, true, false, kHeaderPadUpDown, kHeaderPadLeftRight);
|
||||
}
|
||||
|
||||
// Align right
|
||||
header->AddStretchSpacer();
|
||||
|
||||
// Draw a little bar
|
||||
//header->Add(NewSplitter(wxSize(1, 1), wxColour(0x38, 0x38, 0x38)), 0, wxEXPAND);
|
||||
|
||||
// HEADER PANEL 2# levels
|
||||
{
|
||||
AuList<AuString> chkName = {"Debug", "Warn", "Info", "Game"};
|
||||
|
||||
auto checkboxes = _new wxBoxSizer(wxHORIZONTAL);
|
||||
if (!checkboxes) return;
|
||||
|
||||
auto checkboxesContainer = _new wxBoxSizer(wxVERTICAL);
|
||||
if (!checkboxes) return;
|
||||
|
||||
auto checkboxLabel = _new wxStaticText(this, -1, "LEVEL");
|
||||
if (!checkboxLabel) return;
|
||||
|
||||
checkboxLabel->SetFont(font);
|
||||
checkboxLabel->SetBackgroundColour(kBackgroundColor);
|
||||
checkboxLabel->SetForegroundColour(kTextBoxColor);
|
||||
|
||||
for (int i = 0; i < chkName.size(); i++)
|
||||
{
|
||||
const auto &name = chkName[i];
|
||||
|
||||
if (kDrawOwnCheckboxes)
|
||||
{
|
||||
if (i != 0)
|
||||
{
|
||||
checkboxes->Add(NewSplitter(wxSize(6, 6)), wxSizerFlags().Expand());
|
||||
}
|
||||
|
||||
auto label = _new wxStaticText(this, -1, name.c_str());
|
||||
label->SetBackgroundColour(kBackgroundColor);
|
||||
label->SetForegroundColour(kTextBoxColor);
|
||||
label->SetFont(font2);
|
||||
|
||||
checkboxes->Add(label);
|
||||
checkboxes->Add(NewSplitter(wxSize(2, 2)), wxSizerFlags().Expand());
|
||||
}
|
||||
|
||||
auto checkbox1 = new wxCheckBox(this, -1, kDrawOwnCheckboxes ? "" : name.c_str(), wxDefaultPosition, wxDefaultSize);
|
||||
checkbox1->SetFont(font2);
|
||||
checkbox1->SetValue(true);
|
||||
|
||||
checkboxes->Add(NewSplitter(wxSize(2, 2)), wxSizerFlags().Expand());
|
||||
checkboxes->Add(checkbox1, wxSizerFlags(0).CenterVertical().GetFlags());
|
||||
checkboxes->Add(NewSplitter(wxSize(2, 2)), wxSizerFlags().Expand());
|
||||
}
|
||||
|
||||
checkboxesContainer->Add(checkboxLabel);
|
||||
checkboxesContainer->Add(NewSplitter(wxSize(kTitleContentSplitterDepth, kTitleContentSplitterDepth)), wxSizerFlags().Expand());
|
||||
checkboxesContainer->Add(checkboxes);
|
||||
addHeaderPanel(header, checkboxesContainer, true, true, false, true, kHeaderPadUpDown, kHeaderPadLeftRight);
|
||||
}
|
||||
|
||||
sizer_->Add(header, 0, wxEXPAND);
|
||||
|
||||
|
||||
// Shadow down
|
||||
if (/*useWin32DarkHack*/ true)
|
||||
{
|
||||
sizer_->Add(NewSplitter(wxSize(kTextboxWin32PadInner, kTextboxWin32PadInner), kTextBoxInner), 0, wxEXPAND);
|
||||
sizer_->Add(NewSplitter(wxSize(kTextboxWin32PadOutter, kTextboxWin32PadOutter), kTextBoxOutter), 0, wxEXPAND);
|
||||
}
|
||||
|
||||
// Rich text box
|
||||
{
|
||||
richtextbox_ = _new wxRichTextCtrl(this, -1, wxEmptyString,
|
||||
wxDefaultPosition, wxDefaultSize,
|
||||
(kTextBoxHandlePad ? wxBORDER_NONE : 0) | wxTE_MULTILINE | wxRE_READONLY | wxRE_CENTER_CARET);
|
||||
if (!richtextbox_) return;
|
||||
|
||||
if (useWin32DarkHack)
|
||||
{
|
||||
richtextbox_->SetBackgroundColour(kBackgroundColor);
|
||||
richtextbox_->SetForegroundColour(kTextBoxColor);
|
||||
this->Connect(wxEVT_SHOW, wxWindowCreateEventHandler(ConsoleFrame::OnShow));
|
||||
}
|
||||
|
||||
sizer_->Add(richtextbox_, 1, wxEXPAND);
|
||||
}
|
||||
|
||||
// Shadow down
|
||||
if (/*useWin32DarkHack*/ true)
|
||||
{
|
||||
sizer_->Add(NewSplitter(wxSize(kTextboxWin32PadInner, kTextboxWin32PadInner), kTextBoxInner), 0, wxEXPAND);
|
||||
sizer_->Add(NewSplitter(wxSize(kTextboxWin32PadOutter, kTextboxWin32PadOutter), kTextBoxOutter), 0, wxEXPAND);
|
||||
}
|
||||
|
||||
// Command Box
|
||||
{
|
||||
commandbox_ = addTextbox(sizer_, 0, kTextboxHeight, true);
|
||||
commandbox_->SetHint("Type a command here");
|
||||
commandbox_->Connect(wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(ConsoleFrame::OnCmd));
|
||||
}
|
||||
|
||||
|
||||
SetSizer(sizer_);
|
||||
SetMenuBar(menuBar_);
|
||||
// SetAutoLayout(true);
|
||||
|
||||
timer_.Bind(wxEVT_TIMER, &ConsoleFrame::OnPump, this);
|
||||
timer_.Start(100);
|
||||
@ -324,47 +554,46 @@ ConsoleFrame::ConsoleFrame(const wxString &title, const wxPoint &pos, const wxSi
|
||||
}
|
||||
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
#include <Uxtheme.h>
|
||||
#include <Extensions/Win32/DarkTheme.hpp>
|
||||
#include <Uxtheme.h>
|
||||
#include <Extensions/Win32/DarkTheme.hpp>
|
||||
|
||||
static bool DarkModeEnabled()
|
||||
{
|
||||
return Aurora::Extensions::Win32::g_darkModeSupported;
|
||||
}
|
||||
static bool DarkModeEnabled()
|
||||
{
|
||||
return Aurora::Extensions::Win32::g_darkModeSupported;
|
||||
}
|
||||
|
||||
void ConsoleFrame::OnInit(wxWindowCreateEvent &event)
|
||||
{
|
||||
OnShow(event);
|
||||
}
|
||||
void ConsoleFrame::OnInit(wxWindowCreateEvent &event)
|
||||
{
|
||||
OnShow(event);
|
||||
}
|
||||
|
||||
void ConsoleFrame::OnShow(wxWindowCreateEvent &event)
|
||||
{
|
||||
if (!DarkModeEnabled()) return;
|
||||
void ConsoleFrame::OnShow(wxWindowCreateEvent &event)
|
||||
{
|
||||
if (!DarkModeEnabled()) return;
|
||||
|
||||
auto handle = event.GetWindow()->GetHWND();
|
||||
Aurora::Extensions::Win32::AllowDarkModeForWindow(handle, true);
|
||||
auto handle = event.GetWindow()->GetHWND();
|
||||
Aurora::Extensions::Win32::AllowDarkModeForWindow(handle, true);
|
||||
|
||||
if (Aurora::Extensions::Win32::_FlushMenuThemes)
|
||||
Aurora::Extensions::Win32::_FlushMenuThemes();
|
||||
if (Aurora::Extensions::Win32::_FlushMenuThemes)
|
||||
Aurora::Extensions::Win32::_FlushMenuThemes();
|
||||
|
||||
SetWindowTheme(handle, L"DarkMode_Explorer", NULL);
|
||||
SendMessageW(handle, WM_THEMECHANGED, 0, 0);
|
||||
|
||||
Aurora::Extensions::Win32::RefreshTitleBarThemeColor(handle);
|
||||
UpdateWindow(handle);
|
||||
}
|
||||
SetWindowTheme(handle, L"DarkMode_Explorer", NULL);
|
||||
SendMessageW(handle, WM_THEMECHANGED, 0, 0);
|
||||
|
||||
Aurora::Extensions::Win32::RefreshTitleBarThemeColor(handle);
|
||||
UpdateWindow(handle);
|
||||
}
|
||||
#else
|
||||
void ConsoleFrame::OnInit(wxWindowCreateEvent &event)
|
||||
{}
|
||||
void ConsoleFrame::OnInit(wxWindowCreateEvent &event)
|
||||
{}
|
||||
|
||||
void ConsoleFrame::OnShow(wxWindowCreateEvent &event)
|
||||
{}
|
||||
void ConsoleFrame::OnShow(wxWindowCreateEvent &event)
|
||||
{}
|
||||
|
||||
static bool DarkModeEnabled()
|
||||
{
|
||||
return Aurora::Build::EPlatform == Aurora::Build::EPlatform::kPlatformLinux;
|
||||
}
|
||||
static bool DarkModeEnabled()
|
||||
{
|
||||
return Aurora::Build::EPlatform == Aurora::Build::EPlatform::kPlatformLinux;
|
||||
}
|
||||
#endif
|
||||
|
||||
void ConsoleFrame::OnExit(wxCommandEvent &event)
|
||||
@ -403,20 +632,25 @@ namespace Aurora::Console::ConsoleWxWidgets
|
||||
|
||||
static bool UseWxConsole()
|
||||
{
|
||||
if (gRuntimeConfig.console.disableAll)
|
||||
if (gRuntimeConfig.console.disableAllConsoles)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (!gRuntimeConfig.console.enableWxWidgets)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
if (GetConsoleWindow())
|
||||
{
|
||||
if (!gRuntimeConfig.console.forceToolKitWindow)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -464,7 +698,7 @@ namespace Aurora::Console::ConsoleWxWidgets
|
||||
return;
|
||||
}
|
||||
|
||||
Threading::LockGuardPtr re(gMutex.get()); // pupose two of the mutex: locking deconstruction/gWxConsoleReady
|
||||
AU_LOCK_GUARD(gMutex.get()); // pupose two of the mutex: locking deconstruction/gWxConsoleReady
|
||||
// its a horible hack, but -
|
||||
// 1) our dtor comes before the final apps class, and
|
||||
// 2) the app will deregister the top window before the dtor
|
||||
@ -509,10 +743,17 @@ namespace Aurora::Console::ConsoleWxWidgets
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Start();
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
if (std::exchange(gConsoleStarted, true)) return;
|
||||
|
||||
gMutex = Aurora::Threading::Primitives::MutexUnique();
|
||||
|
||||
Aurora::Console::Hooks::AddHook([&](const Aurora::Console::ConsoleMessage &string) -> void
|
||||
Aurora::Console::Hooks::AddFunctionalHook([&](const Aurora::Console::ConsoleMessage &string) -> void
|
||||
{
|
||||
gMutex->Lock();
|
||||
gPendingLines.push_back(string);
|
||||
@ -545,7 +786,7 @@ namespace Aurora::Console::ConsoleWxWidgets
|
||||
|
||||
AuList<Console::ConsoleMessage> lines;
|
||||
{
|
||||
Aurora::Threading::LockGuardPtr re(gMutex.get());
|
||||
AU_LOCK_GUARD(gMutex);
|
||||
lines = std::exchange(gPendingLines, {});
|
||||
}
|
||||
|
||||
@ -557,16 +798,6 @@ namespace Aurora::Console::ConsoleWxWidgets
|
||||
|
||||
void Pump()
|
||||
{
|
||||
#if 0
|
||||
Aurora::Threading::LockGuardPtr re(gMutex.get());
|
||||
|
||||
if (!gWxConsoleReady) return;
|
||||
|
||||
wxTheApp->GetTopWindow()->GetEventHandler()->CallAfter([]()
|
||||
{
|
||||
WxWidgetsPump();
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void Exit()
|
||||
@ -583,6 +814,7 @@ namespace Aurora::Console::ConsoleWxWidgets
|
||||
|
||||
gMutex.reset();
|
||||
gPendingLines.clear();
|
||||
gConsoleStarted = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -593,12 +825,18 @@ namespace Aurora::Console::ConsoleWxWidgets
|
||||
void Init()
|
||||
{
|
||||
}
|
||||
|
||||
void Pump()
|
||||
{
|
||||
}
|
||||
|
||||
void Exit()
|
||||
{
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -11,5 +11,6 @@ namespace Aurora::Console::ConsoleWxWidgets
|
||||
{
|
||||
void Init();
|
||||
void Pump();
|
||||
void Start();
|
||||
void Exit();
|
||||
}
|
94
Source/Console/Flusher.cpp
Normal file
94
Source/Console/Flusher.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: Flusher.cpp
|
||||
Date: 2021-8-27
|
||||
Author: Reece
|
||||
***/
|
||||
#include <RuntimeInternal.hpp>
|
||||
#include "Flusher.hpp"
|
||||
|
||||
#include "ConsoleFIO/ConsoleFIO.hpp"
|
||||
|
||||
namespace Aurora::Console
|
||||
{
|
||||
static Threading::Threads::ThreadUnique_t gWriterThread;
|
||||
|
||||
class ShutdownFlushHook : public Threading::Threads::IThreadFeature
|
||||
{
|
||||
public:
|
||||
void Init() override;
|
||||
void Cleanup() override;
|
||||
};
|
||||
|
||||
void ShutdownFlushHook::Init()
|
||||
{
|
||||
}
|
||||
|
||||
void ShutdownFlushHook::Cleanup()
|
||||
{
|
||||
// Flush all internal consoles on shutdown
|
||||
ForceFlush();
|
||||
}
|
||||
|
||||
static void SlowStartupTasks()
|
||||
{
|
||||
ConsoleFIO::FIOCleanup();
|
||||
}
|
||||
|
||||
static void LogThreadEP()
|
||||
{
|
||||
auto thread = Threading::Threads::GetThread();
|
||||
|
||||
SlowStartupTasks();
|
||||
|
||||
while (!thread->Exiting())
|
||||
{
|
||||
Sleep(500);
|
||||
ForceFlush();
|
||||
}
|
||||
}
|
||||
|
||||
static void DestroyFlushThread()
|
||||
{
|
||||
gWriterThread.reset();
|
||||
}
|
||||
|
||||
static void InitFlushThread()
|
||||
{
|
||||
|
||||
// Startup a runner thread that will take care of all the stress inducing IO every so often on a remote thread
|
||||
Threading::Threads::AbstractThreadVectors handler;
|
||||
handler.DoRun = [](Threading::Threads::IAuroraThread *)
|
||||
{
|
||||
LogThreadEP();
|
||||
};
|
||||
|
||||
gWriterThread = Threading::Threads::ThreadUnique(handler);
|
||||
if (!gWriterThread)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gWriterThread->SetName("CasualConsoleAsyncWritter");
|
||||
gWriterThread->Run();
|
||||
}
|
||||
|
||||
void InitFlusher()
|
||||
{
|
||||
// Add a 'ShutdownFlushHook' object to the main threads TLS hook
|
||||
Threading::Threads::GetThread()->AddLastHopeTlsHook(AuMakeShared<ShutdownFlushHook>());
|
||||
|
||||
InitFlushThread();
|
||||
}
|
||||
|
||||
void DeinitFlusher()
|
||||
{
|
||||
DestroyFlushThread();
|
||||
}
|
||||
|
||||
void ForceFlush()
|
||||
{
|
||||
ConsoleFIO::Flush();
|
||||
}
|
||||
}
|
15
Source/Console/Flusher.hpp
Normal file
15
Source/Console/Flusher.hpp
Normal file
@ -0,0 +1,15 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: Flusher.hpp
|
||||
Date: 2021-8-27
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Console
|
||||
{
|
||||
void ForceFlush();
|
||||
void InitFlusher();
|
||||
void DeinitFlusher();
|
||||
}
|
@ -10,27 +10,43 @@
|
||||
|
||||
namespace Aurora::Console::Hooks
|
||||
{
|
||||
static auto gMutex = Threading::Primitives::MutexUnique();
|
||||
static AuList<Hooks::LineHook_cb> gLineCallbacks;
|
||||
static Threading::Primitives::MutexUnique_t gMutex;
|
||||
static AuList<Hooks::LineHook_cb> gLineFunctionalCallbacks;
|
||||
static AuList<AuSPtr<IConsoleSubscriber>> gLineSubscribers;
|
||||
|
||||
void AddHook(LineHook_cb hook)
|
||||
AUKN_SYM void AddSubscription(const AuSPtr<IConsoleSubscriber> &subscriber)
|
||||
{
|
||||
Aurora::Threading::WaitableLockGuard guard(gMutex.get());
|
||||
gLineCallbacks.push_back(hook);
|
||||
AU_LOCK_GUARD(gMutex);
|
||||
AuTryInsert(gLineSubscribers, subscriber);
|
||||
}
|
||||
|
||||
AUKN_SYM void RemoveSubscription(const AuSPtr<IConsoleSubscriber> &subscriber)
|
||||
{
|
||||
AU_LOCK_GUARD(gMutex);
|
||||
AuTryDeleteList(gLineSubscribers, subscriber);
|
||||
}
|
||||
|
||||
AUKN_SYM void AddFunctionalHook(LineHook_cb hook)
|
||||
{
|
||||
AU_LOCK_GUARD(gMutex);
|
||||
AuTryInsert(gLineFunctionalCallbacks, hook);
|
||||
}
|
||||
|
||||
void WriteLine(const ConsoleMessage &msg)
|
||||
{
|
||||
gMutex->Lock();
|
||||
auto callbacks = gLineCallbacks;
|
||||
gMutex->Unlock();
|
||||
AU_LOCK_GUARD(gMutex);
|
||||
|
||||
if (msg.line.find('\n') == std::string::npos) [[likely]]
|
||||
{
|
||||
for (const auto &callback : callbacks)
|
||||
for (const auto &callback : gLineFunctionalCallbacks)
|
||||
{
|
||||
callback(msg);
|
||||
}
|
||||
|
||||
for (const auto &sub : gLineSubscribers)
|
||||
{
|
||||
sub->OnMessage(msg);
|
||||
}
|
||||
}
|
||||
else [[unlikely]]
|
||||
{
|
||||
@ -39,11 +55,29 @@ namespace Aurora::Console::Hooks
|
||||
{
|
||||
ConsoleMessage dup = msg;
|
||||
dup.line = line;
|
||||
for (const auto &callback : callbacks)
|
||||
|
||||
for (const auto &callback : gLineFunctionalCallbacks)
|
||||
{
|
||||
callback(dup);
|
||||
}
|
||||
|
||||
for (const auto &sub : gLineSubscribers)
|
||||
{
|
||||
sub->OnMessage(dup);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
gMutex = Threading::Primitives::MutexUnique();
|
||||
}
|
||||
|
||||
void Deinit()
|
||||
{
|
||||
gLineFunctionalCallbacks.clear();
|
||||
gLineSubscribers.clear();
|
||||
gMutex.reset();
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user