Merge remote-tracking branch 'origin/1.4.10' into 1.4.10

# Conflicts:
#	CMakeLists.txt
This commit is contained in:
WolverinDEV 2021-04-15 03:28:52 +02:00
commit 2747c67f44
5 changed files with 133 additions and 5 deletions

View File

@ -88,7 +88,7 @@ if (MSVC)
CMAKE_C_FLAGS_RELEASE
)
foreach(CompilerFlag ${CompilerFlags})
string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}")
string(REGEX REPLACE "/M[DT]d?" "/MT" ${CompilerFlag} "${${CompilerFlag}}")
endforeach()
add_compile_options("/EHsc") #We require exception handling
else()
@ -173,6 +173,12 @@ set(HEADER_FILES
src/channel/TreeView.h
)
if(NOT ThreadPool_FOUND)
set(SOURCE_FILES ${SOURCE_FILES}
src/misc/threads.cpp
)
endif()
if(FEATURE_LOGGING)
set(SOURCE_FILES ${SOURCE_FILES}
src/log/LogUtils.cpp

View File

@ -3,9 +3,10 @@
//
#include "./task_executor.h"
#include <ThreadPool/ThreadHelper.h>
#include "./threads.h"
#include <cassert>
#include <iostream>
#include <algorithm>
using std::chrono::system_clock;
using namespace ts;
@ -315,7 +316,7 @@ void task_executor::executor(std::shared_ptr<executor_context> executor_context)
continue;
}
auto execute_timestamp = system_clock::now();
auto execute_timestamp = std::chrono::system_clock::now();
std::chrono::system_clock::time_point next_timestamp{};
if(task_context->task_recurring_head) {
if(task_context->task_recurring_head->scheduled_invoke <= execute_timestamp) {
@ -338,7 +339,9 @@ void task_executor::executor(std::shared_ptr<executor_context> executor_context)
}
task->last_invoked = execute_timestamp;
task->scheduled_invoke = std::max(system_clock::now(), execute_timestamp + task->interval);
auto expected_next_invoke = execute_timestamp + std::chrono::duration_cast<std::chrono::system_clock::duration>(task->interval);
task->scheduled_invoke = std::max(std::chrono::system_clock::now(), expected_next_invoke);
task_lock.lock();
executor_context->executing_recurring_task = nullptr;

93
src/misc/threads.cpp Normal file
View File

@ -0,0 +1,93 @@
#include "./threads.h"
#include <system_error>
#ifdef WIN32
#include <Windows.h>
#else
#include <pthread.h>
#endif
std::string threads::name(std::thread &thread) {
#ifdef WIN32
static std::string _empty{};
return _empty;
#else
char buffer[255]; /* min 16 characters */
pthread_getname_np(thread.native_handle(), buffer, 255);
return std::string{buffer};
#endif
}
bool threads::name(std::thread &thread, const std::string_view &name) {
#ifdef WIN32
return false;
#else
char buffer[255]; /* min 16 characters */
memcpy(buffer, name.data(), name.length());
buffer[name.length()] = '\0';
buffer[16] = '\0'; /* cut of the name after 16 characters */
auto error = pthread_setname_np(thread.native_handle(), buffer);
return error == 0;
#endif
}
bool threads::save_join(std::thread &thread, bool rd) {
try {
if(thread.joinable())
thread.join();
} catch(const std::system_error& ex) {
if(ex.code() == std::errc::resource_deadlock_would_occur) {
if(rd)
return false;
throw;
} else if(ex.code() == std::errc::no_such_process) {
return false;
} else if(ex.code() == std::errc::invalid_argument) {
return false;
} else {
throw;
}
}
return true;
}
bool threads::timed_join(std::thread &thread, const std::chrono::nanoseconds &timeout) {
#ifdef WIN32
auto result = WaitForSingleObject(thread.native_handle(), (DWORD) std::chrono::floor<std::chrono::milliseconds>(timeout).count());
if(result != 0)
return false;
if(thread.joinable())
thread.join();
return result;
#else
struct timespec ts{};
if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
return false; /* failed to get clock time */
auto seconds = std::chrono::floor<std::chrono::seconds>(timeout);
auto nanoseconds = std::chrono::ceil<std::chrono::nanoseconds>(timeout) - seconds;
ts.tv_sec += seconds.count();
ts.tv_nsec += nanoseconds.count();
if(ts.tv_nsec >= 1e9) {
ts.tv_sec += 1;
ts.tv_nsec -= 1e9;
}
auto result = pthread_timedjoin_np(thread.native_handle(), nullptr, &ts);
if(result > 0 && result != ESRCH) return false;
/* let the std lib set their flags */
std::thread _empty{}; /* could be destroyed even with an "active" thread handle because we overwrote the std::terminate() function with a macro */
_empty = std::move(thread);
/*
* Undefined behaviour:
* We destroy everything in a non trivial class,
* But when we take a closer look its just a wrapper around the native_handle type which could be an DWORD or a pthread_t which are both trivial destructible!
*/
memset(&_empty, 0, sizeof(_empty)); // NOLINT(bugprone-undefined-memory-manipulation)
return true;
#endif
}

26
src/misc/threads.h Normal file
View File

@ -0,0 +1,26 @@
#pragma once
#include <thread>
#include <string>
#include <string_view>
namespace threads {
extern bool name(std::thread& /* thread */, const std::string_view& /* name */);
extern std::string name(std::thread& /* thread */);
/*
* This function will not throw an error if the thread has already been joined.
* It returns true if join succeeded, false on any error (like thread has already be joined)
*/
extern bool save_join(std::thread& /* thread */, bool /* ignore resource deadlock */ = false);
extern bool timed_join(std::thread& /* thread */, const std::chrono::nanoseconds& /* timeout */);
template <typename Clock>
inline bool timed_join(std::thread& thread, const std::chrono::time_point<Clock>& timeout) {
auto now = Clock::now();
if(now > timeout)
timeout = now;
return timed_join(thread, timeout - now);
}
}

View File

@ -1,6 +1,6 @@
//#define NO_OPEN_SSL /* because we're lazy and dont want to build this lib extra for the TeaClient */
#define FIXEDINT_H_INCLUDED /* else it will be included by ge */
#include <stdint.h>
#include <cstdint>
#include <ed25519/ge.h>
#include <ed25519/ed25519.h>
#include <mutex>