From 9e0dc2e706d12717d1219845ab544ae522e95446 Mon Sep 17 00:00:00 2001 From: fasiondog Date: Mon, 20 Apr 2020 23:59:47 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=85=A8=E5=B1=80=E7=BA=BF?= =?UTF-8?q?=E7=A8=8B=E6=B1=A0=EF=BC=9B=E7=89=88=E6=9C=AC=E6=9E=84=E5=BB=BA?= =?UTF-8?q?=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.h.in | 5 --- hikyuu_cpp/hikyuu/GlobalInitializer.cpp | 8 ++-- hikyuu_cpp/hikyuu/GlobalTaskGroup.cpp | 41 +++++++++++++++++++ hikyuu_cpp/hikyuu/GlobalTaskGroup.h | 38 +++++++++++++++++ hikyuu_cpp/hikyuu/Log.cpp | 6 +-- hikyuu_cpp/hikyuu/Log.h | 6 +-- hikyuu_cpp/hikyuu/StockManager.cpp | 40 ++++++++++++------ hikyuu_cpp/hikyuu/StockManager.h | 11 ++--- hikyuu_cpp/hikyuu/hikyuu.cpp | 16 ++++++++ hikyuu_cpp/hikyuu/hikyuu.h | 5 +++ .../hikyuu/utilities/thread/ThreadPool.h | 17 +++++++- hikyuu_cpp/hikyuu/version.h | 22 ++++++++++ hikyuu_cpp/hikyuu/xmake.lua | 1 + version.h.in | 22 ++++++++++ xmake.lua | 2 +- 15 files changed, 205 insertions(+), 35 deletions(-) create mode 100644 hikyuu_cpp/hikyuu/GlobalTaskGroup.cpp create mode 100644 hikyuu_cpp/hikyuu/GlobalTaskGroup.h create mode 100644 hikyuu_cpp/hikyuu/version.h create mode 100644 version.h.in diff --git a/config.h.in b/config.h.in index c9ddcc3f..233649c6 100644 --- a/config.h.in +++ b/config.h.in @@ -4,11 +4,6 @@ // clang-format off -#define HKU_VERSION "${VERSION}" -#define HKU_VERSION_MAJOR ${VERSION_MAJOR} -#define HKU_VERSION_MINOR ${VERSION_MINOR} -#define HKU_VERSION_ALTER ${VERSION_ALTER} - // support serialization #define HKU_SUPPORT_SERIALIZATION ${SUPPORT_SERIALIZATION} diff --git a/hikyuu_cpp/hikyuu/GlobalInitializer.cpp b/hikyuu_cpp/hikyuu/GlobalInitializer.cpp index f9a66149..a0db646e 100644 --- a/hikyuu_cpp/hikyuu/GlobalInitializer.cpp +++ b/hikyuu_cpp/hikyuu/GlobalInitializer.cpp @@ -9,7 +9,9 @@ #include #include +#include #include "Log.h" +#include "hikyuu.h" #include "GlobalInitializer.h" #include "StockManager.h" #include "debug.h" @@ -33,16 +35,16 @@ void GlobalInitializer::init() { _CrtSetBreakAlloc(-1); #endif - init_logger(); + fmt::print("Initialize hikyuu_{} ...\n", getVersionWithBuild()); + + initLogger(); DataDriverFactory::init(); auto& sm = StockManager::instance(); } void GlobalInitializer::clean() { StockManager::quit(); - DataDriverFactory::release(); - H5close(); #if USE_SPDLOG_LOGGER diff --git a/hikyuu_cpp/hikyuu/GlobalTaskGroup.cpp b/hikyuu_cpp/hikyuu/GlobalTaskGroup.cpp new file mode 100644 index 00000000..3f4514c1 --- /dev/null +++ b/hikyuu_cpp/hikyuu/GlobalTaskGroup.cpp @@ -0,0 +1,41 @@ +/* + * GlobalTaskGroup.cpp + * + * Copyright (c) 2019 hikyuu.org + * + * Created on: 2020-4-20 + * Author: fasiondog + */ + +#include +#include "GlobalTaskGroup.h" + +namespace hku { + +static ThreadPool* g_threadPool; + +HKU_API ThreadPool* getGlobalTaskGroup() { + return g_threadPool; +} + +void initThreadPool() { + if (!g_threadPool) { + auto cpu_num = std::thread::hardware_concurrency(); + if (cpu_num >= 4) { + cpu_num -= 2; + } else if (cpu_num > 1) { + cpu_num--; + } + g_threadPool = new ThreadPool(cpu_num); + } +} + +void releaseThreadPool() { + if (g_threadPool) { + g_threadPool->stop(); + delete g_threadPool; + g_threadPool = nullptr; + } +} + +} /* namespace hku */ \ No newline at end of file diff --git a/hikyuu_cpp/hikyuu/GlobalTaskGroup.h b/hikyuu_cpp/hikyuu/GlobalTaskGroup.h new file mode 100644 index 00000000..e2a0dfad --- /dev/null +++ b/hikyuu_cpp/hikyuu/GlobalTaskGroup.h @@ -0,0 +1,38 @@ +/* + * GlobalTaskGroup.h + * + * Copyright (c) 2019 hikyuu.org + * + * Created on: 2020-4-20 + * Author: fasiondog + */ + +#pragma +#ifndef HKU_GLOBAL_TASK_GROUP +#define HKU_GLOBAL_TASK_GROUP + +#include "utilities/thread/ThreadPool.h" + +#ifndef HKU_API +#define HKU_API +#endif + +namespace hku { + +/** + * 获取全局线程池任务组 + * @note 请使用 future 获取任务返回 + */ +HKU_API ThreadPool* getGlobalTaskGroup(); + +/* + * 内部函数,初始化全局任务组 + */ +void initThreadPool(); + +/* 内部函数,初始化全局任务组 */ +void releaseThreadPool(); + +} /* namespace hku */ + +#endif /* HKU_GLOBAL_TASK_GROUP */ diff --git a/hikyuu_cpp/hikyuu/Log.cpp b/hikyuu_cpp/hikyuu/Log.cpp index f8de6fe9..b27398c8 100644 --- a/hikyuu_cpp/hikyuu/Log.cpp +++ b/hikyuu_cpp/hikyuu/Log.cpp @@ -37,7 +37,7 @@ std::shared_ptr getHikyuuLogger() { *********************************************/ #if USE_SPDLOG_LOGGER #if HKU_USE_SPDLOG_ASYNC_LOGGER -void init_logger() { +void initLogger() { // auto stdout_sink = std::make_shared(std::cout, true); auto stdout_sink = std::make_shared(); stdout_sink->set_level(spdlog::level::trace); @@ -56,7 +56,7 @@ void init_logger() { #else /* #if HKU_USE_SPDLOG_ASYNC_LOGGER */ -void init_logger() { +void initLogger() { auto stdout_sink = std::make_shared(); stdout_sink->set_level(spdlog::level::trace); auto logger = std::make_shared("hikyuu", stdout_sink); @@ -77,7 +77,7 @@ void set_log_level(LOG_LEVEL level) { /********************************************** * Use SPDLOG for logging *********************************************/ -void init_logger() {} +void initLogger() {} void set_log_level(LOG_LEVEL level) { g_log_level = level; diff --git a/hikyuu_cpp/hikyuu/Log.h b/hikyuu_cpp/hikyuu/Log.h index e9dbb4b2..7d61d1b6 100644 --- a/hikyuu_cpp/hikyuu/Log.h +++ b/hikyuu_cpp/hikyuu/Log.h @@ -87,9 +87,9 @@ std::shared_ptr HKU_API getHikyuuLogger(); #define HKU_FATAL(...) SPDLOG_LOGGER_CRITICAL(hku::getHikyuuLogger(), __VA_ARGS__) #if HKU_USE_SPDLOG_ASYNC_LOGGER -void init_logger(); +void initLogger(); #else -void init_logger(); +void initLogger(); #endif #else @@ -105,7 +105,7 @@ enum LOG_LEVEL { LOG_LEVEL HKU_API get_log_level(); void HKU_API set_log_level(LOG_LEVEL level); -void init_logger(); +void initLogger(); #if LOG_ACTIVE_LEVEL <= 0 #define HKU_TRACE(...) \ diff --git a/hikyuu_cpp/hikyuu/StockManager.cpp b/hikyuu_cpp/hikyuu/StockManager.cpp index f9503d4a..1d05b04c 100644 --- a/hikyuu_cpp/hikyuu/StockManager.cpp +++ b/hikyuu_cpp/hikyuu/StockManager.cpp @@ -7,12 +7,14 @@ #include "GlobalInitializer.h" #include +#include #include #include #include "utilities/IniParser.h" #include "utilities/util.h" #include "StockManager.h" +#include "GlobalTaskGroup.h" #include "data_driver/KDataTempCsvDriver.h" #include "data_driver/base_info/sqlite/SQLiteBaseInfoDriver.h" #include "data_driver/base_info/mysql/MySQLBaseInfoDriver.h" @@ -26,16 +28,21 @@ namespace hku { StockManager* StockManager::m_sm = nullptr; void StockManager::quit() { - // Cannot use log output when exiting! - // HKU_TRACE("Quit Hikyuu system!\n"); + releaseThreadPool(); if (m_sm) { - std::cout << "Quit Hikyuu system!\n" << std::endl; delete m_sm; m_sm = nullptr; } } -StockManager::~StockManager() {} +StockManager::StockManager() {} +StockManager::~StockManager() { + auto tg = getGlobalTaskGroup(); + if (tg && !tg->done()) { + releaseThreadPool(); + } + fmt::print("Quit Hikyuu system!\n\n"); +} StockManager& StockManager::instance() { if (!m_sm) { @@ -67,15 +74,21 @@ Parameter default_other_param() { return param; } -void StockManager::init(const Parameter& baseInfoParam, const Parameter& blockParam, const Parameter& kdataParam, - const Parameter& preloadParam, const Parameter& hikyuuParam) { +void StockManager::init(const Parameter& baseInfoParam, const Parameter& blockParam, + const Parameter& kdataParam, const Parameter& preloadParam, + const Parameter& hikyuuParam) { m_baseInfoDriverParam = baseInfoParam; m_blockDriverParam = blockParam; m_kdataDriverParam = kdataParam; m_preloadParam = preloadParam; m_hikyuuParam = hikyuuParam; - //获取临时路径信息 + // 创建内部线程池 + // 不能同过 GlobalInitializer 初始化全局线程池 + // 原因是 std::thread 无法在 dllmain 中创建使用,会造成死锁 + initThreadPool(); + + // 获取临时路径信息 try { m_tmpdir = hikyuuParam.get("tmpdir"); } catch (...) { @@ -111,7 +124,8 @@ void StockManager::init(const Parameter& baseInfoParam, const Parameter& blockPa setKDataDriver(kdata_driver); // add special Market, for temp csv file - m_marketInfoDict["TMP"] = MarketInfo("TMP", "Temp Csv file", "temp load from csv file", "000001", Null()); + m_marketInfoDict["TMP"] = + MarketInfo("TMP", "Temp Csv file", "temp load from csv file", "000001", Null()); std::chrono::duration sec = std::chrono::system_clock::now() - start_time; HKU_INFO("{:<.2f}s Loaded Data.", sec.count()); @@ -336,13 +350,13 @@ DatetimeList StockManager::getTradingCalendar(const KQuery& query, const string& return result; } -Stock StockManager::addTempCsvStock(const string& code, const string& day_filename, const string& min_filename, - price_t tick, price_t tickValue, int precision, size_t minTradeNumber, - size_t maxTradeNumber) { +Stock StockManager::addTempCsvStock(const string& code, const string& day_filename, + const string& min_filename, price_t tick, price_t tickValue, + int precision, size_t minTradeNumber, size_t maxTradeNumber) { string new_code(code); to_upper(new_code); - Stock result("TMP", new_code, day_filename, STOCKTYPE_TMP, true, Datetime(199901010000), Null(), tick, - tickValue, precision, minTradeNumber, maxTradeNumber); + Stock result("TMP", new_code, day_filename, STOCKTYPE_TMP, true, Datetime(199901010000), + Null(), tick, tickValue, precision, minTradeNumber, maxTradeNumber); KDataTempCsvDriver* p = new KDataTempCsvDriver(day_filename, min_filename); result.setKDataDriver(KDataDriverPtr(p)); diff --git a/hikyuu_cpp/hikyuu/StockManager.h b/hikyuu_cpp/hikyuu/StockManager.h index a58c0ffd..31c2312f 100644 --- a/hikyuu_cpp/hikyuu/StockManager.h +++ b/hikyuu_cpp/hikyuu/StockManager.h @@ -39,8 +39,8 @@ public: * @param preloadParam * @param hikyuuParam */ - void init(const Parameter& baseInfoParam, const Parameter& blockParam, const Parameter& kdataParam, - const Parameter& preloadParam = default_preload_param(), + void init(const Parameter& baseInfoParam, const Parameter& blockParam, + const Parameter& kdataParam, const Parameter& preloadParam = default_preload_param(), const Parameter& hikyuuParam = default_other_param()); /** 主动退出并释放资源 */ @@ -153,8 +153,9 @@ public: * @param maxTradeNumber 单笔最大交易量,默认1000000 * @return */ - Stock addTempCsvStock(const string& code, const string& day_filename, const string& min_filename, - price_t tick = 0.01, price_t tickValue = 0.01, int precision = 2, size_t minTradeNumber = 1, + Stock addTempCsvStock(const string& code, const string& day_filename, + const string& min_filename, price_t tick = 0.01, price_t tickValue = 0.01, + int precision = 2, size_t minTradeNumber = 1, size_t maxTradeNumber = 1000000); /** @@ -173,7 +174,7 @@ public: } private: - StockManager() {} + StockManager(); private: static StockManager* m_sm; diff --git a/hikyuu_cpp/hikyuu/hikyuu.cpp b/hikyuu_cpp/hikyuu/hikyuu.cpp index 9d93d592..ea897834 100644 --- a/hikyuu_cpp/hikyuu/hikyuu.cpp +++ b/hikyuu_cpp/hikyuu/hikyuu.cpp @@ -5,8 +5,10 @@ * Author: fasiondog */ +#include #include "utilities/IniParser.h" #include "hikyuu.h" +#include "version.h" namespace hku { @@ -68,4 +70,18 @@ string getVersion() { return HKU_VERSION; } +std::string HKU_API getVersionWithBuild() { +#if defined(__arm__) + return fmt::format("{}_{}_arm", HKU_VERSION, HKU_VERSION_BUILD); +#elif defined(__aarch64__) + return fmt::format("{}_{}_aarch64", HKU_VERSION, HKU_VERSION_BUILD); +#elif defined(__x86_64__) || defined(_WIN64) + return fmt::format("{}_{}_x64", HKU_VERSION, HKU_VERSION_BUILD); +#elif defined(__i386__) || defined(_WIN32) + return fmt::format("{}_{}_i386", HKU_VERSION, HKU_VERSION_BUILD); +#else + return fmt::format("{}_{}_unknow_arch", HKU_VERSION, HKU_VERSION_BUILD); +#endif +} + } // namespace hku diff --git a/hikyuu_cpp/hikyuu/hikyuu.h b/hikyuu_cpp/hikyuu/hikyuu.h index f108b62b..fe3f21ce 100644 --- a/hikyuu_cpp/hikyuu/hikyuu.h +++ b/hikyuu_cpp/hikyuu/hikyuu.h @@ -29,6 +29,11 @@ void HKU_API hikyuu_init(const string& config_file_name); */ string HKU_API getVersion(); +/** + * 获取详细版本号,包含构建时间 + */ +std::string HKU_API getVersionWithBuild(); + } // namespace hku #endif /* HIKYUU_H_ */ diff --git a/hikyuu_cpp/hikyuu/utilities/thread/ThreadPool.h b/hikyuu_cpp/hikyuu/utilities/thread/ThreadPool.h index a8765be0..dbfb5794 100644 --- a/hikyuu_cpp/hikyuu/utilities/thread/ThreadPool.h +++ b/hikyuu_cpp/hikyuu/utilities/thread/ThreadPool.h @@ -11,6 +11,7 @@ #ifndef HIKYUU_UTILITIES_THREAD_THREADPOOL_H #define HIKYUU_UTILITIES_THREAD_THREADPOOL_H +//#include #include #include #include @@ -84,11 +85,22 @@ public: return res; } + /** 返回线程池结束状态 */ + bool done() const { + return m_done; + } + /** * 等待各线程完成当前执行的任务后立即结束退出 */ void stop() { m_done = true; + + // 同时加入结束任务指示,以便在dll退出时也能够终止 + for (size_t i = 0; i < m_worker_num; i++) { + m_queues[i]->push_front(std::move(FuncWrapper())); + } + m_cv.notify_all(); // 唤醒所有工作线程 for (size_t i = 0; i < m_worker_num; i++) { if (m_threads[i].joinable()) { @@ -134,8 +146,8 @@ private: // 线程本地变量 inline static thread_local WorkStealQueue* m_local_work_queue = nullptr; // 本地任务队列 - inline static thread_local size_t m_index = 0; //在线程池中的序号 - inline static thread_local bool m_thread_need_stop = false; // 线程停止运行指示 + inline static thread_local size_t m_index = 0; //在线程池中的序号 + inline static thread_local bool m_thread_need_stop = false; // 线程停止运行指示 void worker_thread(size_t index) { m_thread_need_stop = false; @@ -144,6 +156,7 @@ private: while (!m_thread_need_stop && !m_done) { run_pending_task(); } + // fmt::print("thread ({}) finished!\n", std::this_thread::get_id()); } void run_pending_task() { diff --git a/hikyuu_cpp/hikyuu/version.h b/hikyuu_cpp/hikyuu/version.h new file mode 100644 index 00000000..9edb15ee --- /dev/null +++ b/hikyuu_cpp/hikyuu/version.h @@ -0,0 +1,22 @@ +/* + * version.h + * + * Copyright (c) 2020, hikyuu.org + * + * Created on: 2020-4-19 + * Author: fasiondog + */ + +#pragma once +#ifndef HKU_VERSION_H +#define HKU_VERSION_H + +// clang-format off +#define HKU_VERSION "1.1.5" +#define HKU_VERSION_MAJOR 1 +#define HKU_VERSION_MINOR 1 +#define HKU_VERSION_ALTER 5 +#define HKU_VERSION_BUILD 202004202342 +// clang-format on + +#endif /* HKU_VERSION_H */ \ No newline at end of file diff --git a/hikyuu_cpp/hikyuu/xmake.lua b/hikyuu_cpp/hikyuu/xmake.lua index f5b903d5..367f16fb 100644 --- a/hikyuu_cpp/hikyuu/xmake.lua +++ b/hikyuu_cpp/hikyuu/xmake.lua @@ -12,6 +12,7 @@ target("hikyuu") -- set version for release set_configdir("./") add_configfiles("$(projectdir)/config.h.in") + add_configfiles("$(projectdir)/version.h.in") if is_plat("windows") then add_cxflags("-wd4819") diff --git a/version.h.in b/version.h.in new file mode 100644 index 00000000..244b8370 --- /dev/null +++ b/version.h.in @@ -0,0 +1,22 @@ +/* + * version.h + * + * Copyright (c) 2020, hikyuu.org + * + * Created on: 2020-4-19 + * Author: fasiondog + */ + +#pragma once +#ifndef HKU_VERSION_H +#define HKU_VERSION_H + +// clang-format off +#define HKU_VERSION "${VERSION}" +#define HKU_VERSION_MAJOR ${VERSION_MAJOR} +#define HKU_VERSION_MINOR ${VERSION_MINOR} +#define HKU_VERSION_ALTER ${VERSION_ALTER} +#define HKU_VERSION_BUILD ${VERSION_BUILD} +// clang-format on + +#endif /* HKU_VERSION_H */ \ No newline at end of file diff --git a/xmake.lua b/xmake.lua index 96fa03d5..e7d57ff4 100644 --- a/xmake.lua +++ b/xmake.lua @@ -4,7 +4,7 @@ set_xmakever("2.2.5") set_project("hikyuu") -- version -set_version("1.1.5") +set_version("1.1.5", {build="%Y%m%d%H%M"}) if is_mode("debug") then set_configvar("LOG_ACTIVE_LEVEL", 0) -- 激活的日志级别 else