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
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:
21
Telegram/lib_crl/crl/winapi/crl_winapi_async.cpp
Normal file
21
Telegram/lib_crl/crl/winapi/crl_winapi_async.cpp
Normal 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
|
||||
50
Telegram/lib_crl/crl/winapi/crl_winapi_async.h
Normal file
50
Telegram/lib_crl/crl/winapi/crl_winapi_async.h
Normal 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
|
||||
66
Telegram/lib_crl/crl/winapi/crl_winapi_dll.h
Normal file
66
Telegram/lib_crl/crl/winapi/crl_winapi_dll.h
Normal 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
|
||||
47
Telegram/lib_crl/crl/winapi/crl_winapi_fp_exceptions.cpp
Normal file
47
Telegram/lib_crl/crl/winapi/crl_winapi_fp_exceptions.cpp
Normal 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
|
||||
23
Telegram/lib_crl/crl/winapi/crl_winapi_fp_exceptions.h
Normal file
23
Telegram/lib_crl/crl/winapi/crl_winapi_fp_exceptions.h
Normal 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
|
||||
92
Telegram/lib_crl/crl/winapi/crl_winapi_list.cpp
Normal file
92
Telegram/lib_crl/crl/winapi/crl_winapi_list.cpp
Normal 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
|
||||
101
Telegram/lib_crl/crl/winapi/crl_winapi_list.h
Normal file
101
Telegram/lib_crl/crl/winapi/crl_winapi_list.h
Normal 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
|
||||
39
Telegram/lib_crl/crl/winapi/crl_winapi_semaphore.cpp
Normal file
39
Telegram/lib_crl/crl/winapi/crl_winapi_semaphore.cpp
Normal 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
|
||||
47
Telegram/lib_crl/crl/winapi/crl_winapi_semaphore.h
Normal file
47
Telegram/lib_crl/crl/winapi/crl_winapi_semaphore.h
Normal 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
|
||||
50
Telegram/lib_crl/crl/winapi/crl_winapi_time.cpp
Normal file
50
Telegram/lib_crl/crl/winapi/crl_winapi_time.cpp
Normal 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
|
||||
13
Telegram/lib_crl/crl/winapi/crl_winapi_windows_h.h
Normal file
13
Telegram/lib_crl/crl/winapi/crl_winapi_windows_h.h
Normal 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
|
||||
Reference in New Issue
Block a user