Browse Source

feat: 更新执行策略

ChunelFeng 2 years ago
parent
commit
4c9a7f1520
29 changed files with 754 additions and 322 deletions
  1. +1
    -1
      CMakeLists.txt
  2. +3
    -0
      README.md
  3. +2
    -0
      src/CBasic/CBasicInclude.h
  4. +76
    -0
      src/CBasic/CDescInfo.h
  5. +10
    -5
      src/CBasic/CException.h
  6. +33
    -5
      src/CBasic/CFuncType.h
  7. +38
    -42
      src/CBasic/CStatus.h
  8. +8
    -5
      src/CBasic/CStrDefine.h
  9. +25
    -0
      src/CBasic/CStruct.h
  10. +8
    -5
      src/CBasic/CValType.h
  11. +20
    -16
      src/UtilsCtrl/ThreadPool/Queue/UAtomicPriorityQueue.h
  12. +37
    -22
      src/UtilsCtrl/ThreadPool/Queue/UAtomicQueue.h
  13. +93
    -8
      src/UtilsCtrl/ThreadPool/Queue/UAtomicRingBufferQueue.h
  14. +23
    -0
      src/UtilsCtrl/ThreadPool/Queue/UQueueDefine.h
  15. +1
    -0
      src/UtilsCtrl/ThreadPool/Queue/UQueueObject.h
  16. +23
    -9
      src/UtilsCtrl/ThreadPool/Queue/UWorkStealingQueue.h
  17. +2
    -2
      src/UtilsCtrl/ThreadPool/Task/UTaskGroup.h
  18. +40
    -6
      src/UtilsCtrl/ThreadPool/Thread/UThreadBase.h
  19. +56
    -38
      src/UtilsCtrl/ThreadPool/Thread/UThreadPrimary.h
  20. +22
    -25
      src/UtilsCtrl/ThreadPool/Thread/UThreadSecondary.h
  21. +1
    -0
      src/UtilsCtrl/ThreadPool/UThreadObject.h
  22. +41
    -21
      src/UtilsCtrl/ThreadPool/UThreadPool.cpp
  23. +21
    -10
      src/UtilsCtrl/ThreadPool/UThreadPool.h
  24. +2
    -4
      src/UtilsCtrl/ThreadPool/UThreadPool.inl
  25. +18
    -14
      src/UtilsCtrl/ThreadPool/UThreadPoolConfig.h
  26. +14
    -24
      src/UtilsCtrl/ThreadPool/UThreadPoolDefine.h
  27. +28
    -6
      src/UtilsCtrl/UAllocator.h
  28. +81
    -33
      src/UtilsCtrl/UtilsDefine.h
  29. +27
    -21
      src/UtilsCtrl/UtilsFunction.h

+ 1
- 1
CMakeLists.txt View File

@ -9,7 +9,7 @@ message("* * * * * * * * * * * * * * * * *")
cmake_minimum_required(VERSION 3.2.5) cmake_minimum_required(VERSION 3.2.5)
project(CThreadPool VERSION 1.2.0)
project(CThreadPool VERSION 1.2.1)
set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD 11)

+ 3
- 0
README.md View File

@ -83,6 +83,9 @@ int main() {
[2023.03.07 - v1.2.0 - Chunel] [2023.03.07 - v1.2.0 - Chunel]
* 优化windows版本功能 * 优化windows版本功能
[2023.10.07 - v1.2.1 - Chunel]
* 更新执行策略,优化整体性能
------------ ------------
#### 附录-2. 联系方式 #### 附录-2. 联系方式
* 微信: ChunelFeng * 微信: ChunelFeng

+ 2
- 0
src/CBasic/CBasicInclude.h View File

@ -17,5 +17,7 @@
#include "CBasicDefine.h" #include "CBasicDefine.h"
#include "CStrDefine.h" #include "CStrDefine.h"
#include "CStdEx.h" #include "CStdEx.h"
#include "CDescInfo.h"
#include "CStruct.h"
#endif //CGRAPH_CBASICINCLUDE_H #endif //CGRAPH_CBASICINCLUDE_H

+ 76
- 0
src/CBasic/CDescInfo.h View File

@ -0,0 +1,76 @@
/***************************
@Author: Chunel
@Contact: chunel@foxmail.com
@File: CDescInfo.h
@Time: 2023/2/19 15:56
@Desc:
***************************/
#ifndef CGRAPH_CDESCINFO_H
#define CGRAPH_CDESCINFO_H
#include <string>
#include "CBasicDefine.h"
CGRAPH_NAMESPACE_BEGIN
class CDescInfo {
public:
/**
*
* @return
*/
const std::string& getName() const {
return name_;
}
/**
* id信息
* @return
*/
const std::string& getSession() const {
return session_;
}
/**
*
* @return
*/
const std::string& getDescription() const {
return description_;
}
/**
*
* @param name
* @return
*/
virtual auto setName(const std::string& name)
-> decltype(this) {
name_ = name;
return this;
}
/**
*
* @param description
* @return
*/
virtual auto setDescription(const std::string& description)
-> decltype(this) {
description_ = description;
return this;
}
virtual ~CDescInfo() = default;
protected:
std::string name_; //
std::string session_; // id信息
std::string description_; //
};
CGRAPH_NAMESPACE_END
#endif //CGRAPH_CDESCINFO_H

+ 10
- 5
src/CBasic/CException.h View File

@ -18,20 +18,25 @@ CGRAPH_NAMESPACE_BEGIN
class CEXCEPTION : public std::exception { class CEXCEPTION : public std::exception {
public: public:
explicit CEXCEPTION(const std::string& info = CGRAPH_EMPTY) {
info_ = info.empty() ? CGRAPH_BASIC_EXCEPTION : info;
explicit CEXCEPTION(const std::string& info,
const std::string& locate = CGRAPH_EMPTY) {
/**
* CStatus有一个联动
*
*/
exception_info_ = locate + " | " + info;
} }
/** /**
* *
* @return * @return
*/ */
[[nodiscard]] const char* what() const noexcept override {
return info_.c_str();
const char* what() const noexcept override {
return exception_info_.c_str();
} }
private: private:
std::string info_; //
std::string exception_info_; //
}; };
CGRAPH_NAMESPACE_END CGRAPH_NAMESPACE_END

+ 33
- 5
src/CBasic/CFuncType.h View File

@ -45,13 +45,30 @@ enum class CFunctionType {
#define CGRAPH_EMPTY_FUNCTION \ #define CGRAPH_EMPTY_FUNCTION \
return CStatus(); \ return CStatus(); \
/** 不支持当前功能 */
#define CGRAPH_NO_SUPPORT \
return CStatus(CGRAPH_FUNCTION_NO_SUPPORT); \
/** 获取当前代码所在的位置信息 */
#define CGRAPH_GET_LOCATE \
(std::string(__FILE__) + " | " + std::string(__FUNCTION__) \
+ " | line = [" + ::std::to_string( __LINE__) + "]")
/** 生成一个包含异常位置的 CStatus
* CStatus
* */
#define CErrStatus(info) \
CStatus(info, CGRAPH_GET_LOCATE) \
/** 返回异常信息和状态 */ /** 返回异常信息和状态 */
#define CGRAPH_RETURN_ERROR_STATUS(info) \ #define CGRAPH_RETURN_ERROR_STATUS(info) \
return CStatus(info); \
return CErrStatus(info); \
/** 根据条件判断是否返回错误状态 */
#define CGRAPH_RETURN_ERROR_STATUS_BY_CONDITION(cond, info) \
if (unlikely(cond)) { CGRAPH_RETURN_ERROR_STATUS(info); } \
/** 不支持当前功能 */
#define CGRAPH_NO_SUPPORT \
return CErrStatus(CGRAPH_FUNCTION_NO_SUPPORT); \
/** 定义为不能赋值和拷贝的对象类型 */ /** 定义为不能赋值和拷贝的对象类型 */
#define CGRAPH_NO_ALLOWED_COPY(CType) \ #define CGRAPH_NO_ALLOWED_COPY(CType) \
@ -60,7 +77,18 @@ enum class CFunctionType {
/** 抛出异常 */ /** 抛出异常 */
#define CGRAPH_THROW_EXCEPTION(info) \ #define CGRAPH_THROW_EXCEPTION(info) \
throw CException(info); \
throw CException(info, CGRAPH_GET_LOCATE); \
/** 在异常状态的情况下,抛出异常 */
#define CGRAPH_THROW_EXCEPTION_BY_STATUS(status) \
if (unlikely((status).isErr())) { \
CGRAPH_THROW_EXCEPTION((status).getInfo()); \
} \
/** 根据条件判断是否抛出异常 */
#define CGRAPH_THROW_EXCEPTION_BY_CONDITION(cond, info) \
if (unlikely(cond)) { CGRAPH_THROW_EXCEPTION(info); } \
CGRAPH_NAMESPACE_END CGRAPH_NAMESPACE_END

+ 38
- 42
src/CBasic/CStatus.h View File

@ -19,86 +19,89 @@ CGRAPH_NAMESPACE_BEGIN
/** /**
* *
* 0 * 0
* warning逻辑
* error逻辑 * error逻辑
* *
*/ */
static const int STATUS_OK = 0; /** 正常流程返回值 */ static const int STATUS_OK = 0; /** 正常流程返回值 */
static const int STATUS_ERR = -1; /** 异常流程返回值 */ static const int STATUS_ERR = -1; /** 异常流程返回值 */
static const int STATUS_CRASH = -996; /** 异常流程返回值 */
static const char* STATUS_ERROR_INFO_CONNECTOR = " && "; /** 多异常信息连接符号 */ static const char* STATUS_ERROR_INFO_CONNECTOR = " && "; /** 多异常信息连接符号 */
class CSTATUS { class CSTATUS {
public: public:
explicit CSTATUS() = default; explicit CSTATUS() = default;
explicit CSTATUS(const std::string &errorInfo) {
explicit CSTATUS(const std::string &errorInfo,
const std::string &locateInfo = CGRAPH_EMPTY) {
this->error_code_ = STATUS_ERR; // error code信息 this->error_code_ = STATUS_ERR; // error code信息
this->error_info_ = errorInfo; this->error_info_ = errorInfo;
this->error_locate_ = locateInfo;
} }
explicit CSTATUS(int errorCode, const std::string &errorInfo) {
explicit CSTATUS(int errorCode, const std::string &errorInfo,
const std::string &locateInfo = CGRAPH_EMPTY) {
this->error_code_ = errorCode; this->error_code_ = errorCode;
this->error_info_ = errorInfo; this->error_info_ = errorInfo;
this->error_locate_ = locateInfo;
} }
CSTATUS(const CSTATUS &status) { CSTATUS(const CSTATUS &status) {
this->error_code_ = status.error_code_; this->error_code_ = status.error_code_;
this->error_info_ = status.error_info_; this->error_info_ = status.error_info_;
this->error_locate_ = status.error_locate_;
} }
CSTATUS(const CSTATUS &&status) noexcept { CSTATUS(const CSTATUS &&status) noexcept {
this->error_code_ = status.error_code_; this->error_code_ = status.error_code_;
this->error_info_ = status.error_info_; this->error_info_ = status.error_info_;
this->error_locate_ = status.error_locate_;
} }
CSTATUS& operator=(const CSTATUS& status) = default; CSTATUS& operator=(const CSTATUS& status) = default;
CSTATUS& operator+=(const CSTATUS& cur) { CSTATUS& operator+=(const CSTATUS& cur) {
if (this->isOK() && cur.isOK()) {
return (*this);
/**
*
*
*/
if (!this->isErr() && cur.isErr()) {
this->error_code_ = cur.error_code_;
this->error_info_ = cur.error_info_;
this->error_locate_ = cur.error_locate_;
} }
error_info_ = this->isOK()
? cur.error_info_
: (cur.isOK()
? error_info_
: (error_info_ + STATUS_ERROR_INFO_CONNECTOR + cur.error_info_));
error_code_ = STATUS_ERR;
return (*this); return (*this);
} }
void setStatus(const std::string& info) {
error_code_ = STATUS_ERR;
error_info_ = info;
}
void setStatus(int code, const std::string& info) {
error_code_ = code;
error_info_ = info;
}
[[nodiscard]] int getCode() const {
/**
*
* @return
*/
int getCode() const {
return this->error_code_; return this->error_code_;
} }
[[nodiscard]] const std::string& getInfo() const {
/**
*
* @return
*/
const std::string& getInfo() const {
return this->error_info_; return this->error_info_;
} }
/** /**
*
*
* @return
*/ */
void reset() {
error_code_ = STATUS_OK;
error_info_ = CGRAPH_EMPTY;
const std::string& getLocate() const {
return this->error_locate_;
} }
/** /**
* *
* @return * @return
*/ */
[[nodiscard]] bool isOK() const {
bool isOK() const {
return STATUS_OK == error_code_; return STATUS_OK == error_code_;
} }
@ -106,29 +109,22 @@ public:
* *
* @return * @return
*/ */
[[nodiscard]] bool isErr() const {
bool isErr() const {
return error_code_ < STATUS_OK; // return error_code_ < STATUS_OK; //
} }
/** /**
*
* @return
*/
[[nodiscard]] bool isNotErr() const {
return error_code_ >= STATUS_OK;
}
/**
* ok的error warning
*
* @return * @return
*/ */
[[nodiscard]] bool isNotOK() const {
return error_code_ != STATUS_OK;
bool isCrash() const {
return STATUS_CRASH == error_code_;
} }
private: private:
int error_code_ { STATUS_OK }; //
int error_code_ = STATUS_OK; //
std::string error_info_; // std::string error_info_; //
std::string error_locate_; // file|function|line
}; };
CGRAPH_NAMESPACE_END CGRAPH_NAMESPACE_END

+ 8
- 5
src/CBasic/CStrDefine.h View File

@ -9,15 +9,18 @@
#ifndef CGRAPH_CSTRDEFINE_H #ifndef CGRAPH_CSTRDEFINE_H
#define CGRAPH_CSTRDEFINE_H #define CGRAPH_CSTRDEFINE_H
#include <string>
#include "CBasicDefine.h" #include "CBasicDefine.h"
CGRAPH_NAMESPACE_BEGIN CGRAPH_NAMESPACE_BEGIN
static const char* CGRAPH_EMPTY = "";
static const char* CGRAPH_DEFAULT = "default";
static const char* CGRAPH_UNKNOWN = "unknown";
static const char* CGRAPH_BASIC_EXCEPTION = "CGraph default exception";
static const char* CGRAPH_FUNCTION_NO_SUPPORT = "CGraph function no support";
static const std::string& CGRAPH_EMPTY = "";
static const std::string& CGRAPH_DEFAULT = "default";
static const std::string& CGRAPH_UNKNOWN = "unknown";
static const std::string& CGRAPH_BASIC_EXCEPTION = "CGraph default exception";
static const std::string& CGRAPH_FUNCTION_NO_SUPPORT = "CGraph function no support";
static const std::string& CGRAPH_INPUT_IS_NULL = "input is nullptr";
CGRAPH_NAMESPACE_END CGRAPH_NAMESPACE_END

+ 25
- 0
src/CBasic/CStruct.h View File

@ -0,0 +1,25 @@
/***************************
@Author: Chunel
@Contact: chunel@foxmail.com
@File: CStruct.h
@Time: 2023/7/16 11:36
@Desc:
***************************/
#ifndef CGRAPH_CSTRUCT_H
#define CGRAPH_CSTRUCT_H
#include "CBasicDefine.h"
CGRAPH_NAMESPACE_BEGIN
/**
*
* bean
*/
class CStruct {
};
CGRAPH_NAMESPACE_END
#endif //CGRAPH_CSTRUCT_H

+ 8
- 5
src/CBasic/CValType.h View File

@ -9,27 +9,30 @@
#ifndef CGRAPH_CVALTYPE_H #ifndef CGRAPH_CVALTYPE_H
#define CGRAPH_CVALTYPE_H #define CGRAPH_CVALTYPE_H
#include "CBasicDefine.h"
#include "CStatus.h" #include "CStatus.h"
#include "CException.h" #include "CException.h"
using CChar = CTP::CCHAR; using CChar = CTP::CCHAR;
using CUint = CTP::CUINT; using CUint = CTP::CUINT;
using CSec = CTP::CUINT; // , for second
using CMSec = CTP::CUINT; // , for millisecond
using CSize = CTP::CSIZE; using CSize = CTP::CSIZE;
using CVoid = CTP::CVOID; using CVoid = CTP::CVOID;
using CVoidPtr = CTP::CVOID *; using CVoidPtr = CTP::CVOID *;
using CInt = CTP::CINT; using CInt = CTP::CINT;
using CLevel = CTP::CINT;
using CLong = CTP::CLONG; using CLong = CTP::CLONG;
using CULong = CTP::CULONG; using CULong = CTP::CULONG;
using CBool = CTP::CBOOL; using CBool = CTP::CBOOL;
using CIndex = CTP::CINT; //
using CIndex = CTP::CINT; //
using CFloat = CTP::CFLOAT; using CFloat = CTP::CFLOAT;
using CDouble = CTP::CDOUBLE; using CDouble = CTP::CDOUBLE;
using CConStr = CTP::CCONSTR; // const char*
using CConStr = CTP::CCONSTR; // const char*
using CBigBool = CTP::CBIGBOOL; using CBigBool = CTP::CBIGBOOL;
using CLevel = CTP::CINT;
using CSec = CTP::CLONG; // , for second
using CMSec = CTP::CLONG; // , for millisecond
using CFMSec = CTP::CDOUBLE; //
using CStatus = CTP::CSTATUS; using CStatus = CTP::CSTATUS;
using CException = CTP::CEXCEPTION; using CException = CTP::CEXCEPTION;

+ 20
- 16
src/UtilsCtrl/ThreadPool/Queue/UAtomicPriorityQueue.h View File

@ -26,13 +26,17 @@ public:
* @return * @return
*/ */
CBool tryPop(T& value) { CBool tryPop(T& value) {
CGRAPH_LOCK_GUARD lk(mutex_);
if (priority_queue_.empty()) {
return false;
CBool result = false;
if (mutex_.try_lock()) {
if (!priority_queue_.empty()) {
value = std::move(*priority_queue_.top());
priority_queue_.pop();
result = true;
}
mutex_.unlock();
} }
value = std::move(*priority_queue_.top());
priority_queue_.pop();
return true;
return result;
} }
@ -43,17 +47,17 @@ public:
* @return * @return
*/ */
CBool tryPop(std::vector<T>& values, int maxPoolBatchSize) { CBool tryPop(std::vector<T>& values, int maxPoolBatchSize) {
CGRAPH_LOCK_GUARD lk(mutex_);
if (priority_queue_.empty() || maxPoolBatchSize <= 0) {
return false;
}
while (!priority_queue_.empty() && maxPoolBatchSize--) {
values.emplace_back(std::move(*priority_queue_.top()));
priority_queue_.pop();
CBool result = false;
if (mutex_.try_lock()) {
while (!priority_queue_.empty() && maxPoolBatchSize-- > 0) {
values.emplace_back(std::move(*priority_queue_.top()));
priority_queue_.pop();
result = true;
}
mutex_.unlock();
} }
return true;
return result;
} }
@ -74,7 +78,7 @@ public:
* *
* @return * @return
*/ */
[[nodiscard]] CBool empty() {
CBool empty() {
CGRAPH_LOCK_GUARD lk(mutex_); CGRAPH_LOCK_GUARD lk(mutex_);
return priority_queue_.empty(); return priority_queue_.empty();
} }

+ 37
- 22
src/UtilsCtrl/ThreadPool/Queue/UAtomicQueue.h View File

@ -42,13 +42,17 @@ public:
* @return * @return
*/ */
CBool tryPop(T& value) { CBool tryPop(T& value) {
CGRAPH_LOCK_GUARD lk(mutex_);
if (queue_.empty()) {
return false;
CBool result = false;
if (mutex_.try_lock()) {
if (!queue_.empty()) {
value = std::move(*queue_.front());
queue_.pop();
result = true;
}
mutex_.unlock();
} }
value = std::move(*queue_.front());
queue_.pop();
return true;
return result;
} }
@ -59,17 +63,17 @@ public:
* @return * @return
*/ */
CBool tryPop(std::vector<T>& values, int maxPoolBatchSize) { CBool tryPop(std::vector<T>& values, int maxPoolBatchSize) {
CGRAPH_LOCK_GUARD lk(mutex_);
if (queue_.empty() || maxPoolBatchSize <= 0) {
return false;
}
while (!queue_.empty() && maxPoolBatchSize--) {
values.emplace_back(std::move(*queue_.front()));
queue_.pop();
CBool result = false;
if (mutex_.try_lock()) {
while (!queue_.empty() && maxPoolBatchSize-- > 0) {
values.emplace_back(std::move(*queue_.front()));
queue_.pop();
result = true;
}
mutex_.unlock();
} }
return true;
return result;
} }
@ -77,11 +81,14 @@ public:
* *
* @return * @return
*/ */
std::unique_ptr<T> waitPop() {
std::unique_ptr<T> popWithTimeout(CMSec ms) {
CGRAPH_UNIQUE_LOCK lk(mutex_); CGRAPH_UNIQUE_LOCK lk(mutex_);
cv_.wait(lk, [this] { return !queue_.empty(); });
if (!cv_.wait_for(lk, std::chrono::milliseconds(ms), [this] { return !queue_.empty(); })) {
return nullptr;
}
std::unique_ptr<T> result = std::move(queue_.front()); std::unique_ptr<T> result = std::move(queue_.front());
queue_.pop();
queue_.pop(); //
return result; return result;
} }
@ -104,9 +111,17 @@ public:
* @param value * @param value
*/ */
CVoid push(T&& value) { CVoid push(T&& value) {
std::unique_ptr<T> task(c_make_unique<T>(std::move(value)));
CGRAPH_LOCK_GUARD lk(mutex_);
queue_.push(std::move(task));
std::unique_ptr<typename std::remove_reference<T>::type> \
task(c_make_unique<typename std::remove_reference<T>::type>(std::forward<T>(value)));
while (true) {
if (mutex_.try_lock()) {
queue_.push(std::move(task));
mutex_.unlock();
break;
} else {
std::this_thread::yield();
}
}
cv_.notify_one(); cv_.notify_one();
} }
@ -115,7 +130,7 @@ public:
* *
* @return * @return
*/ */
[[nodiscard]] CBool empty() {
CBool empty() {
CGRAPH_LOCK_GUARD lk(mutex_); CGRAPH_LOCK_GUARD lk(mutex_);
return queue_.empty(); return queue_.empty();
} }

+ 93
- 8
src/UtilsCtrl/ThreadPool/Queue/UAtomicRingBufferQueue.h View File

@ -11,6 +11,7 @@
#include <vector> #include <vector>
#include <atomic> #include <atomic>
#include <chrono>
#include "UQueueObject.h" #include "UQueueObject.h"
@ -46,21 +47,32 @@ public:
* *
* @return * @return
*/ */
[[nodiscard]] CUint getCapacity() const {
CUint getCapacity() const {
return capacity_; return capacity_;
} }
/** /**
* *
* @tparam TImpl
* @param value * @param value
* @param strategy
* @return * @return
*/ */
template<class TImpl = T> template<class TImpl = T>
CVoid push(const TImpl& value) {
CVoid push(const TImpl& value, URingBufferPushStrategy strategy) {
{ {
CGRAPH_UNIQUE_LOCK lk(mutex_); CGRAPH_UNIQUE_LOCK lk(mutex_);
if (isFull()) { if (isFull()) {
push_cv_.wait(lk, [this] { return !isFull(); });
switch (strategy) {
case URingBufferPushStrategy::WAIT:
push_cv_.wait(lk, [this] { return !isFull(); });
break;
case URingBufferPushStrategy::REPLACE:
head_ = (head_ + 1) % capacity_;
break;
case URingBufferPushStrategy::DROP:
return; //
}
} }
ring_buffer_queue_[tail_] = std::move(c_make_unique<TImpl>(value)); ring_buffer_queue_[tail_] = std::move(c_make_unique<TImpl>(value));
@ -70,23 +82,88 @@ public:
} }
/** /**
*
* @tparam TImpl
* @param value
* @param strategy
* @return
*/
template<class TImpl = T>
CVoid push(std::unique_ptr<TImpl>& value, URingBufferPushStrategy strategy) {
{
CGRAPH_UNIQUE_LOCK lk(mutex_);
if (isFull()) {
switch (strategy) {
case URingBufferPushStrategy::WAIT:
push_cv_.wait(lk, [this] { return !isFull(); });
break;
case URingBufferPushStrategy::REPLACE:
head_ = (head_ + 1) % capacity_;
break;
case URingBufferPushStrategy::DROP:
return; //
}
}
ring_buffer_queue_[tail_] = std::move(value);
tail_ = (tail_ + 1) % capacity_;
}
pop_cv_.notify_one();
}
/**
* *
* @param value * @param value
* @param timeout
* @return * @return
*/ */
template<class TImpl = T> template<class TImpl = T>
CVoid waitPop(TImpl& value) {
CStatus waitPopWithTimeout(TImpl& value, CMSec timeout) {
CGRAPH_FUNCTION_BEGIN
{ {
CGRAPH_UNIQUE_LOCK lk(mutex_); CGRAPH_UNIQUE_LOCK lk(mutex_);
if (isEmpty()) {
pop_cv_.wait(lk, [this] { return !isEmpty(); });
if (isEmpty()
&& !pop_cv_.wait_for(lk, std::chrono::milliseconds(timeout),
[this] { return !isEmpty(); })) {
// timeout的时间内
CGRAPH_RETURN_ERROR_STATUS("receive message timeout.")
} }
value = (*ring_buffer_queue_[head_]);
*ring_buffer_queue_[head_] = {};
value = *ring_buffer_queue_[head_]; // copy
head_ = (head_ + 1) % capacity_; head_ = (head_ + 1) % capacity_;
} }
push_cv_.notify_one(); push_cv_.notify_one();
CGRAPH_FUNCTION_END
}
/**
* ps
* @tparam TImpl
* @param value
* @param timeout
* @return
*/
template<class TImpl = T>
CStatus waitPopWithTimeout(std::unique_ptr<TImpl>& value, CMSec timeout) {
CGRAPH_FUNCTION_BEGIN
{
CGRAPH_UNIQUE_LOCK lk(mutex_);
if (isEmpty()
&& !pop_cv_.wait_for(lk, std::chrono::milliseconds(timeout),
[this] { return !isEmpty(); })) {
// timeout的时间内
CGRAPH_RETURN_ERROR_STATUS("receive message timeout.")
}
/**
*
* move转移过去好了
*/
value = std::move(ring_buffer_queue_[head_]);
head_ = (head_ + 1) % capacity_;
}
push_cv_.notify_one();
CGRAPH_FUNCTION_END
} }
/** /**
@ -102,11 +179,19 @@ public:
} }
protected: protected:
/**
*
* @return
*/
CBool isFull() { CBool isFull() {
// tail写入 // tail写入
return head_ == (tail_ + 1) % capacity_; return head_ == (tail_ + 1) % capacity_;
} }
/**
*
* @return
*/
CBool isEmpty() { CBool isEmpty() {
return head_ == tail_; return head_ == tail_;
} }

+ 23
- 0
src/UtilsCtrl/ThreadPool/Queue/UQueueDefine.h View File

@ -0,0 +1,23 @@
/***************************
@Author: Chunel
@Contact: chunel@foxmail.com
@File: UQueueDefine.h
@Time: 2023/9/15 21:31
@Desc:
***************************/
#ifndef CGRAPH_UQUEUEDEFINE_H
#define CGRAPH_UQUEUEDEFINE_H
CGRAPH_NAMESPACE_BEGIN
/** 当环形队列满的时候,写入信息时候的策略 */
enum class URingBufferPushStrategy {
WAIT = 1, //
REPLACE = 2, //
DROP = 3, //
};
CGRAPH_NAMESPACE_END
#endif //CGRAPH_UQUEUEDEFINE_H

+ 1
- 0
src/UtilsCtrl/ThreadPool/Queue/UQueueObject.h View File

@ -12,6 +12,7 @@
#include <mutex> #include <mutex>
#include "../UThreadObject.h" #include "../UThreadObject.h"
#include "UQueueDefine.h"
CGRAPH_NAMESPACE_BEGIN CGRAPH_NAMESPACE_BEGIN

+ 23
- 9
src/UtilsCtrl/ThreadPool/Queue/UWorkStealingQueue.h View File

@ -10,7 +10,6 @@
#ifndef CGRAPH_UWORKSTEALINGQUEUE_H #ifndef CGRAPH_UWORKSTEALINGQUEUE_H
#define CGRAPH_UWORKSTEALINGQUEUE_H #define CGRAPH_UWORKSTEALINGQUEUE_H
#include <queue>
#include <deque> #include <deque>
#include "UQueueObject.h" #include "UQueueObject.h"
@ -27,7 +26,7 @@ public:
*/ */
CVoid push(UTask&& task) { CVoid push(UTask&& task) {
while (true) { while (true) {
if (lock_.tryLock()) {
if (lock_.try_lock()) {
deque_.emplace_front(std::move(task)); deque_.emplace_front(std::move(task));
lock_.unlock(); lock_.unlock();
break; break;
@ -39,6 +38,22 @@ public:
/** /**
*
* @param task
* @return
*/
CBool tryPush(UTask&& task) {
CBool result = false;
if (lock_.try_lock()) {
deque_.emplace_back(std::move(task));
lock_.unlock();
result = true;
}
return result;
}
/**
* *
* @param task * @param task
* @return * @return
@ -46,7 +61,7 @@ public:
CBool tryPop(UTask& task) { CBool tryPop(UTask& task) {
// 使raii锁线 // 使raii锁线
bool result = false; bool result = false;
if (lock_.tryLock()) {
if (lock_.try_lock()) {
if (!deque_.empty()) { if (!deque_.empty()) {
task = std::move(deque_.front()); // task = std::move(deque_.front()); //
deque_.pop_front(); deque_.pop_front();
@ -65,10 +80,9 @@ public:
* @param maxLocalBatchSize * @param maxLocalBatchSize
* @return * @return
*/ */
CBool tryPop(UTaskArrRef taskArr,
int maxLocalBatchSize) {
CBool tryPop(UTaskArrRef taskArr, int maxLocalBatchSize) {
bool result = false; bool result = false;
if (lock_.tryLock()) {
if (lock_.try_lock()) {
while (!deque_.empty() && maxLocalBatchSize--) { while (!deque_.empty() && maxLocalBatchSize--) {
taskArr.emplace_back(std::move(deque_.front())); taskArr.emplace_back(std::move(deque_.front()));
deque_.pop_front(); deque_.pop_front();
@ -88,7 +102,7 @@ public:
*/ */
CBool trySteal(UTask& task) { CBool trySteal(UTask& task) {
bool result = false; bool result = false;
if (lock_.tryLock()) {
if (lock_.try_lock()) {
if (!deque_.empty()) { if (!deque_.empty()) {
task = std::move(deque_.back()); // task = std::move(deque_.back()); //
deque_.pop_back(); deque_.pop_back();
@ -108,7 +122,7 @@ public:
*/ */
CBool trySteal(UTaskArrRef taskArr, int maxStealBatchSize) { CBool trySteal(UTaskArrRef taskArr, int maxStealBatchSize) {
bool result = false; bool result = false;
if (lock_.tryLock()) {
if (lock_.try_lock()) {
while (!deque_.empty() && maxStealBatchSize--) { while (!deque_.empty() && maxStealBatchSize--) {
taskArr.emplace_back(std::move(deque_.back())); taskArr.emplace_back(std::move(deque_.back()));
deque_.pop_back(); deque_.pop_back();
@ -126,7 +140,7 @@ public:
private: private:
std::deque<UTask> deque_; // std::deque<UTask> deque_; //
USpinLock lock_; //
std::mutex lock_; // deque_的锁
}; };
CGRAPH_NAMESPACE_END CGRAPH_NAMESPACE_END

+ 2
- 2
src/UtilsCtrl/ThreadPool/Task/UTaskGroup.h View File

@ -66,7 +66,7 @@ public:
* *
* @return * @return
*/ */
[[nodiscard]] CMSec getTtl() const {
CMSec getTtl() const {
return this->ttl_; return this->ttl_;
} }
@ -81,7 +81,7 @@ public:
* *
* @return * @return
*/ */
[[nodiscard]] CSize getSize() const {
CSize getSize() const {
auto size = task_arr_.size(); auto size = task_arr_.size();
return size; return size;
} }

+ 40
- 6
src/UtilsCtrl/ThreadPool/Thread/UThreadBase.h View File

@ -3,7 +3,7 @@
@Contact: chunel@foxmail.com @Contact: chunel@foxmail.com
@File: UThreadBase.h @File: UThreadBase.h
@Time: 2021/7/2 11:24 @Time: 2021/7/2 11:24
@Desc:
@Desc:
***************************/ ***************************/
#ifndef CGRAPH_UTHREADBASE_H #ifndef CGRAPH_UTHREADBASE_H
@ -118,6 +118,40 @@ protected:
total_task_num_ = 0; total_task_num_ = 0;
} }
/**
*
* @return
*/
virtual CVoid processTask() = 0;
/**
* task信息
*/
virtual CVoid processTasks() = 0;
/**
*
* @return
*/
CStatus loopProcess() {
CGRAPH_FUNCTION_BEGIN
CGRAPH_ASSERT_NOT_NULL(config_)
if (config_->batch_task_enable_) {
while (done_) {
processTasks(); //
}
} else {
while (done_) {
processTask(); //
}
}
CGRAPH_FUNCTION_END
}
/** /**
* 线windows平台使用 * 线windows平台使用
@ -138,7 +172,7 @@ protected:
sched_param param = { calcPriority(priority) }; sched_param param = { calcPriority(priority) };
int ret = pthread_setschedparam(handle, calcPolicy(policy), &param); int ret = pthread_setschedparam(handle, calcPolicy(policy), &param);
if (0 != ret) { if (0 != ret) {
CGRAPH_ECHO("warning : set thread sched param failed, error code is [%d]", ret);
CGRAPH_ECHO("warning : set thread sched param failed, system error code is [%d]", ret);
} }
#endif #endif
} }
@ -147,7 +181,7 @@ protected:
* 线linux系统 * 线linux系统
*/ */
CVoid setAffinity(int index) { CVoid setAffinity(int index) {
#ifdef __linux__
#if defined(__linux__) && !defined(__ANDROID__)
if (!config_->bind_cpu_enable_ || CGRAPH_CPU_NUM == 0 || index < 0) { if (!config_->bind_cpu_enable_ || CGRAPH_CPU_NUM == 0 || index < 0) {
return; return;
} }
@ -159,7 +193,7 @@ protected:
auto handle = thread_.native_handle(); auto handle = thread_.native_handle();
int ret = pthread_setaffinity_np(handle, sizeof(cpu_set_t), &mask); int ret = pthread_setaffinity_np(handle, sizeof(cpu_set_t), &mask);
if (0 != ret) { if (0 != ret) {
CGRAPH_ECHO("warning : set thread affinity failed, error code is [%d]", ret);
CGRAPH_ECHO("warning : set thread affinity failed, system error code is [%d]", ret);
} }
#endif #endif
} }
@ -172,7 +206,7 @@ private:
* @param policy * @param policy
* @return * @return
*/ */
[[nodiscard]] static int calcPolicy(int policy) {
static int calcPolicy(int policy) {
return (CGRAPH_THREAD_SCHED_OTHER == policy return (CGRAPH_THREAD_SCHED_OTHER == policy
|| CGRAPH_THREAD_SCHED_RR == policy || CGRAPH_THREAD_SCHED_RR == policy
|| CGRAPH_THREAD_SCHED_FIFO == policy) || CGRAPH_THREAD_SCHED_FIFO == policy)
@ -186,7 +220,7 @@ private:
* @param priority * @param priority
* @return * @return
*/ */
[[nodiscard]] static int calcPriority(int priority) {
static int calcPriority(int priority) {
return (priority >= CGRAPH_THREAD_MIN_PRIORITY return (priority >= CGRAPH_THREAD_MIN_PRIORITY
&& priority <= CGRAPH_THREAD_MAX_PRIORITY) && priority <= CGRAPH_THREAD_MAX_PRIORITY)
? priority : CGRAPH_THREAD_MIN_PRIORITY; ? priority : CGRAPH_THREAD_MIN_PRIORITY;

+ 56
- 38
src/UtilsCtrl/ThreadPool/Thread/UThreadPrimary.h View File

@ -17,6 +17,7 @@ class UThreadPrimary : public UThreadBase {
protected: protected:
explicit UThreadPrimary() { explicit UThreadPrimary() {
index_ = CGRAPH_SECONDARY_THREAD_COMMON_ID; index_ = CGRAPH_SECONDARY_THREAD_COMMON_ID;
steal_range_ = 0;
pool_threads_ = nullptr; pool_threads_ = nullptr;
type_ = CGRAPH_THREAD_TYPE_PRIMARY; type_ = CGRAPH_THREAD_TYPE_PRIMARY;
} }
@ -25,8 +26,10 @@ protected:
CStatus init() override { CStatus init() override {
CGRAPH_FUNCTION_BEGIN CGRAPH_FUNCTION_BEGIN
CGRAPH_ASSERT_INIT(false) CGRAPH_ASSERT_INIT(false)
CGRAPH_ASSERT_NOT_NULL(config_)
is_init_ = true; is_init_ = true;
steal_range_ = config_->calcStealRange();
thread_ = std::move(std::thread(&UThreadPrimary::run, this)); thread_ = std::move(std::thread(&UThreadPrimary::run, this));
setSchedParam(); setSchedParam();
setAffinity(index_); setAffinity(index_);
@ -47,9 +50,7 @@ protected:
UThreadPoolConfigPtr config) { UThreadPoolConfigPtr config) {
CGRAPH_FUNCTION_BEGIN CGRAPH_FUNCTION_BEGIN
CGRAPH_ASSERT_INIT(false) // CGRAPH_ASSERT_INIT(false) //
CGRAPH_ASSERT_NOT_NULL(poolTaskQueue)
CGRAPH_ASSERT_NOT_NULL(poolThreads)
CGRAPH_ASSERT_NOT_NULL(config)
CGRAPH_ASSERT_NOT_NULL(poolTaskQueue, poolThreads, config)
this->index_ = index; this->index_ = index;
this->pool_task_queue_ = poolTaskQueue; this->pool_task_queue_ = poolTaskQueue;
@ -67,7 +68,6 @@ protected:
CGRAPH_FUNCTION_BEGIN CGRAPH_FUNCTION_BEGIN
CGRAPH_ASSERT_INIT(true) CGRAPH_ASSERT_INIT(true)
CGRAPH_ASSERT_NOT_NULL(pool_threads_) CGRAPH_ASSERT_NOT_NULL(pool_threads_)
CGRAPH_ASSERT_NOT_NULL(config_)
/** /**
* 线primary线程为null都不可以执行 * 线primary线程为null都不可以执行
@ -81,38 +81,22 @@ protected:
CGRAPH_RETURN_ERROR_STATUS("primary thread is null") CGRAPH_RETURN_ERROR_STATUS("primary thread is null")
} }
if (config_->calcBatchTaskRatio()) {
while (done_) {
processTasks(); //
}
} else {
while (done_) {
processTask(); //
}
}
status = loopProcess();
CGRAPH_FUNCTION_END CGRAPH_FUNCTION_END
} }
/**
*
* @return
*/
CVoid processTask() {
CVoid processTask() override {
UTask task; UTask task;
if (popTask(task) || popPoolTask(task) || stealTask(task)) { if (popTask(task) || popPoolTask(task) || stealTask(task)) {
runTask(task); runTask(task);
} else { } else {
std::this_thread::yield();
std::this_thread::yield();
} }
} }
/**
* task信息
*/
CVoid processTasks() {
CVoid processTasks() override {
UTaskArr tasks; UTaskArr tasks;
if (popTask(tasks) || popPoolTask(tasks) || stealTask(tasks)) { if (popTask(tasks) || popPoolTask(tasks) || stealTask(tasks)) {
// 线/task // 线/task
@ -124,12 +108,25 @@ protected:
/** /**
* push到任一队列里yieldpush
* @param task
* @return
*/
CVoid pushTask(UTask&& task) {
while (!(primary_queue_.tryPush(std::move(task))
|| secondary_queue_.tryPush(std::move(task)))) {
std::this_thread::yield();
}
}
/**
* *
* @param task * @param task
* @return * @return
*/ */
bool popTask(UTaskRef task) { bool popTask(UTaskRef task) {
return work_stealing_queue_.tryPop(task);
return primary_queue_.tryPop(task) || secondary_queue_.tryPop(task);
} }
@ -139,7 +136,13 @@ protected:
* @return * @return
*/ */
bool popTask(UTaskArrRef tasks) { bool popTask(UTaskArrRef tasks) {
return work_stealing_queue_.tryPop(tasks, config_->max_local_batch_size_);
CBool result = primary_queue_.tryPop(tasks, config_->max_local_batch_size_);
auto leftSize = config_->max_local_batch_size_ - tasks.size();
if (leftSize > 0) {
//
result |= (secondary_queue_.tryPop(tasks, leftSize));
}
return result;
} }
@ -161,15 +164,16 @@ protected:
* primary线程中窃取 * primary线程中窃取
* primary线程数 * primary线程数
*/ */
int range = config_->calcStealRange();
for (int i = 0; i < range; i++) {
for (int i = 0; i < steal_range_; i++) {
/** /**
* 线thread中 * 线thread中
* true * true
* steal
*/ */
int curIndex = (index_ + i + 1) % config_->default_thread_size_; int curIndex = (index_ + i + 1) % config_->default_thread_size_;
if (nullptr != (*pool_threads_)[curIndex]
&& ((*pool_threads_)[curIndex])->work_stealing_queue_.trySteal(task)) {
if (likely((*pool_threads_)[curIndex])
&& (((*pool_threads_)[curIndex])->secondary_queue_.trySteal(task))
|| ((*pool_threads_)[curIndex])->primary_queue_.trySteal(task)) {
return true; return true;
} }
} }
@ -184,16 +188,28 @@ protected:
* @return * @return
*/ */
bool stealTask(UTaskArrRef tasks) { bool stealTask(UTaskArrRef tasks) {
if (unlikely(pool_threads_->size() < config_->default_thread_size_)) {
if (unlikely(pool_threads_->size() != config_->default_thread_size_)) {
return false; return false;
} }
int range = config_->calcStealRange();
for (int i = 0; i < range; i++) {
for (int i = 0; i < steal_range_; i++) {
int curIndex = (index_ + i + 1) % config_->default_thread_size_; int curIndex = (index_ + i + 1) % config_->default_thread_size_;
if (nullptr != (*pool_threads_)[curIndex]
&& ((*pool_threads_)[curIndex])->work_stealing_queue_.trySteal(tasks, config_->max_steal_batch_size_)) {
return true;
if (likely((*pool_threads_)[curIndex])) {
bool result = ((*pool_threads_)[curIndex])->secondary_queue_.trySteal(tasks, config_->max_steal_batch_size_);
auto leftSize = config_->max_steal_batch_size_ - tasks.size();
if (leftSize > 0) {
result |= ((*pool_threads_)[curIndex])->primary_queue_.trySteal(tasks, leftSize);
}
if (result) {
/**
*
* 线(secondaryprimary) x(=max_steal_batch_size_) task
* y(<=x) tasksteal的流程
* steal成功
*/
return true;
}
} }
} }
@ -201,8 +217,10 @@ protected:
} }
private: private:
int index_ {CGRAPH_SECONDARY_THREAD_COMMON_ID}; // 线index
UWorkStealingQueue work_stealing_queue_; //
int index_; // 线index
int steal_range_; //
UWorkStealingQueue primary_queue_; //
UWorkStealingQueue secondary_queue_; //
std::vector<UThreadPrimary *>* pool_threads_; // 线线 std::vector<UThreadPrimary *>* pool_threads_; // 线线
friend class UThreadPool; friend class UThreadPool;

+ 22
- 25
src/UtilsCtrl/ThreadPool/Thread/UThreadSecondary.h View File

@ -47,9 +47,7 @@ protected:
UThreadPoolConfigPtr config) { UThreadPoolConfigPtr config) {
CGRAPH_FUNCTION_BEGIN CGRAPH_FUNCTION_BEGIN
CGRAPH_ASSERT_INIT(false) // CGRAPH_ASSERT_INIT(false) //
CGRAPH_ASSERT_NOT_NULL(poolTaskQueue)
CGRAPH_ASSERT_NOT_NULL(poolPriorityTaskQueue)
CGRAPH_ASSERT_NOT_NULL(config)
CGRAPH_ASSERT_NOT_NULL(poolTaskQueue, poolPriorityTaskQueue, config)
this->pool_task_queue_ = poolTaskQueue; this->pool_task_queue_ = poolTaskQueue;
this->pool_priority_task_queue_ = poolPriorityTaskQueue; this->pool_priority_task_queue_ = poolPriorityTaskQueue;
@ -61,44 +59,43 @@ protected:
CStatus run() override { CStatus run() override {
CGRAPH_FUNCTION_BEGIN CGRAPH_FUNCTION_BEGIN
CGRAPH_ASSERT_INIT(true) CGRAPH_ASSERT_INIT(true)
CGRAPH_ASSERT_NOT_NULL(config_)
if (config_->calcBatchTaskRatio()) {
while (done_) {
processTasks(); //
}
} else {
while (done_) {
processTask(); //
}
}
status = loopProcess();
CGRAPH_FUNCTION_END CGRAPH_FUNCTION_END
} }
/**
* 线
*/
CVoid processTask() {
CVoid processTask() override {
UTask task; UTask task;
if (popPoolTask(task)) { if (popPoolTask(task)) {
runTask(task); runTask(task);
} else { } else {
std::this_thread::yield();
//
waitRunTask(config_->queue_emtpy_interval_);
} }
} }
/**
* n个任务
*/
CVoid processTasks() {
CVoid processTasks() override {
UTaskArr tasks; UTaskArr tasks;
if (popPoolTask(tasks)) { if (popPoolTask(tasks)) {
runTasks(tasks); runTasks(tasks);
} else { } else {
std::this_thread::yield();
waitRunTask(config_->queue_emtpy_interval_);
}
}
/**
*
* @param ms
* @return
* @notice cpu的占用率
*/
CVoid waitRunTask(CMSec ms) {
auto task = this->pool_task_queue_->popWithTimeout(ms);
if (nullptr != task) {
(*task)();
} }
} }
@ -115,7 +112,7 @@ protected:
cur_ttl_--; // 线ttl-1 cur_ttl_--; // 线ttl-1
} }
return cur_ttl_ <= 0;
return cur_ttl_ <= 0 && done_; // 线
} }
private: private:

+ 1
- 0
src/UtilsCtrl/ThreadPool/UThreadObject.h View File

@ -10,6 +10,7 @@
#define CGRAPH_UTHREADOBJECT_H #define CGRAPH_UTHREADOBJECT_H
#include "../UtilsObject.h" #include "../UtilsObject.h"
#include "UThreadPoolDefine.h"
CGRAPH_NAMESPACE_BEGIN CGRAPH_NAMESPACE_BEGIN

+ 41
- 21
src/UtilsCtrl/ThreadPool/UThreadPool.cpp View File

@ -13,15 +13,7 @@ CGRAPH_NAMESPACE_BEGIN
UThreadPool::UThreadPool(CBool autoInit, const UThreadPoolConfig& config) noexcept { UThreadPool::UThreadPool(CBool autoInit, const UThreadPoolConfig& config) noexcept {
cur_index_ = 0; cur_index_ = 0;
is_init_ = false; is_init_ = false;
input_task_num_ = 0;
this->setConfig(config); // setConfig 函数,用在 is_init_ 设定之后 this->setConfig(config); // setConfig 函数,用在 is_init_ 设定之后
is_monitor_ = config_.monitor_enable_; /** 根据参数设定,决定是否开启监控线程。默认开启 */
/**
* CGraph
* windows平台上Visual Studio(2017) UThreadPool .dll文件时
* https://github.com/ChunelFeng/CGraph/issues/17
*/
monitor_thread_ = std::move(std::thread(&UThreadPool::monitor, this));
if (autoInit) { if (autoInit) {
this->init(); this->init();
} }
@ -29,7 +21,7 @@ UThreadPool::UThreadPool(CBool autoInit, const UThreadPoolConfig& config) noexce
UThreadPool::~UThreadPool() { UThreadPool::~UThreadPool() {
is_monitor_ = false; // 在析构的时候,才释放监控线程。先释放监控线程,再释放其他的线程
this->config_.monitor_enable_ = false; // 在析构的时候,才释放监控线程。先释放监控线程,再释放其他的线程
if (monitor_thread_.joinable()) { if (monitor_thread_.joinable()) {
monitor_thread_.join(); monitor_thread_.join();
} }
@ -53,6 +45,7 @@ CStatus UThreadPool::init() {
CGRAPH_FUNCTION_END CGRAPH_FUNCTION_END
} }
monitor_thread_ = std::move(std::thread(&UThreadPool::monitor, this));
thread_record_map_.clear(); thread_record_map_.clear();
primary_threads_.reserve(config_.default_thread_size_); primary_threads_.reserve(config_.default_thread_size_);
for (int i = 0; i < config_.default_thread_size_; i++) { for (int i = 0; i < config_.default_thread_size_; i++) {
@ -89,16 +82,16 @@ CStatus UThreadPool::submit(const UTaskGroup& taskGroup, CMSec ttl) {
} }
// 计算最终运行时间信息 // 计算最终运行时间信息
auto deadline = std::chrono::system_clock::now()
auto deadline = std::chrono::steady_clock::now()
+ std::chrono::milliseconds(std::min(taskGroup.getTtl(), ttl)); + std::chrono::milliseconds(std::min(taskGroup.getTtl(), ttl));
for (auto& fut : futures) { for (auto& fut : futures) {
const auto& futStatus = fut.wait_until(deadline); const auto& futStatus = fut.wait_until(deadline);
switch (futStatus) { switch (futStatus) {
case std::future_status::ready: break; // 正常情况,直接返回了 case std::future_status::ready: break; // 正常情况,直接返回了
case std::future_status::timeout: status += CStatus("thread status timeout"); break;
case std::future_status::deferred: status += CStatus("thread status deferred"); break;
default: status += CStatus("thread status unknown");
case std::future_status::timeout: status += CErrStatus("thread status timeout"); break;
case std::future_status::deferred: status += CErrStatus("thread status deferred"); break;
default: status += CErrStatus("thread status unknown");
} }
} }
@ -116,7 +109,7 @@ CStatus UThreadPool::submit(CGRAPH_DEFAULT_CONST_FUNCTION_REF func, CMSec ttl,
} }
CIndex UThreadPool::getThreadNum(CSize tid) {
CIndex UThreadPool::getThreadIndex(CSize tid) {
int threadNum = CGRAPH_SECONDARY_THREAD_COMMON_ID; int threadNum = CGRAPH_SECONDARY_THREAD_COMMON_ID;
auto result = thread_record_map_.find(tid); auto result = thread_record_map_.find(tid);
if (result != thread_record_map_.end()) { if (result != thread_record_map_.end()) {
@ -164,11 +157,35 @@ CStatus UThreadPool::destroy() {
} }
CIndex UThreadPool::dispatch(CIndex origIndex) {
if (unlikely(config_.fair_lock_enable_)) {
return CGRAPH_DEFAULT_TASK_STRATEGY; // 如果开启fair lock,则全部写入 pool的queue中,依次执行
CBool UThreadPool::isInit() const {
return is_init_;
}
CStatus UThreadPool::releaseSecondaryThread(CInt size) {
CGRAPH_FUNCTION_BEGIN
// 先将所有已经结束的,给删掉
CGRAPH_LOCK_GUARD lock(st_mutex_);
for (auto iter = secondary_threads_.begin(); iter != secondary_threads_.end(); ) {
!(*iter)->done_ ? secondary_threads_.erase(iter++) : iter++;
} }
CGRAPH_RETURN_ERROR_STATUS_BY_CONDITION((size > secondary_threads_.size()), \
"cannot release [" + std::to_string(size) + "] secondary thread," \
+ "only [" + std::to_string(secondary_threads_.size()) + "] left.")
// 再标记几个需要删除的信息
for (auto iter = secondary_threads_.begin();
iter != secondary_threads_.end() && size-- > 0; ) {
(*iter)->done_ = false;
iter++;
}
CGRAPH_FUNCTION_END
}
CIndex UThreadPool::dispatch(CIndex origIndex) {
CIndex realIndex = 0; CIndex realIndex = 0;
if (CGRAPH_DEFAULT_TASK_STRATEGY == origIndex) { if (CGRAPH_DEFAULT_TASK_STRATEGY == origIndex) {
/** /**
@ -192,6 +209,8 @@ CStatus UThreadPool::createSecondaryThread(CInt size) {
int leftSize = (int)(config_.max_thread_size_ - config_.default_thread_size_ - secondary_threads_.size()); int leftSize = (int)(config_.max_thread_size_ - config_.default_thread_size_ - secondary_threads_.size());
int realSize = std::min(size, leftSize); // 使用 realSize 来确保所有的线程数量之和,不会超过设定max值 int realSize = std::min(size, leftSize); // 使用 realSize 来确保所有的线程数量之和,不会超过设定max值
CGRAPH_LOCK_GUARD lock(st_mutex_);
for (int i = 0; i < realSize; i++) { for (int i = 0; i < realSize; i++) {
auto ptr = CGRAPH_MAKE_UNIQUE_COBJECT(UThreadSecondary) auto ptr = CGRAPH_MAKE_UNIQUE_COBJECT(UThreadSecondary)
ptr->setThreadPoolInfo(&task_queue_, &priority_task_queue_, &config_); ptr->setThreadPoolInfo(&task_queue_, &priority_task_queue_, &config_);
@ -204,21 +223,22 @@ CStatus UThreadPool::createSecondaryThread(CInt size) {
CVoid UThreadPool::monitor() { CVoid UThreadPool::monitor() {
while (is_monitor_) {
while (is_monitor_ && !is_init_) {
while (config_.monitor_enable_) {
while (config_.monitor_enable_ && !is_init_) {
// 如果没有init,则一直处于空跑状态 // 如果没有init,则一直处于空跑状态
CGRAPH_SLEEP_SECOND(1) CGRAPH_SLEEP_SECOND(1)
} }
int span = config_.monitor_span_; int span = config_.monitor_span_;
while (is_monitor_ && is_init_ && span--) {
while (config_.monitor_enable_ && is_init_ && span--) {
CGRAPH_SLEEP_SECOND(1) // 保证可以快速退出 CGRAPH_SLEEP_SECOND(1) // 保证可以快速退出
} }
// 如果 primary线程都在执行,则表示忙碌 // 如果 primary线程都在执行,则表示忙碌
bool busy = std::all_of(primary_threads_.begin(), primary_threads_.end(),
bool busy = !primary_threads_.empty() && std::all_of(primary_threads_.begin(), primary_threads_.end(),
[](UThreadPrimaryPtr ptr) { return nullptr != ptr && ptr->is_running_; }); [](UThreadPrimaryPtr ptr) { return nullptr != ptr && ptr->is_running_; });
CGRAPH_LOCK_GUARD lock(st_mutex_);
// 如果忙碌或者priority_task_queue_中有任务,则需要添加 secondary线程 // 如果忙碌或者priority_task_queue_中有任务,则需要添加 secondary线程
if (busy || !priority_task_queue_.empty()) { if (busy || !priority_task_queue_.empty()) {
createSecondaryThread(1); createSecondaryThread(1);

+ 21
- 10
src/UtilsCtrl/ThreadPool/UThreadPool.h View File

@ -78,7 +78,7 @@ public:
template<typename FunctionType> template<typename FunctionType>
auto commitWithPriority(const FunctionType& func, auto commitWithPriority(const FunctionType& func,
int priority) int priority)
-> std::future<decltype(std::declval<FunctionType>()())>;
-> std::future<decltype(std::declval<FunctionType>()())>;;
/** /**
* *
@ -102,12 +102,12 @@ public:
CGRAPH_CALLBACK_CONST_FUNCTION_REF onFinished = nullptr); CGRAPH_CALLBACK_CONST_FUNCTION_REF onFinished = nullptr);
/** /**
* 线id信息线num信息
* 线id信息线index信息
* @param tid * @param tid
* @return * @return
* @notice 线-1 * @notice 线-1
*/ */
CIndex getThreadNum(CSize tid);
CIndex getThreadIndex(CSize tid);
/** /**
* 线 * 线
@ -115,14 +115,11 @@ public:
*/ */
CStatus destroy() final; CStatus destroy() final;
protected:
/** /**
*
* @param origIndex
* 线
* @return * @return
*/ */
virtual CIndex dispatch(CIndex origIndex);
CBool isInit() const;
/** /**
* 线线 * 线线
@ -132,6 +129,21 @@ protected:
CStatus createSecondaryThread(CInt size); CStatus createSecondaryThread(CInt size);
/** /**
* 线
* @param size
* @return
*/
CStatus releaseSecondaryThread(CInt size);
protected:
/**
*
* @param origIndex
* @return
*/
virtual CIndex dispatch(CIndex origIndex);
/**
* 线线线 * 线线线
* / secondary类型线程生效 * / secondary类型线程生效
*/ */
@ -141,9 +153,7 @@ protected:
private: private:
CBool is_init_ { false }; // CBool is_init_ { false }; //
CBool is_monitor_ { true }; //
CInt cur_index_ = 0; // 线 CInt cur_index_ = 0; // 线
CULong input_task_num_ = 0; //
UAtomicQueue<UTask> task_queue_; // UAtomicQueue<UTask> task_queue_; //
UAtomicPriorityQueue<UTask> priority_task_queue_; // 线 UAtomicPriorityQueue<UTask> priority_task_queue_; // 线
std::vector<UThreadPrimaryPtr> primary_threads_; // 线 std::vector<UThreadPrimaryPtr> primary_threads_; // 线
@ -151,6 +161,7 @@ private:
UThreadPoolConfig config_; // 线 UThreadPoolConfig config_; // 线
std::thread monitor_thread_; // 线 std::thread monitor_thread_; // 线
std::map<CSize, int> thread_record_map_; // 线 std::map<CSize, int> thread_record_map_; // 线
std::mutex st_mutex_; // 线mutex信息
}; };
using UThreadPoolPtr = UThreadPool *; using UThreadPoolPtr = UThreadPool *;

+ 2
- 4
src/UtilsCtrl/ThreadPool/UThreadPool.inl View File

@ -24,7 +24,7 @@ auto UThreadPool::commit(const FunctionType& func, CIndex index)
CIndex realIndex = dispatch(index); CIndex realIndex = dispatch(index);
if (realIndex >= 0 && realIndex < config_.default_thread_size_) { if (realIndex >= 0 && realIndex < config_.default_thread_size_) {
// 如果返回的结果,在主线程数量之间,则放到主线程的queue中执行 // 如果返回的结果,在主线程数量之间,则放到主线程的queue中执行
primary_threads_[realIndex]->work_stealing_queue_.push(std::move(task));
primary_threads_[realIndex]->pushTask(std::move(task));
} else if (CGRAPH_LONG_TIME_TASK_STRATEGY == realIndex) { } else if (CGRAPH_LONG_TIME_TASK_STRATEGY == realIndex) {
/** /**
* 如果是长时间任务,则交给特定的任务队列,仅由辅助线程处理 * 如果是长时间任务,则交给特定的任务队列,仅由辅助线程处理
@ -36,7 +36,6 @@ auto UThreadPool::commit(const FunctionType& func, CIndex index)
// 返回其他结果,放到pool的queue中执行 // 返回其他结果,放到pool的queue中执行
task_queue_.push(std::move(task)); task_queue_.push(std::move(task));
} }
input_task_num_++; // 计数
return result; return result;
} }
@ -54,10 +53,9 @@ auto UThreadPool::commitWithPriority(const FunctionType& func, int priority)
} }
priority_task_queue_.push(std::move(task), priority); priority_task_queue_.push(std::move(task), priority);
input_task_num_++;
return result; return result;
} }
CGRAPH_NAMESPACE_END CGRAPH_NAMESPACE_END
#endif // CGRAPH_UTHREADPOOL_INL
#endif // CGRAPH_UTHREADPOOL_INL

+ 18
- 14
src/UtilsCtrl/ThreadPool/UThreadPoolConfig.h View File

@ -14,7 +14,7 @@
CGRAPH_NAMESPACE_BEGIN CGRAPH_NAMESPACE_BEGIN
struct UThreadPoolConfig : public UThreadObject {
struct UThreadPoolConfig : public CStruct {
/** 具体值含义,参考UThreadPoolDefine.h文件 */ /** 具体值含义,参考UThreadPoolDefine.h文件 */
int default_thread_size_ = CGRAPH_DEFAULT_THREAD_SIZE; int default_thread_size_ = CGRAPH_DEFAULT_THREAD_SIZE;
int secondary_thread_size_ = CGRAPH_SECONDARY_THREAD_SIZE; int secondary_thread_size_ = CGRAPH_SECONDARY_THREAD_SIZE;
@ -25,37 +25,41 @@ struct UThreadPoolConfig : public UThreadObject {
int max_steal_batch_size_ = CGRAPH_MAX_STEAL_BATCH_SIZE; int max_steal_batch_size_ = CGRAPH_MAX_STEAL_BATCH_SIZE;
int secondary_thread_ttl_ = CGRAPH_SECONDARY_THREAD_TTL; int secondary_thread_ttl_ = CGRAPH_SECONDARY_THREAD_TTL;
int monitor_span_ = CGRAPH_MONITOR_SPAN; int monitor_span_ = CGRAPH_MONITOR_SPAN;
CMSec queue_emtpy_interval_ = CGRAPH_QUEUE_EMPTY_INTERVAL;
int primary_thread_policy_ = CGRAPH_PRIMARY_THREAD_POLICY; int primary_thread_policy_ = CGRAPH_PRIMARY_THREAD_POLICY;
int secondary_thread_policy_ = CGRAPH_SECONDARY_THREAD_POLICY; int secondary_thread_policy_ = CGRAPH_SECONDARY_THREAD_POLICY;
int primary_thread_priority_ = CGRAPH_PRIMARY_THREAD_PRIORITY; int primary_thread_priority_ = CGRAPH_PRIMARY_THREAD_PRIORITY;
int secondary_thread_priority_ = CGRAPH_SECONDARY_THREAD_PRIORITY; int secondary_thread_priority_ = CGRAPH_SECONDARY_THREAD_PRIORITY;
bool bind_cpu_enable_ = CGRAPH_BIND_CPU_ENABLE; bool bind_cpu_enable_ = CGRAPH_BIND_CPU_ENABLE;
bool batch_task_enable_ = CGRAPH_BATCH_TASK_ENABLE; bool batch_task_enable_ = CGRAPH_BATCH_TASK_ENABLE;
bool fair_lock_enable_ = CGRAPH_FAIR_LOCK_ENABLE;
bool monitor_enable_ = CGRAPH_MONITOR_ENABLE; bool monitor_enable_ = CGRAPH_MONITOR_ENABLE;
CStatus check() const {
CGRAPH_FUNCTION_BEGIN
if (default_thread_size_ < 0 || secondary_thread_size_ < 0) {
CGRAPH_RETURN_ERROR_STATUS("thread size cannot less than 0")
}
if (default_thread_size_ + secondary_thread_size_ > max_thread_size_) {
CGRAPH_RETURN_ERROR_STATUS("max thread size is less than default + secondary thread")
}
if (monitor_enable_ && monitor_span_ <= 0) {
CGRAPH_RETURN_ERROR_STATUS("monitor span cannot less than 0")
}
CGRAPH_FUNCTION_END
}
protected: protected:
/** /**
* 线-1 * 线-1
* @return * @return
*/ */
[[nodiscard]] int calcStealRange() const {
int calcStealRange() const {
int range = std::min(this->max_task_steal_range_, this->default_thread_size_ - 1); int range = std::min(this->max_task_steal_range_, this->default_thread_size_ - 1);
return range; return range;
} }
/**
*
*
* @return
*/
[[nodiscard]] bool calcBatchTaskRatio() const {
bool ratio = (this->batch_task_enable_) && (!this->fair_lock_enable_);
return ratio;
}
friend class UThreadPrimary; friend class UThreadPrimary;
friend class UThreadSecondary; friend class UThreadSecondary;
}; };

+ 14
- 24
src/UtilsCtrl/ThreadPool/UThreadPoolDefine.h View File

@ -21,17 +21,6 @@
CGRAPH_NAMESPACE_BEGIN CGRAPH_NAMESPACE_BEGIN
#if __cplusplus >= 201703L
using CGRAPH_READ_LOCK = std::shared_lock<std::shared_mutex>;
using CGRAPH_WRITE_LOCK = std::unique_lock<std::shared_mutex>;
#else
using CGRAPH_READ_LOCK = std::unique_lock<std::mutex>; // C++14使mutex替代
using CGRAPH_WRITE_LOCK = std::unique_lock<std::mutex>;
#endif
using CGRAPH_LOCK_GUARD = std::lock_guard<std::mutex>;
using CGRAPH_UNIQUE_LOCK = std::unique_lock<std::mutex>;
static const int CGRAPH_CPU_NUM = (int)std::thread::hardware_concurrency(); static const int CGRAPH_CPU_NUM = (int)std::thread::hardware_concurrency();
static const int CGRAPH_THREAD_TYPE_PRIMARY = 1; static const int CGRAPH_THREAD_TYPE_PRIMARY = 1;
static const int CGRAPH_THREAD_TYPE_SECONDARY = 2; static const int CGRAPH_THREAD_TYPE_SECONDARY = 2;
@ -45,37 +34,38 @@ static const int CGRAPH_THREAD_SCHED_OTHER = 0;
static const int CGRAPH_THREAD_SCHED_RR = 0; static const int CGRAPH_THREAD_SCHED_RR = 0;
static const int CGRAPH_THREAD_SCHED_FIFO = 0; static const int CGRAPH_THREAD_SCHED_FIFO = 0;
#endif #endif
static const int CGRAPH_THREAD_MIN_PRIORITY = 0; // 线
static const int CGRAPH_THREAD_MAX_PRIORITY = 99; // 线
static const CMSec CGRAPH_MAX_BLOCK_TTL = 10000000; // ms
static const CInt CGRAPH_THREAD_MIN_PRIORITY = 0; // 线
static const CInt CGRAPH_THREAD_MAX_PRIORITY = 99; // 线
static const CMSec CGRAPH_MAX_BLOCK_TTL = 1999999999; // ms
static const CUint CGRAPH_DEFAULT_RINGBUFFER_SIZE = 1024; // static const CUint CGRAPH_DEFAULT_RINGBUFFER_SIZE = 1024; //
const static CIndex CGRAPH_SECONDARY_THREAD_COMMON_ID = -1; // 线id标识
static const CIndex CGRAPH_SECONDARY_THREAD_COMMON_ID = -1; // 线id标识
static const CInt CGRAPH_DEFAULT_PRIORITY = 0; //
static const int CGRAPH_DEFAULT_TASK_STRATEGY = -1; // 线 static const int CGRAPH_DEFAULT_TASK_STRATEGY = -1; // 线
static const int CGRAPH_POOL_TASK_STRATEGY = -2; // pool中的队列的调度策略
static const int CGRAPH_LONG_TIME_TASK_STRATEGY = -101; // static const int CGRAPH_LONG_TIME_TASK_STRATEGY = -101; //
static const int CGRAPH_REGION_TASK_STRATEGY = -102; // region的调度策略
static const int CGRAPH_EVENT_TASK_STRATEGY = -103; // event的调度策略
/** /**
* 线 * 线
*/ */
static const int CGRAPH_DEFAULT_THREAD_SIZE = 8; // 线
static const int CGRAPH_SECONDARY_THREAD_SIZE = 0; // 线
static const int CGRAPH_MAX_THREAD_SIZE = (CGRAPH_DEFAULT_THREAD_SIZE * 2) + 1; // 线
static const int CGRAPH_DEFAULT_THREAD_SIZE = 0; // 线
static const int CGRAPH_SECONDARY_THREAD_SIZE = 8; // 线
static const int CGRAPH_MAX_THREAD_SIZE = 16; // 线
static const int CGRAPH_MAX_TASK_STEAL_RANGE = 2; // static const int CGRAPH_MAX_TASK_STEAL_RANGE = 2; //
static const bool CGRAPH_BATCH_TASK_ENABLE = false; // static const bool CGRAPH_BATCH_TASK_ENABLE = false; //
static const int CGRAPH_MAX_LOCAL_BATCH_SIZE = 2; // static const int CGRAPH_MAX_LOCAL_BATCH_SIZE = 2; //
static const int CGRAPH_MAX_POOL_BATCH_SIZE = 2; // static const int CGRAPH_MAX_POOL_BATCH_SIZE = 2; //
static const int CGRAPH_MAX_STEAL_BATCH_SIZE = 2; // static const int CGRAPH_MAX_STEAL_BATCH_SIZE = 2; //
static const bool CGRAPH_FAIR_LOCK_ENABLE = false; // CGRAPH_BATCH_TASK_ENABLE无效
static const int CGRAPH_SECONDARY_THREAD_TTL = 10; // 线ttls static const int CGRAPH_SECONDARY_THREAD_TTL = 10; // 线ttls
static const bool CGRAPH_MONITOR_ENABLE = true; // 线
static const bool CGRAPH_MONITOR_ENABLE = false; //
static const int CGRAPH_MONITOR_SPAN = 5; // 线s static const int CGRAPH_MONITOR_SPAN = 5; // 线s
static const CMSec CGRAPH_QUEUE_EMPTY_INTERVAL = 3; // 线ms
static const bool CGRAPH_BIND_CPU_ENABLE = false; // cpu模式线 static const bool CGRAPH_BIND_CPU_ENABLE = false; // cpu模式线
static const int CGRAPH_PRIMARY_THREAD_POLICY = CGRAPH_THREAD_SCHED_OTHER; // 线 static const int CGRAPH_PRIMARY_THREAD_POLICY = CGRAPH_THREAD_SCHED_OTHER; // 线
static const int CGRAPH_SECONDARY_THREAD_POLICY = CGRAPH_THREAD_SCHED_OTHER; // 线 static const int CGRAPH_SECONDARY_THREAD_POLICY = CGRAPH_THREAD_SCHED_OTHER; // 线
static const int CGRAPH_PRIMARY_THREAD_PRIORITY = CGRAPH_THREAD_MIN_PRIORITY; // 线0~99
static const int CGRAPH_SECONDARY_THREAD_PRIORITY = CGRAPH_THREAD_MIN_PRIORITY; // 线0~99
static const int CGRAPH_PRIMARY_THREAD_PRIORITY = CGRAPH_THREAD_MIN_PRIORITY; // 线0~99使
static const int CGRAPH_SECONDARY_THREAD_PRIORITY = CGRAPH_THREAD_MIN_PRIORITY; // 线
CGRAPH_NAMESPACE_END CGRAPH_NAMESPACE_END

+ 28
- 6
src/UtilsCtrl/UAllocator.h View File

@ -22,18 +22,25 @@ CGRAPH_NAMESPACE_BEGIN
class UAllocator : public CObject { class UAllocator : public CObject {
public: public:
/** /**
*
* CObject
* @tparam T * @tparam T
* @return * @return
*/ */
template<typename T, template<typename T,
c_enable_if_t<std::is_base_of<CObject, T>::value, int> = 0> c_enable_if_t<std::is_base_of<CObject, T>::value, int> = 0>
static T* safeMallocCObject() { static T* safeMallocCObject() {
T* ptr = nullptr;
while (!ptr) {
ptr = new(std::nothrow) T();
}
return ptr;
return safeMalloc<T>();
}
/**
* CStruct
* @tparam T
* @return
*/
template<typename T,
c_enable_if_t<std::is_base_of<CStruct, T>::value, int> = 0>
static T* safeMallocCStruct() {
return safeMalloc<T>();
} }
/** /**
@ -64,6 +71,21 @@ public:
static std::unique_ptr<T> makeUniqueCObject() { static std::unique_ptr<T> makeUniqueCObject() {
return c_make_unique<T>(); return c_make_unique<T>();
} }
private:
/**
* T类型的对象
* @tparam T
* @return
*/
template<class T>
static T* safeMalloc() {
T* ptr = nullptr;
while (!ptr) {
ptr = new(std::nothrow) T();
}
return ptr;
}
}; };

+ 81
- 33
src/UtilsCtrl/UtilsDefine.h View File

@ -12,6 +12,12 @@
#include <iostream> #include <iostream>
#include <string> #include <string>
#if __cplusplus >= 201703L
#include <shared_mutex>
#else
#include <mutex>
#endif
#include "../CBasic/CBasicInclude.h" #include "../CBasic/CBasicInclude.h"
#include "UAllocator.h" #include "UAllocator.h"
#include "UtilsFunction.h" #include "UtilsFunction.h"
@ -26,60 +32,102 @@ CGRAPH_NAMESPACE_BEGIN
#define unlikely #define unlikely
#endif #endif
/* 判断传入的指针信息是否为空 */
#define CGRAPH_ASSERT_NOT_NULL(ptr) \
if (unlikely(nullptr == (ptr))) { \
return CStatus("input is nullptr"); \
} \
using CGRAPH_LOCK_GUARD = std::lock_guard<std::mutex>;
using CGRAPH_UNIQUE_LOCK = std::unique_lock<std::mutex>;
#if __cplusplus >= 201703L
using CGRAPH_READ_LOCK = std::shared_lock<std::shared_mutex>;
using CGRAPH_WRITE_LOCK = std::unique_lock<std::shared_mutex>;
#else
using CGRAPH_READ_LOCK = CGRAPH_LOCK_GUARD; // C++14使mutex替代
using CGRAPH_WRITE_LOCK = CGRAPH_LOCK_GUARD;
#endif
#define CGRAPH_ASSERT_NOT_NULL_RETURN_NULL(ptr) \
if (unlikely(nullptr == (ptr))) { \
return nullptr; \
} \
template<typename T>
CStatus __ASSERT_NOT_NULL(T t) {
return (unlikely(nullptr == t))
? CErrStatus(CGRAPH_INPUT_IS_NULL)
: CStatus();
}
#define CGRAPH_ASSERT_NOT_NULL_THROW_ERROR(ptr) \
if (unlikely(nullptr == (ptr))) { \
CGRAPH_THROW_EXCEPTION("input is null") \
template<typename T, typename... Args>
CStatus __ASSERT_NOT_NULL(T t, Args... args) {
if (unlikely(t == nullptr)) {
return __ASSERT_NOT_NULL(t);
} }
return __ASSERT_NOT_NULL(args...);
}
template<typename T>
CVoid __ASSERT_NOT_NULL_THROW_EXCEPTION(T t) {
if (unlikely(nullptr == t)) {
CGRAPH_THROW_EXCEPTION("[CException] " + CGRAPH_INPUT_IS_NULL)
}
}
template<typename T, typename... Args>
CVoid __ASSERT_NOT_NULL_THROW_EXCEPTION(T t, Args... args) {
if (unlikely(nullptr == t)) {
__ASSERT_NOT_NULL_THROW_EXCEPTION(t);
}
__ASSERT_NOT_NULL_THROW_EXCEPTION(args...);
}
/** 判断传入的多个指针信息,是否为空 */
#define CGRAPH_ASSERT_NOT_NULL(ptr, ...) \
{ \
const CStatus& __cur_status__ = __ASSERT_NOT_NULL(ptr, ##__VA_ARGS__); \
if (unlikely(__cur_status__.isErr())) { return __cur_status__; } \
} \
/** 判断传入的多个指针,是否为空。如果为空,则抛出异常信息 */
#define CGRAPH_ASSERT_NOT_NULL_THROW_ERROR(ptr, ...) \
__ASSERT_NOT_NULL_THROW_EXCEPTION(ptr, ##__VA_ARGS__); \
/* 判断函数流程是否可以继续 */ /* 判断函数流程是否可以继续 */
static std::mutex g_check_status_mtx; static std::mutex g_check_status_mtx;
#define CGRAPH_FUNCTION_CHECK_STATUS \ #define CGRAPH_FUNCTION_CHECK_STATUS \
if (unlikely(status.isErr())) { \ if (unlikely(status.isErr())) { \
std::lock_guard<std::mutex> lock{ g_check_status_mtx }; \
CGRAPH_ECHO("%s | %s | line = [%d], errorCode = [%d], errorInfo = [%s].", \
__FILE__, __FUNCTION__, __LINE__, status.getCode(), status.getInfo().c_str()); \
if (status.isCrash()) { throw CException(status.getInfo()); } \
CGRAPH_LOCK_GUARD lock{ g_check_status_mtx }; \
CGRAPH_ECHO("%s, errorCode = [%d], errorInfo = [%s].", \
status.getLocate().c_str(), status.getCode(), status.getInfo().c_str()); \
return status; \ return status; \
} \ } \
/* 删除资源信息 */ /* 删除资源信息 */
#define CGRAPH_DELETE_PTR(ptr) \
if (unlikely((ptr) != nullptr)) { \
delete (ptr); \
(ptr) = nullptr; \
} \
#define CGRAPH_DELETE_PTR(ptr) \
if (unlikely((ptr) != nullptr)) { \
delete (ptr); \
(ptr) = nullptr; \
} \
#define CGRAPH_ASSERT_INIT(isInit) \
if (unlikely((isInit) != is_init_)) { \
return CStatus("init status is not suitable"); \
} \
#define CGRAPH_ASSERT_INIT(isInit) \
if (unlikely((isInit) != is_init_)) { \
CGRAPH_RETURN_ERROR_STATUS("init status is not suitable") \
} \
#define CGRAPH_ASSERT_INIT_RETURN_NULL(isInit) \
if (unlikely((isInit) != is_init_)) { \
return nullptr; \
} \
#define CGRAPH_ASSERT_INIT_THROW_ERROR(isInit) \
if (unlikely((isInit) != is_init_)) { \
CGRAPH_THROW_EXCEPTION("[CException] init status is not suitable") \
} \
#define CGRAPH_CHECK_STATUS_RETURN_THIS_OR_NULL \
return status.isOK() ? this : nullptr; \
#define CGRAPH_SLEEP_MILLISECOND(ms) \
std::this_thread::sleep_for(std::chrono::milliseconds(ms)); \
#define CGRAPH_CHECK_STATUS_RETURN_THIS_OR_NULL \
return status.isOK() ? this : nullptr; \
#define CGRAPH_SLEEP_SECOND(s) \ #define CGRAPH_SLEEP_SECOND(s) \
std::this_thread::sleep_for(std::chrono::seconds(s)); \ std::this_thread::sleep_for(std::chrono::seconds(s)); \
#define CGRAPH_SLEEP_MILLISECOND(ms) \
std::this_thread::sleep_for(std::chrono::milliseconds(ms)); \
CGRAPH_NAMESPACE_END CGRAPH_NAMESPACE_END
#endif //CGRAPH_UTILSDEFINE_H #endif //CGRAPH_UTILSDEFINE_H

+ 27
- 21
src/UtilsCtrl/UtilsFunction.h View File

@ -11,6 +11,7 @@
#include <mutex> #include <mutex>
#include <chrono> #include <chrono>
#include <iomanip>
#include <ctime> #include <ctime>
#include <cstdarg> #include <cstdarg>
#include <algorithm> #include <algorithm>
@ -32,28 +33,11 @@ inline CVoid CGRAPH_ECHO(const char *cmd, ...) {
#endif #endif
std::lock_guard<std::mutex> lock{ g_echo_mtx }; std::lock_guard<std::mutex> lock{ g_echo_mtx };
#ifndef _WIN32
// windows系统
auto now = std::chrono::system_clock::now(); auto now = std::chrono::system_clock::now();
//
uint64_t disMs = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count()
- std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count() * 1000;
time_t tt = std::chrono::system_clock::to_time_t(now);
auto localTime = localtime(&tt);
char strTime[32] = { 0 };
sprintf(strTime, "[%04d-%02d-%02d %02d:%02d:%02d.%03d]", localTime->tm_year + 1900,
localTime->tm_mon + 1, localTime->tm_mday, localTime->tm_hour,
localTime->tm_min, localTime->tm_sec, (int)disMs);
std::cout << "[CGraph] " << strTime << " ";
#else
// windows系统
time_t curTime;
time(&curTime);
std::string ct = ctime(&curTime);
std::cout << "[CGraph] ["
<< ct.assign(ct.begin(), ct.end()-1) // \n信息
<< "] ";
#endif
auto time = std::chrono::system_clock::to_time_t(now);
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count() % 1000;
std::cout << "[" << std::put_time(std::localtime(&time), "%Y-%m-%d %H:%M:%S.") \
<< std::setfill('0') << std::setw(3) << ms << "] ";
va_list args; va_list args;
va_start(args, cmd); va_start(args, cmd);
@ -64,6 +48,28 @@ inline CVoid CGRAPH_ECHO(const char *cmd, ...) {
/** /**
* ms信息
* @return
*/
inline CMSec CGRAPH_GET_CURRENT_MS() {
//
return (CMSec)std::chrono::time_point_cast<std::chrono::milliseconds> \
(std::chrono::steady_clock::now()).time_since_epoch().count();
}
/**
* ms信息()
* @return
*/
inline CFMSec CGRAPH_GET_CURRENT_ACCURATE_MS() {
//
return (CFMSec)std::chrono::time_point_cast<std::chrono::microseconds> \
(std::chrono::steady_clock::now()).time_since_epoch().count() / (CFMSec)1000.0;
}
/**
* *
* @tparam T (std::vector<int>) * @tparam T (std::vector<int>)
* @param container * @param container

Loading…
Cancel
Save