hikyuu 2.7.0__py3-none-manylinux2014_aarch64.whl → 2.7.5__py3-none-manylinux2014_aarch64.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 +28 -8
- hikyuu/__init__.pyi +26 -14
- hikyuu/analysis/__init__.pyi +7 -1
- hikyuu/analysis/analysis.pyi +8 -2
- hikyuu/core.pyi +9 -3
- hikyuu/cpp/core310.pyi +172 -68
- hikyuu/cpp/core310.so +0 -0
- hikyuu/cpp/core311.pyi +172 -68
- hikyuu/cpp/core311.so +0 -0
- hikyuu/cpp/core312.pyi +172 -68
- hikyuu/cpp/core312.so +0 -0
- hikyuu/cpp/core313.pyi +172 -68
- hikyuu/cpp/core313.so +0 -0
- hikyuu/cpp/i18n/zh_CN/hikyuu.mo +0 -0
- hikyuu/cpp/i18n/zh_CN/hikyuu_plugin.mo +0 -0
- hikyuu/cpp/libboost_atomic.so +0 -0
- hikyuu/cpp/libboost_atomic.so.1.90.0 +0 -0
- hikyuu/cpp/{libboost_charconv-mt.so → libboost_charconv.so} +0 -0
- hikyuu/cpp/{libboost_charconv-mt.so.1.88.0 → libboost_charconv.so.1.90.0} +0 -0
- hikyuu/cpp/libboost_chrono.so +0 -0
- hikyuu/cpp/libboost_chrono.so.1.90.0 +0 -0
- hikyuu/cpp/libboost_container.so +0 -0
- hikyuu/cpp/libboost_container.so.1.90.0 +0 -0
- hikyuu/cpp/libboost_date_time.so +0 -0
- hikyuu/cpp/libboost_date_time.so.1.90.0 +0 -0
- hikyuu/cpp/libboost_locale.so +0 -0
- hikyuu/cpp/libboost_locale.so.1.90.0 +0 -0
- hikyuu/cpp/libboost_random.so +0 -0
- hikyuu/cpp/libboost_random.so.1.90.0 +0 -0
- hikyuu/cpp/libboost_serialization.so +0 -0
- hikyuu/cpp/libboost_serialization.so.1.90.0 +0 -0
- hikyuu/cpp/libboost_thread.so +0 -0
- hikyuu/cpp/libboost_thread.so.1.90.0 +0 -0
- hikyuu/cpp/libboost_wserialization.so +0 -0
- hikyuu/cpp/libboost_wserialization.so.1.90.0 +0 -0
- hikyuu/cpp/libhikyuu.so +0 -0
- hikyuu/cpp/libmimalloc.so +0 -0
- hikyuu/cpp/libmimalloc.so.3 +0 -0
- hikyuu/cpp/libmimalloc.so.3.1 +0 -0
- hikyuu/cpp/libsqlite3.so +0 -0
- hikyuu/data/clickhouse_upgrade/0001.sql +2 -0
- hikyuu/data/clickhouse_upgrade/0002.sql +9 -0
- hikyuu/data/common_clickhouse.py +1 -3
- hikyuu/data/common_mysql.py +1 -1
- hikyuu/data/download_block.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 +31 -4
- hikyuu/data/mysql_upgrade/0029.sql +2 -0
- hikyuu/data/mysql_upgrade/0030.sql +3 -0
- hikyuu/data/pytdx_to_clickhouse.py +86 -32
- hikyuu/data/pytdx_to_h5.py +73 -28
- hikyuu/data/pytdx_to_mysql.py +65 -21
- hikyuu/data/pytdx_weight_to_clickhouse.py +2 -0
- hikyuu/data/pytdx_weight_to_mysql.py +2 -0
- hikyuu/data/pytdx_weight_to_sqlite.py +2 -0
- hikyuu/data/sqlite_upgrade/0029.sql +4 -0
- 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/__init__.pyi +1 -1
- hikyuu/draw/drawplot/bokeh_draw.pyi +17 -9
- hikyuu/draw/drawplot/echarts_draw.pyi +17 -9
- hikyuu/draw/drawplot/matplotlib_draw.py +23 -9
- hikyuu/draw/drawplot/matplotlib_draw.pyi +17 -9
- 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 +10 -4
- hikyuu/gui/HikyuuTDX.py +42 -3
- hikyuu/gui/data/MainWindow.py +189 -129
- 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 +28 -12
- hikyuu/include/hikyuu/StockTypeInfo.h +9 -9
- hikyuu/include/hikyuu/StockWeight.h +9 -9
- hikyuu/include/hikyuu/StrategyContext.h +4 -4
- 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 +24 -5
- 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 +147 -74
- 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/KDataToClickHouseImporter.h +40 -0
- hikyuu/include/hikyuu/plugin/KDataToMySQLImporter.h +40 -0
- hikyuu/include/hikyuu/plugin/checkdata.h +20 -0
- hikyuu/include/hikyuu/plugin/extind.h +3 -0
- hikyuu/include/hikyuu/plugin/hkuextra.h +4 -0
- hikyuu/include/hikyuu/plugin/interface/CheckDataPluginInterface.h +25 -0
- hikyuu/include/hikyuu/plugin/interface/HkuExtraPluginInterface.h +4 -0
- hikyuu/include/hikyuu/plugin/interface/ImportKDataToClickHousePluginInterface.h +44 -0
- hikyuu/include/hikyuu/plugin/interface/ImportKDataToMySQLPluginInterface.h +42 -0
- hikyuu/include/hikyuu/plugin/interface/plugins.h +6 -0
- hikyuu/include/hikyuu/python/convert_any.h +9 -6
- hikyuu/include/hikyuu/python/pybind_utils.h +22 -5
- hikyuu/include/hikyuu/strategy/Strategy.h +1 -1
- hikyuu/include/hikyuu/trade_manage/TradeCostBase.h +5 -3
- hikyuu/include/hikyuu/trade_manage/TradeManagerBase.h +9 -3
- hikyuu/include/hikyuu/trade_manage/TradeRecord.h +2 -1
- hikyuu/include/hikyuu/trade_sys/allocatefunds/AllocateFundsBase.h +8 -4
- hikyuu/include/hikyuu/trade_sys/allocatefunds/build_in.h +1 -0
- hikyuu/include/hikyuu/trade_sys/allocatefunds/crt/AF_FixedAmount.h +26 -0
- hikyuu/include/hikyuu/trade_sys/allocatefunds/imp/FixAmountFunds.h +18 -0
- 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 +13 -13
- 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/Log.h +6 -7
- hikyuu/include/hikyuu/utilities/LruCache.h +299 -0
- hikyuu/include/hikyuu/utilities/Parameter.h +17 -0
- hikyuu/include/hikyuu/utilities/arithmetic.h +2 -2
- hikyuu/include/hikyuu/utilities/config.h +28 -0
- hikyuu/include/hikyuu/utilities/omp_macro.h +25 -0
- hikyuu/include/hikyuu/utilities/plugin/PluginBase.h +17 -2
- hikyuu/include/hikyuu/utilities/plugin/PluginManager.h +46 -22
- hikyuu/include/hikyuu/utilities/thread/GlobalStealThreadPool.h +71 -19
- hikyuu/include/hikyuu/utilities/thread/GlobalThreadPool.h +1 -5
- hikyuu/include/hikyuu/utilities/thread/MQStealThreadPool.h +286 -0
- hikyuu/include/hikyuu/utilities/thread/MQThreadPool.h +1 -0
- hikyuu/include/hikyuu/utilities/thread/StealThreadPool.h +297 -0
- hikyuu/include/hikyuu/utilities/thread/ThreadPool.h +1 -4
- hikyuu/include/hikyuu/utilities/thread/WorkStealQueue.h +9 -8
- hikyuu/include/hikyuu/utilities/thread/algorithm.h +350 -14
- hikyuu/include/hikyuu/version.h +4 -4
- hikyuu/plugin/libbacktest.so +0 -0
- hikyuu/plugin/libcheckdata.so +0 -0
- hikyuu/plugin/libclickhousedriver.so +0 -0
- hikyuu/plugin/libdataserver.so +0 -0
- hikyuu/plugin/libdataserver_parquet.so +0 -0
- hikyuu/plugin/libdevice.so +0 -0
- hikyuu/plugin/libextind.so +0 -0
- hikyuu/plugin/libhkuextra.so +0 -0
- hikyuu/plugin/libimport2ch.so +0 -0
- hikyuu/plugin/libimport2hdf5.so +0 -0
- hikyuu/plugin/libimport2mysql.so +0 -0
- hikyuu/plugin/libtmreport.so +0 -0
- hikyuu/test/Indicator.py +1 -2
- hikyuu/trade_manage/__init__.pyi +14 -8
- hikyuu/trade_manage/trade.pyi +14 -8
- hikyuu/trade_sys/trade_sys.py +54 -5
- hikyuu/util/__init__.pyi +2 -2
- hikyuu/util/singleton.pyi +1 -1
- {hikyuu-2.7.0.dist-info → hikyuu-2.7.5.dist-info}/METADATA +10 -4
- {hikyuu-2.7.0.dist-info → hikyuu-2.7.5.dist-info}/RECORD +282 -252
- hikyuu/cpp/libboost_chrono-mt.so +0 -0
- hikyuu/cpp/libboost_chrono-mt.so.1.88.0 +0 -0
- hikyuu/cpp/libboost_date_time-mt.so +0 -0
- hikyuu/cpp/libboost_date_time-mt.so.1.88.0 +0 -0
- hikyuu/cpp/libboost_serialization-mt.so +0 -0
- hikyuu/cpp/libboost_serialization-mt.so.1.88.0 +0 -0
- hikyuu/cpp/libboost_system-mt.so +0 -0
- hikyuu/cpp/libboost_system-mt.so.1.88.0 +0 -0
- hikyuu/cpp/libboost_thread-mt.so +0 -0
- hikyuu/cpp/libboost_thread-mt.so.1.88.0 +0 -0
- hikyuu/cpp/libboost_wserialization-mt.so +0 -0
- hikyuu/cpp/libboost_wserialization-mt.so.1.88.0 +0 -0
- hikyuu/data/pytdx_to_taos.py +0 -736
- {hikyuu-2.7.0.dist-info → hikyuu-2.7.5.dist-info}/WHEEL +0 -0
- {hikyuu-2.7.0.dist-info → hikyuu-2.7.5.dist-info}/entry_points.txt +0 -0
- {hikyuu-2.7.0.dist-info → hikyuu-2.7.5.dist-info}/top_level.txt +0 -0
|
@@ -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,12 +218,46 @@ public:
|
|
|
218
218
|
}
|
|
219
219
|
}
|
|
220
220
|
|
|
221
|
+
m_done.store(true, std::memory_order_release);
|
|
221
222
|
m_master_work_queue.clear();
|
|
222
223
|
for (size_t i = 0; i < m_worker_num; i++) {
|
|
223
224
|
m_queues[i]->clear();
|
|
224
225
|
}
|
|
226
|
+
m_threads.clear();
|
|
227
|
+
}
|
|
225
228
|
|
|
226
|
-
|
|
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;
|
|
227
261
|
}
|
|
228
262
|
|
|
229
263
|
private:
|
|
@@ -244,17 +278,20 @@ private:
|
|
|
244
278
|
inline static thread_local WorkStealQueue* m_local_work_queue = nullptr; // 本地任务队列
|
|
245
279
|
inline static thread_local int m_index = -1; // 在线程池中的序号
|
|
246
280
|
inline static thread_local InterruptFlag m_thread_need_stop; // 线程停止运行指示
|
|
281
|
+
inline static thread_local std::thread::id m_thread_id;
|
|
247
282
|
#else
|
|
248
283
|
static thread_local WorkStealQueue* m_local_work_queue; // 本地任务队列
|
|
249
284
|
static thread_local int m_index; // 在线程池中的序号
|
|
250
285
|
static thread_local InterruptFlag m_thread_need_stop; // 线程停止运行指示
|
|
286
|
+
static thread_local std::thread::id m_thread_id;
|
|
251
287
|
#endif
|
|
252
288
|
|
|
253
289
|
void worker_thread(int index) {
|
|
290
|
+
m_thread_id = std::this_thread::get_id();
|
|
254
291
|
m_interrupt_flags[index] = &m_thread_need_stop;
|
|
255
292
|
m_index = index;
|
|
256
293
|
m_local_work_queue = m_queues[index].get();
|
|
257
|
-
while (!m_thread_need_stop.isSet() && !m_done) {
|
|
294
|
+
while (!m_thread_need_stop.isSet() && !m_done.load(std::memory_order_acquire)) {
|
|
258
295
|
run_pending_task();
|
|
259
296
|
}
|
|
260
297
|
m_local_work_queue = nullptr;
|
|
@@ -278,10 +315,18 @@ private:
|
|
|
278
315
|
m_thread_need_stop.set();
|
|
279
316
|
}
|
|
280
317
|
} else if (pop_task_from_other_thread_queue(task)) {
|
|
281
|
-
task()
|
|
318
|
+
if (!task.isNullTask()) {
|
|
319
|
+
task();
|
|
320
|
+
}
|
|
282
321
|
} else {
|
|
322
|
+
// std::this_thread::yield();
|
|
283
323
|
std::unique_lock<std::mutex> lk(m_cv_mutex);
|
|
284
|
-
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
|
+
});
|
|
285
330
|
}
|
|
286
331
|
}
|
|
287
332
|
|
|
@@ -303,8 +348,15 @@ private:
|
|
|
303
348
|
}
|
|
304
349
|
return false;
|
|
305
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
|
+
}
|
|
306
360
|
};
|
|
307
361
|
|
|
308
362
|
} /* namespace hku */
|
|
309
|
-
|
|
310
|
-
#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>
|
|
@@ -174,8 +172,8 @@ public:
|
|
|
174
172
|
}
|
|
175
173
|
}
|
|
176
174
|
|
|
177
|
-
m_master_work_queue.clear();
|
|
178
175
|
m_done = true;
|
|
176
|
+
m_master_work_queue.clear();
|
|
179
177
|
}
|
|
180
178
|
|
|
181
179
|
private:
|
|
@@ -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 */
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* StealMQStealThreadPool.h
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2019 hikyuu.org
|
|
5
|
+
*
|
|
6
|
+
* Created on: 2019-9-16
|
|
7
|
+
* Author: fasiondog
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
#pragma once
|
|
11
|
+
|
|
12
|
+
#include <future>
|
|
13
|
+
#include <thread>
|
|
14
|
+
#include <chrono>
|
|
15
|
+
#include <vector>
|
|
16
|
+
#include "FuncWrapper.h"
|
|
17
|
+
#include "MQStealQueue.h"
|
|
18
|
+
#include "InterruptFlag.h"
|
|
19
|
+
#include "../cppdef.h"
|
|
20
|
+
|
|
21
|
+
#ifdef __GNUC__
|
|
22
|
+
#pragma GCC diagnostic push
|
|
23
|
+
#pragma GCC diagnostic ignored "-Wsign-compare"
|
|
24
|
+
#endif
|
|
25
|
+
#ifndef HKU_UTILS_API
|
|
26
|
+
#define HKU_UTILS_API
|
|
27
|
+
#endif
|
|
28
|
+
|
|
29
|
+
namespace hku {
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @brief 无集中队列多队列偷取任务池
|
|
33
|
+
* @ingroup ThreadPool
|
|
34
|
+
*/
|
|
35
|
+
#ifdef _MSC_VER
|
|
36
|
+
class MQStealThreadPool {
|
|
37
|
+
#else
|
|
38
|
+
class HKU_UTILS_API MQStealThreadPool {
|
|
39
|
+
#endif
|
|
40
|
+
public:
|
|
41
|
+
/**
|
|
42
|
+
* 默认构造函数,创建和当前系统CPU数一致的线程数
|
|
43
|
+
*/
|
|
44
|
+
MQStealThreadPool() : MQStealThreadPool(std::thread::hardware_concurrency()) {}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 构造函数,创建指定数量的线程
|
|
48
|
+
* @param n 指定的线程数
|
|
49
|
+
* @param until_empty 任务队列为空时,自动停止运行
|
|
50
|
+
*/
|
|
51
|
+
explicit MQStealThreadPool(size_t n, bool until_empty = true)
|
|
52
|
+
: m_done(false), m_worker_num(n), m_runnging_until_empty(until_empty) {
|
|
53
|
+
try {
|
|
54
|
+
m_interrupt_flags.resize(m_worker_num);
|
|
55
|
+
for (size_t i = 0; i < m_worker_num; i++) {
|
|
56
|
+
// 创建工作线程及其任务队列
|
|
57
|
+
m_queues.emplace_back(new MQStealQueue<task_type>);
|
|
58
|
+
}
|
|
59
|
+
// 初始完毕所有线程资源后再启动线程
|
|
60
|
+
for (int i = 0; i < m_worker_num; i++) {
|
|
61
|
+
m_threads.emplace_back(&MQStealThreadPool::worker_thread, this, i);
|
|
62
|
+
m_thread_index[m_threads.back().get_id()] = i;
|
|
63
|
+
}
|
|
64
|
+
} catch (...) {
|
|
65
|
+
m_done = true;
|
|
66
|
+
throw;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* 析构函数,等待并阻塞至线程池内所有任务完成
|
|
72
|
+
*/
|
|
73
|
+
~MQStealThreadPool() {
|
|
74
|
+
if (!m_done) {
|
|
75
|
+
join();
|
|
76
|
+
}
|
|
77
|
+
m_threads.clear();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** 获取工作线程数 */
|
|
81
|
+
size_t worker_num() const {
|
|
82
|
+
return m_worker_num;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** 剩余任务数 */
|
|
86
|
+
size_t remain_task_count() const {
|
|
87
|
+
if (m_done) {
|
|
88
|
+
return 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
size_t total = 0;
|
|
92
|
+
for (size_t i = 0; i < m_worker_num; i++) {
|
|
93
|
+
total += m_queues[i]->size();
|
|
94
|
+
}
|
|
95
|
+
return total;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** 先线程池提交任务后返回的对应 future 的类型 */
|
|
99
|
+
template <typename ResultType>
|
|
100
|
+
using task_handle = std::future<ResultType>;
|
|
101
|
+
|
|
102
|
+
#ifdef _MSC_VER
|
|
103
|
+
#pragma warning(push)
|
|
104
|
+
#pragma warning(disable : 4996)
|
|
105
|
+
#endif
|
|
106
|
+
|
|
107
|
+
/** 向线程池提交任务 */
|
|
108
|
+
template <typename FunctionType>
|
|
109
|
+
auto submit(FunctionType f) {
|
|
110
|
+
if (m_done) {
|
|
111
|
+
throw std::logic_error("You can't submit a task to the stopped MQStealThreadPool!");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
int index = -1;
|
|
115
|
+
auto iter = m_thread_index.find(std::this_thread::get_id());
|
|
116
|
+
if (iter != m_thread_index.end()) {
|
|
117
|
+
index = iter->second;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
typedef typename std::invoke_result<FunctionType>::type result_type;
|
|
121
|
+
std::packaged_task<result_type()> task(f);
|
|
122
|
+
task_handle<result_type> res(task.get_future());
|
|
123
|
+
|
|
124
|
+
// 如果是本地线程且线程仍未终止,则加入自身队列
|
|
125
|
+
if (index != -1 && m_interrupt_flags[index]) {
|
|
126
|
+
// 本地线程任务从前部入队列(递归成栈)
|
|
127
|
+
m_queues[index]->push_front(std::move(task));
|
|
128
|
+
return res;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
m_queues[m_current_index]->push(std::move(task));
|
|
132
|
+
m_current_index++;
|
|
133
|
+
if (m_current_index >= m_worker_num) {
|
|
134
|
+
m_current_index = 0;
|
|
135
|
+
}
|
|
136
|
+
return res;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
#ifdef _MSC_VER
|
|
140
|
+
#pragma warning(pop)
|
|
141
|
+
#endif
|
|
142
|
+
|
|
143
|
+
/** 返回线程池结束状态 */
|
|
144
|
+
bool done() const {
|
|
145
|
+
return m_done;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* 等待各线程完成当前执行的任务后立即结束退出
|
|
150
|
+
*/
|
|
151
|
+
void stop() {
|
|
152
|
+
if (m_done) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// 同时加入结束任务指示,以便在dll退出时也能够终止
|
|
157
|
+
for (size_t i = 0; i < m_worker_num; i++) {
|
|
158
|
+
if (m_interrupt_flags[i]) {
|
|
159
|
+
m_interrupt_flags[i].set();
|
|
160
|
+
}
|
|
161
|
+
m_queues[i]->push(FuncWrapper());
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
for (size_t i = 0; i < m_worker_num; i++) {
|
|
165
|
+
if (m_threads[i].joinable()) {
|
|
166
|
+
m_threads[i].join();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
m_done = true;
|
|
171
|
+
for (size_t i = 0; i < m_worker_num; i++) {
|
|
172
|
+
m_queues[i]->clear();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* 等待并阻塞至线程池内所有任务完成
|
|
178
|
+
* @note 至此线程池能工作线程结束不可再使用
|
|
179
|
+
*/
|
|
180
|
+
void join() {
|
|
181
|
+
if (m_done) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// 指示各工作线程在未获取到工作任务时,停止运行
|
|
186
|
+
if (m_runnging_until_empty) {
|
|
187
|
+
while (true) {
|
|
188
|
+
bool can_quit = true;
|
|
189
|
+
for (size_t i = 0; i < m_worker_num; i++) {
|
|
190
|
+
if (!m_queues[i]->empty()) {
|
|
191
|
+
can_quit = false;
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (can_quit) {
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
std::this_thread::yield();
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
m_done = true;
|
|
204
|
+
for (size_t i = 0; i < m_worker_num; i++) {
|
|
205
|
+
if (m_interrupt_flags[i]) {
|
|
206
|
+
m_interrupt_flags[i].set();
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
for (size_t i = 0; i < m_worker_num; i++) {
|
|
212
|
+
m_queues[i]->push(FuncWrapper());
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// 等待线程结束
|
|
216
|
+
for (size_t i = 0; i < m_worker_num; i++) {
|
|
217
|
+
if (m_threads[i].joinable()) {
|
|
218
|
+
m_threads[i].join();
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
m_done = true;
|
|
223
|
+
for (size_t i = 0; i < m_worker_num; i++) {
|
|
224
|
+
m_queues[i]->clear();
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
private:
|
|
229
|
+
typedef FuncWrapper task_type;
|
|
230
|
+
std::atomic_bool m_done; // 线程池全局需终止指示
|
|
231
|
+
size_t m_worker_num; // 工作线程数量
|
|
232
|
+
bool m_runnging_until_empty; // 运行直到队列空时停止
|
|
233
|
+
|
|
234
|
+
std::vector<std::unique_ptr<MQStealQueue<task_type>>> m_queues; // 线程任务队列
|
|
235
|
+
std::vector<InterruptFlag> m_interrupt_flags; // 线程终止标志
|
|
236
|
+
std::vector<std::thread> m_threads; // 工作线程
|
|
237
|
+
|
|
238
|
+
std::unordered_map<std::thread::id, int> m_thread_index;
|
|
239
|
+
int m_current_index = 0; // 当前放置新任务时的队列索引
|
|
240
|
+
|
|
241
|
+
void worker_thread(int index) {
|
|
242
|
+
while (!m_interrupt_flags[index].isSet() && !m_done) {
|
|
243
|
+
run_pending_task(index);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
void run_pending_task(int index) {
|
|
248
|
+
task_type task;
|
|
249
|
+
// 尝试从本地队列获取任务并执行
|
|
250
|
+
if (m_queues[index]->try_pop(task)) {
|
|
251
|
+
if (task.isNullTask()) {
|
|
252
|
+
m_interrupt_flags[index].set();
|
|
253
|
+
} else {
|
|
254
|
+
task();
|
|
255
|
+
}
|
|
256
|
+
} else if (pop_task_from_other_thread_queue(task, index)) {
|
|
257
|
+
task();
|
|
258
|
+
} else {
|
|
259
|
+
// 阻塞并等待本地队列中有新的任务
|
|
260
|
+
// 注:如果是递归情况,任务被优先加入本地队列且彼此依赖,如果任务被其他线程偷取到的话,将导致其他线程被阻塞并等待
|
|
261
|
+
// 所以,此处等待本地队列而不是继续循环偷取
|
|
262
|
+
m_queues[index]->wait_and_pop(task);
|
|
263
|
+
if (task.isNullTask()) {
|
|
264
|
+
m_interrupt_flags[index].set();
|
|
265
|
+
} else {
|
|
266
|
+
task();
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
bool pop_task_from_other_thread_queue(task_type& task, int index) {
|
|
272
|
+
for (size_t i = 0; i < m_worker_num; ++i) {
|
|
273
|
+
size_t pos = (index + i + 1) % m_worker_num;
|
|
274
|
+
if (pos != index && m_queues[pos]->try_steal(task)) {
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
}; // namespace hku
|
|
281
|
+
|
|
282
|
+
} /* namespace hku */
|
|
283
|
+
|
|
284
|
+
#ifdef __GNUC__
|
|
285
|
+
#pragma GCC diagnostic pop
|
|
286
|
+
#endif
|