249 lines
7.3 KiB
C++
249 lines
7.3 KiB
C++
#pragma once
|
|
|
|
#include "../Base/global_include.h"
|
|
#include "magic_enum/../../../export.h"
|
|
|
|
#include <algorithm>
|
|
#include <atomic>
|
|
#include <cassert>
|
|
#include <csignal>
|
|
#include <cstdint>
|
|
#include <ctime>
|
|
#include <deque>
|
|
#include <functional>
|
|
#include <iostream>
|
|
#include <mutex>
|
|
#include <set>
|
|
#include <stack>
|
|
#include <string>
|
|
#include <system_error>
|
|
#include <thread>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#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 DELETE_COPY(Class) \
|
|
Class(const Class&) = delete; \
|
|
Class& operator=(const Class&) = delete;
|
|
|
|
namespace Psc {
|
|
void set_console_utf8();
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
// 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);
|
|
|
|
using Main_Function_Type = int (*)(int, char**);
|
|
|
|
// 接管 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);
|
|
|
|
// 设置给定线程的 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();
|
|
|
|
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 = {});
|
|
|
|
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 free_size() {
|
|
std::lock_guard g(mtx);
|
|
return free_.size() * block_size;
|
|
}
|
|
|
|
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();
|
|
|
|
std::cout << "String_Pool 扩容对象数 【" << grow_count
|
|
<< "】,理论容量 【" << grow_count * block_size << "】"
|
|
<< std::endl;
|
|
|
|
grow(grow_count);
|
|
}
|
|
|
|
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 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);
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
private:
|
|
std::deque<std::string> strings_;
|
|
std::stack<std::string*> free_{};
|
|
|
|
mutable Spin_Lock mtx;
|
|
|
|
size_t block_size; // 每个 std::string 预留的容量。
|
|
size_t pool_size; // 初始创建多少个 string 对象。
|
|
|
|
friend struct Pool_Guard;
|
|
};
|
|
|
|
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() {
|
|
if (!pool) {
|
|
return;
|
|
}
|
|
|
|
if (buf) {
|
|
pool->release(buf);
|
|
}
|
|
|
|
if (!list.empty()) {
|
|
pool->release(list);
|
|
}
|
|
}
|
|
|
|
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& 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;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
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()) {}
|
|
|
|
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;
|
|
|
|
std::string to_string() {
|
|
auto enum_name = std::string(magic_enum::enum_type_name<Enum_Type>());
|
|
return enum_name + "【" + Psc::to_string(nerr) + " native:" + get_error_message(native.value()) + "】";
|
|
}
|
|
};
|
|
|
|
} // namespace Psc
|