Compare commits

...

30 Commits

Author SHA1 Message Date
22e14d760a Use libbacktrace for Linux/macOS 2020-12-16 07:31:39 -05:00
81fb4e4c2d Link debug libnx & remove outdated nxstl includes 2020-10-21 00:35:07 -04:00
Jack Andersen
7f63cabaea Fixes for recent windows SDK changes 2020-08-22 17:28:34 -10:00
41432143fd Only use lm service when LOGVISOR_NX_LM set 2020-05-05 00:14:41 -04:00
Jack Andersen
14ea54f8b5 Add lm service for switch build 2020-05-03 20:09:21 -10:00
Jack Andersen
d62b4ce26e Update fmtlib 2020-04-11 12:44:21 -10:00
Jack Andersen
27814c5276 Exclude CMake CXX standard from MSVC 2020-04-10 18:55:45 -10:00
Jack Andersen
f04a9777eb Merge branch 'master' of ssh://git.axiodl.com:6431/AxioDL/logvisor 2019-09-30 21:21:21 -10:00
Jack Andersen
187c35f3c4 Ensure only one console logger is able to be registered 2019-09-30 21:20:45 -10:00
8c2e711362 Merge pull request #5 from lioncash/noreturn
logvisor: Mark logvisorAbort as [[noreturn]]
2019-09-06 23:26:44 -07:00
Lioncash
63cb911d09 logvisor: Mark logvisorAbort as [[noreturn]]
All variants of logvisorAbort do what they say in their name -- abort.
Given control isn't returned from this function, we can signify that
it's a noreturn function
2019-09-06 07:37:27 -04:00
f623ace3b4 Merge pull request #4 from lioncash/docs
logvisor: Amend documentation comments
2019-08-26 15:55:18 -07:00
8ea97c524c Merge pull request #3 from lioncash/forward
logvisor: std::forward arguments where applicable
2019-08-26 15:55:08 -07:00
81c72ad220 Merge pull request #2 from lioncash/char
logvisor: Use std::fputs/std::fputc where applicable
2019-08-26 15:54:58 -07:00
Lioncash
59f651f24b logvisor: Amend documentation comments
These use fmt-style formatting specifiers, not printf.
2019-08-26 10:57:19 -04:00
Lioncash
2a40c6dc92 logvisor: std::forward arguments where applicable
Forwards arguments into functions to preserve their value category
2019-08-26 10:50:35 -04:00
Lioncash
2f3f06e5ca logvisor: Add missing override specifiers 2019-08-26 10:34:40 -04:00
Lioncash
94d1c558a0 logvisor: Use std::fputs/std::fputc where applicable
We can just use std::fputc when inserting a single character instead of
using std::fputs. Likewise, we can use std::fputs over std::fprintf when
no formatting specifiers are present.
2019-08-26 10:31:45 -04:00
aa9aa0a82c Merge pull request #1 from lioncash/cexpr
logvisor: Make Module constructor constexpr
2019-08-17 22:56:59 -07:00
Lioncash
a57409828c logvisor: Make Module constructor constexpr
Allows the module instances to be constructed at compile time.
Otherwise, this is technically a runtime static constructor when an
instance is declared at file scope.
2019-08-17 19:47:20 -04:00
Jack Andersen
dcd0ffcaec Fix custom formatting of multiple character types 2019-07-25 16:31:54 -10:00
Jack Andersen
3bedd268e8 Integrate libfmt for format strings 2019-07-19 18:21:39 -10:00
Jack Andersen
a0ef17d895 Refactor of CMake for cleaner dependency handling 2019-06-11 15:53:17 -10:00
Jack Andersen
ebe7463e67 Ignore GCC truncation warning 2019-06-09 16:48:06 -10:00
Jack Andersen
7672485d81 Make logvisor publicly link libdl on platforms that have it 2019-05-25 00:14:41 -10:00
Jack Andersen
c54e2596c2 Add cmake package config files 2019-05-22 18:07:58 -10:00
Jack Andersen
c3f34aed0b Update include directory for proper installation 2019-05-22 17:58:40 -10:00
Jack Andersen
a2ffe70b4e Don't kill windows console on abort 2019-05-09 18:06:21 -10:00
Jack Andersen
3da29add5f Implicit switch fallthrough refactor 2019-02-17 19:45:51 -10:00
Jack Andersen
01e291833b New code style refactor 2018-12-07 19:17:15 -10:00
9 changed files with 891 additions and 1183 deletions

6
.gitmodules vendored Normal file
View File

@@ -0,0 +1,6 @@
[submodule "fmt"]
path = fmt
url = https://github.com/fmtlib/fmt
[submodule "libbacktrace"]
path = libbacktrace
url = https://github.com/status-im/libbacktrace.git

View File

@@ -1,8 +1,91 @@
include_directories(include) if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
cmake_minimum_required(VERSION 3.10 FATAL_ERROR) # because of c++17
project(nod VERSION 0.1)
if (NOT MSVC)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
endif()
endif()
include (CMakePackageConfigHelpers)
add_subdirectory(fmt)
add_library(logvisor add_library(logvisor
lib/logvisor.cpp lib/logvisor.cpp
include/logvisor/logvisor.hpp) include/logvisor/logvisor.hpp)
set(LOGVISOR_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include CACHE PATH "logvisor include path" FORCE) if(APPLE OR UNIX)
include(ExternalProject)
find_package(Git REQUIRED)
find_program(MAKE_EXE NAMES gmake make)
ExternalProject_Add(
project_libbacktrace
PREFIX ${PROJECT_BINARY_DIR}/libbacktrace
GIT_REPOSITORY https://github.com/status-im/libbacktrace.git
GIT_TAG 2e878a38dd7144c84b665019b1085ea38ebe56d1
CONFIGURE_COMMAND ${PROJECT_BINARY_DIR}/libbacktrace/src/project_libbacktrace/configure --enable-host-shared --prefix=${PROJECT_BINARY_DIR}/libbacktrace/install --enable-shared=no --enable-static=yes
BUILD_COMMAND ${MAKE_EXE}
INSTALL_COMMAND ${MAKE_EXE} install
BUILD_IN_SOURCE 1
)
add_library(libbacktrace STATIC IMPORTED GLOBAL)
set_target_properties(libbacktrace PROPERTIES IMPORTED_LOCATION "${PROJECT_BINARY_DIR}/libbacktrace/install/lib/libbacktrace.a")
set_target_properties(libbacktrace PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${PROJECT_BINARY_DIR}/libbacktrace/install/include")
# Hack for INTERFACE_INCLUDE_DIRECTORIES propagation
# https://gitlab.kitware.com/cmake/cmake/-/issues/15052
file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/libbacktrace/install/include")
add_dependencies(libbacktrace project_libbacktrace)
set(BACKTRACE_LIBS libbacktrace)
else()
set(BACKTRACE_LIBS "")
endif()
install(DIRECTORY include/logvisor DESTINATION include/logvisor) target_link_libraries(logvisor PUBLIC fmt)
if(NX)
target_link_libraries(logvisor PUBLIC debug nxd optimized nx)
else()
target_link_libraries(logvisor PRIVATE ${CMAKE_DL_LIBS} ${BACKTRACE_LIBS})
endif()
target_include_directories(logvisor PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
install(DIRECTORY include/logvisor DESTINATION include)
install(DIRECTORY fmt/include/fmt DESTINATION include)
set(version_config_file "${PROJECT_BINARY_DIR}/logvisorConfigVersion.cmake")
set(config_file "${PROJECT_BINARY_DIR}/logvisorConfig.cmake")
set(config_install_dir "lib/cmake/logvisor")
# Associate target with export
install(
TARGETS logvisor fmt
EXPORT logvisorTargets
ARCHIVE DESTINATION "lib"
INCLUDES DESTINATION include # This sets the INTERFACE_INCLUDE_DIRECTORIES property of the target.
)
# Install the target config files
install(
EXPORT logvisorTargets
NAMESPACE "logvisor::"
DESTINATION "${config_install_dir}"
)
# Generate version config file
write_basic_package_version_file(
"${version_config_file}"
COMPATIBILITY SameMajorVersion
)
# Generate config file
configure_package_config_file(
"Config.cmake.in"
"${config_file}"
INSTALL_DESTINATION "lib/cmake/logvisor"
)
# Install the config files
install(
FILES "${config_file}" "${version_config_file}"
DESTINATION ${config_install_dir}
)

4
Config.cmake.in Normal file
View File

@@ -0,0 +1,4 @@
@PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/logvisorTargets.cmake")
check_required_components(logvisor)

1
fmt Submodule

Submodule fmt added at 9bdd1596ce

View File

@@ -1,6 +1,5 @@
#pragma once #pragma once
#include <cstdarg>
#include <cstring> #include <cstring>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
@@ -9,16 +8,19 @@
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#ifdef __SWITCH__ #define FMT_STRING_ALIAS 1
#include "nxstl/mutex" #define FMT_ENFORCE_COMPILE_STRING 1
#include <fmt/format.h>
#if defined(__SWITCH__) && !defined(LOGVISOR_NX_LM)
#define LOGVISOR_NX_LM 0
#endif #endif
extern "C" void logvisorBp(); extern "C" void logvisorBp();
namespace logvisor namespace logvisor {
{
void logvisorAbort(); [[noreturn]] void logvisorAbort();
#if _WIN32 && UNICODE #if _WIN32 && UNICODE
#define LOG_UCS2 1 #define LOG_UCS2 1
@@ -30,30 +32,24 @@ extern bool XtermColor;
/** /**
* @brief Severity level for log messages * @brief Severity level for log messages
*/ */
enum Level enum Level {
{ Info, /**< Non-error informative message */
Info, /**< Non-error informative message */ Warning, /**< Non-error warning message */
Warning, /**< Non-error warning message */ Error, /**< Recoverable error message */
Error, /**< Recoverable error message */ Fatal /**< Non-recoverable error message (throws exception) */
Fatal /**< Non-recoverable error message (throws exception) */
}; };
/** /**
* @brief Backend interface for receiving app-wide log events * @brief Backend interface for receiving app-wide log events
*/ */
struct ILogger struct ILogger {
{ virtual ~ILogger() = default;
virtual ~ILogger() {} virtual void report(const char* modName, Level severity, fmt::string_view format, fmt::format_args args) = 0;
virtual void report(const char* modName, Level severity, virtual void report(const char* modName, Level severity, fmt::wstring_view format, fmt::wformat_args args) = 0;
const char* format, va_list ap)=0; virtual void reportSource(const char* modName, Level severity, const char* file, unsigned linenum,
virtual void report(const char* modName, Level severity, fmt::string_view format, fmt::format_args args) = 0;
const wchar_t* format, va_list ap)=0; virtual void reportSource(const char* modName, Level severity, const char* file, unsigned linenum,
virtual void reportSource(const char* modName, Level severity, fmt::wstring_view format, fmt::wformat_args args) = 0;
const char* file, unsigned linenum,
const char* format, va_list ap)=0;
virtual void reportSource(const char* modName, Level severity,
const char* file, unsigned linenum,
const wchar_t* format, va_list ap)=0;
}; };
/** /**
@@ -97,18 +93,16 @@ extern std::atomic_uint_fast64_t FrameIndex;
* *
* Ensures logging streams aren't written concurrently * Ensures logging streams aren't written concurrently
*/ */
struct LogMutex struct LogMutex {
{ bool enabled = true;
bool enabled = true; std::recursive_mutex mutex;
std::recursive_mutex mutex; ~LogMutex() { enabled = false; }
~LogMutex() { enabled = false; } std::unique_lock<std::recursive_mutex> lock() {
std::unique_lock<std::recursive_mutex> lock() if (enabled)
{ return std::unique_lock<std::recursive_mutex>(mutex);
if (enabled) else
return std::unique_lock<std::recursive_mutex>(mutex); return std::unique_lock<std::recursive_mutex>();
else }
return std::unique_lock<std::recursive_mutex>();
}
}; };
extern LogMutex _LogMutex; extern LogMutex _LogMutex;
@@ -116,10 +110,7 @@ extern LogMutex _LogMutex;
* @brief Take a centralized lock for the logging output stream(s) * @brief Take a centralized lock for the logging output stream(s)
* @return RAII mutex lock * @return RAII mutex lock
*/ */
static inline std::unique_lock<std::recursive_mutex> LockLog() inline std::unique_lock<std::recursive_mutex> LockLog() { return _LogMutex.lock(); }
{
return _LogMutex.lock();
}
extern uint64_t _LogCounter; extern uint64_t _LogCounter;
@@ -127,15 +118,12 @@ extern uint64_t _LogCounter;
* @brief Get current count of logging events * @brief Get current count of logging events
* @return Log Count * @return Log Count
*/ */
static inline uint64_t GetLogCounter() inline uint64_t GetLogCounter() { return _LogCounter; }
{
return _LogCounter;
}
/** /**
* @brief Restore centralized logger vector to default state (silent operation) * @brief Restore centralized logger vector to default state (silent operation)
*/ */
static inline void UnregisterLoggers() {MainLoggers.clear();} inline void UnregisterLoggers() { MainLoggers.clear(); }
/** /**
* @brief Construct and register a real-time console logger singleton * @brief Construct and register a real-time console logger singleton
@@ -178,91 +166,141 @@ void RegisterFileLogger(const wchar_t* filepath);
#endif #endif
/** /**
* @brief This is constructed per-subsystem in a locally centralized fashon * @brief This is constructed per-subsystem in a locally centralized fashion
*/ */
class Module class Module {
{ const char* m_modName;
const char* m_modName;
template <typename Char>
void _vreport(Level severity, fmt::basic_string_view<Char> format,
fmt::basic_format_args<fmt::buffer_context<Char>> args) {
auto lk = LockLog();
++_LogCounter;
if (severity == Fatal)
RegisterConsoleLogger();
for (auto& logger : MainLoggers)
logger->report(m_modName, severity, format, args);
if (severity == Error || severity == Fatal)
logvisorBp();
if (severity == Fatal)
logvisorAbort();
else if (severity == Error)
++ErrorCount;
}
template <typename Char>
void _vreportSource(Level severity, const char* file, unsigned linenum, fmt::basic_string_view<Char> format,
fmt::basic_format_args<fmt::buffer_context<Char>> args) {
auto lk = LockLog();
++_LogCounter;
if (severity == Fatal)
RegisterConsoleLogger();
for (auto& logger : MainLoggers)
logger->reportSource(m_modName, severity, file, linenum, format, args);
if (severity == Error || severity == Fatal)
logvisorBp();
if (severity == Fatal)
logvisorAbort();
else if (severity == Error)
++ErrorCount;
}
public: public:
Module(const char* modName) : m_modName(modName) {} constexpr Module(const char* modName) : m_modName(modName) {}
/** /**
* @brief Route new log message to centralized ILogger * @brief Route new log message to centralized ILogger
* @param severity Level of log report severity * @param severity Level of log report severity
* @param format Standard printf-style format string * @param format fmt-style format string
*/ */
template <typename CharType> template <typename S, typename... Args, typename Char = fmt::char_t<S>>
inline void report(Level severity, const CharType* format, ...) void report(Level severity, const S& format, Args&&... args) {
{ if (MainLoggers.empty() && severity != Level::Fatal)
if (MainLoggers.empty() && severity != Level::Fatal) return;
return; _vreport(severity, fmt::to_string_view<Char>(format),
va_list ap; fmt::basic_format_args<fmt::buffer_context<Char>>(
va_start(ap, format); fmt::internal::make_args_checked<Args...>(format, std::forward<Args>(args)...)));
report(severity, format, ap); }
va_end(ap);
}
template <typename CharType> template <typename Char>
inline void report(Level severity, const CharType* format, va_list ap) void vreport(Level severity, fmt::basic_string_view<Char> format,
{ fmt::basic_format_args<fmt::buffer_context<Char>> args) {
auto lk = LockLog(); if (MainLoggers.empty() && severity != Level::Fatal)
++_LogCounter; return;
if (severity == Fatal) _vreport(severity, format, args);
RegisterConsoleLogger(); }
for (auto& logger : MainLoggers)
{
va_list apc;
va_copy(apc, ap);
logger->report(m_modName, severity, format, apc);
va_end(apc);
}
if (severity == Error || severity == Fatal)
logvisorBp();
if (severity == Fatal)
logvisorAbort();
else if (severity == Error)
++ErrorCount;
}
/** /**
* @brief Route new log message with source info to centralized ILogger * @brief Route new log message with source info to centralized ILogger
* @param severity Level of log report severity * @param severity Level of log report severity
* @param file Source file name from __FILE__ macro * @param file Source file name from __FILE__ macro
* @param linenum Source line number from __LINE__ macro * @param linenum Source line number from __LINE__ macro
* @param format Standard printf-style format string * @param format fmt-style format string
*/ */
template <typename CharType> template <typename S, typename... Args, typename Char = fmt::char_t<S>>
inline void reportSource(Level severity, const char* file, unsigned linenum, const CharType* format, ...) void reportSource(Level severity, const char* file, unsigned linenum, const S& format, Args&&... args) {
{ if (MainLoggers.empty() && severity != Level::Fatal)
if (MainLoggers.empty() && severity != Level::Fatal) return;
return; _vreportSource(severity, file, linenum, fmt::to_string_view<Char>(format),
va_list ap; fmt::basic_format_args<fmt::buffer_context<Char>>(
va_start(ap, format); fmt::internal::make_args_checked<Args...>(format, std::forward<Args>(args)...)));
reportSource(severity, file, linenum, format, ap); }
va_end(ap);
}
template <typename CharType> template <typename Char>
inline void reportSource(Level severity, const char* file, unsigned linenum, const CharType* format, va_list ap) void vreportSource(Level severity, const char* file, unsigned linenum, fmt::basic_string_view<Char> format,
{ fmt::basic_format_args<fmt::buffer_context<Char>> args) {
auto lk = LockLog(); if (MainLoggers.empty() && severity != Level::Fatal)
++_LogCounter; return;
if (severity == Fatal) _vreportSource(severity, file, linenum, format, args);
RegisterConsoleLogger(); }
for (auto& logger : MainLoggers)
{
va_list apc;
va_copy(apc, ap);
logger->reportSource(m_modName, severity, file, linenum, format, apc);
va_end(apc);
}
if (severity == Fatal)
logvisorAbort();
else if (severity == Error)
++ErrorCount;
}
}; };
#define FMT_CUSTOM_FORMATTER(tp, fmtstr, ...) \
namespace fmt { \
template <> \
struct formatter<tp, char> { \
template <typename ParseContext> \
constexpr auto parse(ParseContext &ctx) { return ctx.begin(); } \
template <typename FormatContext> \
auto format(const tp &obj, FormatContext &ctx) { \
return format_to(ctx.out(), FMT_STRING(fmtstr), __VA_ARGS__); \
} \
}; \
template <> \
struct formatter<tp, wchar_t> { \
template <typename ParseContext> \
constexpr auto parse(ParseContext &ctx) { return ctx.begin(); } \
template <typename FormatContext> \
auto format(const tp &obj, FormatContext &ctx) { \
return format_to(ctx.out(), FMT_STRING(L##fmtstr), __VA_ARGS__); \
} \
}; \
template <> \
struct formatter<tp, char16_t> { \
template <typename ParseContext> \
constexpr auto parse(ParseContext &ctx) { return ctx.begin(); } \
template <typename FormatContext> \
auto format(const tp &obj, FormatContext &ctx) { \
return format_to(ctx.out(), FMT_STRING(u##fmtstr), __VA_ARGS__); \
} \
}; \
template <> \
struct formatter<tp, char32_t> { \
template <typename ParseContext> \
constexpr auto parse(ParseContext &ctx) { return ctx.begin(); } \
template <typename FormatContext> \
auto format(const tp &obj, FormatContext &ctx) { \
return format_to(ctx.out(), FMT_STRING(U##fmtstr), __VA_ARGS__); \
} \
}; \
} }
} // namespace logvisor
template <typename S, typename... Args, typename Char = fmt::char_t<S>>
void quicklog(const S& format, Args&&... args) {
logvisor::MainLoggers[0]->report(
"quick", logvisor::Info, fmt::to_string_view<Char>(format),
fmt::basic_format_args<fmt::buffer_context<Char>>(
fmt::internal::make_args_checked<Args...>(format, std::forward<Args>(args)...)));
}

View File

@@ -1,155 +0,0 @@
#ifndef _NXSTL_CONDVAR
#define _NXSTL_CONDVAR 1
#ifdef __SWITCH__
extern "C" {
#include <switch/kernel/condvar.h>
#include <switch/result.h>
}
#include <chrono>
#include <bits/std_mutex.h>
#include <ext/concurrence.h>
#include <bits/alloc_traits.h>
#include <bits/allocator.h>
#include <bits/unique_ptr.h>
#include <bits/shared_ptr.h>
#include <bits/cxxabi_forced.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
/// cv_status
enum class cv_status { no_timeout, timeout };
/// condition_variable
class condition_variable
{
typedef chrono::system_clock __clock_t;
typedef CondVar __native_type;
__native_type _M_cond = {};
public:
typedef __native_type* native_handle_type;
constexpr condition_variable() noexcept = default;
~condition_variable() noexcept = default;
condition_variable(const condition_variable&) = delete;
condition_variable& operator=(const condition_variable&) = delete;
void
notify_one() noexcept
{
condvarWakeOne(&_M_cond);
}
void
notify_all() noexcept
{
condvarWakeAll(&_M_cond);
}
void
wait(unique_lock<mutex>& __lock) noexcept
{
condvarWait(&_M_cond, __lock.mutex()->native_handle());
}
template<typename _Predicate>
void
wait(unique_lock<mutex>& __lock, _Predicate __p)
{
while (!__p())
wait(__lock);
}
template<typename _Duration>
cv_status
wait_until(unique_lock<mutex>& __lock,
const chrono::time_point<__clock_t, _Duration>& __atime)
{ return __wait_until_impl(__lock, __atime); }
template<typename _Clock, typename _Duration>
cv_status
wait_until(unique_lock<mutex>& __lock,
const chrono::time_point<_Clock, _Duration>& __atime)
{
// DR 887 - Sync unknown clock to known clock.
const typename _Clock::time_point __c_entry = _Clock::now();
const __clock_t::time_point __s_entry = __clock_t::now();
const auto __delta = __atime - __c_entry;
const auto __s_atime = __s_entry + __delta;
return __wait_until_impl(__lock, __s_atime);
}
template<typename _Clock, typename _Duration, typename _Predicate>
bool
wait_until(unique_lock<mutex>& __lock,
const chrono::time_point<_Clock, _Duration>& __atime,
_Predicate __p)
{
while (!__p())
if (wait_until(__lock, __atime) == cv_status::timeout)
return __p();
return true;
}
template<typename _Rep, typename _Period>
cv_status
wait_for(unique_lock<mutex>& __lock,
const chrono::duration<_Rep, _Period>& __rtime)
{
using __dur = typename __clock_t::duration;
auto __reltime = chrono::duration_cast<__dur>(__rtime);
if (__reltime < __rtime)
++__reltime;
return wait_until(__lock, __clock_t::now() + __reltime);
}
template<typename _Rep, typename _Period, typename _Predicate>
bool
wait_for(unique_lock<mutex>& __lock,
const chrono::duration<_Rep, _Period>& __rtime,
_Predicate __p)
{
using __dur = typename __clock_t::duration;
auto __reltime = chrono::duration_cast<__dur>(__rtime);
if (__reltime < __rtime)
++__reltime;
return wait_until(__lock, __clock_t::now() + __reltime, std::move(__p));
}
native_handle_type
native_handle()
{ return &_M_cond; }
private:
template<typename _Dur>
cv_status
__wait_until_impl(unique_lock<mutex>& __lock,
const chrono::time_point<__clock_t, _Dur>& __atime)
{
auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime);
Result res = condvarWaitTimeout(&_M_cond, __lock.mutex()->native_handle(), __ns.count());
if (R_DESCRIPTION(res) == KernelError_Timeout)
return cv_status::timeout;
return cv_status::no_timeout;
}
};
void
notify_all_at_thread_exit(condition_variable&, unique_lock<mutex>);
struct __at_thread_exit_elt
{
__at_thread_exit_elt* _M_next;
void (*_M_cb)(void*);
};
}
#endif
#endif

View File

@@ -1,112 +0,0 @@
#ifndef _NXSTL_MUTEX
#define _NXSTL_MUTEX 1
#ifdef __SWITCH__
extern "C" {
#include <switch/kernel/mutex.h>
}
namespace std _GLIBCXX_VISIBILITY(default)
{
// Common base class for std::mutex
class __mutex_base
{
protected:
typedef Mutex __native_type;
__native_type _M_mutex = {};
constexpr __mutex_base() noexcept = default;
__mutex_base(const __mutex_base&) = delete;
__mutex_base& operator=(const __mutex_base&) = delete;
};
/// The standard mutex type.
class mutex : private __mutex_base
{
public:
typedef __native_type* native_handle_type;
constexpr mutex() noexcept = default;
~mutex() = default;
mutex(const mutex&) = delete;
mutex& operator=(const mutex&) = delete;
void
lock()
{
mutexLock(&_M_mutex);
}
bool
try_lock() noexcept
{
return mutexTryLock(&_M_mutex);
}
void
unlock()
{
mutexUnlock(&_M_mutex);
}
native_handle_type
native_handle() noexcept
{ return &_M_mutex; }
};
// Common base class for std::recursive_mutex
class __recursive_mutex_base
{
protected:
typedef RMutex __native_type;
__recursive_mutex_base(const __recursive_mutex_base&) = delete;
__recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete;
__native_type _M_mutex = {};
__recursive_mutex_base() = default;
};
/// The standard recursive mutex type.
class recursive_mutex : private __recursive_mutex_base
{
public:
typedef __native_type* native_handle_type;
constexpr recursive_mutex() = default;
~recursive_mutex() = default;
recursive_mutex(const recursive_mutex&) = delete;
recursive_mutex& operator=(const recursive_mutex&) = delete;
void
lock()
{
rmutexLock(&_M_mutex);
}
bool
try_lock() noexcept
{
return rmutexTryLock(&_M_mutex);
}
void
unlock()
{
rmutexUnlock(&_M_mutex);
}
native_handle_type
native_handle() noexcept
{ return &_M_mutex; }
};
}
#endif
#endif

View File

@@ -1,295 +0,0 @@
#ifndef _NXSTL_THREAD
#define _NXSTL_THREAD 1
#ifdef __SWITCH__
extern "C" {
#include <switch/kernel/thread.h>
#include <switch/arm/tls.h>
#include <switch/result.h>
}
#include <memory>
namespace std _GLIBCXX_VISIBILITY(default)
{
/// thread
class thread
{
public:
// Abstract base class for types that wrap arbitrary functors to be
// invoked in the new thread of execution.
struct _State
{
virtual ~_State() = default;
virtual void _M_run() = 0;
};
using _State_ptr = unique_ptr<_State>;
typedef Thread native_handle_type;
/// thread::id
class id
{
native_handle_type _M_thread;
public:
id() noexcept : _M_thread() { }
explicit
id(native_handle_type __id) : _M_thread(__id) { }
private:
friend class thread;
friend class hash<thread::id>;
friend bool
operator==(thread::id __x, thread::id __y) noexcept;
friend bool
operator<(thread::id __x, thread::id __y) noexcept;
template<class _CharT, class _Traits>
friend basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __out, thread::id __id);
};
private:
id _M_id;
public:
thread() noexcept = default;
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2097. packaged_task constructors should be constrained
thread(thread&) = delete;
thread(const thread&) = delete;
thread(const thread&&) = delete;
thread(thread&& __t) noexcept
{ swap(__t); }
template<typename _Callable, typename... _Args>
explicit
thread(_Callable&& __f, _Args&&... __args)
{
_M_start_thread(_S_make_state(
__make_invoker(std::forward<_Callable>(__f),
std::forward<_Args>(__args)...)));
}
~thread()
{
if (joinable())
std::terminate();
}
thread& operator=(const thread&) = delete;
thread& operator=(thread&& __t) noexcept
{
if (joinable())
std::terminate();
swap(__t);
return *this;
}
void
swap(thread& __t) noexcept
{ std::swap(_M_id, __t._M_id); }
bool
joinable() const noexcept
{ return !(_M_id == id()); }
void
join()
{
threadWaitForExit(&_M_id._M_thread);
_M_id = id();
}
void
detach()
{
_M_id = id();
}
thread::id
get_id() const noexcept
{ return _M_id; }
/** @pre thread is joinable
*/
native_handle_type
native_handle()
{ return _M_id._M_thread; }
// Returns a value that hints at the number of hardware thread contexts.
static unsigned int
hardware_concurrency() noexcept
{
return 3;
}
private:
template<typename _Callable>
struct _State_impl : public _State
{
_Callable _M_func;
_State_impl(_Callable&& __f) : _M_func(std::forward<_Callable>(__f))
{ }
void
_M_run() { _M_func(); }
};
static void
execute_native_thread_routine(void *arg)
{
reinterpret_cast<_State*>(arg)->_M_run();
}
void
_M_start_thread(_State_ptr state)
{
Result res = threadCreate(&_M_id._M_thread, execute_native_thread_routine,
state.get(), 8192, 0x2B, -2);
if (R_FAILED(res))
__throw_system_error(res);
res = threadStart(&_M_id._M_thread);
if (R_FAILED(res))
__throw_system_error(res);
state.release();
}
template<typename _Callable>
static _State_ptr
_S_make_state(_Callable&& __f)
{
using _Impl = _State_impl<_Callable>;
return _State_ptr{new _Impl{std::forward<_Callable>(__f)}};
}
private:
// A call wrapper that does INVOKE(forwarded tuple elements...)
template<typename _Tuple>
struct _Invoker
{
_Tuple _M_t;
template<size_t _Index>
static __tuple_element_t<_Index, _Tuple>&&
_S_declval();
template<size_t... _Ind>
auto
_M_invoke(_Index_tuple<_Ind...>)
noexcept(noexcept(std::__invoke(_S_declval<_Ind>()...)))
-> decltype(std::__invoke(_S_declval<_Ind>()...))
{ return std::__invoke(std::get<_Ind>(std::move(_M_t))...); }
using _Indices
= typename _Build_index_tuple<tuple_size<_Tuple>::value>::__type;
auto
operator()()
noexcept(noexcept(std::declval<_Invoker&>()._M_invoke(_Indices())))
-> decltype(std::declval<_Invoker&>()._M_invoke(_Indices()))
{ return _M_invoke(_Indices()); }
};
template<typename... _Tp>
using __decayed_tuple = tuple<typename std::decay<_Tp>::type...>;
public:
// Returns a call wrapper that stores
// tuple{DECAY_COPY(__callable), DECAY_COPY(__args)...}.
template<typename _Callable, typename... _Args>
static _Invoker<__decayed_tuple<_Callable, _Args...>>
__make_invoker(_Callable&& __callable, _Args&&... __args)
{
return { __decayed_tuple<_Callable, _Args...>{
std::forward<_Callable>(__callable), std::forward<_Args>(__args)...
} };
}
};
inline void
swap(thread& __x, thread& __y) noexcept
{ __x.swap(__y); }
inline bool
operator==(thread::id __x, thread::id __y) noexcept
{
// pthread_equal is undefined if either thread ID is not valid, so we
// can't safely use __gthread_equal on default-constructed values (nor
// the non-zero value returned by this_thread::get_id() for
// single-threaded programs using GNU libc). Assume EqualityComparable.
return __x._M_thread.handle == __y._M_thread.handle;
}
inline bool
operator!=(thread::id __x, thread::id __y) noexcept
{ return !(__x == __y); }
inline bool
operator<(thread::id __x, thread::id __y) noexcept
{
// Pthreads doesn't define any way to do this, so we just have to
// assume native_handle_type is LessThanComparable.
return __x._M_thread.handle < __y._M_thread.handle;
}
inline bool
operator<=(thread::id __x, thread::id __y) noexcept
{ return !(__y < __x); }
inline bool
operator>(thread::id __x, thread::id __y) noexcept
{ return __y < __x; }
inline bool
operator>=(thread::id __x, thread::id __y) noexcept
{ return !(__x < __y); }
// DR 889.
/// std::hash specialization for thread::id.
template<>
struct hash<thread::id>
: public __hash_base<size_t, thread::id>
{
size_t
operator()(const thread::id& __id) const noexcept
{ return std::_Hash_impl::hash(__id._M_thread); }
};
template<class _CharT, class _Traits>
inline basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __out, thread::id __id)
{
if (__id == thread::id())
return __out << "thread::id of a non-executing thread";
else
return __out << __id._M_thread;
}
namespace this_thread
{
/// get_id
inline thread::id
get_id() noexcept
{
Thread ret;
uint8_t* tls = (uint8_t*)armGetTls();
uint8_t* threadCtx = *(uint8_t**)(tls + 0x1F8);
ret.handle = *(Handle*)(threadCtx + 0x1B8);
ret.stack_mem = *(void**)(threadCtx + 0x48);
ret.stack_mirror = *(void**)(threadCtx + 0x50);
ret.stack_sz = *(size_t*)(threadCtx + 0x58);
return thread::id(ret);
}
}
}
#endif
#endif

File diff suppressed because it is too large Load Diff