init
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled

This commit is contained in:
allhaileris
2026-02-16 15:50:16 +03:00
commit afb81b8278
13816 changed files with 3689732 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
// This file is part of Desktop App Toolkit,
// a set of libraries for developing nice desktop applications.
//
// For license and copyright information please follow this link:
// https://github.com/desktop-app/legal/blob/master/LEGAL
//
#include <crl/winapi/crl_winapi_async.h>
#ifdef CRL_USE_WINAPI
#include <concrt.h>
namespace crl::details {
void async_plain(void (*callable)(void*), void *argument) {
Concurrency::CurrentScheduler::ScheduleTask(callable, argument);
}
} // namespace crl::details
#endif // CRL_USE_WINAPI

View File

@@ -0,0 +1,50 @@
// This file is part of Desktop App Toolkit,
// a set of libraries for developing nice desktop applications.
//
// For license and copyright information please follow this link:
// https://github.com/desktop-app/legal/blob/master/LEGAL
//
#pragma once
#include <crl/common/crl_common_config.h>
#ifdef CRL_USE_WINAPI
#include <crl/common/crl_common_utils.h>
#include <crl/common/crl_common_sync.h>
#include <type_traits>
namespace crl::details {
void async_plain(void (*callable)(void*), void *argument);
} // namespace crl::details
namespace crl {
template <
typename Callable,
typename Return = decltype(std::declval<Callable>()())>
inline void async(Callable &&callable) {
using Function = std::decay_t<Callable>;
if constexpr (details::is_plain_function_v<Function, Return>) {
using Plain = Return(*)();
const auto copy = static_cast<Plain>(callable);
details::async_plain([](void *passed) {
const auto callable = reinterpret_cast<Plain>(passed);
(*callable)();
}, reinterpret_cast<void*>(copy));
} else {
const auto copy = new Function(std::forward<Callable>(callable));
details::async_plain([](void *passed) {
const auto callable = static_cast<Function*>(passed);
const auto guard = details::finally([=] { delete callable; });
(*callable)();
}, static_cast<void*>(copy));
}
}
} // namespace crl
#endif // CRL_USE_WINAPI

View File

@@ -0,0 +1,66 @@
// This file is part of Desktop App Toolkit,
// a set of libraries for developing nice desktop applications.
//
// For license and copyright information please follow this link:
// https://github.com/desktop-app/legal/blob/master/LEGAL
//
#pragma once
#include <crl/common/crl_common_config.h>
#ifdef CRL_USE_WINAPI
#include <exception>
#include <crl/winapi/crl_winapi_windows_h.h>
namespace crl::details {
class dll {
public:
enum class own_policy {
owner,
load_and_leak,
use_existing,
};
dll(LPCWSTR library, own_policy policy)
: _handle((policy == own_policy::use_existing)
? GetModuleHandle(library)
: LoadLibrary(library))
, _policy(policy) {
}
template <typename Function>
bool try_load(Function &function, const char *name) const {
if (!_handle) {
return false;
}
function = reinterpret_cast<Function>(GetProcAddress(_handle, name));
return (function != nullptr);
}
template <typename Function>
void load(Function &function, const char *name) const {
if (!try_load(function, name)) {
Failed();
}
}
~dll() {
if (_handle && _policy == own_policy::owner) {
FreeLibrary(_handle);
}
}
private:
[[noreturn]] static void Failed() {
std::terminate();
}
HMODULE _handle = nullptr;
own_policy _policy = own_policy::use_existing;
};
} // namespace crl::details
#endif // CRL_USE_WINAPI

View File

@@ -0,0 +1,47 @@
// This file is part of Desktop App Toolkit,
// a set of libraries for developing nice desktop applications.
//
// For license and copyright information please follow this link:
// https://github.com/desktop-app/legal/blob/master/LEGAL
//
#include <crl/crl_time.h>
#ifdef CRL_USE_WINAPI_TIME
#ifdef CRL_THROW_FP_EXCEPTIONS
#include <float.h>
#pragma fenv_access (on)
namespace crl {
void toggle_fp_exceptions(bool throwing) {
// Allow throwing (and reporting) floating point exceptions.
//
// Otherwise x86 build behaves unpredictably on old hardware,
// after an fp-error it may fail some benign operations, like
// std::round(1.) giving 'nan' or double -> int64 giving int64_min.
//
// This results in unexpected assertion violations.
auto state = (unsigned int)0;
// Right now catch only division by zero and invalid operations.
const auto bits = (throwing ? 0 : (_EM_ZERODIVIDE | _EM_INVALID))
| _EM_DENORMAL | _EM_INEXACT | _EM_UNDERFLOW | _EM_OVERFLOW;
_controlfp_s(&state, bits, _MCW_EM);
}
} // namespace crl
#else // CRL_THROW_FP_EXCEPTIONS
namespace crl {
void toggle_fp_exceptions(bool throwing) {
}
} // namespace crl
#endif // CRL_THROW_FP_EXCEPTIONS
#endif // CRL_USE_WINAPI_TIME

View File

@@ -0,0 +1,23 @@
// This file is part of Desktop App Toolkit,
// a set of libraries for developing nice desktop applications.
//
// For license and copyright information please follow this link:
// https://github.com/desktop-app/legal/blob/master/LEGAL
//
#pragma once
#include <crl/common/crl_common_config.h>
#ifdef CRL_USE_WINAPI
#include <crl/common/crl_common_utils.h>
#include <crl/common/crl_common_sync.h>
#include <type_traits>
namespace crl {
void toggle_fp_exceptions(bool throwing);
} // namespace crl
#endif // CRL_USE_WINAPI

View File

@@ -0,0 +1,92 @@
// This file is part of Desktop App Toolkit,
// a set of libraries for developing nice desktop applications.
//
// For license and copyright information please follow this link:
// https://github.com/desktop-app/legal/blob/master/LEGAL
//
#include <crl/winapi/crl_winapi_list.h>
#ifdef CRL_USE_WINAPI_LIST
#include <crl/winapi/crl_winapi_dll.h>
#include <crl/winapi/crl_winapi_windows_h.h>
namespace crl::details {
namespace {
PSLIST_HEADER UnwrapList(void *wrapped) {
return static_cast<PSLIST_HEADER>(wrapped);
}
PSLIST_ENTRY UnwrapEntry(void *wrapped) {
return static_cast<PSLIST_ENTRY>(wrapped);
}
SLIST_ENTRY *ReverseList(SLIST_ENTRY *entry, SLIST_ENTRY *next) {
entry->Next = nullptr;
do {
auto third = next->Next;
next->Next = entry;
entry = next;
next = third;
} while (next);
return entry;
}
PSLIST_ENTRY (NTAPI *RtlFirstEntrySList)(const SLIST_HEADER *ListHead) = nullptr;
} // namespace
list::list()
: _impl(std::make_unique<lock_free_list>())
, _alive(new bool(true)) {
static auto initialize = [] {
const auto library = details::dll(
L"ntdll.dll",
details::dll::own_policy::load_and_leak);
library.load(RtlFirstEntrySList, "RtlFirstEntrySList");
return true;
}(); // TODO crl::once?..
static_assert(alignof(lock_free_list) == MEMORY_ALLOCATION_ALIGNMENT);
static_assert(alignof(lock_free_list) >= alignof(SLIST_HEADER));
static_assert(sizeof(lock_free_list) == sizeof(SLIST_HEADER));
InitializeSListHead(UnwrapList(_impl.get()));
}
bool list::push_entry(BasicEntry *entry) {
return (InterlockedPushEntrySList(
UnwrapList(_impl.get()),
UnwrapEntry(&entry->plain)) == nullptr);
}
bool list::empty() const {
return RtlFirstEntrySList(UnwrapList(_impl.get())) == nullptr;
}
bool list::process() {
if (auto entry = InterlockedFlushSList(UnwrapList(_impl.get()))) {
const auto alive = _alive;
if (const auto next = entry->Next) {
entry = ReverseList(entry, next);
}
do {
const auto basic = reinterpret_cast<BasicEntry*>(entry);
entry = entry->Next;
basic->process(basic);
if (!*alive) {
delete alive;
return false;
}
} while (entry);
}
return true;
}
list::~list() {
*_alive = false;
}
} // namespace crl::details
#endif // CRL_USE_WINAPI_LIST

View File

@@ -0,0 +1,101 @@
// This file is part of Desktop App Toolkit,
// a set of libraries for developing nice desktop applications.
//
// For license and copyright information please follow this link:
// https://github.com/desktop-app/legal/blob/master/LEGAL
//
#pragma once
#include <crl/common/crl_common_config.h>
#ifdef CRL_USE_WINAPI_LIST
#include <crl/common/crl_common_utils.h>
#include <crl/crl_semaphore.h>
#ifndef CRL_USE_WINAPI
#error "This file should not be included by client-code directly."
#endif // CRL_USE_WINAPI
namespace crl::details {
class list {
public:
list();
list(const list &other) = delete;
list &operator=(const list &other) = delete;
template <typename Callable>
bool push_is_first(Callable &&callable) {
return push_entry(AllocateEntry(std::forward<Callable>(callable)));
}
bool process();
bool empty() const;
~list();
private:
#if defined CRL_WINAPI_X64
static constexpr auto kLockFreeAlignment = 16;
#elif defined CRL_WINAPI_X86 // CRL_WINAPI_X64
static constexpr auto kLockFreeAlignment = 8;
#else // CRL_WINAPI_X86
#error "Configuration is not supported."
#endif // !CRL_WINAPI_X86 && !CRL_WINAPI_X64
// Hide WinAPI SLIST_HEADER
struct alignas(kLockFreeAlignment) lock_free_list {
void *Next__; // Hide WinAPI SLIST_ENTRY
unsigned short Depth__; // Hide WinAPI WORD
unsigned short CpuId__; // Hide WinAPI WORD
};
struct alignas(kLockFreeAlignment) BasicEntry;
using ProcessEntryMethod = void(*)(BasicEntry *entry);
struct alignas(kLockFreeAlignment) BasicEntry {
void *plain; // Hide WinAPI SLIST_ENTRY
ProcessEntryMethod process;
};
static_assert(std::is_trivial_v<BasicEntry>);
static_assert(std::is_standard_layout_v<BasicEntry>);
static_assert(offsetof(BasicEntry, plain) == 0);
template <typename Function>
struct Entry : BasicEntry {
Entry(Function &&function) : function(std::move(function)) {
}
Entry(const Function &function) : function(function) {
}
Function function;
static void Process(BasicEntry *entry) {
auto full = static_cast<Entry*>(entry);
auto guard = details::finally([=] { delete full; });
full->function();
}
};
template <typename Callable>
static Entry<std::decay_t<Callable>> *AllocateEntry(
Callable &&callable) {
using Function = std::decay_t<Callable>;
using Type = Entry<Function>;
auto result = new Type(std::forward<Callable>(callable));
result->process = &Type::Process;
return result;
}
bool push_entry(BasicEntry *entry);
const std::unique_ptr<lock_free_list> _impl;
bool *_alive = nullptr;
};
} // namespace crl::details
#endif // CRL_USE_WINAPI_LIST

View File

@@ -0,0 +1,39 @@
// This file is part of Desktop App Toolkit,
// a set of libraries for developing nice desktop applications.
//
// For license and copyright information please follow this link:
// https://github.com/desktop-app/legal/blob/master/LEGAL
//
#include <crl/winapi/crl_winapi_semaphore.h>
#ifdef CRL_USE_WINAPI
#include <crl/winapi/crl_winapi_windows_h.h>
namespace crl {
auto semaphore::implementation::create() -> pointer {
auto result = CreateSemaphore(nullptr, 0, 1, nullptr);
if (!result) {
std::terminate();
}
return result;
}
void semaphore::implementation::operator()(pointer value) {
if (value) {
CloseHandle(value);
}
};
void semaphore::acquire() {
WaitForSingleObject(_handle.get(), INFINITE);
}
void semaphore::release() {
ReleaseSemaphore(_handle.get(), 1, nullptr);
}
} // namespace crl
#endif // CRL_USE_WINAPI

View File

@@ -0,0 +1,47 @@
// This file is part of Desktop App Toolkit,
// a set of libraries for developing nice desktop applications.
//
// For license and copyright information please follow this link:
// https://github.com/desktop-app/legal/blob/master/LEGAL
//
#pragma once
#include <crl/common/crl_common_config.h>
#ifdef CRL_USE_WINAPI
#include <memory>
namespace crl {
class semaphore {
public:
semaphore() : _handle(implementation::create()) {
}
semaphore(const semaphore &other) = delete;
semaphore &operator=(const semaphore &other) = delete;
semaphore(semaphore &&other) noexcept
: _handle(std::move(other._handle)) {
}
semaphore &operator=(semaphore &&other) noexcept {
_handle = std::move(other._handle);
return *this;
}
void acquire();
void release();
private:
// Hide WinAPI HANDLE
struct implementation {
using pointer = void*;
static pointer create();
void operator()(pointer value);
};
std::unique_ptr<implementation::pointer, implementation> _handle;
};
} // namespace crl
#endif // CRL_USE_WINAPI

View File

@@ -0,0 +1,50 @@
// This file is part of Desktop App Toolkit,
// a set of libraries for developing nice desktop applications.
//
// For license and copyright information please follow this link:
// https://github.com/desktop-app/legal/blob/master/LEGAL
//
#include <crl/crl_time.h>
#ifdef CRL_USE_WINAPI_TIME
#include <crl/winapi/crl_winapi_windows_h.h>
namespace crl::details {
namespace {
double Frequency/* = 0.*/;
double ProfileFrequency/* = 0.*/;
} // namespace
void init() {
LARGE_INTEGER value;
QueryPerformanceFrequency(&value);
Frequency = 1000. / double(value.QuadPart);
ProfileFrequency = 1000000. / double(value.QuadPart);
}
inner_time_type current_value() {
LARGE_INTEGER value;
QueryPerformanceCounter(&value);
return value.QuadPart;
}
time convert(inner_time_type value) {
return time(value * Frequency);
}
inner_profile_type current_profile_value() {
LARGE_INTEGER value;
QueryPerformanceCounter(&value);
return value.QuadPart;
}
profile_time convert_profile(inner_profile_type value) {
return profile_time(value * ProfileFrequency);
}
} // namespace crl::details
#endif // CRL_USE_WINAPI_TIME

View File

@@ -0,0 +1,13 @@
// This file is part of Desktop App Toolkit,
// a set of libraries for developing nice desktop applications.
//
// For license and copyright information please follow this link:
// https://github.com/desktop-app/legal/blob/master/LEGAL
//
#pragma once
#include <windows.h>
#ifdef small
#undef small
#endif // small