Aurora Runtime: cross-platform platform-abstraction library - the 100kloc of /base/*.cx nobody wants to write.
Go to file
2022-01-18 19:48:23 +00:00
Include [*] Added an option for leaking strong heap pointers (ToSmartPointer) 2022-01-18 19:31:15 +00:00
Source [*] Fix heap leak -> TryRelease was never called once count hit zero 2022-01-18 19:48:23 +00:00
.gitignore A pretty large patch not worth breaking up into separate commits 2021-11-05 17:34:23 +00:00
Aurora.json [*] Continue to perfer beginthreadex, use CreateThread when the OS loader is locked on Win32 2022-01-18 16:02:24 +00:00
LICENSE [+] Added license 2021-06-30 10:28:35 +01:00
readme.md [+] Added first attempt at the windows version of WaitMultipleObjects/ This will be removed shortly. 2021-11-09 00:04:00 +00:00

IN DEVELOPMENT

AuroraRuntime

The Aurora Runtime is an platform abstraction layer for cross-platform C++ development targeting
embedded and PC systems. Simply fetch a binary package for your toolchain or integrate the build
scripts into your applications build pipeline to get started.

Features

  • Lightweight threading and synchronization primitives
  • Async threading primitives, including WaitMultipleObjects paradigm [WIP]
  • Asynchronous and synchronous IO abstraction
  • Optional event driven async programming paradigm
  • Console; graphical and standard; binary and UTF-8 logger
  • Debug and Telementry; asserts, exception logging, fio, nio backends
  • Crypto ECC/[25519, P-384, P-256], [AES, RSA, X509], [common digests]
  • IPC [WIP]
  • Network
  • Random
  • Hardware Info
  • FIO settings registry
  • Compression
  • Locale and encoding
  • C++ utility templates and macros
  • Follows all strings are UTF-8 convention

API:
Doxygen:
Examples:
Tests:
Cmake-stable:
Build Pipeline:

Utilities

Aurora Sugar: https://git.reece.sx/AuroraSupport/AuroraRuntime/src/branch/master/Include/AuroraUtils.hpp
Aurora Macro Sugar: https://git.reece.sx/AuroraSupport/AuroraRuntime/src/branch/master/Include/AuroraMacros.hpp
Aurora Overloadable Type Declerations: https://git.reece.sx/AuroraSupport/AuroraRuntime/src/branch/master/Include/AuroraTypedefs.hpp

Logging

Aurora Runtime does not attempt to implement your favourite production logger. We instead implement a subscription based log message dispatcher with some default backends including a file logger, Windows debug logging, Windows conhost stdin/out using UTF-8, UNIX stdin/out respecting the applications codepage, a wxWidgets toolkit GUI, and hopefully more to come. Additionally, consoles that provide an input stream can be used in conjunction with the parse subsystem to provide basic command-based deserialization, tokenization, and dispatch of UTF-8 translated strings regardless of the system locale

Loop [WIP]

Aurora Runtime offers a main loop that connects multiple input sources into one delegate.
Timers, semaphores, mutexes, events, X11, FDs, Win32 msg loop, macos, IPC, file aio handles, and
async runner main loop sources will be supported. This equates to a cross-platfom equivalent of
NT's MsgWaitForMultipleObjects in the form of a MainLoop object and a WaitMultiple function.

Thread Primitives

The Aurora Runtime provides platform optimized threading primitives inheriting from a featureful
IWaitable interface. Each method is guaranteed.

IWaitable
   bool TryLock()
   void Lock(relativeTimeoutInMilliseconds)
   void Lock()
   void Unlock() 

Included high performance primitives

  • arbitrary IWaitable condition variable
  • condition mutex : IWaitable
  • condition variable : IWaitable
  • critical section : IWaitable (aka reentrant mutex)
  • event : IWaitable
  • mutex : IWaitable
  • semaphore : IWaitable
  • rwlock (aka shared mutex) IWaitable ::GetRead(), IWaitable ::GetWrite()
  • spinlocks

Problem one (1):
Most STL implementations have generally awful to unnecessarily inefficient abstraction.

Defer to libc++'s abuse of spin while (cond) yield loops and msvc/stl's painfully slow std::mutex and semaphore primitives.

Problem Two (2):
Moving to or from linux, macos, bsd, and win32 under varous kernels, there is no one
standard (even in posix land) for the key thread primitives.

Bonus point NT (3):
The userland CriticalSection/CV set of APIs suck, lacking timeouts and try lock

Bonus point UNIX (4):
No wait multiple mechanism

1, 2, 3: Use the high performance AuThreadPrimitives objects
4: Consider using loop sources, perhaps with the async subsystem, in your async application.
Performance of loop sources will vary wildly between platforms, always being generally worse than
the high performance primitives. They should be used to observe kernel-level signalable resources.
4 ex: Windows developers could use loop sources as a replacement to WaitMultipleObjects with more overhead

Strings

The Aurora Runtime defines an AuString type as an std::string; however, it should be assumed this type
represents a binary blob of UTF-8. Looking to switch to tiny-utf8 for UTF-8 safety.

Memory

User-overloadable type declerations and generic access utilities are defined under utilities
Aurora provides a bring your own container and shared pointer model overloadable in your configuration header.

Types: 
    AuSPtr<Type_t>
    AuWPtr<Type_t>
    AuUPtr<Type_t, Deleter_t>
Functions:
    AuSPtr<T> AuMakeShared<T>(Args&& ...)
    AuSPtr<T> AuUnsafeRaiiToShared<T>(T *)
    AuSPtr<T> AuUnsafeRaiiToShared<T>(AuUPtr<T>) 
Macros:
    AuSPtr<This_T> AuSharedFromThis()
    AuWPtr<This_T> AuWeakFromThis()
    AuFunction<...> AuBindThis(This_t *::?, ...)

Most Aurora Runtime APIs provide generic new and release functions should you not need the overhead of reference counting or unique ptrs
However, strict C codebases would need to shim to C, perhaps using AuUnsafeRaiiToShared to convert T*s to unsafe AuSPtr<T>s, the namespaced C++ functions
It should be noted that most language bindings and generator libraries (^swig, v8pp, nbind, luabind) work with shared pointers.

IO

[TODO] Summary

A note about encoding; stdin, file encoding, text decoders, and other IO resources work with
codepage UTF-8 as the internal encoding scheme. String overloads and dedicated string APIs in
the IO subsystem will always write BOM prefixed UTF-8 and attempt to read a BOM to translate
any other input to UTF-8.

NIO

The networking stack supports a handful of architectural paradigms

  • block on write
  • delegate write to end of network frame on write
  • read with an all-or-nothing flag and an async flag
  • read with an asynchronous stream callback
  • peaking
  • async read/write pump whenever or all

FIO

[TODO] async, fio abstraction, utf8 read/write, blob read/write, stat, dir recursion, stream abstraction

Paths

We assume all paths are messy. Incorrect splitters, double splitters, relative paths, and
keywords are resolved internally. No such URL or path builder, data structure to hold a
tokenized representation, or similar concept exists in the codebase. All string 'paths' are
simply expanded, similar to MSCRT 'fullpath'/UNIX 'realpath', at time of usage.

Path tokens include:
[0] == '.' = cwd
[0] == '~' = platform specific user directory / brand / Profile
[0] == '!' = platform specific app config directory / brand / System
[0] == '?' = ., !, or ~
.. = go back
/ = splitter
\ = splitter

Aurora Async

The Aurora Runtime offers an optional asynchronous task driven model under the AuAsync
namespace. Featuring promises, thread group pooling, functional-to-task wrapping, and
task-completion callback-task-dispatch idioms built around 3 concepts.

Example:

Proccesses

The Aurora Runtime provides worker process monitoring, worker Stdin/out stream redirection,
process spawning, file opening, and url opening functionality.

Locale

Encoding and decoding UTF-8, UTF-16, UTF-32, GBK, GB-2312, and SJIS support using platform
specific APIs. Fetch system language and country backed by environment variables, the OS
system configuration, the unix locale env variable, and/or the provided overload mechanism.

Philosophies

  • Assume C++17 language support in the language driver
  • Solve the large issues nobody is tackling. To avoid reinventing the wheel accept third party
    solutions when the pros (developer time) weighted against the negatives (legal, bulk) makes sense.
  • Use AuXXX type bindings for std types, allow customers to overload the std namespace
  • Keep the code and build chain simple such that any C++ developer could maintain their own software stack built around aurora components.
  • Dependencies should be cross-platform friendly It is recommended to fork and replace any legacy OS specific code with equivalent AuroraRuntime concepts
  • Dependencies, excluding core reference algorithms (eg compression), must be rewritten and phased out over time.
  • Dependencies should not be added if most platforms provide some degree of native support
    Examples:
    -> Don't depend on a pthread shim for windows; implement the best thread
    primitives that lie on the best possible api for them
    Don't depend on ICU when POSIX's iconv and Win32's multibyte apis cover
    everything a conservative developer cares about; chinese, utf-16, utf-8,
    utf-32 conversion, on top of all the ancient windows codepages
  • Dependencies should only be added conservatively when it saves development time and provides production hardening
    Examples:
    -> Use embedded crypto libraries; libtomcrypt, libtommath
    -> While there are some bugs in libtomcrypt and others, none appear to
    cryptographically cripple the library. Could you do better?
    -> Use portable libraries like mbedtls, O(1) heap, mimalloc
    -> Writing a [D]TLS/allocator stack would take too much time
    -> Linking against external allocators, small cross-platform utilities, and
    so on is probably fine
    -> Shim libcurl instead of inventing yet another http stack