fix tc_common double bug

tc_common add time function, tc_autoptr use std::atomic
This commit is contained in:
ruanshudong 2019-12-17 13:48:03 +08:00
parent 4385398f84
commit 43103f10fd
7 changed files with 254 additions and 112 deletions

@ -1 +1 @@
Subproject commit 48a520fe192308217a4529438011d158da60f538
Subproject commit 838bcfada355301f6832c6c88c2d180ac6a25d5f

@ -1 +1 @@
Subproject commit 5f46a694b925be139aa16274a00b7d5ad611004c
Subproject commit e663956b02aa72f9491f759263da89d62502f7e8

View File

@ -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
{

View File

@ -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)
{

View File

@ -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个数

View File

@ -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
}

View File

@ -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()