hikyuu 2.1.0__cp38-none-win_amd64.whl → 2.1.1__cp38-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/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/core38.pyd +0 -0
- hikyuu/cpp/hikyuu.dll +0 -0
- hikyuu/extend.py +3 -1
- hikyuu/gui/HikyuuTDX.py +11 -6
- hikyuu/include/hikyuu/DataType.h +2 -1
- hikyuu/include/hikyuu/KRecord.h +1 -1
- hikyuu/include/hikyuu/StockManager.h +3 -0
- hikyuu/include/hikyuu/analysis/combinate.h +1 -1
- hikyuu/include/hikyuu/config.h +0 -12
- hikyuu/include/hikyuu/strategy/AccountTradeManager.h +3 -1
- hikyuu/include/hikyuu/utilities/FilterNode.h +267 -0
- hikyuu/include/hikyuu/utilities/LRUCache11.h +230 -0
- hikyuu/include/hikyuu/{Log.h → utilities/Log.h} +91 -113
- hikyuu/include/hikyuu/utilities/Null.h +1 -0
- hikyuu/include/hikyuu/utilities/Parameter.h +2 -1
- hikyuu/include/hikyuu/utilities/ResourcePool.h +636 -0
- hikyuu/include/hikyuu/utilities/SpendTimer.h +10 -9
- hikyuu/include/hikyuu/utilities/TimerManager.h +2 -2
- hikyuu/include/hikyuu/utilities/any_to_string.h +142 -0
- hikyuu/include/hikyuu/utilities/arithmetic.h +69 -33
- hikyuu/include/hikyuu/utilities/base64.h +59 -0
- hikyuu/include/hikyuu/utilities/config.h +41 -0
- hikyuu/include/hikyuu/utilities/datetime/Datetime.h +41 -31
- hikyuu/include/hikyuu/utilities/datetime/TimeDelta.h +24 -13
- hikyuu/include/hikyuu/utilities/db_connect/DBCondition.h +48 -48
- hikyuu/include/hikyuu/utilities/db_connect/DBConnect.h +10 -0
- hikyuu/include/hikyuu/utilities/db_connect/DBConnectBase.h +5 -22
- hikyuu/include/hikyuu/utilities/db_connect/DBUpgrade.h +3 -3
- hikyuu/include/hikyuu/utilities/db_connect/SQLException.h +1 -1
- hikyuu/include/hikyuu/utilities/db_connect/SQLResultSet.h +1 -1
- hikyuu/include/hikyuu/utilities/db_connect/SQLStatementBase.h +7 -7
- hikyuu/include/hikyuu/utilities/db_connect/TableMacro.h +1 -2
- hikyuu/include/hikyuu/utilities/db_connect/mysql/MySQLConnect.h +9 -9
- hikyuu/include/hikyuu/utilities/db_connect/mysql/MySQLStatement.h +18 -18
- hikyuu/include/hikyuu/utilities/db_connect/sqlite/SQLiteConnect.h +3 -3
- hikyuu/include/hikyuu/utilities/db_connect/sqlite/SQLiteStatement.h +2 -2
- hikyuu/include/hikyuu/utilities/db_connect/sqlite/SQLiteUtil.h +6 -6
- hikyuu/include/hikyuu/{exception.h → utilities/exception.h} +1 -0
- hikyuu/include/hikyuu/utilities/http_client/HttpClient.h +229 -0
- hikyuu/include/hikyuu/utilities/http_client/nng_wrap.h +517 -0
- hikyuu/include/hikyuu/utilities/http_client/url.h +25 -0
- hikyuu/include/hikyuu/utilities/{IniParser.h → ini_parser/IniParser.h} +10 -5
- hikyuu/include/hikyuu/utilities/ini_parser/__init__.py +1 -0
- hikyuu/include/hikyuu/utilities/md5.h +41 -0
- hikyuu/include/hikyuu/utilities/mo/__init__.py +1 -0
- hikyuu/include/hikyuu/utilities/mo/mo.h +48 -0
- hikyuu/include/hikyuu/utilities/mo/moFileReader.h +836 -0
- hikyuu/include/hikyuu/{global → utilities}/node/NodeClient.h +25 -18
- hikyuu/include/hikyuu/{global → utilities}/node/NodeError.h +1 -1
- hikyuu/include/hikyuu/{global → utilities}/node/NodeMessage.h +3 -2
- hikyuu/include/hikyuu/utilities/node/NodeServer.h +246 -0
- hikyuu/include/hikyuu/utilities/node/__init__.py +1 -0
- hikyuu/include/hikyuu/utilities/os.h +16 -15
- hikyuu/include/hikyuu/utilities/snowflake.h +110 -0
- hikyuu/include/hikyuu/utilities/string_view.h +70 -0
- hikyuu/include/hikyuu/utilities/thread/MQStealThreadPool.h +3 -3
- hikyuu/include/hikyuu/utilities/thread/MQThreadPool.h +3 -3
- hikyuu/include/hikyuu/utilities/thread/StealThreadPool.h +3 -3
- hikyuu/include/hikyuu/utilities/thread/ThreadPool.h +3 -3
- hikyuu/include/hikyuu/version.h +4 -4
- hikyuu/sqlite3.dll +0 -0
- hikyuu/vcruntime140.dll +0 -0
- hikyuu/vcruntime140_1.dll +0 -0
- hikyuu-2.1.1.dist-info/METADATA +115 -0
- {hikyuu-2.1.0.dist-info → hikyuu-2.1.1.dist-info}/RECORD +73 -53
- {hikyuu-2.1.0.dist-info → hikyuu-2.1.1.dist-info}/top_level.txt +4 -1
- hikyuu/README.rst +0 -79
- hikyuu-2.1.0.dist-info/METADATA +0 -126
- /hikyuu/include/hikyuu/{global/node → utilities/http_client}/__init__.py +0 -0
- {hikyuu-2.1.0.dist-info → hikyuu-2.1.1.dist-info}/LICENSE +0 -0
- {hikyuu-2.1.0.dist-info → hikyuu-2.1.1.dist-info}/WHEEL +0 -0
- {hikyuu-2.1.0.dist-info → hikyuu-2.1.1.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,636 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* ResourcePool.h
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2019, hikyuu.org
|
|
5
|
+
*
|
|
6
|
+
* Created on: 2019-8-5
|
|
7
|
+
* Author: fasiondog
|
|
8
|
+
*/
|
|
9
|
+
#pragma once
|
|
10
|
+
#ifndef HKU_UTILS_RESOURCE_POOL_H
|
|
11
|
+
#define HKU_UTILS_RESOURCE_POOL_H
|
|
12
|
+
|
|
13
|
+
#include <thread>
|
|
14
|
+
#include <mutex>
|
|
15
|
+
#include <condition_variable>
|
|
16
|
+
#include <queue>
|
|
17
|
+
#include <chrono>
|
|
18
|
+
#include <unordered_set>
|
|
19
|
+
#include "Parameter.h"
|
|
20
|
+
#include "Log.h"
|
|
21
|
+
|
|
22
|
+
namespace hku {
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* 资源获取超时异常
|
|
26
|
+
*/
|
|
27
|
+
class GetResourceTimeoutException : public hku::exception {
|
|
28
|
+
public:
|
|
29
|
+
GetResourceTimeoutException(const char *msg)
|
|
30
|
+
: hku::exception(fmt::format("GetResourceTimeoutException {}", msg)) {}
|
|
31
|
+
|
|
32
|
+
GetResourceTimeoutException(const std::string &msg)
|
|
33
|
+
: hku::exception(fmt::format("GetResourceTimeoutException {}", msg)) {}
|
|
34
|
+
|
|
35
|
+
virtual ~GetResourceTimeoutException() {}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 新资源创建失败异常
|
|
40
|
+
*/
|
|
41
|
+
class CreateResourceException : public hku::exception {
|
|
42
|
+
public:
|
|
43
|
+
CreateResourceException(const char *msg)
|
|
44
|
+
: hku::exception(fmt::format("CreateResourceException {}", msg)) {}
|
|
45
|
+
|
|
46
|
+
CreateResourceException(const std::string &msg)
|
|
47
|
+
: hku::exception(fmt::format("CreateResourceException {}", msg)) {}
|
|
48
|
+
|
|
49
|
+
virtual ~CreateResourceException() {}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* 通用共享资源池
|
|
54
|
+
* @ingroup Utilities
|
|
55
|
+
*/
|
|
56
|
+
template <typename ResourceType>
|
|
57
|
+
class ResourcePool {
|
|
58
|
+
public:
|
|
59
|
+
ResourcePool() = delete;
|
|
60
|
+
ResourcePool(const ResourcePool &) = delete;
|
|
61
|
+
ResourcePool &operator=(const ResourcePool &) = delete;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* 构造函数
|
|
65
|
+
* @param param 连接参数
|
|
66
|
+
* @param maxPoolSize 允许的最大共享资源数,为 0 表示不限制
|
|
67
|
+
* @param maxIdleNum 运行的最大空闲资源数,为 0 表示用完即刻释放,无缓存
|
|
68
|
+
*/
|
|
69
|
+
explicit ResourcePool(const Parameter ¶m, size_t maxPoolSize = 0, size_t maxIdleNum = 100)
|
|
70
|
+
: m_maxPoolSize(maxPoolSize), m_maxIdelSize(maxIdleNum), m_count(0), m_param(param) {}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* 析构函数,释放所有缓存的资源
|
|
74
|
+
*/
|
|
75
|
+
virtual ~ResourcePool() {
|
|
76
|
+
std::unique_lock<std::mutex> lock(m_mutex);
|
|
77
|
+
|
|
78
|
+
// 将所有已分配资源的 closer 和 pool 解绑
|
|
79
|
+
for (auto iter = m_closer_set.begin(); iter != m_closer_set.end(); ++iter) {
|
|
80
|
+
(*iter)->unbind();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// 删除所有空闲资源
|
|
84
|
+
while (!m_resourceList.empty()) {
|
|
85
|
+
ResourceType *p = m_resourceList.front();
|
|
86
|
+
m_resourceList.pop();
|
|
87
|
+
if (p) {
|
|
88
|
+
delete p;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** 获取当前允许的最大资源数 */
|
|
94
|
+
size_t maxPoolSize() const {
|
|
95
|
+
return m_maxIdelSize;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** 获取当前允许的最大空闲资源数 */
|
|
99
|
+
size_t maxIdleSize() const {
|
|
100
|
+
return m_maxIdelSize;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** 设置最大资源数 */
|
|
104
|
+
void maxPoolSize(size_t num) {
|
|
105
|
+
std::lock_guard<std::mutex> lock(m_mutex);
|
|
106
|
+
m_maxPoolSize = num;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** 设置允许的最大空闲资源数 */
|
|
110
|
+
void maxIdleSize(size_t num) {
|
|
111
|
+
std::lock_guard<std::mutex> lock(m_mutex);
|
|
112
|
+
m_maxIdelSize = num;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** 资源实例指针类型 */
|
|
116
|
+
typedef std::shared_ptr<ResourceType> ResourcePtr;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* 获取可用资源,如超出允许的最大资源数将返回空指针
|
|
120
|
+
* @exception CreateResourceException 新资源创建可能抛出异常
|
|
121
|
+
*/
|
|
122
|
+
ResourcePtr get() {
|
|
123
|
+
std::lock_guard<std::mutex> lock(m_mutex);
|
|
124
|
+
ResourcePtr result;
|
|
125
|
+
ResourceType *p = nullptr;
|
|
126
|
+
if (m_resourceList.empty()) {
|
|
127
|
+
if (m_maxPoolSize > 0 && m_count >= m_maxPoolSize) {
|
|
128
|
+
return result;
|
|
129
|
+
}
|
|
130
|
+
try {
|
|
131
|
+
p = new ResourceType(m_param);
|
|
132
|
+
} catch (const std::exception &e) {
|
|
133
|
+
HKU_THROW_EXCEPTION(CreateResourceException, "Failed create a new Resource! {}",
|
|
134
|
+
e.what());
|
|
135
|
+
} catch (...) {
|
|
136
|
+
HKU_THROW_EXCEPTION(CreateResourceException,
|
|
137
|
+
"Failed create a new Resource! Unknown error!");
|
|
138
|
+
}
|
|
139
|
+
m_count++;
|
|
140
|
+
result = ResourcePtr(p, ResourceCloser(this));
|
|
141
|
+
m_closer_set.insert(std::get_deleter<ResourceCloser>(result));
|
|
142
|
+
return result;
|
|
143
|
+
}
|
|
144
|
+
p = m_resourceList.front();
|
|
145
|
+
m_resourceList.pop();
|
|
146
|
+
result = ResourcePtr(p, ResourceCloser(this));
|
|
147
|
+
m_closer_set.insert(std::get_deleter<ResourceCloser>(result));
|
|
148
|
+
return result;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* 在指定的超时时间内获取可用资源
|
|
153
|
+
* @param ms_timeout 超时时间,单位毫秒
|
|
154
|
+
* @exception GetResourceTimeoutException, CreateResourceException
|
|
155
|
+
*/
|
|
156
|
+
ResourcePtr getWaitFor(uint64_t ms_timeout) { // NOSONAR
|
|
157
|
+
std::unique_lock<std::mutex> lock(m_mutex);
|
|
158
|
+
ResourcePtr result;
|
|
159
|
+
ResourceType *p = nullptr;
|
|
160
|
+
if (m_resourceList.empty()) {
|
|
161
|
+
if (m_maxPoolSize > 0 && m_count >= m_maxPoolSize) {
|
|
162
|
+
// HKU_TRACE("超出最大资源数,等待空闲资源");
|
|
163
|
+
if (ms_timeout > 0) {
|
|
164
|
+
if (m_cond.wait_for(lock,
|
|
165
|
+
std::chrono::duration<uint64_t, std::milli>(ms_timeout),
|
|
166
|
+
[&] { return !m_resourceList.empty(); })) {
|
|
167
|
+
HKU_CHECK_THROW(!m_resourceList.empty(), GetResourceTimeoutException,
|
|
168
|
+
"Failed get resource!");
|
|
169
|
+
} else {
|
|
170
|
+
HKU_THROW_EXCEPTION(GetResourceTimeoutException, "Failed get resource!");
|
|
171
|
+
}
|
|
172
|
+
} else {
|
|
173
|
+
m_cond.wait(lock, [this] { return !m_resourceList.empty(); });
|
|
174
|
+
}
|
|
175
|
+
} else {
|
|
176
|
+
try {
|
|
177
|
+
p = new ResourceType(m_param);
|
|
178
|
+
} catch (const std::exception &e) {
|
|
179
|
+
HKU_THROW_EXCEPTION(CreateResourceException, "Failed create a new Resource! {}",
|
|
180
|
+
e.what());
|
|
181
|
+
} catch (...) {
|
|
182
|
+
HKU_THROW_EXCEPTION(CreateResourceException,
|
|
183
|
+
"Failed create a new Resource! Unknown error!");
|
|
184
|
+
}
|
|
185
|
+
m_count++;
|
|
186
|
+
result = ResourcePtr(p, ResourceCloser(this));
|
|
187
|
+
m_closer_set.insert(std::get_deleter<ResourceCloser>(result));
|
|
188
|
+
return result;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
p = m_resourceList.front();
|
|
192
|
+
m_resourceList.pop();
|
|
193
|
+
result = ResourcePtr(p, ResourceCloser(this));
|
|
194
|
+
m_closer_set.insert(std::get_deleter<ResourceCloser>(result));
|
|
195
|
+
return result;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* 获取可用资源,如超出允许的最大资源数,将阻塞等待直到获得空闲资源
|
|
200
|
+
* @exception CreateResourceException 新资源创建可能抛出异常
|
|
201
|
+
*/
|
|
202
|
+
ResourcePtr getAndWait() {
|
|
203
|
+
return getWaitFor(0);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** 当前活动的资源数, 即全部资源数(含空闲及被使用的资源) */
|
|
207
|
+
size_t count() const {
|
|
208
|
+
return m_count;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** 当前空闲的资源数 */
|
|
212
|
+
size_t idleCount() const {
|
|
213
|
+
return m_resourceList.size();
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/** 释放当前所有的空闲资源 */
|
|
217
|
+
void releaseIdleResource() {
|
|
218
|
+
std::lock_guard<std::mutex> lock(m_mutex);
|
|
219
|
+
_releaseIdleResourceNoLock();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
private:
|
|
223
|
+
void _releaseIdleResourceNoLock() {
|
|
224
|
+
while (!m_resourceList.empty()) {
|
|
225
|
+
ResourceType *p = m_resourceList.front();
|
|
226
|
+
m_resourceList.pop();
|
|
227
|
+
m_count--;
|
|
228
|
+
if (p) {
|
|
229
|
+
delete p;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
private:
|
|
235
|
+
size_t m_maxPoolSize; // 允许的最大共享资源数
|
|
236
|
+
size_t m_maxIdelSize; // 允许的最大空闲资源数
|
|
237
|
+
size_t m_count; // 当前活动的资源数
|
|
238
|
+
Parameter m_param;
|
|
239
|
+
std::mutex m_mutex;
|
|
240
|
+
std::condition_variable m_cond;
|
|
241
|
+
std::queue<ResourceType *> m_resourceList;
|
|
242
|
+
|
|
243
|
+
class ResourceCloser {
|
|
244
|
+
public:
|
|
245
|
+
explicit ResourceCloser(ResourcePool *pool) : m_pool(pool) { // NOSONAR
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
void operator()(ResourceType *conn) { // NOSONAR
|
|
249
|
+
if (conn) {
|
|
250
|
+
// 如果绑定了 pool,则归还资源;否则删除
|
|
251
|
+
if (m_pool) {
|
|
252
|
+
// HKU_DEBUG("retuan to pool");
|
|
253
|
+
m_pool->returnResource(conn, this);
|
|
254
|
+
} else {
|
|
255
|
+
// HKU_DEBUG("delete resource not in pool");
|
|
256
|
+
delete conn;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// 解绑资源池
|
|
262
|
+
void unbind() {
|
|
263
|
+
m_pool = nullptr;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
private:
|
|
267
|
+
ResourcePool *m_pool;
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
/** 归还至资源池 */
|
|
271
|
+
void returnResource(ResourceType *p, ResourceCloser *closer) {
|
|
272
|
+
std::unique_lock<std::mutex> lock(m_mutex);
|
|
273
|
+
if (p) {
|
|
274
|
+
if (m_resourceList.size() < m_maxIdelSize) {
|
|
275
|
+
m_resourceList.push(p);
|
|
276
|
+
m_cond.notify_all();
|
|
277
|
+
} else {
|
|
278
|
+
delete p;
|
|
279
|
+
m_count--;
|
|
280
|
+
}
|
|
281
|
+
} else {
|
|
282
|
+
m_count--;
|
|
283
|
+
// HKU_WARN("Trying to return an empty pointer!");
|
|
284
|
+
}
|
|
285
|
+
if (closer) {
|
|
286
|
+
m_closer_set.erase(closer); // 移除该 closer
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
std::unordered_set<ResourceCloser *> m_closer_set; // 占用资源的 closer
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* @brief 带版本的资源接口,可由需要版本管理的资源继承
|
|
295
|
+
* @details 自带的 getVersion 和 setVerion 方法由 ResourceVersionPool 调用,不建议带有其他用途
|
|
296
|
+
*/
|
|
297
|
+
class ResourceWithVersion {
|
|
298
|
+
public:
|
|
299
|
+
/** 默认构造函数 */
|
|
300
|
+
ResourceWithVersion() : m_version(0) {}
|
|
301
|
+
|
|
302
|
+
/** 析构函数 */
|
|
303
|
+
virtual ~ResourceWithVersion() {}
|
|
304
|
+
|
|
305
|
+
/** 获取资源版本 */
|
|
306
|
+
int getVersion() const {
|
|
307
|
+
return m_version;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/** 设置资源版本 **/
|
|
311
|
+
void setVersion(int version) {
|
|
312
|
+
m_version = version;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
protected:
|
|
316
|
+
int m_version;
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* 通用版本的共享资源池,当资源池参数变更时,保证新资源使用新参数,老版本的资源再使用完毕后被自动回收
|
|
321
|
+
* @details 要求资源类具备 int getVersion() 和 void setVersion(int) 另个接口函数
|
|
322
|
+
* @ingroup Utilities
|
|
323
|
+
*/
|
|
324
|
+
template <typename ResourceType>
|
|
325
|
+
class ResourceVersionPool {
|
|
326
|
+
public:
|
|
327
|
+
ResourceVersionPool() = delete;
|
|
328
|
+
ResourceVersionPool(const ResourceVersionPool &) = delete;
|
|
329
|
+
ResourceVersionPool &operator=(const ResourceVersionPool &) = delete;
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* 构造函数
|
|
333
|
+
* @param param 连接参数
|
|
334
|
+
* @param maxPoolSize 允许的最大共享资源数,为 0 表示不限制
|
|
335
|
+
* @param maxIdleNum 运行的最大空闲资源数,为 0 表示用完即刻释放,无缓存
|
|
336
|
+
*/
|
|
337
|
+
explicit ResourceVersionPool(const Parameter ¶m, size_t maxPoolSize = 0,
|
|
338
|
+
size_t maxIdleNum = 100)
|
|
339
|
+
: m_maxPoolSize(maxPoolSize),
|
|
340
|
+
m_maxIdelSize(maxIdleNum),
|
|
341
|
+
m_count(0),
|
|
342
|
+
m_param(param),
|
|
343
|
+
m_version(0) {}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* 析构函数,释放所有缓存的资源
|
|
347
|
+
*/
|
|
348
|
+
virtual ~ResourceVersionPool() {
|
|
349
|
+
std::unique_lock<std::mutex> lock(m_mutex);
|
|
350
|
+
|
|
351
|
+
// 将所有已分配资源的 closer 和 pool 解绑
|
|
352
|
+
for (auto iter = m_closer_set.begin(); iter != m_closer_set.end(); ++iter) {
|
|
353
|
+
(*iter)->unbind();
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// 删除所有空闲资源
|
|
357
|
+
while (!m_resourceList.empty()) {
|
|
358
|
+
ResourceType *p = m_resourceList.front();
|
|
359
|
+
m_resourceList.pop();
|
|
360
|
+
if (p) {
|
|
361
|
+
delete p;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/** 获取当前允许的最大资源数 */
|
|
367
|
+
size_t maxPoolSize() const {
|
|
368
|
+
return m_maxIdelSize;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/** 获取当前允许的最大空闲资源数 */
|
|
372
|
+
size_t maxIdleSize() const {
|
|
373
|
+
return m_maxIdelSize;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/** 设置最大资源数 */
|
|
377
|
+
void maxPoolSize(size_t num) {
|
|
378
|
+
std::lock_guard<std::mutex> lock(m_mutex);
|
|
379
|
+
m_maxPoolSize = num;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/** 设置允许的最大空闲资源数 */
|
|
383
|
+
void maxIdleSize(size_t num) {
|
|
384
|
+
std::lock_guard<std::mutex> lock(m_mutex);
|
|
385
|
+
m_maxIdelSize = num;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/** 指定参数是否存在 */
|
|
389
|
+
bool haveParam(const std::string &name) {
|
|
390
|
+
std::lock_guard<std::mutex> lock(m_mutex);
|
|
391
|
+
return m_param.have(name);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/** 获取指定参数的值,如参数不存在或类型不匹配抛出异常 */
|
|
395
|
+
template <typename ValueType>
|
|
396
|
+
ValueType getParam(const std::string &name) {
|
|
397
|
+
std::lock_guard<std::mutex> lock(m_mutex);
|
|
398
|
+
return m_param.get<ValueType>(name);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* @brief 设定指定参数的值,参数仅在生成新的资源时生效
|
|
403
|
+
* @details 在原本存在该参数的情况下,新设定的值类型须和原有参数类型相同,否则将抛出异常
|
|
404
|
+
* @param name 参数名
|
|
405
|
+
* @param value 参数值
|
|
406
|
+
* @exception std::logic_error
|
|
407
|
+
*/
|
|
408
|
+
template <typename ValueType>
|
|
409
|
+
void setParam(const std::string &name, const ValueType &value) {
|
|
410
|
+
std::lock_guard<std::mutex> lock(m_mutex);
|
|
411
|
+
// 如果参数未实际发送变化,则直接返回
|
|
412
|
+
HKU_IF_RETURN(m_param.have(name) && value == m_param.get<ValueType>(name), void());
|
|
413
|
+
m_param.set<ValueType>(name, value);
|
|
414
|
+
m_version++;
|
|
415
|
+
_releaseIdleResourceNoLock(); // 释放当前空闲资源,以便新参数值生效
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* @brief 设置资源参数,参数仅在生成新的资源时生效
|
|
420
|
+
* @param param 参数对象
|
|
421
|
+
*/
|
|
422
|
+
void setParameter(const Parameter ¶m) {
|
|
423
|
+
std::lock_guard<std::mutex> lock(m_mutex);
|
|
424
|
+
m_param = param;
|
|
425
|
+
m_version++;
|
|
426
|
+
_releaseIdleResourceNoLock(); // 释放当前空闲资源,以便新参数值生效
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* @brief 设置资源参数,参数仅在生成新的资源时生效
|
|
431
|
+
* @param param 参数对象
|
|
432
|
+
*/
|
|
433
|
+
void setParameter(Parameter &¶m) {
|
|
434
|
+
std::lock_guard<std::mutex> lock(m_mutex);
|
|
435
|
+
m_param = std::move(param);
|
|
436
|
+
m_version++;
|
|
437
|
+
_releaseIdleResourceNoLock(); // 释放当前空闲资源,以便新参数值生效
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/** 获取当前资源池版本 */
|
|
441
|
+
int getVersion() {
|
|
442
|
+
std::lock_guard<std::mutex> lock(m_mutex);
|
|
443
|
+
return m_version;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/** 递增当前资源池版本,相当于通知资源池资源版本发生变化 */
|
|
447
|
+
void incVersion(int version) {
|
|
448
|
+
std::lock_guard<std::mutex> lock(m_mutex);
|
|
449
|
+
m_version++;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/** 资源实例指针类型 */
|
|
453
|
+
typedef std::shared_ptr<ResourceType> ResourcePtr;
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* 获取可用资源,如超出允许的最大资源数将返回空指针
|
|
457
|
+
* @exception CreateResourceException 新资源创建可能抛出异常
|
|
458
|
+
*/
|
|
459
|
+
ResourcePtr get() {
|
|
460
|
+
std::lock_guard<std::mutex> lock(m_mutex);
|
|
461
|
+
ResourcePtr result;
|
|
462
|
+
ResourceType *p = nullptr;
|
|
463
|
+
if (m_resourceList.empty()) {
|
|
464
|
+
if (m_maxPoolSize > 0 && m_count >= m_maxPoolSize) {
|
|
465
|
+
return result;
|
|
466
|
+
}
|
|
467
|
+
try {
|
|
468
|
+
p = new ResourceType(m_param);
|
|
469
|
+
p->setVersion(m_version);
|
|
470
|
+
} catch (const std::exception &e) {
|
|
471
|
+
HKU_THROW_EXCEPTION(CreateResourceException, "Failed create a new Resource! {}",
|
|
472
|
+
e.what());
|
|
473
|
+
} catch (...) {
|
|
474
|
+
HKU_THROW_EXCEPTION(CreateResourceException,
|
|
475
|
+
"Failed create a new Resource! Unknown error!");
|
|
476
|
+
}
|
|
477
|
+
m_count++;
|
|
478
|
+
result = ResourcePtr(p, ResourceCloser(this));
|
|
479
|
+
m_closer_set.insert(std::get_deleter<ResourceCloser>(result));
|
|
480
|
+
return result;
|
|
481
|
+
}
|
|
482
|
+
p = m_resourceList.front();
|
|
483
|
+
m_resourceList.pop();
|
|
484
|
+
result = ResourcePtr(p, ResourceCloser(this));
|
|
485
|
+
m_closer_set.insert(std::get_deleter<ResourceCloser>(result));
|
|
486
|
+
return result;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* 在指定的超时时间内获取可用资源
|
|
491
|
+
* @param ms_timeout 超时时间,单位毫秒
|
|
492
|
+
* @exception GetResourceTimeoutException, CreateResourceException
|
|
493
|
+
*/
|
|
494
|
+
ResourcePtr getWaitFor(uint64_t ms_timeout) { // NOSONAR
|
|
495
|
+
std::unique_lock<std::mutex> lock(m_mutex);
|
|
496
|
+
ResourcePtr result;
|
|
497
|
+
ResourceType *p = nullptr;
|
|
498
|
+
if (m_resourceList.empty()) {
|
|
499
|
+
if (m_maxPoolSize > 0 && m_count >= m_maxPoolSize) {
|
|
500
|
+
// HKU_TRACE("超出最大资源数,等待空闲资源");
|
|
501
|
+
if (ms_timeout > 0) {
|
|
502
|
+
if (m_cond.wait_for(lock,
|
|
503
|
+
std::chrono::duration<uint64_t, std::milli>(ms_timeout),
|
|
504
|
+
[&] { return !m_resourceList.empty(); })) {
|
|
505
|
+
HKU_CHECK_THROW(!m_resourceList.empty(), GetResourceTimeoutException,
|
|
506
|
+
"Failed get resource!");
|
|
507
|
+
} else {
|
|
508
|
+
HKU_THROW_EXCEPTION(GetResourceTimeoutException, "Failed get resource!");
|
|
509
|
+
}
|
|
510
|
+
} else {
|
|
511
|
+
m_cond.wait(lock, [this] { return !m_resourceList.empty(); });
|
|
512
|
+
}
|
|
513
|
+
} else {
|
|
514
|
+
try {
|
|
515
|
+
p = new ResourceType(m_param);
|
|
516
|
+
p->setVersion(m_version);
|
|
517
|
+
} catch (const std::exception &e) {
|
|
518
|
+
HKU_THROW_EXCEPTION(CreateResourceException, "Failed create a new Resource! {}",
|
|
519
|
+
e.what());
|
|
520
|
+
} catch (...) {
|
|
521
|
+
HKU_THROW_EXCEPTION(CreateResourceException,
|
|
522
|
+
"Failed create a new Resource! Unknown error!");
|
|
523
|
+
}
|
|
524
|
+
m_count++;
|
|
525
|
+
result = ResourcePtr(p, ResourceCloser(this));
|
|
526
|
+
m_closer_set.insert(std::get_deleter<ResourceCloser>(result));
|
|
527
|
+
return result;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
p = m_resourceList.front();
|
|
531
|
+
m_resourceList.pop();
|
|
532
|
+
result = ResourcePtr(p, ResourceCloser(this));
|
|
533
|
+
m_closer_set.insert(std::get_deleter<ResourceCloser>(result));
|
|
534
|
+
return result;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* 获取可用资源,如超出允许的最大资源数,将阻塞等待直到获得空闲资源
|
|
539
|
+
* @exception CreateResourceException 新资源创建可能抛出异常
|
|
540
|
+
*/
|
|
541
|
+
ResourcePtr getAndWait() {
|
|
542
|
+
return getWaitFor(0);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
/** 当前活动的资源数, 即全部资源数(含空闲及被使用的资源) */
|
|
546
|
+
size_t count() const {
|
|
547
|
+
return m_count;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/** 当前空闲的资源数 */
|
|
551
|
+
size_t idleCount() const {
|
|
552
|
+
return m_resourceList.size();
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
/** 释放当前所有的空闲资源 */
|
|
556
|
+
void releaseIdleResource() {
|
|
557
|
+
std::lock_guard<std::mutex> lock(m_mutex);
|
|
558
|
+
_releaseIdleResourceNoLock();
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
private:
|
|
562
|
+
void _releaseIdleResourceNoLock() {
|
|
563
|
+
while (!m_resourceList.empty()) {
|
|
564
|
+
ResourceType *p = m_resourceList.front();
|
|
565
|
+
m_resourceList.pop();
|
|
566
|
+
m_count--;
|
|
567
|
+
if (p) {
|
|
568
|
+
delete p;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
private:
|
|
574
|
+
size_t m_maxPoolSize; // 允许的最大共享资源数
|
|
575
|
+
size_t m_maxIdelSize; // 允许的最大空闲资源数
|
|
576
|
+
size_t m_count; // 当前活动的资源数
|
|
577
|
+
Parameter m_param;
|
|
578
|
+
std::mutex m_mutex;
|
|
579
|
+
std::condition_variable m_cond;
|
|
580
|
+
std::queue<ResourceType *> m_resourceList;
|
|
581
|
+
int m_version;
|
|
582
|
+
|
|
583
|
+
class ResourceCloser {
|
|
584
|
+
public:
|
|
585
|
+
explicit ResourceCloser(ResourceVersionPool *pool) : m_pool(pool) { // NOSONAR
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
void operator()(ResourceType *conn) { // NOSONAR
|
|
589
|
+
if (conn) {
|
|
590
|
+
// 如果绑定了 pool,则归还资源;否则删除
|
|
591
|
+
if (m_pool) {
|
|
592
|
+
// HKU_DEBUG("retuan to pool");
|
|
593
|
+
m_pool->returnResource(conn, this);
|
|
594
|
+
} else {
|
|
595
|
+
// HKU_DEBUG("delete resource not in pool");
|
|
596
|
+
delete conn;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
// 解绑资源池
|
|
602
|
+
void unbind() {
|
|
603
|
+
m_pool = nullptr;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
private:
|
|
607
|
+
ResourceVersionPool *m_pool;
|
|
608
|
+
};
|
|
609
|
+
|
|
610
|
+
/** 归还至资源池 */
|
|
611
|
+
void returnResource(ResourceType *p, ResourceCloser *closer) {
|
|
612
|
+
std::unique_lock<std::mutex> lock(m_mutex);
|
|
613
|
+
if (p) {
|
|
614
|
+
// 当前归还资源的版本和资源池版本相等,且空闲资源列表小于最大空闲资源数时,接受归还的资源
|
|
615
|
+
if (p->getVersion() == m_version && m_resourceList.size() < m_maxIdelSize) {
|
|
616
|
+
m_resourceList.push(p);
|
|
617
|
+
m_cond.notify_all();
|
|
618
|
+
} else {
|
|
619
|
+
delete p;
|
|
620
|
+
m_count--;
|
|
621
|
+
}
|
|
622
|
+
} else {
|
|
623
|
+
m_count--;
|
|
624
|
+
// HKU_WARN("Trying to return an empty pointer!");
|
|
625
|
+
}
|
|
626
|
+
if (closer) {
|
|
627
|
+
m_closer_set.erase(closer); // 移除该 closer
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
std::unordered_set<ResourceCloser *> m_closer_set; // 占用资源的 closer
|
|
632
|
+
};
|
|
633
|
+
|
|
634
|
+
} // namespace hku
|
|
635
|
+
|
|
636
|
+
#endif /* HKU_UTILS_RESOURCE_POOL_H */
|
|
@@ -21,9 +21,10 @@
|
|
|
21
21
|
#include <chrono>
|
|
22
22
|
#include <vector>
|
|
23
23
|
#include <fmt/format.h>
|
|
24
|
+
#include "hikyuu/utilities/config.h"
|
|
24
25
|
|
|
25
|
-
#ifndef
|
|
26
|
-
#define
|
|
26
|
+
#ifndef HKU_UTILS_API
|
|
27
|
+
#define HKU_UTILS_API
|
|
27
28
|
#endif
|
|
28
29
|
#ifdef __ANDROID__
|
|
29
30
|
#include <android/log.h>
|
|
@@ -138,7 +139,7 @@ namespace hku {
|
|
|
138
139
|
* @note 不建议直接使用,应使用相关工具宏
|
|
139
140
|
* @see SPEND_TIME, SPEND_TIME_MSG, SPEND_TIMG_CONTROL
|
|
140
141
|
*/
|
|
141
|
-
class
|
|
142
|
+
class HKU_UTILS_API SpendTimer {
|
|
142
143
|
public:
|
|
143
144
|
/** 构造函数,记录当前系统时间 */
|
|
144
145
|
explicit SpendTimer()
|
|
@@ -237,19 +238,19 @@ private:
|
|
|
237
238
|
std::vector<std::string> m_keep_desc;
|
|
238
239
|
|
|
239
240
|
static bool ms_closed;
|
|
240
|
-
friend void
|
|
241
|
-
friend void
|
|
242
|
-
friend bool
|
|
241
|
+
friend void HKU_UTILS_API close_spend_time();
|
|
242
|
+
friend void HKU_UTILS_API open_spend_time();
|
|
243
|
+
friend bool HKU_UTILS_API get_spend_time_status();
|
|
243
244
|
};
|
|
244
245
|
|
|
245
246
|
/** 全局关闭耗时打印输出 */
|
|
246
|
-
void
|
|
247
|
+
void HKU_UTILS_API close_spend_time();
|
|
247
248
|
|
|
248
249
|
/** 全局开启耗时打印输出 */
|
|
249
|
-
void
|
|
250
|
+
void HKU_UTILS_API open_spend_time();
|
|
250
251
|
|
|
251
252
|
/** 获取全局耗时打印输出状态:true - 开启,false - 关闭 */
|
|
252
|
-
bool
|
|
253
|
+
bool HKU_UTILS_API get_spend_time_status();
|
|
253
254
|
|
|
254
255
|
/**
|
|
255
256
|
* 耗时计时器开启关闭状态看守,记录之前的耗时开关状态,并置为指定状态,释放时恢复原状态
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
#include <unordered_map>
|
|
12
12
|
#include <functional>
|
|
13
13
|
#include "hikyuu/utilities/datetime/Datetime.h"
|
|
14
|
-
#include "hikyuu/Log.h"
|
|
14
|
+
#include "hikyuu/utilities/Log.h"
|
|
15
15
|
#include "thread/ThreadPool.h"
|
|
16
16
|
#include "cppdef.h"
|
|
17
17
|
|
|
@@ -399,7 +399,7 @@ private:
|
|
|
399
399
|
// 分配 timer_id
|
|
400
400
|
int getNewTimerId() {
|
|
401
401
|
int max_int = std::numeric_limits<int>::max();
|
|
402
|
-
HKU_WARN_IF_RETURN(m_timers.size() >= max_int, -1, "Timer queue is full!");
|
|
402
|
+
HKU_WARN_IF_RETURN(m_timers.size() >= size_t(max_int), -1, "Timer queue is full!");
|
|
403
403
|
|
|
404
404
|
if (m_current_timer_id >= max_int) {
|
|
405
405
|
m_current_timer_id = 0;
|