mirror of
https://gitee.com/TarsCloud/TarsCpp.git
synced 2024-12-22 22:16:38 +08:00
fix tc_common double bug
tc_common add time function, tc_autoptr use std::atomic
This commit is contained in:
parent
4385398f84
commit
43103f10fd
@ -1 +1 @@
|
||||
Subproject commit 48a520fe192308217a4529438011d158da60f538
|
||||
Subproject commit 838bcfada355301f6832c6c88c2d180ac6a25d5f
|
2
unittest
2
unittest
@ -1 +1 @@
|
||||
Subproject commit 5f46a694b925be139aa16274a00b7d5ad611004c
|
||||
Subproject commit e663956b02aa72f9491f759263da89d62502f7e8
|
@ -17,17 +17,13 @@
|
||||
#ifndef __TC_AUTOPTR_H
|
||||
#define __TC_AUTOPTR_H
|
||||
|
||||
#include "util/tc_atomic.h"
|
||||
#include "util/tc_ex.h"
|
||||
#include "util/tc_atomic.h"
|
||||
#include <atomic>
|
||||
#include <typeinfo>
|
||||
|
||||
namespace tars
|
||||
{
|
||||
///////////////////////////////////////////////////////
|
||||
/**
|
||||
* @file tc_autoptr.h
|
||||
* @brief 智能指针类(智能指针不能相互引用, 否则内存泄漏).
|
||||
*/
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @brief 空指针异常
|
||||
@ -43,22 +39,17 @@ struct TC_AutoPtrNull_Exception : public TC_Exception
|
||||
*
|
||||
* 所有需要智能指针支持的类都需要从该对象继承,
|
||||
*
|
||||
* 内部采用引用计数TC_Atomic实现,对象可以放在容器中;
|
||||
*/
|
||||
template<class T>
|
||||
class TC_HandleBaseT
|
||||
class TC_HandleBase
|
||||
{
|
||||
public:
|
||||
|
||||
/** 原子计数类型*/
|
||||
typedef T atomic_type;
|
||||
|
||||
/**
|
||||
* @brief 复制.
|
||||
*
|
||||
* @return TC_HandleBase&
|
||||
*/
|
||||
TC_HandleBaseT& operator=(const TC_HandleBaseT&)
|
||||
TC_HandleBase& operator=(const TC_HandleBase&)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
@ -66,14 +57,14 @@ public:
|
||||
/**
|
||||
* @brief 增加计数
|
||||
*/
|
||||
void incRef() { _atomic.inc_fast(); }
|
||||
void incRef() { ++_atomic; }
|
||||
|
||||
/**
|
||||
* @brief 减少计数, 当计数==0时, 且需要删除数据时, 释放对象
|
||||
*/
|
||||
void decRef()
|
||||
{
|
||||
if(_atomic.dec_and_test() && !_bNoDelete)
|
||||
if((--_atomic) == 0 && !_bNoDelete)
|
||||
{
|
||||
_bNoDelete = true;
|
||||
delete this;
|
||||
@ -85,7 +76,7 @@ public:
|
||||
*
|
||||
* @return int 计数值
|
||||
*/
|
||||
int getRef() const { return _atomic.get(); }
|
||||
int getRef() const { return _atomic; }
|
||||
|
||||
/**
|
||||
* @brief 设置不自动释放.
|
||||
@ -99,21 +90,21 @@ protected:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
TC_HandleBaseT() : _atomic(0), _bNoDelete(false)
|
||||
TC_HandleBase() : _atomic(0), _bNoDelete(false)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 拷贝构造
|
||||
*/
|
||||
TC_HandleBaseT(const TC_HandleBaseT&) : _atomic(0), _bNoDelete(false)
|
||||
TC_HandleBase(const TC_HandleBase&) : _atomic(0), _bNoDelete(false)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 析够
|
||||
*/
|
||||
virtual ~TC_HandleBaseT()
|
||||
virtual ~TC_HandleBase()
|
||||
{
|
||||
}
|
||||
|
||||
@ -122,7 +113,7 @@ protected:
|
||||
/**
|
||||
* 计数
|
||||
*/
|
||||
atomic_type _atomic;
|
||||
std::atomic<int> _atomic;
|
||||
|
||||
/**
|
||||
* 是否自动删除
|
||||
@ -130,34 +121,6 @@ protected:
|
||||
bool _bNoDelete;
|
||||
};
|
||||
|
||||
template<>
|
||||
inline void TC_HandleBaseT<int>::incRef()
|
||||
{
|
||||
//__sync_fetch_and_add(&_atomic,1);
|
||||
++_atomic;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void TC_HandleBaseT<int>::decRef()
|
||||
{
|
||||
//int c = __sync_fetch_and_sub(&_atomic, 1);
|
||||
//if(c == 1 && !_bNoDelete)
|
||||
if(--_atomic == 0 && !_bNoDelete)
|
||||
{
|
||||
_bNoDelete = true;
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
inline int TC_HandleBaseT<int>::getRef() const
|
||||
{
|
||||
//return __sync_fetch_and_sub(const_cast<volatile int*>(&_atomic), 0);
|
||||
return _atomic;
|
||||
}
|
||||
|
||||
typedef TC_HandleBaseT<TC_Atomic> TC_HandleBase;
|
||||
|
||||
/**
|
||||
* @brief 智能指针模板类.
|
||||
*
|
||||
@ -425,7 +388,7 @@ public:
|
||||
template<typename T> inline void
|
||||
TC_AutoPtr<T>::throwNullHandleException() const
|
||||
{
|
||||
throw TC_AutoPtrNull_Exception("autoptr null handle error");
|
||||
throw TC_AutoPtrNull_Exception("autoptr null handle error![" + string(typeid(T).name()) +"]");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -443,14 +406,9 @@ inline bool operator==(const TC_AutoPtr<T>& lhs, const TC_AutoPtr<U>& rhs)
|
||||
{
|
||||
T* l = lhs.get();
|
||||
U* r = rhs.get();
|
||||
if(l && r)
|
||||
{
|
||||
return *l == *r;
|
||||
}
|
||||
else
|
||||
{
|
||||
return !l && !r;
|
||||
}
|
||||
|
||||
// 改为直接比较指针,而不是比较值
|
||||
return (l == r);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -468,14 +426,9 @@ inline bool operator!=(const TC_AutoPtr<T>& lhs, const TC_AutoPtr<U>& rhs)
|
||||
{
|
||||
T* l = lhs.get();
|
||||
U* r = rhs.get();
|
||||
if(l && r)
|
||||
{
|
||||
return *l != *r;
|
||||
}
|
||||
else
|
||||
{
|
||||
return l || r;
|
||||
}
|
||||
|
||||
// 改为直接比较指针,而不是比较值
|
||||
return (l != r);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -495,7 +448,9 @@ inline bool operator<(const TC_AutoPtr<T>& lhs, const TC_AutoPtr<U>& rhs)
|
||||
U* r = rhs.get();
|
||||
if(l && r)
|
||||
{
|
||||
return *l < *r;
|
||||
//return *l < *r;
|
||||
// 改为直接比较指针,而不是比较值
|
||||
return (l < r);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -21,6 +21,13 @@
|
||||
#define __USE_XOPEN
|
||||
#endif
|
||||
|
||||
#include "util/tc_platform.h"
|
||||
|
||||
#if TARGET_PLATFORM_LINUX || TARGET_PLATFORM_IOS
|
||||
#include <unistd.h>
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
@ -38,6 +45,7 @@
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
|
||||
@ -149,6 +157,15 @@ public:
|
||||
*/
|
||||
static int strgmt2tm(const string &sString, struct tm &stTm);
|
||||
|
||||
/**
|
||||
* @brief 格式化的字符串时间转为时间戳.
|
||||
*
|
||||
* @param sString 格式化的字符串时间
|
||||
* @param sFormat 格式化的字符串时间的格式,默认为紧凑格式
|
||||
* @return time_t 转换后的时间戳
|
||||
*/
|
||||
static time_t str2time(const string &sString, const string &sFormat = "%Y%m%d%H%M%S");
|
||||
|
||||
/**
|
||||
* @brief 时间转换成字符串.
|
||||
*
|
||||
@ -167,6 +184,30 @@ public:
|
||||
*/
|
||||
static string tm2str(const time_t &t, const string &sFormat = "%Y%m%d%H%M%S");
|
||||
|
||||
|
||||
/**
|
||||
* @brief 时间转换tm.
|
||||
*
|
||||
* @param t 时间结构
|
||||
*/
|
||||
static void tm2time(const time_t &t, struct tm &tt);
|
||||
|
||||
/**
|
||||
* @brief time_t转换成tm(不用系统的localtime_r, 否则很慢!!!)
|
||||
*
|
||||
* @param t 时间结构
|
||||
* @param sFormat 需要转换的目标格式,默认为紧凑格式
|
||||
* @return string 转换后的时间字符串
|
||||
*/
|
||||
static void tm2tm(const time_t &t, struct tm &stTm);
|
||||
|
||||
/**
|
||||
* @brief 获取当前的秒和毫秒
|
||||
*
|
||||
* @param t 时间结构
|
||||
*/
|
||||
static int gettimeofday(struct timeval &tv);
|
||||
|
||||
/**
|
||||
* @brief 当前时间转换成紧凑格式字符串
|
||||
* @param sFormat 格式,默认为紧凑格式
|
||||
@ -297,6 +338,15 @@ public:
|
||||
template<typename K, typename V, typename D, typename A>
|
||||
static string tostr(const multimap<K, V, D, A> &t);
|
||||
|
||||
/**
|
||||
* @brief 把map输出为字符串.
|
||||
*
|
||||
* @param map<K, V, D, A> 要转换的map对象
|
||||
* @return string 输出的字符串
|
||||
*/
|
||||
template<typename K, typename V, typename D, typename P, typename A>
|
||||
static string tostr(const unordered_map<K, V, D, P, A> &t);
|
||||
|
||||
/**
|
||||
* @brief pair 转化为字符串,保证map等关系容器可以直接用tostr来输出
|
||||
* @param pair<F, S> pair对象
|
||||
@ -757,6 +807,22 @@ string TC_Common::tostr(const multimap<K, V, D, A> &t)
|
||||
return sBuffer;
|
||||
}
|
||||
|
||||
template<typename K, typename V, typename D, typename P, typename A>
|
||||
string TC_Common::tostr(const unordered_map<K, V, D, P, A> &t)
|
||||
{
|
||||
string sBuffer;
|
||||
typename unordered_map<K, V, D, P, A>::const_iterator it = t.begin();
|
||||
while (it != t.end()) {
|
||||
sBuffer += " [";
|
||||
sBuffer += tostr(it->first);
|
||||
sBuffer += "]=[";
|
||||
sBuffer += tostr(it->second);
|
||||
sBuffer += "] ";
|
||||
++it;
|
||||
}
|
||||
return sBuffer;
|
||||
}
|
||||
|
||||
template<typename F, typename S>
|
||||
string TC_Common::tostr(const pair<F, S> &itPair)
|
||||
{
|
||||
|
@ -551,9 +551,9 @@ public:
|
||||
|
||||
/**
|
||||
* 获取当前连接数
|
||||
* @return size_t
|
||||
* @return int
|
||||
*/
|
||||
size_t getNowConnection() const;
|
||||
int getNowConnection() const;
|
||||
|
||||
/**
|
||||
* 获取EpollServer
|
||||
@ -769,7 +769,7 @@ public:
|
||||
/**
|
||||
* 当前连接数
|
||||
*/
|
||||
TC_Atomic _iCurConns;
|
||||
std::atomic<int> _iCurConns;
|
||||
|
||||
/**
|
||||
* Handle个数
|
||||
|
@ -108,9 +108,12 @@ string TC_Common::tostr<unsigned long>(const unsigned long &t)
|
||||
template <>
|
||||
string TC_Common::tostr<float>(const float &t)
|
||||
{
|
||||
char buf[32];
|
||||
snprintf(buf, 32, "%.5f", t);
|
||||
string s(buf);
|
||||
//C++11 to_string,默认保留后面6位小数
|
||||
string s = std::to_string(t);
|
||||
|
||||
// char buf[32];
|
||||
// snprintf(buf, 32, "%.5f", t);
|
||||
// string s(buf);
|
||||
|
||||
//去掉无效0, eg. 1.0300 -> 1.03;1.00 -> 1
|
||||
bool bFlag = false;
|
||||
@ -142,9 +145,12 @@ string TC_Common::tostr<float>(const float &t)
|
||||
template <>
|
||||
string TC_Common::tostr<double>(const double &t)
|
||||
{
|
||||
char buf[32];
|
||||
snprintf(buf, 32, "%.5f", t);
|
||||
string s(buf);
|
||||
//C++11 to_string,默认保留后面6位小数
|
||||
string s = std::to_string(t);
|
||||
|
||||
// char buf[32];
|
||||
// snprintf(buf, 32, "%.5f", t);
|
||||
// string s(buf);
|
||||
|
||||
//去掉无效0, eg. 1.0300 -> 1.03;1.00 -> 1
|
||||
bool bFlag = false;
|
||||
@ -364,12 +370,61 @@ bool TC_Common::isdigit(const string &sInput)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//用于计算时区差异!
|
||||
class TimezoneHelper
|
||||
{
|
||||
public:
|
||||
TimezoneHelper()
|
||||
{
|
||||
struct tm timeinfo;
|
||||
time_t secs, local_secs, gmt_secs;
|
||||
time(&secs);
|
||||
|
||||
//带时区时间
|
||||
#if TARGET_PLATFORM_WINDOWS
|
||||
localtime_s(&timeinfo, &secs);
|
||||
#else
|
||||
localtime_r(&secs, &timeinfo);
|
||||
#endif
|
||||
|
||||
local_secs = mktime(&timeinfo);
|
||||
|
||||
//不带时区时间
|
||||
|
||||
#if TARGET_PLATFORM_WINDOWS
|
||||
gmtime_s(&timeinfo, &secs);
|
||||
#else
|
||||
gmtime_r(&secs, &timeinfo);
|
||||
#endif
|
||||
|
||||
gmt_secs = mktime(&timeinfo);
|
||||
timezone_diff_secs = local_secs - gmt_secs;
|
||||
}
|
||||
|
||||
static int64_t timezone_diff_secs;
|
||||
};
|
||||
|
||||
int64_t TimezoneHelper::timezone_diff_secs = 0;
|
||||
|
||||
int TC_Common::str2tm(const string &sString, const string &sFormat, struct tm &stTm)
|
||||
{
|
||||
char *p = strptime(sString.c_str(), sFormat.c_str(), &stTm);
|
||||
return (p != NULL) ? 0 : -1;
|
||||
}
|
||||
|
||||
time_t TC_Common::str2time(const string &sString, const string &sFormat)
|
||||
{
|
||||
struct tm stTm;
|
||||
if (0 == str2tm(sString, sFormat, stTm))
|
||||
{
|
||||
//注意这里没有直接用mktime, mktime会访问时区文件, 会巨慢!
|
||||
static TimezoneHelper helper;
|
||||
return timegm(&stTm) - TimezoneHelper::timezone_diff_secs;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TC_Common::strgmt2tm(const string &sString, struct tm &stTm)
|
||||
{
|
||||
return str2tm(sString, "%a, %d %b %Y %H:%M:%S GMT", stTm);
|
||||
@ -384,14 +439,65 @@ string TC_Common::tm2str(const struct tm &stTm, const string &sFormat)
|
||||
return string(sTimeString);
|
||||
}
|
||||
|
||||
int TC_Common::gettimeofday(struct timeval &tv)
|
||||
{
|
||||
#if TARGET_PLATFORM_WINDOWS
|
||||
static const DWORDLONG FILETIME_to_timeval_skew = 116444736000000000;
|
||||
FILETIME tfile;
|
||||
::GetSystemTimeAsFileTime(&tfile);
|
||||
|
||||
ULARGE_INTEGER tmp;
|
||||
tmp.LowPart = tfile.dwLowDateTime;
|
||||
tmp.HighPart = tfile.dwHighDateTime;
|
||||
tmp.QuadPart -= FILETIME_to_timeval_skew;
|
||||
|
||||
ULARGE_INTEGER largeInt;
|
||||
largeInt.QuadPart = tmp.QuadPart / (10000 * 1000);
|
||||
tv.tv_sec = (long)(tmp.QuadPart / (10000 * 1000));
|
||||
tv.tv_usec = (long)((tmp.QuadPart % (10000 * 1000)) / 10);
|
||||
return 0;
|
||||
#else
|
||||
return ::gettimeofday(&tv, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void TC_Common::tm2time(const time_t &t, struct tm &tt)
|
||||
{
|
||||
//加快速度, 否则会比较慢, 不用localtime_r(会访问时区文件, 较慢)
|
||||
static TimezoneHelper helper;
|
||||
time_t localt = t + TimezoneHelper::timezone_diff_secs;
|
||||
|
||||
#if TARGET_PLATFORM_WINDOWS
|
||||
//localtime_s
|
||||
gmtime_s(&tt, &localt);
|
||||
#else
|
||||
gmtime_r(&localt, &tt);
|
||||
#endif
|
||||
}
|
||||
|
||||
string TC_Common::tm2str(const time_t &t, const string &sFormat)
|
||||
{
|
||||
struct tm tt;
|
||||
localtime_r(&t, &tt);
|
||||
tm2time(t, tt);
|
||||
// localtime_r(&t, &tt);
|
||||
|
||||
return tm2str(tt, sFormat);
|
||||
}
|
||||
|
||||
|
||||
void TC_Common::tm2tm(const time_t &t, struct tm &tt)
|
||||
{
|
||||
static TimezoneHelper helper;
|
||||
time_t localt = t + TimezoneHelper::timezone_diff_secs;
|
||||
|
||||
#if TARGET_PLATFORM_WINDOWS
|
||||
gmtime_s(&tt, &localt);
|
||||
#else
|
||||
gmtime_r(&localt, &tt);
|
||||
#endif
|
||||
// gmtime_r(&localt, &stTm);
|
||||
}
|
||||
|
||||
string TC_Common::now2str(const string &sFormat)
|
||||
{
|
||||
time_t t = time(NULL);
|
||||
@ -407,8 +513,15 @@ string TC_Common::now2GMTstr()
|
||||
string TC_Common::tm2GMTstr(const time_t &t)
|
||||
{
|
||||
struct tm tt;
|
||||
#if TARGET_PLATFORM_LINUX || TARGET_PLATFORM_IOS
|
||||
gmtime_r(&t, &tt);
|
||||
#elif TARGET_PLATFORM_WINDOWS
|
||||
_gmtime64_s(&tt, &t);
|
||||
#endif
|
||||
return tm2str(tt, "%a, %d %b %Y %H:%M:%S GMT");
|
||||
|
||||
// gmtime_r(&t, &tt);
|
||||
// return tm2str(tt, "%a, %d %b %Y %H:%M:%S GMT");
|
||||
}
|
||||
|
||||
string TC_Common::tm2GMTstr(const struct tm &stTm)
|
||||
@ -430,7 +543,8 @@ int64_t TC_Common::now2ms()
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, 0);
|
||||
// gettimeofday(&tv, 0);
|
||||
TC_Common::gettimeofday(tv);
|
||||
|
||||
return tv.tv_sec * (int64_t)1000 + tv.tv_usec/1000;
|
||||
}
|
||||
@ -439,7 +553,8 @@ int64_t TC_Common::now2us()
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, 0);
|
||||
TC_Common::gettimeofday(tv);
|
||||
// gettimeofday(&tv, 0);
|
||||
|
||||
return tv.tv_sec * (int64_t)1000000 + tv.tv_usec;
|
||||
}
|
||||
@ -634,6 +749,7 @@ bool TC_Common::matchPeriod(const string& s, const vector<string>& pat)
|
||||
return false;
|
||||
}
|
||||
|
||||
#if TARGET_PLATFORM_LINUX || __APPLE__
|
||||
void TC_Common::daemon()
|
||||
{
|
||||
pid_t pid;
|
||||
@ -677,6 +793,7 @@ void TC_Common::ignorePipe()
|
||||
sigemptyset(&sig.sa_mask);
|
||||
sigaction(SIGPIPE,&sig,NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool TC_Common::isPrimeNumber(size_t n)
|
||||
{
|
||||
@ -735,6 +852,8 @@ size_t TC_Common::toSize(const string &s, size_t iDefaultSize)
|
||||
return iDefaultSize;
|
||||
}
|
||||
|
||||
#if TARGET_PLATFORM_LINUX || __APPLE__
|
||||
|
||||
// Generate the randome string, a SHA1-sized random number
|
||||
void TC_Common::getRandomHexChars(char* p, unsigned int len)
|
||||
{
|
||||
@ -753,5 +872,7 @@ void TC_Common::getRandomHexChars(char* p, unsigned int len)
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
@ -546,17 +546,17 @@ bool TC_EpollServer::BindAdapter::isLimitMaxConnection() const
|
||||
|
||||
void TC_EpollServer::BindAdapter::decreaseNowConnection()
|
||||
{
|
||||
_iCurConns.dec();
|
||||
_iCurConns++;
|
||||
}
|
||||
|
||||
void TC_EpollServer::BindAdapter::increaseNowConnection()
|
||||
{
|
||||
_iCurConns.inc();
|
||||
_iCurConns--;
|
||||
}
|
||||
|
||||
size_t TC_EpollServer::BindAdapter::getNowConnection() const
|
||||
int TC_EpollServer::BindAdapter::getNowConnection() const
|
||||
{
|
||||
return _iCurConns.get();
|
||||
return _iCurConns;
|
||||
}
|
||||
|
||||
vector<TC_EpollServer::ConnStatus> TC_EpollServer::BindAdapter::getConnStatus()
|
||||
|
Loading…
Reference in New Issue
Block a user