重新设置代码格式

This commit is contained in:
2026-06-25 15:44:25 +08:00
parent 4669ba9c6b
commit d1f0f6e836
77 changed files with 9557 additions and 9416 deletions
+299 -275
View File
@@ -29,8 +29,8 @@
#endif
#if defined(_MSC_VER) && defined(_CRTDBG_MAP_ALLOC)
#include <cstdlib>
#include <crtdbg.h>
#include <cstdlib>
#endif
#ifdef _USE_GTEST
@@ -39,328 +39,352 @@
namespace Psc {
namespace {
bool local_time_from_time_t(std::time_t value, std::tm& out) noexcept {
bool local_time_from_time_t(std::time_t value, std::tm &out) noexcept {
#if defined(_WIN32)
// MinGW / Clang / MSVC 对 localtime_s 支持不完全一致,这里统一用带锁的 std::localtime。
static std::mutex mtx;
std::lock_guard<std::mutex> lock(mtx);
std::tm* tmp = std::localtime(&value);
if (!tmp) {
return false;
}
out = *tmp;
return true;
// MinGW / Clang / MSVC 对 localtime_s 支持不完全一致,这里统一用带锁的
// std::localtime。
static std::mutex mtx;
std::lock_guard<std::mutex> lock(mtx);
std::tm *tmp = std::localtime(&value);
if (!tmp) {
return false;
}
out = *tmp;
return true;
#elif defined(__unix__) || defined(__APPLE__)
return ::localtime_r(&value, &out) != nullptr;
return ::localtime_r(&value, &out) != nullptr;
#else
std::tm* tmp = std::localtime(&value);
if (!tmp) {
return false;
}
out = *tmp;
return true;
std::tm *tmp = std::localtime(&value);
if (!tmp) {
return false;
}
out = *tmp;
return true;
#endif
}
}
} // namespace
std::uint64_t get_current_millisecond_timestamp() {
const auto now = std::chrono::system_clock::now();
const auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
now.time_since_epoch());
return static_cast<std::uint64_t>(duration.count());
}
std::uint64_t get_current_millisecond_timestamp() {
const auto now = std::chrono::system_clock::now();
const auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
return static_cast<std::uint64_t>(duration.count());
}
int redict_main_with_gtest(int argc, char* argv[], Main_Function_Type main_func) {
int redict_main_with_gtest(int argc, char *argv[],
Main_Function_Type main_func) {
#if defined(_MSC_VER) && defined(_CRTDBG_MAP_ALLOC)
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
set_console_utf8();
set_console_utf8();
if (argc == 1) {
if (argc == 1) {
#ifdef _USE_GTEST
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
#else
return main_func(argc, argv);
return main_func(argc, argv);
#endif
}
}
const int new_argc = argc - 1;
char** new_argv = &argv[1];
const int new_argc = argc - 1;
char **new_argv = &argv[1];
int ret = 0;
int ret = 0;
#ifdef _USE_GTEST
const std::string type = argv[1];
if (type != "main") {
::testing::InitGoogleTest(&argc, argv);
ret = RUN_ALL_TESTS();
} else {
ret = main_func(new_argc, new_argv);
}
const std::string type = argv[1];
if (type != "main") {
::testing::InitGoogleTest(&argc, argv);
ret = RUN_ALL_TESTS();
} else {
ret = main_func(new_argc, new_argv);
}
#else
ret = main_func(new_argc, new_argv);
ret = main_func(new_argc, new_argv);
#endif
#if defined(_MSC_VER) && defined(_CRTDBG_MAP_ALLOC)
if (_CrtDumpMemoryLeaks()) {
std::cout << "[CRT] Detected memory leaks.\n";
} else {
std::cout << "[CRT] No memory leaks detected.\n";
}
if (_CrtDumpMemoryLeaks()) {
std::cout << "[CRT] Detected memory leaks.\n";
} else {
std::cout << "[CRT] No memory leaks detected.\n";
}
#endif
std::cout << "ecap ret: " << ret << std::endl;
return ret;
std::cout << "ecap ret: " << ret << std::endl;
return ret;
}
std::string get_exe_dir() {
const std::string exe_path = get_exe_path();
if (exe_path.empty()) {
return "";
}
return std::filesystem::path(exe_path).parent_path().string();
}
std::string get_abs_path(const std::string &path) {
if (path.empty()) {
return path;
}
if (path.rfind("@", 0) == 0) {
return get_exe_dir() + path.substr(1);
}
if (path.rfind("~", 0) == 0) {
return get_home_dir() + path.substr(1);
}
return path;
}
std::string utc_2_local_time(std::time_t us_timestamp, const char *format) {
std::tm local_tm{};
if (!local_time_from_time_t(us_timestamp, local_tm)) {
return "invalid_time";
}
std::ostringstream oss;
oss << std::put_time(&local_tm, format ? format : "%H:%M:%S");
return oss.str();
}
namespace {
constexpr std::uint8_t alphabet_map[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
constexpr std::uint8_t invalid_base64 = 255;
constexpr std::uint8_t decode_char(unsigned char ch) noexcept {
return (ch >= 'A' && ch <= 'Z') ? static_cast<std::uint8_t>(ch - 'A')
: (ch >= 'a' && ch <= 'z') ? static_cast<std::uint8_t>(ch - 'a' + 26)
: (ch >= '0' && ch <= '9') ? static_cast<std::uint8_t>(ch - '0' + 52)
: (ch == '+') ? 62
: (ch == '/') ? 63
: (ch == '=') ? 64
: invalid_base64;
}
std::uint32_t base64_encode_raw(const std::uint8_t *text,
std::uint32_t text_len, std::uint8_t *encode) {
std::uint32_t i = 0;
std::uint32_t j = 0;
for (; i + 3 <= text_len; i += 3) {
encode[j++] = alphabet_map[text[i] >> 2];
encode[j++] = alphabet_map[((text[i] << 4) & 0x30) | (text[i + 1] >> 4)];
encode[j++] =
alphabet_map[((text[i + 1] << 2) & 0x3c) | (text[i + 2] >> 6)];
encode[j++] = alphabet_map[text[i + 2] & 0x3f];
}
if (i < text_len) {
const std::uint32_t tail = text_len - i;
if (tail == 1) {
encode[j++] = alphabet_map[text[i] >> 2];
encode[j++] = alphabet_map[(text[i] << 4) & 0x30];
encode[j++] = '=';
encode[j++] = '=';
} else {
encode[j++] = alphabet_map[text[i] >> 2];
encode[j++] = alphabet_map[((text[i] << 4) & 0x30) | (text[i + 1] >> 4)];
encode[j++] = alphabet_map[(text[i + 1] << 2) & 0x3c];
encode[j++] = '=';
}
}
return j;
}
std::uint32_t base64_decode_raw(const std::uint8_t *code,
std::uint32_t code_len, std::uint8_t *plain) {
if (!code || !plain || (code_len & 0x03U) != 0U) {
return 0;
}
std::uint32_t j = 0;
for (std::uint32_t i = 0; i < code_len; i += 4) {
const std::uint8_t q0 = decode_char(code[i]);
const std::uint8_t q1 = decode_char(code[i + 1]);
const std::uint8_t q2 = decode_char(code[i + 2]);
const std::uint8_t q3 = decode_char(code[i + 3]);
if (q0 >= 64 || q1 >= 64) {
return j;
}
std::string get_exe_dir() {
const std::string exe_path = get_exe_path();
if (exe_path.empty()) {
return "";
}
return std::filesystem::path(exe_path).parent_path().string();
plain[j++] = static_cast<std::uint8_t>((q0 << 2) | (q1 >> 4));
if (q2 == 64) {
break;
}
if (q2 > 64) {
return j;
}
std::string get_abs_path(const std::string& path) {
if (path.empty()) {
return path;
}
plain[j++] = static_cast<std::uint8_t>((q1 << 4) | (q2 >> 2));
if (path.rfind("@", 0) == 0) {
return get_exe_dir() + path.substr(1);
}
if (path.rfind("~", 0) == 0) {
return get_home_dir() + path.substr(1);
}
return path;
if (q3 == 64) {
break;
}
if (q3 > 64) {
return j;
}
std::string utc_2_local_time(std::time_t us_timestamp, const char* format) {
std::tm local_tm{};
if (!local_time_from_time_t(us_timestamp, local_tm)) {
return "invalid_time";
}
plain[j++] = static_cast<std::uint8_t>((q2 << 6) | q3);
}
std::ostringstream oss;
oss << std::put_time(&local_tm, format ? format : "%H:%M:%S");
return oss.str();
}
return j;
}
} // namespace
namespace {
constexpr std::uint8_t alphabet_map[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
constexpr std::uint8_t invalid_base64 = 255;
std::string base64_encode(const std::string &data) {
const auto text_len = static_cast<std::uint32_t>(data.size());
std::vector<std::uint8_t> encode(4 * ((text_len + 2) / 3));
const std::uint32_t encoded_len =
base64_encode_raw(reinterpret_cast<const std::uint8_t *>(data.data()),
text_len, encode.data());
return std::string(encode.begin(), encode.begin() + encoded_len);
}
constexpr std::uint8_t decode_char(unsigned char ch) noexcept {
return (ch >= 'A' && ch <= 'Z') ? static_cast<std::uint8_t>(ch - 'A') :
(ch >= 'a' && ch <= 'z') ? static_cast<std::uint8_t>(ch - 'a' + 26) :
(ch >= '0' && ch <= '9') ? static_cast<std::uint8_t>(ch - '0' + 52) :
(ch == '+') ? 62 :
(ch == '/') ? 63 :
(ch == '=') ? 64 :
invalid_base64;
}
std::string base64_decode(const std::string &data) {
const auto code_len = static_cast<std::uint32_t>(data.size());
if ((code_len & 0x03U) != 0U) {
return "";
}
std::uint32_t base64_encode_raw(const std::uint8_t* text, std::uint32_t text_len, std::uint8_t* encode) {
std::uint32_t i = 0;
std::uint32_t j = 0;
std::vector<std::uint8_t> plain(code_len * 3 / 4);
const std::uint32_t decoded_len =
base64_decode_raw(reinterpret_cast<const std::uint8_t *>(data.data()),
code_len, plain.data());
return std::string(plain.begin(), plain.begin() + decoded_len);
}
for (; i + 3 <= text_len; i += 3) {
encode[j++] = alphabet_map[text[i] >> 2];
encode[j++] = alphabet_map[((text[i] << 4) & 0x30) | (text[i + 1] >> 4)];
encode[j++] = alphabet_map[((text[i + 1] << 2) & 0x3c) | (text[i + 2] >> 6)];
encode[j++] = alphabet_map[text[i + 2] & 0x3f];
}
if (i < text_len) {
const std::uint32_t tail = text_len - i;
if (tail == 1) {
encode[j++] = alphabet_map[text[i] >> 2];
encode[j++] = alphabet_map[(text[i] << 4) & 0x30];
encode[j++] = '=';
encode[j++] = '=';
} else {
encode[j++] = alphabet_map[text[i] >> 2];
encode[j++] = alphabet_map[((text[i] << 4) & 0x30) | (text[i + 1] >> 4)];
encode[j++] = alphabet_map[(text[i + 1] << 2) & 0x3c];
encode[j++] = '=';
}
}
return j;
}
std::uint32_t base64_decode_raw(const std::uint8_t* code, std::uint32_t code_len, std::uint8_t* plain) {
if (!code || !plain || (code_len & 0x03U) != 0U) {
return 0;
}
std::uint32_t j = 0;
for (std::uint32_t i = 0; i < code_len; i += 4) {
const std::uint8_t q0 = decode_char(code[i]);
const std::uint8_t q1 = decode_char(code[i + 1]);
const std::uint8_t q2 = decode_char(code[i + 2]);
const std::uint8_t q3 = decode_char(code[i + 3]);
if (q0 >= 64 || q1 >= 64) {
return j;
}
plain[j++] = static_cast<std::uint8_t>((q0 << 2) | (q1 >> 4));
if (q2 == 64) {
break;
}
if (q2 > 64) {
return j;
}
plain[j++] = static_cast<std::uint8_t>((q1 << 4) | (q2 >> 2));
if (q3 == 64) {
break;
}
if (q3 > 64) {
return j;
}
plain[j++] = static_cast<std::uint8_t>((q2 << 6) | q3);
}
return j;
}
}
std::string base64_encode(const std::string& data) {
const auto text_len = static_cast<std::uint32_t>(data.size());
std::vector<std::uint8_t> encode(4 * ((text_len + 2) / 3));
const std::uint32_t encoded_len = base64_encode_raw(
reinterpret_cast<const std::uint8_t*>(data.data()), text_len, encode.data());
return std::string(encode.begin(), encode.begin() + encoded_len);
}
std::string base64_decode(const std::string& data) {
const auto code_len = static_cast<std::uint32_t>(data.size());
if ((code_len & 0x03U) != 0U) {
return "";
}
std::vector<std::uint8_t> plain(code_len * 3 / 4);
const std::uint32_t decoded_len = base64_decode_raw(
reinterpret_cast<const std::uint8_t*>(data.data()), code_len, plain.data());
return std::string(plain.begin(), plain.begin() + decoded_len);
}
std::string signal_to_string(int signal) {
switch (signal) {
case SIGINT: return "SIGINT (Ctrl+C)";
case SIGILL: return "SIGILL (Illegal Instruction)";
case SIGFPE: return "SIGFPE (Floating Point Exception)";
case SIGSEGV: return "SIGSEGV (Segmentation Fault)";
case SIGTERM: return "SIGTERM (Termination Request)";
case SIGABRT: return "SIGABRT (Abort Signal)";
std::string signal_to_string(int signal) {
switch (signal) {
case SIGINT:
return "SIGINT (Ctrl+C)";
case SIGILL:
return "SIGILL (Illegal Instruction)";
case SIGFPE:
return "SIGFPE (Floating Point Exception)";
case SIGSEGV:
return "SIGSEGV (Segmentation Fault)";
case SIGTERM:
return "SIGTERM (Termination Request)";
case SIGABRT:
return "SIGABRT (Abort Signal)";
#if defined(_WIN32) && defined(SIGBREAK)
case SIGBREAK: return "SIGBREAK (Breakpoint)";
case SIGBREAK:
return "SIGBREAK (Breakpoint)";
#endif
#if defined(_MSC_VER) && defined(SIGABRT_COMPAT)
case SIGABRT_COMPAT: return "SIGABRT_COMPAT (Abort Compatibility Signal)";
case SIGABRT_COMPAT:
return "SIGABRT_COMPAT (Abort Compatibility Signal)";
#endif
default: return "Unknown signal:" + std::to_string(signal);
}
default:
return "Unknown signal:" + std::to_string(signal);
}
}
std::string get_current_time_as_string() {
const auto now = std::chrono::system_clock::now();
const std::time_t now_time = std::chrono::system_clock::to_time_t(now);
std::tm local_tm{};
if (!local_time_from_time_t(now_time, local_tm)) {
return "invalid_time";
}
std::ostringstream ss;
ss << std::put_time(&local_tm, "%Y-%m-%d_%H-%M-%S");
return ss.str();
}
namespace fs = std::filesystem;
void create_file_if_not_exists(const std::string &file_name) {
std::error_code ec;
const fs::path file_path(file_name);
if (fs::exists(file_path, ec)) {
return;
}
const fs::path parent = file_path.parent_path();
if (!parent.empty()) {
fs::create_directories(parent, ec);
if (ec) {
std::cerr << "Failed to create parent directory: " << parent.string()
<< ", error: " << ec.message() << std::endl;
return;
}
}
std::string get_current_time_as_string() {
const auto now = std::chrono::system_clock::now();
const std::time_t now_time = std::chrono::system_clock::to_time_t(now);
std::ofstream ofs(file_path, std::ios::out | std::ios::app);
if (!ofs) {
std::cerr << "Failed to create the file: " << file_name << std::endl;
return;
}
std::tm local_tm{};
if (!local_time_from_time_t(now_time, local_tm)) {
return "invalid_time";
}
const auto perms =
fs::perms::owner_all | fs::perms::group_all | fs::perms::others_all;
fs::permissions(file_path, perms, ec);
}
std::ostringstream ss;
ss << std::put_time(&local_tm, "%Y-%m-%d_%H-%M-%S");
return ss.str();
void create_dir_if_not_exists(const std::string &dir_name) {
std::error_code ec;
const fs::path dir_path(dir_name);
if (!fs::exists(dir_path, ec)) {
fs::create_directories(dir_path, ec);
if (ec) {
std::cerr << "Failed to create directory: " << dir_name
<< ", error: " << ec.message() << std::endl;
return;
}
}
namespace fs = std::filesystem;
const auto perms =
fs::perms::owner_all | fs::perms::group_all | fs::perms::others_all;
fs::permissions(dir_path, perms, ec);
}
void create_file_if_not_exists(const std::string& file_name) {
std::error_code ec;
const fs::path file_path(file_name);
void write_stack_trace_to_file(const std::string &stack_trace,
const std::string &filename) {
create_file_if_not_exists(filename);
std::ofstream out_file(filename, std::ios::out | std::ios::app);
if (out_file.is_open()) {
out_file << stack_trace << std::endl;
} else {
std::cerr << "Unable to open file " << filename << " for writing."
<< std::endl;
}
}
if (fs::exists(file_path, ec)) {
return;
}
void signal_handler(int signal_code) {
std::cout << "signal_handler [" << signal_to_string(signal_code) << "]"
<< std::endl;
stop_program = signal_code;
}
const fs::path parent = file_path.parent_path();
if (!parent.empty()) {
fs::create_directories(parent, ec);
if (ec) {
std::cerr << "Failed to create parent directory: " << parent.string()
<< ", error: " << ec.message() << std::endl;
return;
}
}
void signal_handler_ignore(int) {}
std::ofstream ofs(file_path, std::ios::out | std::ios::app);
if (!ofs) {
std::cerr << "Failed to create the file: " << file_name << std::endl;
return;
}
void init_signal_config(std::set<int> normal_quit,
std::set<int> ignore_signal) {
if (is_big_endian) {
std::cout << "大端序 This system is Big-endian." << std::endl;
} else {
std::cout << "小端序 This system is Little-endian." << std::endl;
}
const auto perms = fs::perms::owner_all | fs::perms::group_all | fs::perms::others_all;
fs::permissions(file_path, perms, ec);
}
void create_dir_if_not_exists(const std::string& dir_name) {
std::error_code ec;
const fs::path dir_path(dir_name);
if (!fs::exists(dir_path, ec)) {
fs::create_directories(dir_path, ec);
if (ec) {
std::cerr << "Failed to create directory: " << dir_name
<< ", error: " << ec.message() << std::endl;
return;
}
}
const auto perms = fs::perms::owner_all | fs::perms::group_all | fs::perms::others_all;
fs::permissions(dir_path, perms, ec);
}
void write_stack_trace_to_file(const std::string& stack_trace, const std::string& filename) {
create_file_if_not_exists(filename);
std::ofstream out_file(filename, std::ios::out | std::ios::app);
if (out_file.is_open()) {
out_file << stack_trace << std::endl;
} else {
std::cerr << "Unable to open file " << filename << " for writing." << std::endl;
}
}
void signal_handler(int signal_code) {
std::cout << "signal_handler [" << signal_to_string(signal_code) << "]" << std::endl;
stop_program = signal_code;
}
void signal_handler_ignore(int) {}
void init_signal_config(std::set<int> normal_quit, std::set<int> ignore_signal) {
if (is_big_endian) {
std::cout << "大端序 This system is Big-endian." << std::endl;
} else {
std::cout << "小端序 This system is Little-endian." << std::endl;
}
for (auto signum : normal_quit) {
std::signal(signum, signal_handler);
}
for (auto signum : ignore_signal) {
std::signal(signum, signal_handler_ignore);
}
}
for (auto signum : normal_quit) {
std::signal(signum, signal_handler);
}
for (auto signum : ignore_signal) {
std::signal(signum, signal_handler_ignore);
}
}
} // namespace Psc
+171 -173
View File
@@ -2,7 +2,6 @@
#include "../Base/global_include.h"
#include <algorithm>
#include <atomic>
#include <cassert>
@@ -24,228 +23,227 @@
#include "3rd/magic_enum/export.h"
#include "magic_enum/magic_enum.hpp"
#define PSC_LOAD_LIBRARY_PARAMS(M, SEP) \
M(const std::string&, library_path)
#define PSC_LOAD_LIBRARY_PARAMS(M, SEP) M(const std::string &, library_path)
#define PSC_LOAD_FUNCTION_PARAMS(M, SEP) \
M(void*, library) SEP() \
M(const std::string&, function_name)
#define PSC_LOAD_FUNCTION_PARAMS(M, SEP) \
M(void *, library) SEP() M(const std::string &, function_name)
#define DELETE_COPY(Class) \
Class(const Class&) = delete; \
Class& operator=(const Class&) = delete;
#define DELETE_COPY(Class) \
Class(const Class &) = delete; \
Class &operator=(const Class &) = delete;
namespace Psc {
void set_console_utf8();
void set_console_utf8();
std::string get_stack_trace();
std::string get_computer_serial_number();
std::string get_stack_trace();
std::string get_computer_serial_number();
PSC_DECLARE_TRIPLE_API(void*, load_library, PSC_LOAD_LIBRARY_PARAMS);
void* load_library_fail_fast(const std::string& library_path);
PSC_DECLARE_TRIPLE_API(void *, load_library, PSC_LOAD_LIBRARY_PARAMS);
void *load_library_fail_fast(const std::string &library_path);
void free_library(void* library);
void free_library(void *library);
PSC_DECLARE_TRIPLE_API(void*, load_function, PSC_LOAD_FUNCTION_PARAMS);
void* load_function_fail_fast(void* library, const std::string& function_name);
PSC_DECLARE_TRIPLE_API(void *, load_function, PSC_LOAD_FUNCTION_PARAMS);
void *load_function_fail_fast(void *library, const std::string &function_name);
std::string get_home_dir();
std::string get_exe_path();
std::string get_exe_dir();
std::string get_home_dir();
std::string get_exe_path();
std::string get_exe_dir();
std::string get_abs_path(const std::string& path);
std::string to_upper_case(const std::string& input);
std::string base64_encode(const std::string& data);
std::string base64_decode(const std::string& data);
std::string get_abs_path(const std::string &path);
std::string to_upper_case(const std::string &input);
std::string base64_encode(const std::string &data);
std::string base64_decode(const std::string &data);
// strftime 格式,例如 "%Y-%m-%d %H:%M:%S" / "%H:%M:%S"。
std::string utc_2_local_time(std::time_t us_timestamp, const char* format = "%H:%M:%S");
// strftime 格式,例如 "%Y-%m-%d %H:%M:%S" / "%H:%M:%S"。
std::string utc_2_local_time(std::time_t us_timestamp,
const char *format = "%H:%M:%S");
std::uint64_t get_current_millisecond_timestamp();
void set_current_thread_name(const std::string& name);
std::uint64_t get_current_millisecond_timestamp();
void set_current_thread_name(const std::string &name);
using Main_Function_Type = int (*)(int, char**);
using Main_Function_Type = int (*)(int, char **);
// 接管 main 函数,联通 gtest。
int redict_main_with_gtest(int argc, char* argv[], Main_Function_Type main_func);
// 接管 main 函数,联通 gtest。
int redict_main_with_gtest(int argc, char *argv[],
Main_Function_Type main_func);
// 设置给定 std::thread 的优先级。
// Windows: void* 版本要求传 Win32 HANDLE。
// Linux: void* 版本要求传 pthread_t*,例如 pthread_t pt = pthread_self(); set_thread_priority(&pt, ...)。
bool set_thread_priority(void* thread, int priority, bool realtime);
bool set_thread_priority(std::thread* thread, int priority, bool realtime);
// 设置给定 std::thread 的优先级。
// Windows: void* 版本要求传 Win32 HANDLE。
// Linux: void* 版本要求传 pthread_t*,例如 pthread_t pt = pthread_self();
// set_thread_priority(&pt, ...)。
bool set_thread_priority(void *thread, int priority, bool realtime);
bool set_thread_priority(std::thread *thread, int priority, bool realtime);
// 设置给定线程的 CPU 亲和性。
// Windows: void* 版本要求传 Win32 HANDLE。
// Linux: void* 版本要求传 pthread_t*。
bool set_thread_affinity(void* thread, unsigned cpu_index);
bool set_thread_affinity(std::thread* thread, unsigned cpu_index);
// 设置给定线程的 CPU 亲和性。
// Windows: void* 版本要求传 Win32 HANDLE。
// Linux: void* 版本要求传 pthread_t*。
bool set_thread_affinity(void *thread, unsigned cpu_index);
bool set_thread_affinity(std::thread *thread, unsigned cpu_index);
size_t get_system_memory();
size_t get_process_memory();
std::string get_memory_info();
size_t get_system_memory();
size_t get_process_memory();
std::string get_memory_info();
std::string signal_to_string(int signal);
std::string get_current_time_as_string();
void create_file_if_not_exists(const std::string& file_name);
void create_dir_if_not_exists(const std::string& dir_name);
std::string signal_to_string(int signal);
std::string get_current_time_as_string();
void create_file_if_not_exists(const std::string &file_name);
void create_dir_if_not_exists(const std::string &dir_name);
void init_signal_config(std::set<int> normal_quit = {SIGINT, SIGTERM}, std::set<int> ignore_signal = {});
void init_signal_config(std::set<int> normal_quit = {SIGINT, SIGTERM},
std::set<int> ignore_signal = {});
class String_Pool {
public:
explicit String_Pool(size_t block_size, size_t pool_size)
: block_size(block_size), pool_size(pool_size) {
grow(pool_size);
}
class String_Pool {
public:
explicit String_Pool(size_t block_size, size_t pool_size)
: block_size(block_size), pool_size(pool_size) {
grow(pool_size);
}
size_t remain_size() {
std::lock_guard g(mtx);
return strings_.size() * block_size;
}
size_t remain_size() {
std::lock_guard g(mtx);
return strings_.size() * block_size;
}
size_t free_size() {
std::lock_guard g(mtx);
return free_.size() * block_size;
}
size_t free_size() {
std::lock_guard g(mtx);
return free_.size() * block_size;
}
std::string* get() {
std::lock_guard g(mtx);
std::string *get() {
std::lock_guard g(mtx);
if (free_.empty()) {
const size_t grow_count = strings_.empty() ? std::max<size_t>(pool_size, 1) : strings_.size();
if (free_.empty()) {
const size_t grow_count =
strings_.empty() ? std::max<size_t>(pool_size, 1) : strings_.size();
std::cout << "String_Pool 扩容对象数 【" << grow_count
<< "】,理论容量 【" << grow_count * block_size << ""
<< std::endl;
std::cout << "String_Pool 扩容对象数 【" << grow_count
<< "】,理论容量 【" << grow_count * block_size << ""
<< std::endl;
grow(grow_count);
}
grow(grow_count);
}
std::string* ptr = free_.top();
free_.pop();
return ptr;
}
std::string *ptr = free_.top();
free_.pop();
return ptr;
}
[[nodiscard]] size_t capacity() const {
std::lock_guard g(mtx);
return strings_.size();
}
[[nodiscard]] size_t capacity() const {
std::lock_guard g(mtx);
return strings_.size();
}
[[nodiscard]] size_t free_count() const {
std::lock_guard g(mtx);
return free_.size();
}
[[nodiscard]] size_t free_count() const {
std::lock_guard g(mtx);
return free_.size();
}
private:
void grow(size_t count) {
for (size_t i = 0; i < count; ++i) {
strings_.emplace_back();
std::string& str = strings_.back();
str.reserve(block_size);
free_.push(&str);
}
}
private:
void grow(size_t count) {
for (size_t i = 0; i < count; ++i) {
strings_.emplace_back();
std::string &str = strings_.back();
str.reserve(block_size);
free_.push(&str);
}
}
void release(std::string* ptr) {
std::lock_guard g(mtx);
if (ptr) {
ptr->clear();
free_.push(ptr);
}
}
void release(std::string *ptr) {
std::lock_guard g(mtx);
if (ptr) {
ptr->clear();
free_.push(ptr);
}
}
void release(const std::vector<std::string*>& list) {
std::lock_guard g(mtx);
for (auto* li : list) {
if (li) {
li->clear();
free_.push(li);
}
}
}
void release(const std::vector<std::string *> &list) {
std::lock_guard g(mtx);
for (auto *li : list) {
if (li) {
li->clear();
free_.push(li);
}
}
}
private:
std::deque<std::string> strings_;
std::stack<std::string*> free_{};
private:
std::deque<std::string> strings_;
std::stack<std::string *> free_{};
mutable Spin_Lock mtx;
mutable Spin_Lock mtx;
size_t block_size; // 每个 std::string 预留的容量。
size_t pool_size; // 初始创建多少个 string 对象。
size_t block_size; // 每个 std::string 预留的容量。
size_t pool_size; // 初始创建多少个 string 对象。
friend struct Pool_Guard;
};
friend struct Pool_Guard;
};
struct Pool_Guard {
Pool_Guard(String_Pool* pool, std::string* buf)
: pool(pool), buf(buf) {}
struct Pool_Guard {
Pool_Guard(String_Pool *pool, std::string *buf) : pool(pool), buf(buf) {}
Pool_Guard(String_Pool* pool, std::vector<std::string*> list)
: pool(pool), list(std::move(list)) {}
Pool_Guard(String_Pool *pool, std::vector<std::string *> list)
: pool(pool), list(std::move(list)) {}
~Pool_Guard() {
if (!pool) {
return;
}
~Pool_Guard() {
if (!pool) {
return;
}
if (buf) {
pool->release(buf);
}
if (buf) {
pool->release(buf);
}
if (!list.empty()) {
pool->release(list);
}
}
if (!list.empty()) {
pool->release(list);
}
}
Pool_Guard(const Pool_Guard&) = delete;
Pool_Guard& operator=(const Pool_Guard&) = delete;
Pool_Guard(const Pool_Guard &) = delete;
Pool_Guard &operator=(const Pool_Guard &) = delete;
Pool_Guard(Pool_Guard&& other) noexcept
: pool(other.pool),
list(std::move(other.list)),
buf(other.buf) {
other.pool = nullptr;
other.buf = nullptr;
}
Pool_Guard(Pool_Guard &&other) noexcept
: pool(other.pool), list(std::move(other.list)), buf(other.buf) {
other.pool = nullptr;
other.buf = nullptr;
}
Pool_Guard& operator=(Pool_Guard&& other) noexcept {
if (this != &other) {
pool = other.pool;
list = std::move(other.list);
buf = other.buf;
Pool_Guard &operator=(Pool_Guard &&other) noexcept {
if (this != &other) {
pool = other.pool;
list = std::move(other.list);
buf = other.buf;
other.pool = nullptr;
other.buf = nullptr;
}
other.pool = nullptr;
other.buf = nullptr;
}
return *this;
}
return *this;
}
protected:
String_Pool* pool{};
std::vector<std::string*> list;
std::string* buf{};
};
protected:
String_Pool *pool{};
std::vector<std::string *> list;
std::string *buf{};
};
template <typename Enum_Type>
class Enum_Err {
public:
explicit Enum_Err(Enum_Type errc)
: nerr(errc),
native(get_error_code(), std::system_category()) {}
template <typename Enum_Type> class Enum_Err {
public:
explicit Enum_Err(Enum_Type errc)
: nerr(errc), native(get_error_code(), std::system_category()) {}
Enum_Err(Enum_Type errc, ERROR_CODE_TYPE code)
: nerr(errc),
native(std::error_code(code, std::system_category())) {}
Enum_Err(Enum_Type errc, ERROR_CODE_TYPE code)
: nerr(errc), native(std::error_code(code, std::system_category())) {}
Enum_Type nerr;
std::error_code native;
Enum_Type nerr;
std::error_code native;
std::string to_string() {
auto enum_name = std::string(magic_enum::template enum_type_name<Enum_Type>());
return enum_name + "" + Psc::to_string(nerr) + " native:" + get_error_message(native.value()) + "";
}
};
std::string to_string() {
auto enum_name =
std::string(magic_enum::template enum_type_name<Enum_Type>());
return enum_name + "" + Psc::to_string(nerr) +
" native:" + get_error_message(native.value()) + "";
}
};
} // namespace Psc
+368 -367
View File
@@ -3,8 +3,8 @@
#include "export.h"
#include <algorithm>
#include <cerrno>
#include <cctype>
#include <cerrno>
#include <clocale>
#include <csignal>
#include <cstdint>
@@ -41,396 +41,397 @@
namespace Psc {
namespace {
std::string trim_copy(std::string value) {
auto not_space = [](unsigned char ch) { return !std::isspace(ch); };
value.erase(value.begin(), std::find_if(value.begin(), value.end(), not_space));
value.erase(std::find_if(value.rbegin(), value.rend(), not_space).base(), value.end());
return value;
}
std::string read_first_line(const std::string& file_name) {
std::ifstream in(file_name);
std::string line;
if (std::getline(in, line)) {
return trim_copy(line);
}
return "";
}
std::string execute_command_single(const char* cmd) {
if (!cmd || !*cmd) {
return "";
}
int pipefd[2]{};
if (pipe(pipefd) != 0) {
return "";
}
pid_t pid = fork();
if (pid < 0) {
close(pipefd[0]);
close(pipefd[1]);
return "";
}
if (pid == 0) {
close(pipefd[0]);
dup2(pipefd[1], STDOUT_FILENO);
close(pipefd[1]);
setsid();
execl("/bin/sh", "sh", "-c", cmd, static_cast<char*>(nullptr));
_exit(127);
}
close(pipefd[1]);
std::string out;
char buf[1024];
ssize_t n = 0;
while ((n = read(pipefd[0], buf, sizeof(buf))) > 0) {
out.append(buf, static_cast<size_t>(n));
}
close(pipefd[0]);
waitpid(pid, nullptr, 0);
return out;
}
size_t read_proc_status_kb(const char* key) {
std::ifstream status("/proc/self/status");
std::string line;
while (std::getline(status, line)) {
if (line.rfind(key, 0) == 0) {
size_t value_kb = 0;
if (std::sscanf(line.c_str(), "%*s %zu kB", &value_kb) == 1) {
return value_kb;
}
}
}
return 0;
}
std::string trim_copy(std::string value) {
auto not_space = [](unsigned char ch) { return !std::isspace(ch); };
value.erase(value.begin(),
std::find_if(value.begin(), value.end(), not_space));
value.erase(std::find_if(value.rbegin(), value.rend(), not_space).base(),
value.end());
return value;
}
std::string extract_address(const std::string& input) {
const std::regex address_regex(R"(\[([0-9a-fA-Fx]+)\])");
std::smatch match;
if (std::regex_search(input, match, address_regex)) {
return match[1].str();
}
return "";
std::string read_first_line(const std::string &file_name) {
std::ifstream in(file_name);
std::string line;
if (std::getline(in, line)) {
return trim_copy(line);
}
return "";
}
std::string execute_command_single(const char *cmd) {
if (!cmd || !*cmd) {
return "";
}
int pipefd[2]{};
if (pipe(pipefd) != 0) {
return "";
}
pid_t pid = fork();
if (pid < 0) {
close(pipefd[0]);
close(pipefd[1]);
return "";
}
if (pid == 0) {
close(pipefd[0]);
dup2(pipefd[1], STDOUT_FILENO);
close(pipefd[1]);
setsid();
execl("/bin/sh", "sh", "-c", cmd, static_cast<char *>(nullptr));
_exit(127);
}
close(pipefd[1]);
std::string out;
char buf[1024];
ssize_t n = 0;
while ((n = read(pipefd[0], buf, sizeof(buf))) > 0) {
out.append(buf, static_cast<size_t>(n));
}
close(pipefd[0]);
waitpid(pid, nullptr, 0);
return out;
}
size_t read_proc_status_kb(const char *key) {
std::ifstream status("/proc/self/status");
std::string line;
while (std::getline(status, line)) {
if (line.rfind(key, 0) == 0) {
size_t value_kb = 0;
if (std::sscanf(line.c_str(), "%*s %zu kB", &value_kb) == 1) {
return value_kb;
}
}
}
return 0;
}
} // namespace
std::string execute_command(const std::string& cmd) {
FILE* fp = popen(cmd.c_str(), "r");
if (!fp) {
return "";
}
std::string extract_address(const std::string &input) {
const std::regex address_regex(R"(\[([0-9a-fA-Fx]+)\])");
std::smatch match;
if (std::regex_search(input, match, address_regex)) {
return match[1].str();
}
return "";
}
std::string result;
char buffer[1024];
while (fgets(buffer, sizeof(buffer), fp) != nullptr) {
result.append(buffer);
}
pclose(fp);
return result;
std::string execute_command(const std::string &cmd) {
FILE *fp = popen(cmd.c_str(), "r");
if (!fp) {
return "";
}
std::string result;
char buffer[1024];
while (fgets(buffer, sizeof(buffer), fp) != nullptr) {
result.append(buffer);
}
pclose(fp);
return result;
}
std::string get_tool(const std::string &name) {
std::string ret = name;
const std::string exe_dir = get_exe_dir();
const std::string ret_1 = exe_dir + "/" + name;
std::filesystem::path path = std::filesystem::u8path(exe_dir);
const auto parent = path.parent_path();
const std::string parent_path = path_to_utf8(parent);
const std::string ret_2 = parent_path + "/lib/" + name;
if (std::filesystem::exists(ret_1)) {
ret = ret_1;
} else if (std::filesystem::exists(ret_2)) {
ret = ret_2;
}
return ret;
}
std::string get_stack_trace() {
std::ostringstream oss;
constexpr int max_frames = 64;
void *stack[max_frames]{};
const int stack_size = backtrace(stack, max_frames);
char **symbols = backtrace_symbols(stack, stack_size);
if (!symbols) {
oss << "Error retrieving stack symbols\n";
return oss.str();
}
const std::string addr2line = get_tool("addr2line");
const std::string cppfilt = get_tool("c++filt");
const std::string exe = get_exe_path();
oss << "addr2line: " << addr2line << '\n';
oss << "cppfilt: " << cppfilt << '\n';
oss << "Stack trace: " << exe << '\n';
for (int i = 0; i < stack_size; ++i) {
const auto addr = reinterpret_cast<std::uintptr_t>(stack[i]);
oss << "" << std::dec << std::left << std::setw(2) << i << "";
char cmd[4096];
std::snprintf(cmd, sizeof(cmd), R"(%s -e "%s" -f -i 0x%lx | %s)",
addr2line.c_str(), exe.c_str(),
static_cast<unsigned long>(addr), cppfilt.c_str());
std::string str = execute_command_single(cmd);
if (str.empty() && symbols[i]) {
str = symbols[i];
}
std::replace(str.begin(), str.end(), '\n', ' ');
oss << " " << str << "【0x" << std::hex << addr << std::dec << ""
<< '\n';
}
std::string get_tool(const std::string& name) {
std::string ret = name;
const std::string exe_dir = get_exe_dir();
const std::string ret_1 = exe_dir + "/" + name;
free(symbols);
return oss.str();
}
std::filesystem::path path = std::filesystem::u8path(exe_dir);
const auto parent = path.parent_path();
const std::string parent_path = path_to_utf8(parent);
const std::string ret_2 = parent_path + "/lib/" + name;
std::string get_computer_serial_number() {
static const char *candidates[] = {
"/sys/class/dmi/id/product_serial", "/sys/class/dmi/id/board_serial",
"/sys/class/dmi/id/product_uuid", "/sys/class/dmi/id/chassis_serial"};
if (std::filesystem::exists(ret_1)) {
ret = ret_1;
} else if (std::filesystem::exists(ret_2)) {
ret = ret_2;
}
return ret;
for (const char *file : candidates) {
std::string value = read_first_line(file);
if (!value.empty() && value != "None" && value != "Not Specified" &&
value != "To Be Filled By O.E.M.") {
return value;
}
}
std::string get_stack_trace() {
std::ostringstream oss;
constexpr int max_frames = 64;
void* stack[max_frames]{};
return "Unknown";
}
const int stack_size = backtrace(stack, max_frames);
char** symbols = backtrace_symbols(stack, stack_size);
if (!symbols) {
oss << "Error retrieving stack symbols\n";
return oss.str();
}
void set_current_thread_name(const std::string &name) {
std::string trimmed =
name.substr(0, 15); // Linux 线程名最多 16 字节,含结尾 \0。
(void)pthread_setname_np(pthread_self(), trimmed.c_str());
}
const std::string addr2line = get_tool("addr2line");
const std::string cppfilt = get_tool("c++filt");
const std::string exe = get_exe_path();
void set_console_utf8() {
if (setlocale(LC_ALL, "") != nullptr) {
return;
}
if (setlocale(LC_ALL, "C.UTF-8") != nullptr) {
return;
}
(void)setlocale(LC_ALL, "en_US.UTF-8");
}
oss << "addr2line: " << addr2line << '\n';
oss << "cppfilt: " << cppfilt << '\n';
oss << "Stack trace: " << exe << '\n';
PSC_DEFINE_TRIPLE_API_FROM_BOOL(void *, load_library, PSC_LOAD_LIBRARY_PARAMS)
for (int i = 0; i < stack_size; ++i) {
const auto addr = reinterpret_cast<std::uintptr_t>(stack[i]);
oss << "" << std::dec << std::left << std::setw(2) << i << "";
bool load_library_ec(const std::string &library_path, void *&out,
std::error_code &ec) noexcept {
out = nullptr;
ec.clear();
(void)dlerror();
char cmd[4096];
std::snprintf(cmd, sizeof(cmd),
R"(%s -e "%s" -f -i 0x%lx | %s)",
addr2line.c_str(), exe.c_str(), static_cast<unsigned long>(addr), cppfilt.c_str());
void *library = dlopen(library_path.c_str(), RTLD_LAZY);
if (!library) {
const char *err = dlerror();
std::cerr << library_path
<< " Failed to load library: " << (err ? err : "unknown") << '\n';
ec = std::make_error_code(std::errc::no_such_file_or_directory);
return false;
}
std::string str = execute_command_single(cmd);
if (str.empty() && symbols[i]) {
str = symbols[i];
}
std::replace(str.begin(), str.end(), '\n', ' ');
oss << " " << str << "【0x" << std::hex << addr << std::dec << "" << '\n';
}
out = library;
return true;
}
free(symbols);
return oss.str();
void *load_library_fail_fast(const std::string &library_path) {
auto ret = try_load_library(library_path);
if (!ret) {
Psc::fail_fast();
}
return ret.value();
}
void free_library(void *library) {
if (library) {
dlclose(library);
}
}
PSC_DEFINE_TRIPLE_API_FROM_BOOL(void *, load_function, PSC_LOAD_FUNCTION_PARAMS)
bool load_function_ec(void *library, const std::string &function_name,
void *&out, std::error_code &ec) noexcept {
out = nullptr;
ec.clear();
if (!library) {
std::cerr << function_name << " function not loaded (library == nullptr)\n";
ec = std::make_error_code(std::errc::invalid_argument);
return false;
}
(void)dlerror();
void *func = dlsym(library, function_name.c_str());
const char *err = dlerror();
if (err != nullptr) {
std::cerr << "dlsym failed for " << function_name << " : " << err << '\n';
ec = std::make_error_code(std::errc::function_not_supported);
return false;
}
out = func;
return true;
}
void *load_function_fail_fast(void *library, const std::string &function_name) {
auto ret = try_load_function(library, function_name);
if (!ret) {
Psc::fail_fast();
}
return ret.value();
}
std::string get_error_message() {
const int ec = errno;
return "错误码:" + std::to_string(ec) + ": " + std::strerror(ec);
}
std::string get_error_message(ERROR_CODE_TYPE ec) {
return "错误码:" + std::to_string(ec) + ": " +
std::strerror(static_cast<int>(ec));
}
ERROR_CODE_TYPE get_error_code() { return errno; }
void set_error_code(ERROR_CODE_TYPE code) { errno = static_cast<int>(code); }
std::string get_exe_path() {
std::vector<char> buffer(PATH_MAX + 1, '\0');
const ssize_t len =
readlink("/proc/self/exe", buffer.data(), buffer.size() - 1);
if (len == -1) {
return "";
}
buffer[static_cast<size_t>(len)] = '\0';
return std::string(buffer.data());
}
std::string get_home_dir() {
if (const char *home = std::getenv("HOME")) {
return home;
}
struct passwd *pw = getpwuid(getuid());
if (pw && pw->pw_dir) {
return std::string(pw->pw_dir);
}
return "";
}
bool set_thread_priority(void *thread_ptr, int priority, bool realtime) {
if (!thread_ptr) {
return false;
}
pthread_t pthread = *static_cast<pthread_t *>(thread_ptr);
int policy = realtime ? SCHED_FIFO : SCHED_OTHER;
sched_param param{};
if (realtime) {
const int min_prio = sched_get_priority_min(policy);
const int max_prio = sched_get_priority_max(policy);
if (min_prio >= 0 && max_prio >= min_prio) {
priority = std::max(min_prio, std::min(max_prio, priority));
}
param.sched_priority = priority;
} else {
param.sched_priority = 0;
}
std::string get_computer_serial_number() {
static const char* candidates[] = {
"/sys/class/dmi/id/product_serial",
"/sys/class/dmi/id/board_serial",
"/sys/class/dmi/id/product_uuid",
"/sys/class/dmi/id/chassis_serial"
};
const int ret = pthread_setschedparam(pthread, policy, &param);
if (ret != 0) {
errno = ret;
return false;
}
return true;
}
for (const char* file : candidates) {
std::string value = read_first_line(file);
if (!value.empty() && value != "None" && value != "Not Specified" && value != "To Be Filled By O.E.M.") {
return value;
}
}
bool set_thread_priority(std::thread *thread, int priority, bool realtime) {
if (!thread) {
return false;
}
return "Unknown";
pthread_t pthread = thread->native_handle();
return set_thread_priority(static_cast<void *>(&pthread), priority, realtime);
}
bool set_thread_affinity(void *thread_ptr, unsigned cpu_index) {
if (!thread_ptr) {
return false;
}
if (cpu_index >= CPU_SETSIZE) {
errno = EINVAL;
return false;
}
pthread_t pthread = *static_cast<pthread_t *>(thread_ptr);
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(cpu_index, &cpuset);
const int ret = pthread_setaffinity_np(pthread, sizeof(cpu_set_t), &cpuset);
if (ret != 0) {
errno = ret;
std::cerr << "Error setting thread affinity: " << std::strerror(ret)
<< std::endl;
return false;
}
return true;
}
bool set_thread_affinity(std::thread *thread, unsigned cpu_index) {
if (!thread) {
return false;
}
pthread_t pthread = thread->native_handle();
return set_thread_affinity(static_cast<void *>(&pthread), cpu_index);
}
std::string get_memory_info() {
auto ret = JSON::object();
ret.append({"VmRSS (MB)", read_proc_status_kb("VmRSS:") / 1024});
ret.append({"VmSize (MB)", read_proc_status_kb("VmSize:") / 1024});
ret.append({"VmPeak (MB)", read_proc_status_kb("VmPeak:") / 1024});
ret.append({"VmHWM (MB)", read_proc_status_kb("VmHWM:") / 1024});
return ret.to_json_string();
}
size_t get_system_memory() {
std::ifstream meminfo("/proc/meminfo");
std::string line;
while (std::getline(meminfo, line)) {
if (line.rfind("MemTotal:", 0) == 0) {
size_t mem_total_kb = 0;
if (std::sscanf(line.c_str(), "MemTotal: %zu kB", &mem_total_kb) == 1) {
return mem_total_kb * 1024;
}
}
}
return 0;
}
void set_current_thread_name(const std::string& name) {
std::string trimmed = name.substr(0, 15); // Linux 线程名最多 16 字节,含结尾 \0。
(void)pthread_setname_np(pthread_self(), trimmed.c_str());
}
void set_console_utf8() {
if (setlocale(LC_ALL, "") != nullptr) {
return;
}
if (setlocale(LC_ALL, "C.UTF-8") != nullptr) {
return;
}
(void)setlocale(LC_ALL, "en_US.UTF-8");
}
PSC_DEFINE_TRIPLE_API_FROM_BOOL(void*, load_library, PSC_LOAD_LIBRARY_PARAMS)
bool load_library_ec(const std::string& library_path, void*& out, std::error_code& ec) noexcept {
out = nullptr;
ec.clear();
(void)dlerror();
void* library = dlopen(library_path.c_str(), RTLD_LAZY);
if (!library) {
const char* err = dlerror();
std::cerr << library_path << " Failed to load library: "
<< (err ? err : "unknown") << '\n';
ec = std::make_error_code(std::errc::no_such_file_or_directory);
return false;
}
out = library;
return true;
}
void* load_library_fail_fast(const std::string& library_path) {
auto ret = try_load_library(library_path);
if (!ret) {
Psc::fail_fast();
}
return ret.value();
}
void free_library(void* library) {
if (library) {
dlclose(library);
}
}
PSC_DEFINE_TRIPLE_API_FROM_BOOL(void*, load_function, PSC_LOAD_FUNCTION_PARAMS)
bool load_function_ec(void* library, const std::string& function_name, void*& out, std::error_code& ec) noexcept {
out = nullptr;
ec.clear();
if (!library) {
std::cerr << function_name << " function not loaded (library == nullptr)\n";
ec = std::make_error_code(std::errc::invalid_argument);
return false;
}
(void)dlerror();
void* func = dlsym(library, function_name.c_str());
const char* err = dlerror();
if (err != nullptr) {
std::cerr << "dlsym failed for " << function_name << " : " << err << '\n';
ec = std::make_error_code(std::errc::function_not_supported);
return false;
}
out = func;
return true;
}
void* load_function_fail_fast(void* library, const std::string& function_name) {
auto ret = try_load_function(library, function_name);
if (!ret) {
Psc::fail_fast();
}
return ret.value();
}
std::string get_error_message() {
const int ec = errno;
return "错误码:" + std::to_string(ec) + ": " + std::strerror(ec);
}
std::string get_error_message(ERROR_CODE_TYPE ec) {
return "错误码:" + std::to_string(ec) + ": " + std::strerror(static_cast<int>(ec));
}
ERROR_CODE_TYPE get_error_code() {
return errno;
}
void set_error_code(ERROR_CODE_TYPE code) {
errno = static_cast<int>(code);
}
std::string get_exe_path() {
std::vector<char> buffer(PATH_MAX + 1, '\0');
const ssize_t len = readlink("/proc/self/exe", buffer.data(), buffer.size() - 1);
if (len == -1) {
return "";
}
buffer[static_cast<size_t>(len)] = '\0';
return std::string(buffer.data());
}
std::string get_home_dir() {
if (const char* home = std::getenv("HOME")) {
return home;
}
struct passwd* pw = getpwuid(getuid());
if (pw && pw->pw_dir) {
return std::string(pw->pw_dir);
}
return "";
}
bool set_thread_priority(void* thread_ptr, int priority, bool realtime) {
if (!thread_ptr) {
return false;
}
pthread_t pthread = *static_cast<pthread_t*>(thread_ptr);
int policy = realtime ? SCHED_FIFO : SCHED_OTHER;
sched_param param{};
if (realtime) {
const int min_prio = sched_get_priority_min(policy);
const int max_prio = sched_get_priority_max(policy);
if (min_prio >= 0 && max_prio >= min_prio) {
priority = std::max(min_prio, std::min(max_prio, priority));
}
param.sched_priority = priority;
} else {
param.sched_priority = 0;
}
const int ret = pthread_setschedparam(pthread, policy, &param);
if (ret != 0) {
errno = ret;
return false;
}
return true;
}
bool set_thread_priority(std::thread* thread, int priority, bool realtime) {
if (!thread) {
return false;
}
pthread_t pthread = thread->native_handle();
return set_thread_priority(static_cast<void*>(&pthread), priority, realtime);
}
bool set_thread_affinity(void* thread_ptr, unsigned cpu_index) {
if (!thread_ptr) {
return false;
}
if (cpu_index >= CPU_SETSIZE) {
errno = EINVAL;
return false;
}
pthread_t pthread = *static_cast<pthread_t*>(thread_ptr);
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(cpu_index, &cpuset);
const int ret = pthread_setaffinity_np(pthread, sizeof(cpu_set_t), &cpuset);
if (ret != 0) {
errno = ret;
std::cerr << "Error setting thread affinity: " << std::strerror(ret) << std::endl;
return false;
}
return true;
}
bool set_thread_affinity(std::thread* thread, unsigned cpu_index) {
if (!thread) {
return false;
}
pthread_t pthread = thread->native_handle();
return set_thread_affinity(static_cast<void*>(&pthread), cpu_index);
}
std::string get_memory_info() {
auto ret = JSON::object();
ret.append({"VmRSS (MB)", read_proc_status_kb("VmRSS:") / 1024});
ret.append({"VmSize (MB)", read_proc_status_kb("VmSize:") / 1024});
ret.append({"VmPeak (MB)", read_proc_status_kb("VmPeak:") / 1024});
ret.append({"VmHWM (MB)", read_proc_status_kb("VmHWM:") / 1024});
return ret.to_json_string();
}
size_t get_system_memory() {
std::ifstream meminfo("/proc/meminfo");
std::string line;
while (std::getline(meminfo, line)) {
if (line.rfind("MemTotal:", 0) == 0) {
size_t mem_total_kb = 0;
if (std::sscanf(line.c_str(), "MemTotal: %zu kB", &mem_total_kb) == 1) {
return mem_total_kb * 1024;
}
}
}
return 0;
}
size_t get_process_memory() {
return read_proc_status_kb("VmRSS:") * 1024;
}
size_t get_process_memory() { return read_proc_status_kb("VmRSS:") * 1024; }
} // namespace Psc
+584 -570
View File
File diff suppressed because it is too large Load Diff