hikyuu 2.7.2__py3-none-win_amd64.whl → 2.7.5__py3-none-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hikyuu/__init__.py +21 -7
- hikyuu/__init__.pyi +16 -14
- hikyuu/analysis/__init__.pyi +2 -0
- hikyuu/analysis/analysis.pyi +3 -1
- hikyuu/core.pyi +4 -2
- hikyuu/cpp/boost_date_time-mt.dll +0 -0
- hikyuu/cpp/boost_serialization-mt.dll +0 -0
- hikyuu/cpp/boost_wserialization-mt.dll +0 -0
- hikyuu/cpp/core310.pyd +0 -0
- hikyuu/cpp/core310.pyi +123 -62
- hikyuu/cpp/core311.pyd +0 -0
- hikyuu/cpp/core311.pyi +123 -62
- hikyuu/cpp/core312.pyd +0 -0
- hikyuu/cpp/core312.pyi +123 -62
- hikyuu/cpp/core313.pyd +0 -0
- hikyuu/cpp/core313.pyi +123 -62
- hikyuu/cpp/hikyuu.dll +0 -0
- hikyuu/cpp/hikyuu.lib +0 -0
- hikyuu/cpp/i18n/zh_CN/hikyuu.mo +0 -0
- hikyuu/cpp/mimalloc-redirect.dll +0 -0
- hikyuu/cpp/mimalloc.dll +0 -0
- hikyuu/data/clickhouse_upgrade/0002.sql +9 -0
- hikyuu/data/common_mysql.py +1 -1
- hikyuu/data/em_block_to_mysql.py +16 -4
- hikyuu/data/em_block_to_sqlite.py +16 -4
- hikyuu/data/hku_config_template.py +21 -3
- hikyuu/data/mysql_upgrade/0030.sql +3 -0
- hikyuu/data/pytdx_to_h5.py +2 -2
- hikyuu/data/pytdx_to_mysql.py +5 -5
- hikyuu/data/sqlite_upgrade/0030.sql +5 -0
- hikyuu/data/tdx_to_clickhouse.py +2 -2
- hikyuu/data/tdx_to_h5.py +11 -11
- hikyuu/data/tdx_to_mysql.py +2 -2
- hikyuu/draw/__init__.pyi +1 -1
- hikyuu/draw/drawplot/bokeh_draw.pyi +8 -6
- hikyuu/draw/drawplot/echarts_draw.pyi +8 -6
- hikyuu/draw/drawplot/matplotlib_draw.py +19 -11
- hikyuu/draw/drawplot/matplotlib_draw.pyi +8 -6
- hikyuu/examples/notebook/001-overview.ipynb +112 -78
- hikyuu/examples/notebook/004-IndicatorOverview.ipynb +52 -65
- hikyuu/examples/notebook/006-TradeManager.ipynb +402 -291
- hikyuu/examples/notebook/008-Pickle.ipynb +25 -17
- hikyuu/examples/notebook/009-RealData.ipynb +36 -38
- hikyuu/examples/notebook/Demo/Demo2.ipynb +146 -116
- hikyuu/extend.pyi +5 -3
- hikyuu/gui/HikyuuTDX.py +20 -0
- hikyuu/gui/data/MainWindow.py +169 -133
- hikyuu/gui/data/UseTdxImportToH5Thread.py +4 -2
- hikyuu/gui/start_qmt.py +1 -1
- hikyuu/hub.pyi +6 -6
- hikyuu/include/hikyuu/Block.h +9 -9
- hikyuu/include/hikyuu/HistoryFinanceInfo.h +3 -3
- hikyuu/include/hikyuu/KData.h +51 -28
- hikyuu/include/hikyuu/KDataImp.h +12 -7
- hikyuu/include/hikyuu/KDataPrivatedBufferImp.h +13 -7
- hikyuu/include/hikyuu/KDataSharedBufferImp.h +8 -6
- hikyuu/include/hikyuu/KQuery.h +11 -11
- hikyuu/include/hikyuu/KRecord.h +1 -1
- hikyuu/include/hikyuu/MarketInfo.h +10 -10
- hikyuu/include/hikyuu/Stock.h +30 -30
- hikyuu/include/hikyuu/StockManager.h +24 -12
- hikyuu/include/hikyuu/StockTypeInfo.h +9 -9
- hikyuu/include/hikyuu/StockWeight.h +9 -9
- hikyuu/include/hikyuu/TimeLineRecord.h +1 -1
- hikyuu/include/hikyuu/TransRecord.h +1 -1
- hikyuu/include/hikyuu/data_driver/BaseInfoDriver.h +2 -1
- hikyuu/include/hikyuu/data_driver/BlockInfoDriver.h +6 -0
- hikyuu/include/hikyuu/data_driver/KDataDriver.h +6 -7
- hikyuu/include/hikyuu/data_driver/kdata/mysql/MySQLKDataDriver.h +5 -1
- hikyuu/include/hikyuu/data_driver/kdata/sqlite/SQLiteKDataDriver.h +1 -1
- hikyuu/include/hikyuu/global/sysinfo.h +1 -1
- hikyuu/include/hikyuu/indicator/IndParam.h +1 -1
- hikyuu/include/hikyuu/indicator/Indicator.h +56 -27
- hikyuu/include/hikyuu/indicator/Indicator2InImp.h +0 -4
- hikyuu/include/hikyuu/indicator/IndicatorImp.h +146 -73
- hikyuu/include/hikyuu/indicator/crt/CONTEXT.h +11 -1
- hikyuu/include/hikyuu/indicator/crt/IC.h +19 -14
- hikyuu/include/hikyuu/indicator/crt/ICIR.h +4 -7
- hikyuu/include/hikyuu/indicator/imp/IAbs.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/IAcos.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/IAd.h +0 -2
- hikyuu/include/hikyuu/indicator/imp/IAdvance.h +3 -0
- hikyuu/include/hikyuu/indicator/imp/IAma.h +3 -0
- hikyuu/include/hikyuu/indicator/imp/IAsin.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/IAtan.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/IAtr.h +2 -3
- hikyuu/include/hikyuu/indicator/imp/IBackset.h +2 -4
- hikyuu/include/hikyuu/indicator/imp/IBlockSetNum.h +3 -0
- hikyuu/include/hikyuu/indicator/imp/ICeil.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/IContext.h +0 -3
- hikyuu/include/hikyuu/indicator/imp/ICorr.h +3 -0
- hikyuu/include/hikyuu/indicator/imp/ICos.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/ICost.h +0 -2
- hikyuu/include/hikyuu/indicator/imp/ICount.h +2 -1
- hikyuu/include/hikyuu/indicator/imp/ICval.h +1 -4
- hikyuu/include/hikyuu/indicator/imp/ICycle.h +0 -2
- hikyuu/include/hikyuu/indicator/imp/IDecline.h +3 -0
- hikyuu/include/hikyuu/indicator/imp/IDevsq.h +4 -1
- hikyuu/include/hikyuu/indicator/imp/IDiff.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/IDma.h +2 -0
- hikyuu/include/hikyuu/indicator/imp/IDropna.h +0 -4
- hikyuu/include/hikyuu/indicator/imp/IEma.h +3 -1
- hikyuu/include/hikyuu/indicator/imp/IEvery.h +5 -1
- hikyuu/include/hikyuu/indicator/imp/IExist.h +5 -1
- hikyuu/include/hikyuu/indicator/imp/IExp.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/IFilter.h +4 -5
- hikyuu/include/hikyuu/indicator/imp/IFinance.h +1 -2
- hikyuu/include/hikyuu/indicator/imp/IFloor.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/IHhvbars.h +5 -1
- hikyuu/include/hikyuu/indicator/imp/IHighLine.h +5 -1
- hikyuu/include/hikyuu/indicator/imp/IHsl.h +0 -2
- hikyuu/include/hikyuu/indicator/imp/IIc.h +3 -6
- hikyuu/include/hikyuu/indicator/imp/IInBlock.h +1 -2
- hikyuu/include/hikyuu/indicator/imp/IIntpart.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/IIsInf.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/IIsInfa.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/IIsLastBar.h +0 -1
- hikyuu/include/hikyuu/indicator/imp/IIsNa.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/IJumpDown.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/IJumpUp.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/IKData.h +1 -2
- hikyuu/include/hikyuu/indicator/imp/ILiuTongPan.h +0 -2
- hikyuu/include/hikyuu/indicator/imp/ILn.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/ILog.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/ILowLine.h +5 -1
- hikyuu/include/hikyuu/indicator/imp/ILowLineBars.h +5 -1
- hikyuu/include/hikyuu/indicator/imp/IMa.h +6 -1
- hikyuu/include/hikyuu/indicator/imp/IMacd.h +2 -0
- hikyuu/include/hikyuu/indicator/imp/INot.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/IPow.h +3 -1
- hikyuu/include/hikyuu/indicator/imp/IQuantileTrunc.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/IRecover.h +3 -0
- hikyuu/include/hikyuu/indicator/imp/IRef.h +3 -1
- hikyuu/include/hikyuu/indicator/imp/IResult.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/IReverse.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/IRoc.h +6 -1
- hikyuu/include/hikyuu/indicator/imp/IRocp.h +5 -1
- hikyuu/include/hikyuu/indicator/imp/IRocr.h +5 -1
- hikyuu/include/hikyuu/indicator/imp/IRocr100.h +5 -1
- hikyuu/include/hikyuu/indicator/imp/IRound.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/IRoundDown.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/IRoundUp.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/ISaftyLoss.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/ISign.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/ISin.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/ISlope.h +5 -1
- hikyuu/include/hikyuu/indicator/imp/ISma.h +2 -0
- hikyuu/include/hikyuu/indicator/imp/ISpearman.h +3 -0
- hikyuu/include/hikyuu/indicator/imp/ISqrt.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/IStdev.h +5 -1
- hikyuu/include/hikyuu/indicator/imp/IStdp.h +5 -1
- hikyuu/include/hikyuu/indicator/imp/ISum.h +6 -1
- hikyuu/include/hikyuu/indicator/imp/ITan.h +1 -0
- hikyuu/include/hikyuu/indicator/imp/ITime.h +1 -2
- hikyuu/include/hikyuu/indicator/imp/ITimeLine.h +0 -2
- hikyuu/include/hikyuu/indicator/imp/ITr.h +1 -2
- hikyuu/include/hikyuu/indicator/imp/IVar.h +5 -1
- hikyuu/include/hikyuu/indicator/imp/IVarp.h +5 -1
- hikyuu/include/hikyuu/indicator/imp/IVigor.h +0 -2
- hikyuu/include/hikyuu/indicator/imp/IWma.h +5 -1
- hikyuu/include/hikyuu/indicator/imp/IZongGuBen.h +1 -2
- hikyuu/include/hikyuu/indicator_talib/imp/TaAdosc.h +0 -2
- hikyuu/include/hikyuu/indicator_talib/imp/TaSar.h +0 -2
- hikyuu/include/hikyuu/indicator_talib/imp/TaSarext.h +0 -4
- hikyuu/include/hikyuu/indicator_talib/imp/TaStoch.h +0 -3
- hikyuu/include/hikyuu/indicator_talib/imp/TaStochf.h +0 -2
- hikyuu/include/hikyuu/indicator_talib/imp/TaUltosc.h +0 -2
- hikyuu/include/hikyuu/indicator_talib/imp/ta_defines.h +2 -4
- hikyuu/include/hikyuu/indicator_talib/imp/ta_imp.h +70 -90
- hikyuu/include/hikyuu/plugin/extind.h +3 -0
- hikyuu/include/hikyuu/plugin/hkuextra.h +2 -0
- hikyuu/include/hikyuu/plugin/interface/HkuExtraPluginInterface.h +2 -0
- hikyuu/include/hikyuu/python/pybind_utils.h +22 -5
- hikyuu/include/hikyuu/trade_manage/TradeCostBase.h +5 -3
- hikyuu/include/hikyuu/trade_manage/TradeManagerBase.h +9 -3
- hikyuu/include/hikyuu/trade_sys/allocatefunds/AllocateFundsBase.h +8 -4
- hikyuu/include/hikyuu/trade_sys/condition/ConditionBase.h +5 -3
- hikyuu/include/hikyuu/trade_sys/environment/EnvironmentBase.h +6 -3
- hikyuu/include/hikyuu/trade_sys/moneymanager/MoneyManagerBase.h +5 -3
- hikyuu/include/hikyuu/trade_sys/multifactor/MultiFactorBase.h +23 -20
- hikyuu/include/hikyuu/trade_sys/multifactor/NormalizeBase.h +6 -4
- hikyuu/include/hikyuu/trade_sys/multifactor/ScoresFilterBase.h +5 -3
- hikyuu/include/hikyuu/trade_sys/multifactor/crt/MF_EqualWeight.h +3 -3
- hikyuu/include/hikyuu/trade_sys/multifactor/crt/MF_ICIRWeight.h +4 -4
- hikyuu/include/hikyuu/trade_sys/multifactor/crt/MF_ICWeight.h +4 -4
- hikyuu/include/hikyuu/trade_sys/multifactor/crt/MF_Weight.h +4 -4
- hikyuu/include/hikyuu/trade_sys/portfolio/Portfolio.h +16 -13
- hikyuu/include/hikyuu/trade_sys/profitgoal/ProfitGoalBase.h +4 -3
- hikyuu/include/hikyuu/trade_sys/selector/SelectorBase.h +12 -3
- hikyuu/include/hikyuu/trade_sys/selector/crt/SE_MultiFactor.h +1 -1
- hikyuu/include/hikyuu/trade_sys/selector/crt/SE_MultiFactor2.h +1 -1
- hikyuu/include/hikyuu/trade_sys/selector/imp/MultiFactorSelector.h +1 -0
- hikyuu/include/hikyuu/trade_sys/selector/imp/MultiFactorSelector2.h +1 -0
- hikyuu/include/hikyuu/trade_sys/selector/imp/optimal/OptimalSelectorBase.h +0 -2
- hikyuu/include/hikyuu/trade_sys/selector/imp/optimal/PerformanceOptimalSelector.h +0 -4
- hikyuu/include/hikyuu/trade_sys/signal/SignalBase.h +5 -3
- hikyuu/include/hikyuu/trade_sys/slippage/SlippageBase.h +5 -3
- hikyuu/include/hikyuu/trade_sys/stoploss/StoplossBase.h +5 -3
- hikyuu/include/hikyuu/trade_sys/system/System.h +6 -4
- hikyuu/include/hikyuu/utilities/LruCache.h +299 -0
- hikyuu/include/hikyuu/utilities/arithmetic.h +2 -2
- hikyuu/include/hikyuu/utilities/omp_macro.h +25 -0
- hikyuu/include/hikyuu/utilities/plugin/PluginManager.h +5 -0
- hikyuu/include/hikyuu/utilities/thread/GlobalStealThreadPool.h +72 -19
- hikyuu/include/hikyuu/utilities/thread/GlobalThreadPool.h +0 -4
- hikyuu/include/hikyuu/utilities/thread/MQStealThreadPool.h +1 -0
- hikyuu/include/hikyuu/utilities/thread/MQThreadPool.h +1 -0
- hikyuu/include/hikyuu/utilities/thread/StealThreadPool.h +1 -0
- hikyuu/include/hikyuu/utilities/thread/ThreadPool.h +1 -4
- hikyuu/include/hikyuu/utilities/thread/algorithm.h +286 -0
- hikyuu/include/hikyuu/version.h +4 -4
- hikyuu/plugin/backtest.dll +0 -0
- hikyuu/plugin/checkdata.dll +0 -0
- hikyuu/plugin/clickhousedriver.dll +0 -0
- hikyuu/plugin/dataserver.dll +0 -0
- hikyuu/plugin/dataserver_parquet.dll +0 -0
- hikyuu/plugin/device.dll +0 -0
- hikyuu/plugin/extind.dll +0 -0
- hikyuu/plugin/hkuextra.dll +0 -0
- hikyuu/plugin/import2ch.dll +0 -0
- hikyuu/plugin/import2hdf5.dll +0 -0
- hikyuu/plugin/import2mysql.dll +0 -0
- hikyuu/plugin/tmreport.dll +0 -0
- hikyuu/test/Indicator.py +1 -2
- hikyuu/trade_manage/__init__.pyi +7 -5
- hikyuu/trade_manage/trade.pyi +7 -5
- hikyuu/util/singleton.pyi +1 -1
- {hikyuu-2.7.2.dist-info → hikyuu-2.7.5.dist-info}/METADATA +2 -13
- {hikyuu-2.7.2.dist-info → hikyuu-2.7.5.dist-info}/RECORD +232 -225
- {hikyuu-2.7.2.dist-info → hikyuu-2.7.5.dist-info}/WHEEL +1 -1
- {hikyuu-2.7.2.dist-info → hikyuu-2.7.5.dist-info}/entry_points.txt +0 -0
- {hikyuu-2.7.2.dist-info → hikyuu-2.7.5.dist-info}/top_level.txt +0 -0
|
@@ -86,12 +86,12 @@ public:
|
|
|
86
86
|
/** 子类计算接口,由setTO调用 */
|
|
87
87
|
virtual void _calculate() = 0;
|
|
88
88
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
return false;
|
|
89
|
+
bool isPythonObject() const noexcept {
|
|
90
|
+
return m_is_python_object;
|
|
92
91
|
}
|
|
93
92
|
|
|
94
93
|
protected:
|
|
94
|
+
bool m_is_python_object{false};
|
|
95
95
|
string m_name;
|
|
96
96
|
TradeManagerPtr m_tm;
|
|
97
97
|
KData m_kdata;
|
|
@@ -104,6 +104,7 @@ private:
|
|
|
104
104
|
friend class boost::serialization::access;
|
|
105
105
|
template <class Archive>
|
|
106
106
|
void save(Archive& ar, const unsigned int version) const {
|
|
107
|
+
ar& BOOST_SERIALIZATION_NVP(m_is_python_object);
|
|
107
108
|
ar& BOOST_SERIALIZATION_NVP(m_name);
|
|
108
109
|
ar& BOOST_SERIALIZATION_NVP(m_params);
|
|
109
110
|
// m_kdata都是系统运行时临时设置,不需要序列化
|
|
@@ -112,6 +113,7 @@ private:
|
|
|
112
113
|
|
|
113
114
|
template <class Archive>
|
|
114
115
|
void load(Archive& ar, const unsigned int version) {
|
|
116
|
+
ar& BOOST_SERIALIZATION_NVP(m_is_python_object);
|
|
115
117
|
ar& BOOST_SERIALIZATION_NVP(m_name);
|
|
116
118
|
ar& BOOST_SERIALIZATION_NVP(m_params);
|
|
117
119
|
// m_kdata都是系统运行时临时设置,不需要序列化
|
|
@@ -36,7 +36,7 @@ class HKU_API WalkForwardSystem;
|
|
|
36
36
|
* 交易系统基类
|
|
37
37
|
* @ingroup System
|
|
38
38
|
*/
|
|
39
|
-
class HKU_API System {
|
|
39
|
+
class HKU_API System : public enable_shared_from_this<System> {
|
|
40
40
|
PARAMETER_SUPPORT_WITH_CHECK
|
|
41
41
|
friend class HKU_API Portfolio;
|
|
42
42
|
friend class HKU_API AllocateFundsBase;
|
|
@@ -276,9 +276,8 @@ public:
|
|
|
276
276
|
// 处理延迟买入请求,仅供 PF 调用
|
|
277
277
|
virtual TradeRecord pfProcessDelayBuyRequest(const Datetime& date);
|
|
278
278
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
return false;
|
|
279
|
+
bool isPythonObject() const noexcept {
|
|
280
|
+
return m_is_python_object;
|
|
282
281
|
}
|
|
283
282
|
|
|
284
283
|
private:
|
|
@@ -352,6 +351,7 @@ protected:
|
|
|
352
351
|
KData m_kdata;
|
|
353
352
|
KData m_src_kdata; // 未复权的原始 K 线数据
|
|
354
353
|
|
|
354
|
+
bool m_is_python_object{false};
|
|
355
355
|
bool m_calculated; // 控制是否需要重新计算
|
|
356
356
|
bool m_pre_ev_valid;
|
|
357
357
|
bool m_pre_cn_valid;
|
|
@@ -394,6 +394,7 @@ private:
|
|
|
394
394
|
ar& BOOST_SERIALIZATION_NVP(m_kdata);
|
|
395
395
|
ar& BOOST_SERIALIZATION_NVP(m_stock);
|
|
396
396
|
|
|
397
|
+
ar& BOOST_SERIALIZATION_NVP(m_is_python_object);
|
|
397
398
|
ar& BOOST_SERIALIZATION_NVP(m_calculated);
|
|
398
399
|
ar& BOOST_SERIALIZATION_NVP(m_pre_ev_valid);
|
|
399
400
|
ar& BOOST_SERIALIZATION_NVP(m_pre_cn_valid);
|
|
@@ -428,6 +429,7 @@ private:
|
|
|
428
429
|
ar& BOOST_SERIALIZATION_NVP(m_kdata);
|
|
429
430
|
ar& BOOST_SERIALIZATION_NVP(m_stock);
|
|
430
431
|
|
|
432
|
+
ar& BOOST_SERIALIZATION_NVP(m_is_python_object);
|
|
431
433
|
ar& BOOST_SERIALIZATION_NVP(m_calculated);
|
|
432
434
|
ar& BOOST_SERIALIZATION_NVP(m_pre_ev_valid);
|
|
433
435
|
ar& BOOST_SERIALIZATION_NVP(m_pre_cn_valid);
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 hikyuu.org
|
|
3
|
+
*
|
|
4
|
+
* Created on: 2026-01-18
|
|
5
|
+
* Author: fasiondog
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
#include <unordered_map>
|
|
10
|
+
#include <list>
|
|
11
|
+
#include <mutex>
|
|
12
|
+
#include <shared_mutex>
|
|
13
|
+
#include <atomic>
|
|
14
|
+
#include <optional>
|
|
15
|
+
|
|
16
|
+
namespace hku {
|
|
17
|
+
|
|
18
|
+
class NullLock {
|
|
19
|
+
public:
|
|
20
|
+
void lock() noexcept {}
|
|
21
|
+
void unlock() noexcept {}
|
|
22
|
+
bool try_lock() noexcept {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
void lock_shared() noexcept {}
|
|
26
|
+
void unlock_shared() noexcept {}
|
|
27
|
+
bool try_lock_shared() noexcept {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @brief LRU (Least Recently Used)
|
|
34
|
+
* 缓存实现(非严格意义LRU以便提升并发读取性能)
|
|
35
|
+
* @tparam KeyType 键的类型,必须支持哈希和相等比较
|
|
36
|
+
* @tparam ValueType 值的类型,必须支持拷贝和移动操作
|
|
37
|
+
*/
|
|
38
|
+
template <typename KeyType, typename ValueType, class Lock = NullLock>
|
|
39
|
+
class LruCache final {
|
|
40
|
+
public:
|
|
41
|
+
using key_type = KeyType;
|
|
42
|
+
using value_type = ValueType;
|
|
43
|
+
using size_type = size_t;
|
|
44
|
+
typedef Lock lock_type;
|
|
45
|
+
using UniqueGuard = std::unique_lock<lock_type>;
|
|
46
|
+
using SharedGuard = std::shared_lock<lock_type>;
|
|
47
|
+
|
|
48
|
+
// 存储结构:值 + 原子脏标记(标记是否被get访问过,需要更新LRU顺序)
|
|
49
|
+
using CacheValue = std::pair<value_type, std::atomic<bool>>;
|
|
50
|
+
using LruList = std::list<key_type>;
|
|
51
|
+
using CacheMap =
|
|
52
|
+
std::unordered_map<key_type, std::pair<typename LruList::iterator, CacheValue>>;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @brief 构造函数
|
|
56
|
+
* @param capacity 缓存容量,默认为64,0表示无限制容量
|
|
57
|
+
* @param overflow 溢出容量,默认为8,允许缓存临时超出设定容量
|
|
58
|
+
* 仅当缓存大小 >= 容量+溢出容量时才触发淘汰机制
|
|
59
|
+
*/
|
|
60
|
+
explicit LruCache(size_type capacity = 64, size_type overflow = 8)
|
|
61
|
+
: m_capacity(capacity), m_overflow(overflow) {}
|
|
62
|
+
|
|
63
|
+
~LruCache() {
|
|
64
|
+
UniqueGuard lock(m_mutex);
|
|
65
|
+
m_cache.clear();
|
|
66
|
+
m_lru_list.clear();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @brief 插入键值对
|
|
71
|
+
* @param key 键
|
|
72
|
+
* @param value 值
|
|
73
|
+
*/
|
|
74
|
+
void insert(const key_type& key, const value_type& value) {
|
|
75
|
+
UniqueGuard lock(m_mutex);
|
|
76
|
+
_batch_update_dirty_nodes();
|
|
77
|
+
auto it = m_cache.find(key);
|
|
78
|
+
if (it != m_cache.end()) {
|
|
79
|
+
it->second.second.first = value;
|
|
80
|
+
it->second.second.second.store(false, std::memory_order_relaxed);
|
|
81
|
+
m_lru_list.splice(m_lru_list.begin(), m_lru_list, it->second.first);
|
|
82
|
+
} else {
|
|
83
|
+
m_lru_list.emplace_front(key);
|
|
84
|
+
m_cache.emplace(key, std::make_pair(m_lru_list.begin(),
|
|
85
|
+
std::make_pair(value, false) // 初始脏标记为false
|
|
86
|
+
));
|
|
87
|
+
_prune_if_needed();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @brief 插入键值对(移动版本)
|
|
93
|
+
* @param key 键
|
|
94
|
+
* @param value 值(右值引用)
|
|
95
|
+
*/
|
|
96
|
+
void insert(const key_type& key, value_type&& value) {
|
|
97
|
+
UniqueGuard lock(m_mutex);
|
|
98
|
+
_batch_update_dirty_nodes();
|
|
99
|
+
auto it = m_cache.find(key);
|
|
100
|
+
if (it != m_cache.end()) {
|
|
101
|
+
it->second.second.first = std::move(value);
|
|
102
|
+
it->second.second.second.store(false, std::memory_order_relaxed);
|
|
103
|
+
m_lru_list.splice(m_lru_list.begin(), m_lru_list, it->second.first);
|
|
104
|
+
} else {
|
|
105
|
+
m_lru_list.emplace_front(key);
|
|
106
|
+
m_cache.emplace(
|
|
107
|
+
key, std::make_pair(m_lru_list.begin(), std::make_pair(std::move(value), false)));
|
|
108
|
+
_prune_if_needed();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* @brief 获取键对应的值
|
|
114
|
+
* @param key 键
|
|
115
|
+
* @return 存在则返回值,否则返回ValueType的默认构造值
|
|
116
|
+
*/
|
|
117
|
+
value_type get(const key_type& key) {
|
|
118
|
+
SharedGuard lock(m_mutex);
|
|
119
|
+
auto it = m_cache.find(key);
|
|
120
|
+
if (it != m_cache.end()) {
|
|
121
|
+
it->second.second.second.store(true, std::memory_order_relaxed);
|
|
122
|
+
return it->second.second.first;
|
|
123
|
+
}
|
|
124
|
+
return value_type{};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* @brief 尝试获取键对应的值
|
|
129
|
+
* @param key 键
|
|
130
|
+
* @param value 用于接收值的引用参数
|
|
131
|
+
* @return 如果键存在返回true,否则返回false
|
|
132
|
+
*/
|
|
133
|
+
bool tryGet(const key_type& key, value_type& value) {
|
|
134
|
+
SharedGuard lock(m_mutex);
|
|
135
|
+
auto it = m_cache.find(key);
|
|
136
|
+
if (it != m_cache.end()) {
|
|
137
|
+
it->second.second.second.store(true, std::memory_order_relaxed);
|
|
138
|
+
value = it->second.second.first;
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* @brief 检查是否包含指定键
|
|
146
|
+
* @param key 键
|
|
147
|
+
* @return 存在返回true,否则返回false
|
|
148
|
+
*/
|
|
149
|
+
bool contains(const key_type& key) {
|
|
150
|
+
SharedGuard lock(m_mutex);
|
|
151
|
+
return m_cache.find(key) != m_cache.end();
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* @brief 删除指定键
|
|
156
|
+
* @param key 要删除的键
|
|
157
|
+
* @return 成功删除返回true,不存在返回false
|
|
158
|
+
*/
|
|
159
|
+
bool remove(const key_type& key) {
|
|
160
|
+
UniqueGuard lock(m_mutex);
|
|
161
|
+
auto it = m_cache.find(key);
|
|
162
|
+
if (it != m_cache.end()) {
|
|
163
|
+
m_lru_list.erase(it->second.first);
|
|
164
|
+
m_cache.erase(it);
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* @brief 清空缓存
|
|
172
|
+
*/
|
|
173
|
+
void clear() {
|
|
174
|
+
UniqueGuard lock(m_mutex);
|
|
175
|
+
m_cache.clear();
|
|
176
|
+
m_lru_list.clear();
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* @brief 获取缓存当前大小
|
|
181
|
+
* @return 当前缓存元素数量
|
|
182
|
+
*/
|
|
183
|
+
size_type size() const {
|
|
184
|
+
SharedGuard lock(m_mutex);
|
|
185
|
+
return m_cache.size();
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* @brief 检查缓存是否为空
|
|
190
|
+
* @return 空返回true,否则返回false
|
|
191
|
+
*/
|
|
192
|
+
bool empty() const {
|
|
193
|
+
SharedGuard lock(m_mutex);
|
|
194
|
+
return m_cache.empty();
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* @brief 获取缓存容量
|
|
199
|
+
* @return 缓存容量
|
|
200
|
+
*/
|
|
201
|
+
size_type capacity() const {
|
|
202
|
+
SharedGuard lock(m_mutex);
|
|
203
|
+
return m_capacity;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* @brief 获取缓存溢出容量
|
|
208
|
+
* @return 缓存溢出容量
|
|
209
|
+
*/
|
|
210
|
+
size_type overflow() const {
|
|
211
|
+
SharedGuard lock(m_mutex);
|
|
212
|
+
return m_overflow;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* @brief 设置缓存容量
|
|
217
|
+
* @param capacity 新的容量,0表示不限制容量
|
|
218
|
+
*/
|
|
219
|
+
void resize(size_type capacity) {
|
|
220
|
+
UniqueGuard lock(m_mutex);
|
|
221
|
+
m_capacity = capacity;
|
|
222
|
+
_prune_if_needed();
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* @brief 设置缓存溢出容量
|
|
227
|
+
* @param overflow 新的溢出容量
|
|
228
|
+
*/
|
|
229
|
+
void setOverflow(size_type overflow) {
|
|
230
|
+
UniqueGuard lock(m_mutex);
|
|
231
|
+
m_overflow = overflow;
|
|
232
|
+
_prune_if_needed();
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
private:
|
|
236
|
+
// 如果缓存已满,移除最久未使用的项
|
|
237
|
+
size_t _prune_if_needed() {
|
|
238
|
+
size_t maxAllowed = m_capacity + m_overflow;
|
|
239
|
+
if (m_capacity == 0 || m_cache.size() <= maxAllowed) {
|
|
240
|
+
return 0;
|
|
241
|
+
}
|
|
242
|
+
size_t count = 0;
|
|
243
|
+
while (m_cache.size() > m_capacity) {
|
|
244
|
+
m_cache.erase(m_lru_list.back());
|
|
245
|
+
m_lru_list.pop_back();
|
|
246
|
+
++count;
|
|
247
|
+
}
|
|
248
|
+
return count;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// 批量更新所有脏节点:移到链表头部,清除脏标记
|
|
252
|
+
void _batch_update_dirty_nodes() {
|
|
253
|
+
// 修复点1:避免默认构造,改用指针/引用追踪最新脏节点
|
|
254
|
+
typename LruList::reverse_iterator latest_dirty_it;
|
|
255
|
+
bool has_dirty = false;
|
|
256
|
+
|
|
257
|
+
// 反向遍历链表:从尾部→头部,找第一个脏节点(最新访问的节点)
|
|
258
|
+
for (auto it = m_lru_list.rbegin(); it != m_lru_list.rend(); ++it) {
|
|
259
|
+
const key_type& key = *it;
|
|
260
|
+
auto cache_it = m_cache.find(key);
|
|
261
|
+
if (cache_it == m_cache.end()) {
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
auto& dirty_flag = cache_it->second.second.second;
|
|
266
|
+
// 修复点2:原子加载判断,避免未初始化访问
|
|
267
|
+
if (dirty_flag.load(std::memory_order_relaxed)) {
|
|
268
|
+
latest_dirty_it = it;
|
|
269
|
+
has_dirty = true;
|
|
270
|
+
break; // 仅处理最新访问的脏节点,保留1在尾部
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// 仅移动最新访问的脏节点到头部(修复点3:反向迭代器转正向迭代器)
|
|
275
|
+
if (has_dirty) {
|
|
276
|
+
// C++17:反向迭代器转正向迭代器(base()方法)
|
|
277
|
+
auto forward_it = latest_dirty_it.base();
|
|
278
|
+
--forward_it; // 反向迭代器base()返回的是下一个正向迭代器,需减1
|
|
279
|
+
|
|
280
|
+
const key_type& key = *forward_it;
|
|
281
|
+
auto cache_it = m_cache.find(key);
|
|
282
|
+
if (cache_it != m_cache.end()) {
|
|
283
|
+
// 清除脏标记
|
|
284
|
+
cache_it->second.second.second.store(false, std::memory_order_relaxed);
|
|
285
|
+
// 移动节点到链表头部(splice仅支持正向迭代器)
|
|
286
|
+
m_lru_list.splice(m_lru_list.begin(), m_lru_list, forward_it);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
private:
|
|
292
|
+
size_type m_capacity;
|
|
293
|
+
size_type m_overflow;
|
|
294
|
+
LruList m_lru_list;
|
|
295
|
+
CacheMap m_cache;
|
|
296
|
+
mutable lock_type m_mutex;
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
} // namespace hku
|
|
@@ -209,12 +209,12 @@ extern template float HKU_UTILS_API roundDown(float number, int ndigits);
|
|
|
209
209
|
#endif
|
|
210
210
|
|
|
211
211
|
/** 转小写字符串 */
|
|
212
|
-
inline void to_lower(std::string &s) {
|
|
212
|
+
inline void to_lower(std::string &s) noexcept {
|
|
213
213
|
std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return std::tolower(c); });
|
|
214
214
|
}
|
|
215
215
|
|
|
216
216
|
/** 转大写字符串 */
|
|
217
|
-
inline void to_upper(std::string &s) {
|
|
217
|
+
inline void to_upper(std::string &s) noexcept {
|
|
218
218
|
std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return std::toupper(c); });
|
|
219
219
|
}
|
|
220
220
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 hikyuu.org
|
|
3
|
+
*
|
|
4
|
+
* Created on: 2026-01-16
|
|
5
|
+
* Author: fasiondog
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#include "hikyuu/utilities/config.h"
|
|
11
|
+
|
|
12
|
+
#if defined(_OPENMP)
|
|
13
|
+
#include <omp.h>
|
|
14
|
+
#define HKU_OMP_PARALLEL_FOR _Pragma("omp parallel for")
|
|
15
|
+
#define HKU_OMP_SAFETY_PARALLEL_FOR \
|
|
16
|
+
_Pragma("omp parallel for num_threads(omp_get_max_threads()) if (!omp_in_parallel())")
|
|
17
|
+
#define HKU_OMP_CHECK_THRESHOLD(guard, threshold) \
|
|
18
|
+
if ((guard) > (threshold) && !omp_in_parallel()) { \
|
|
19
|
+
omp_set_num_threads(omp_get_max_threads()); \
|
|
20
|
+
}
|
|
21
|
+
#else
|
|
22
|
+
#define HKU_OMP_PARALLEL_FOR
|
|
23
|
+
#define HKU_OMP_SAFETY_PARALLEL_FOR
|
|
24
|
+
#define HKU_OMP_CHECK_THRESHOLD(guard, threshold)
|
|
25
|
+
#endif
|
|
@@ -37,6 +37,11 @@ public:
|
|
|
37
37
|
m_plugin_path = plugin_path;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
void clear() noexcept {
|
|
41
|
+
std::unique_lock<std::shared_mutex> write_lock(m_mutex);
|
|
42
|
+
m_plugins.clear();
|
|
43
|
+
}
|
|
44
|
+
|
|
40
45
|
template <typename PluginInterfaceT>
|
|
41
46
|
PluginInterfaceT* getPlugin(const std::string& pluginname) noexcept {
|
|
42
47
|
PluginInterfaceT* ret{nullptr};
|
|
@@ -8,8 +8,6 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
#pragma once
|
|
11
|
-
#ifndef HIKYUU_UTILITIES_THREAD_STEALTHREADPOOL_H
|
|
12
|
-
#define HIKYUU_UTILITIES_THREAD_STEALTHREADPOOL_H
|
|
13
11
|
|
|
14
12
|
#include <future>
|
|
15
13
|
#include <thread>
|
|
@@ -65,7 +63,7 @@ public:
|
|
|
65
63
|
m_threads.emplace_back(&GlobalStealThreadPool::worker_thread, this, i);
|
|
66
64
|
}
|
|
67
65
|
} catch (...) {
|
|
68
|
-
m_done
|
|
66
|
+
m_done.store(true, std::memory_order_release);
|
|
69
67
|
throw;
|
|
70
68
|
}
|
|
71
69
|
}
|
|
@@ -74,7 +72,7 @@ public:
|
|
|
74
72
|
* 析构函数,等待并阻塞至线程池内所有任务完成
|
|
75
73
|
*/
|
|
76
74
|
~GlobalStealThreadPool() {
|
|
77
|
-
if (!m_done) {
|
|
75
|
+
if (!m_done.load(std::memory_order_acquire)) {
|
|
78
76
|
join();
|
|
79
77
|
}
|
|
80
78
|
}
|
|
@@ -86,7 +84,7 @@ public:
|
|
|
86
84
|
|
|
87
85
|
/** 剩余任务数 */
|
|
88
86
|
size_t remain_task_count() const {
|
|
89
|
-
if (m_done) {
|
|
87
|
+
if (m_done.load(std::memory_order_acquire)) {
|
|
90
88
|
return 0;
|
|
91
89
|
}
|
|
92
90
|
size_t total = m_master_work_queue.size();
|
|
@@ -108,7 +106,7 @@ public:
|
|
|
108
106
|
/** 向线程池提交任务 */
|
|
109
107
|
template <typename FunctionType>
|
|
110
108
|
auto submit(FunctionType f) {
|
|
111
|
-
if (m_thread_need_stop.isSet() || m_done) {
|
|
109
|
+
if (m_thread_need_stop.isSet() || m_done.load(std::memory_order_acquire)) {
|
|
112
110
|
throw std::logic_error(
|
|
113
111
|
"You can't submit a task to the stopped GlobalStealThreadPool!!");
|
|
114
112
|
}
|
|
@@ -116,13 +114,16 @@ public:
|
|
|
116
114
|
typedef typename std::invoke_result<FunctionType>::type result_type;
|
|
117
115
|
std::packaged_task<result_type()> task(f);
|
|
118
116
|
task_handle<result_type> res(task.get_future());
|
|
119
|
-
|
|
117
|
+
|
|
118
|
+
std::thread::id id = std::this_thread::get_id();
|
|
119
|
+
if (m_local_work_queue && id == m_thread_id) {
|
|
120
120
|
// 本地线程任务从前部入队列(递归成栈)
|
|
121
121
|
m_local_work_queue->push_front(std::move(task));
|
|
122
122
|
} else {
|
|
123
123
|
m_master_work_queue.push(std::move(task));
|
|
124
124
|
m_cv.notify_one();
|
|
125
125
|
}
|
|
126
|
+
|
|
126
127
|
return res;
|
|
127
128
|
}
|
|
128
129
|
|
|
@@ -132,19 +133,17 @@ public:
|
|
|
132
133
|
|
|
133
134
|
/** 返回线程池结束状态 */
|
|
134
135
|
bool done() const {
|
|
135
|
-
return m_done;
|
|
136
|
+
return m_done.load(std::memory_order_acquire);
|
|
136
137
|
}
|
|
137
138
|
|
|
138
139
|
/**
|
|
139
140
|
* 等待各线程完成当前执行的任务后立即结束退出
|
|
140
141
|
*/
|
|
141
142
|
void stop() {
|
|
142
|
-
if (m_done) {
|
|
143
|
+
if (m_done.exchange(true, std::memory_order_acq_rel)) {
|
|
143
144
|
return;
|
|
144
145
|
}
|
|
145
146
|
|
|
146
|
-
m_done = true;
|
|
147
|
-
|
|
148
147
|
// 同时加入结束任务指示,以便在dll退出时也能够终止
|
|
149
148
|
for (size_t i = 0; i < m_worker_num; i++) {
|
|
150
149
|
if (m_interrupt_flags[i]) {
|
|
@@ -164,6 +163,7 @@ public:
|
|
|
164
163
|
for (size_t i = 0; i < m_worker_num; i++) {
|
|
165
164
|
m_queues[i]->clear();
|
|
166
165
|
}
|
|
166
|
+
m_threads.clear();
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
/**
|
|
@@ -171,7 +171,7 @@ public:
|
|
|
171
171
|
* @note 至此线程池能工作线程结束不可再使用
|
|
172
172
|
*/
|
|
173
173
|
void join() {
|
|
174
|
-
if (m_done) {
|
|
174
|
+
if (m_done.load(std::memory_order_acquire)) {
|
|
175
175
|
return;
|
|
176
176
|
}
|
|
177
177
|
|
|
@@ -196,7 +196,7 @@ public:
|
|
|
196
196
|
}
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
-
m_done
|
|
199
|
+
m_done.store(true, std::memory_order_release);
|
|
200
200
|
for (size_t i = 0; i < m_worker_num; i++) {
|
|
201
201
|
if (m_interrupt_flags[i]) {
|
|
202
202
|
m_interrupt_flags[i]->set();
|
|
@@ -218,11 +218,46 @@ public:
|
|
|
218
218
|
}
|
|
219
219
|
}
|
|
220
220
|
|
|
221
|
-
m_done
|
|
221
|
+
m_done.store(true, std::memory_order_release);
|
|
222
222
|
m_master_work_queue.clear();
|
|
223
223
|
for (size_t i = 0; i < m_worker_num; i++) {
|
|
224
224
|
m_queues[i]->clear();
|
|
225
225
|
}
|
|
226
|
+
m_threads.clear();
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
public:
|
|
230
|
+
bool run_available_task_once() {
|
|
231
|
+
bool task_run = true;
|
|
232
|
+
task_type task;
|
|
233
|
+
if (m_local_work_queue) {
|
|
234
|
+
if (pop_task_from_local_queue(task)) {
|
|
235
|
+
if (!task.isNullTask()) {
|
|
236
|
+
task();
|
|
237
|
+
} else {
|
|
238
|
+
m_thread_need_stop.set();
|
|
239
|
+
}
|
|
240
|
+
} else if (pop_task_from_master_queue(task)) {
|
|
241
|
+
if (!task.isNullTask()) {
|
|
242
|
+
task();
|
|
243
|
+
} else {
|
|
244
|
+
m_thread_need_stop.set();
|
|
245
|
+
}
|
|
246
|
+
} else if (pop_task_from_other_thread_queue(task)) {
|
|
247
|
+
if (!task.isNullTask()) {
|
|
248
|
+
task();
|
|
249
|
+
}
|
|
250
|
+
} else {
|
|
251
|
+
task_run = false;
|
|
252
|
+
}
|
|
253
|
+
} else if (pop_task_from_master_queue(task)) {
|
|
254
|
+
if (!task.isNullTask()) {
|
|
255
|
+
task();
|
|
256
|
+
}
|
|
257
|
+
} else {
|
|
258
|
+
task_run = false;
|
|
259
|
+
}
|
|
260
|
+
return task_run;
|
|
226
261
|
}
|
|
227
262
|
|
|
228
263
|
private:
|
|
@@ -243,17 +278,20 @@ private:
|
|
|
243
278
|
inline static thread_local WorkStealQueue* m_local_work_queue = nullptr; // 本地任务队列
|
|
244
279
|
inline static thread_local int m_index = -1; // 在线程池中的序号
|
|
245
280
|
inline static thread_local InterruptFlag m_thread_need_stop; // 线程停止运行指示
|
|
281
|
+
inline static thread_local std::thread::id m_thread_id;
|
|
246
282
|
#else
|
|
247
283
|
static thread_local WorkStealQueue* m_local_work_queue; // 本地任务队列
|
|
248
284
|
static thread_local int m_index; // 在线程池中的序号
|
|
249
285
|
static thread_local InterruptFlag m_thread_need_stop; // 线程停止运行指示
|
|
286
|
+
static thread_local std::thread::id m_thread_id;
|
|
250
287
|
#endif
|
|
251
288
|
|
|
252
289
|
void worker_thread(int index) {
|
|
290
|
+
m_thread_id = std::this_thread::get_id();
|
|
253
291
|
m_interrupt_flags[index] = &m_thread_need_stop;
|
|
254
292
|
m_index = index;
|
|
255
293
|
m_local_work_queue = m_queues[index].get();
|
|
256
|
-
while (!m_thread_need_stop.isSet() && !m_done) {
|
|
294
|
+
while (!m_thread_need_stop.isSet() && !m_done.load(std::memory_order_acquire)) {
|
|
257
295
|
run_pending_task();
|
|
258
296
|
}
|
|
259
297
|
m_local_work_queue = nullptr;
|
|
@@ -277,10 +315,18 @@ private:
|
|
|
277
315
|
m_thread_need_stop.set();
|
|
278
316
|
}
|
|
279
317
|
} else if (pop_task_from_other_thread_queue(task)) {
|
|
280
|
-
task()
|
|
318
|
+
if (!task.isNullTask()) {
|
|
319
|
+
task();
|
|
320
|
+
}
|
|
281
321
|
} else {
|
|
322
|
+
// std::this_thread::yield();
|
|
282
323
|
std::unique_lock<std::mutex> lk(m_cv_mutex);
|
|
283
|
-
m_cv.
|
|
324
|
+
m_cv.wait_for(lk, std::chrono::microseconds(10), [this] {
|
|
325
|
+
return this->m_done.load(std::memory_order_acquire) ||
|
|
326
|
+
!this->m_master_work_queue.empty() ||
|
|
327
|
+
(m_local_work_queue && !m_local_work_queue->empty()) ||
|
|
328
|
+
has_other_remain_task();
|
|
329
|
+
});
|
|
284
330
|
}
|
|
285
331
|
}
|
|
286
332
|
|
|
@@ -302,8 +348,15 @@ private:
|
|
|
302
348
|
}
|
|
303
349
|
return false;
|
|
304
350
|
}
|
|
351
|
+
|
|
352
|
+
bool has_other_remain_task() {
|
|
353
|
+
for (int i = 0; i < m_worker_num; ++i) {
|
|
354
|
+
if (i != m_index && m_queues[i] && !m_queues[i]->empty()) {
|
|
355
|
+
return true;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
return false;
|
|
359
|
+
}
|
|
305
360
|
};
|
|
306
361
|
|
|
307
362
|
} /* namespace hku */
|
|
308
|
-
|
|
309
|
-
#endif /* HIKYUU_UTILITIES_THREAD_STEALTHREADPOOL_H */
|
|
@@ -8,8 +8,6 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
#pragma once
|
|
11
|
-
#ifndef HIKYUU_UTILITIES_THREAD_THREADPOOL_H
|
|
12
|
-
#define HIKYUU_UTILITIES_THREAD_THREADPOOL_H
|
|
13
11
|
|
|
14
12
|
#include <cstdio>
|
|
15
13
|
#include <future>
|
|
@@ -220,5 +218,3 @@ private:
|
|
|
220
218
|
#ifdef __GNUC__
|
|
221
219
|
#pragma GCC diagnostic pop
|
|
222
220
|
#endif
|
|
223
|
-
|
|
224
|
-
#endif /* HIKYUU_UTILITIES_THREAD_THREADPOOL_H */
|