Compare commits
4 Commits
1208f1f59f
...
2d5a7316f1
| Author | SHA1 | Date | |
|---|---|---|---|
| 2d5a7316f1 | |||
| cf45aaa39a | |||
| def8d0b6b8 | |||
| f7daa58b38 |
@ -19,7 +19,6 @@
|
|||||||
#pragma comment(lib, "kernel32")
|
#pragma comment(lib, "kernel32")
|
||||||
extern "C" __declspec(dllimport) void __stdcall DebugBreak();
|
extern "C" __declspec(dllimport) void __stdcall DebugBreak();
|
||||||
#define MIJIN_TRAP() DebugBreak()
|
#define MIJIN_TRAP() DebugBreak()
|
||||||
#define MIJIN_FUNC() __FUNCSIG__
|
|
||||||
#else // _WIN32
|
#else // _WIN32
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#define MIJIN_TRAP() \
|
#define MIJIN_TRAP() \
|
||||||
@ -34,7 +33,6 @@ extern "C" __declspec(dllimport) void __stdcall DebugBreak();
|
|||||||
: "rcx", "r11", "memory" \
|
: "rcx", "r11", "memory" \
|
||||||
); \
|
); \
|
||||||
}
|
}
|
||||||
#define MIJIN_FUNC() "" // TODO: __PRETTY_FUNCTION__ is not working for some reason -.-
|
|
||||||
#endif // !_WIN32
|
#endif // !_WIN32
|
||||||
|
|
||||||
namespace mijin
|
namespace mijin
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include "../internal/common.hpp"
|
#include "../internal/common.hpp"
|
||||||
#include "../util/annot.hpp"
|
#include "../util/annot.hpp"
|
||||||
|
#include "../util/iterators.hpp"
|
||||||
|
|
||||||
namespace mijin
|
namespace mijin
|
||||||
{
|
{
|
||||||
@ -126,11 +127,8 @@ public:
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
BaseLogger(const BaseLogger&) = default;
|
BaseLogger(const BaseLogger&) = default;
|
||||||
|
|
||||||
BaseLogger(BaseLogger&&) = default;
|
BaseLogger(BaseLogger&&) = default;
|
||||||
|
|
||||||
BaseLogger& operator=(const BaseLogger&) = default;
|
BaseLogger& operator=(const BaseLogger&) = default;
|
||||||
|
|
||||||
BaseLogger& operator=(BaseLogger&&) = default;
|
BaseLogger& operator=(BaseLogger&&) = default;
|
||||||
|
|
||||||
void addSink(sink_t& sink)
|
void addSink(sink_t& sink)
|
||||||
@ -158,12 +156,28 @@ public:
|
|||||||
|
|
||||||
template<typename... TArgs>
|
template<typename... TArgs>
|
||||||
void log(const level_t& level, const channel_t& channel, std::source_location sourceLocation,
|
void log(const level_t& level, const channel_t& channel, std::source_location sourceLocation,
|
||||||
std::basic_format_string<char_t, std::type_identity_t<TArgs>...> fmt, TArgs&& ... args) const
|
std::basic_format_string<char_t, std::type_identity_t<TArgs>...> fmt, TArgs&& ... args) const MIJIN_NOEXCEPT
|
||||||
MIJIN_NOEXCEPT_IF(noexcept(std::declval<allocator_t>().allocate(1)))
|
|
||||||
{
|
{
|
||||||
string_t buffer(allocator_t(mSinks.get_allocator()));
|
// TODO: make the logger use a traits struct to make this adjustable
|
||||||
std::format_to(std::back_inserter(buffer), fmt, std::forward<TArgs>(args)...);
|
static constexpr std::size_t BUFFER_SIZE = 256;
|
||||||
log(level, channel, std::move(sourceLocation), buffer.c_str());
|
std::array<char_t, BUFFER_SIZE> buffer;
|
||||||
|
|
||||||
|
// first try to write into a buffer on the stack
|
||||||
|
FixedArrayOutputIterator itAfter = std::format_to(FixedArrayOutputIterator(buffer), fmt, std::forward<TArgs>(args)...);
|
||||||
|
*itAfter = '\0';
|
||||||
|
++itAfter;
|
||||||
|
if (!itAfter.didOverflow())
|
||||||
|
{
|
||||||
|
log(level, channel, std::move(sourceLocation), buffer.data());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if that didn't work, allocate more space
|
||||||
|
const std::size_t newBufferSize = itAfter.getCounter();
|
||||||
|
char_t* newBuffer = static_cast<char_t*>(alloca(newBufferSize * sizeof(char_t)));
|
||||||
|
const std::format_to_n_result result = std::format_to_n(newBuffer, newBufferSize - 1, fmt, std::forward<TArgs>(args)...);
|
||||||
|
*result.out = '\0';
|
||||||
|
log(level, channel, std::move(sourceLocation), newBuffer);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -4,8 +4,18 @@
|
|||||||
#if !defined(MIJIN_UTIL_COMMON_MACROS_HPP_INCLUDED)
|
#if !defined(MIJIN_UTIL_COMMON_MACROS_HPP_INCLUDED)
|
||||||
#define MIJIN_UTIL_COMMON_MACROS_HPP_INCLUDED 1
|
#define MIJIN_UTIL_COMMON_MACROS_HPP_INCLUDED 1
|
||||||
|
|
||||||
|
#include "../detect.hpp"
|
||||||
|
|
||||||
#define MIJIN_CONCAT_DETAIL(a, b) a ## b
|
#define MIJIN_CONCAT_DETAIL(a, b) a ## b
|
||||||
#define MIJIN_CONCAT(a, b) MIJIN_CONCAT_DETAIL(a, b)
|
#define MIJIN_CONCAT(a, b) MIJIN_CONCAT_DETAIL(a, b)
|
||||||
#define MIJIN_CONCAT3(a, b, c) MIJIN_CONCAT(a, MIJIN_CONCAT(b, c))
|
#define MIJIN_CONCAT3(a, b, c) MIJIN_CONCAT(a, MIJIN_CONCAT(b, c))
|
||||||
|
|
||||||
|
#if MIJIN_COMPILER == MIJIN_COMPILER_GCC || MIJIN_COMPILER == MIJIN_COMPILER_CLANG
|
||||||
|
#define MIJIN_FUNCNAME() __PRETTY_FUNCTION__
|
||||||
|
#elif MIJIN_COMPILER == MIJIN_COMPILER_MSVC
|
||||||
|
#define MIJIN_FUNCNAME() __FUNCSIG__
|
||||||
|
#else
|
||||||
|
#define MIJIN_FUNCNAME() __func__
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // defined(MIJIN_UTIL_COMMON_MACROS_HPP_INCLUDED)
|
#endif // defined(MIJIN_UTIL_COMMON_MACROS_HPP_INCLUDED)
|
||||||
@ -13,6 +13,7 @@
|
|||||||
#include <variant>
|
#include <variant>
|
||||||
#include "../container/optional.hpp"
|
#include "../container/optional.hpp"
|
||||||
#include "../internal/common.hpp"
|
#include "../internal/common.hpp"
|
||||||
|
#include "../util/annot.hpp"
|
||||||
|
|
||||||
namespace mijin
|
namespace mijin
|
||||||
{
|
{
|
||||||
@ -855,6 +856,64 @@ TAs collect(TIterable&& iterable)
|
|||||||
return TAs(iterable.begin(), iterable.end());
|
return TAs(iterable.begin(), iterable.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename TEle, std::size_t numEles>
|
||||||
|
class FixedArrayOutputIterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using array_t = std::array<TEle, numEles>;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using value_type = TEle;
|
||||||
|
using pointer = value_type*;
|
||||||
|
using reference = value_type&;
|
||||||
|
|
||||||
|
static constexpr std::size_t NUM_ELES = numEles;
|
||||||
|
private:
|
||||||
|
not_null_t<array_t*> array_;
|
||||||
|
std::size_t counter_ = 0;
|
||||||
|
public:
|
||||||
|
constexpr explicit FixedArrayOutputIterator(array_t& array) MIJIN_NOEXCEPT : array_(&array) {}
|
||||||
|
constexpr explicit FixedArrayOutputIterator(array_t& array, array_t::iterator pos) MIJIN_NOEXCEPT
|
||||||
|
: array_(&array), counter_(static_cast<std::size_t>(pos - array.begin())) {}
|
||||||
|
constexpr FixedArrayOutputIterator(const FixedArrayOutputIterator&) noexcept = default;
|
||||||
|
|
||||||
|
constexpr FixedArrayOutputIterator& operator=(const FixedArrayOutputIterator&) noexcept = default;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr std::size_t getCounter() const MIJIN_NOEXCEPT
|
||||||
|
{
|
||||||
|
return counter_;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr bool didOverflow() const MIJIN_NOEXCEPT
|
||||||
|
{
|
||||||
|
return counter_ >= NUM_ELES;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr reference operator*() const MIJIN_NOEXCEPT
|
||||||
|
{
|
||||||
|
static TEle dummy_; // returned when we're at the end of the array
|
||||||
|
if (counter_ < NUM_ELES) {
|
||||||
|
return array_->at(counter_);
|
||||||
|
}
|
||||||
|
return dummy_;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr FixedArrayOutputIterator& operator++() MIJIN_NOEXCEPT
|
||||||
|
{
|
||||||
|
++counter_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr FixedArrayOutputIterator operator++(int) const MIJIN_NOEXCEPT
|
||||||
|
{
|
||||||
|
FixedArrayOutputIterator copy(*this);
|
||||||
|
++copy;
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static_assert(std::output_iterator<FixedArrayOutputIterator<int, 1>, int>);
|
||||||
|
|
||||||
namespace pipe
|
namespace pipe
|
||||||
{
|
{
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@ -973,7 +1032,7 @@ auto operator|(TIterable&& iterable, Xth<idx>)
|
|||||||
{
|
{
|
||||||
return map(std::forward<TIterable>(iterable), [](auto&& element) { return std::get<idx>(element); } );
|
return map(std::forward<TIterable>(iterable), [](auto&& element) { return std::get<idx>(element); } );
|
||||||
}
|
}
|
||||||
}
|
} // namespace pipe
|
||||||
} // namespace mijin
|
} // namespace mijin
|
||||||
|
|
||||||
#endif // MIJIN_UTIL_ITERATORS_HPP_INCLUDED
|
#endif // MIJIN_UTIL_ITERATORS_HPP_INCLUDED
|
||||||
@ -10,6 +10,7 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <time.h>
|
||||||
#elif MIJIN_TARGET_OS == MIJIN_OS_WINDOWS
|
#elif MIJIN_TARGET_OS == MIJIN_OS_WINDOWS
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
@ -42,7 +43,16 @@ namespace mijin
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
std::mutex gDlErrorMutex; // dlerror may not be thread-safe
|
std::mutex gDlErrorMutex; // dlerror may not be thread-safe
|
||||||
}
|
|
||||||
|
const std::uint64_t gCPUClockResolution = []()
|
||||||
|
{
|
||||||
|
struct timespec time;
|
||||||
|
[[maybe_unused]] const int result = clock_getres(CLOCK_PROCESS_CPUTIME_ID, &time);
|
||||||
|
MIJIN_ASSERT(result == 0, "Error getting cputime resolution.");
|
||||||
|
MIJIN_ASSERT(time.tv_sec == 0, "What kind of cpu clock is this?");
|
||||||
|
return static_cast<std::uint64_t>(time.tv_nsec);
|
||||||
|
}();
|
||||||
|
};
|
||||||
#endif // MIJIN_TARGET_OS == MIJIN_OS_LINUX
|
#endif // MIJIN_TARGET_OS == MIJIN_OS_LINUX
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -178,4 +188,26 @@ void alignedFree(void* ptr)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::uint64_t getCPUTicks() MIJIN_NOEXCEPT
|
||||||
|
{
|
||||||
|
#if MIJIN_TARGET_OS == MIJIN_OS_LINUX
|
||||||
|
struct timespec time;
|
||||||
|
[[maybe_unused]] const int result = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time);
|
||||||
|
MIJIN_ASSERT(result == 0, "Error getting cpu time.");
|
||||||
|
return (static_cast<std::uint64_t>(time.tv_sec) * 1e9 + time.tv_nsec) / gCPUClockResolution;
|
||||||
|
#else
|
||||||
|
MIJIN_ERROR("TODO");
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint64_t getCPUTicksPerSecond() MIJIN_NOEXCEPT
|
||||||
|
{
|
||||||
|
#if MIJIN_TARGET_OS == MIJIN_OS_LINUX
|
||||||
|
return 1e9 / gCPUClockResolution;
|
||||||
|
#else
|
||||||
|
MIJIN_ERROR("TODO");
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
} // namespace mijin
|
} // namespace mijin
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
#define MIJIN_UTIL_OS_HPP_INCLUDED 1
|
#define MIJIN_UTIL_OS_HPP_INCLUDED 1
|
||||||
|
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@ -85,6 +86,9 @@ void setCurrentThreadName(const char* threadName) MIJIN_NOEXCEPT;
|
|||||||
[[nodiscard]] void* alignedRealloc(void* ptr, std::size_t alignment, std::size_t size) MIJIN_NOEXCEPT;
|
[[nodiscard]] void* alignedRealloc(void* ptr, std::size_t alignment, std::size_t size) MIJIN_NOEXCEPT;
|
||||||
void alignedFree(void* ptr);
|
void alignedFree(void* ptr);
|
||||||
|
|
||||||
|
[[nodiscard]] std::uint64_t getCPUTicks() MIJIN_NOEXCEPT;
|
||||||
|
[[nodiscard]] std::uint64_t getCPUTicksPerSecond() MIJIN_NOEXCEPT;
|
||||||
|
|
||||||
SharedLibrary::~SharedLibrary() MIJIN_NOEXCEPT
|
SharedLibrary::~SharedLibrary() MIJIN_NOEXCEPT
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user