| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393 |
- /*
- * Copyright: JessMA Open Source (ldcsaa@gmail.com)
- *
- * Author : Bruce Liang
- * Website : https://github.com/ldcsaa
- * Project : https://github.com/ldcsaa/HP-Socket
- * Blog : http://www.cnblogs.com/ldcsaa
- * Wiki : http://www.oschina.net/p/hp-socket
- * QQ Group : 44636872, 75375912
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #include "FuncHelper.h"
- #include "Thread.h"
- #include <ctype.h>
- #include <sched.h>
- #include <sys/time.h>
- #include <sys/select.h>
- #include <sys/timerfd.h>
- #if !defined(__ANDROID__)
- #include <sys/timeb.h>
- #include <execinfo.h>
- #ifdef __GNUC__
- #include <cxxabi.h>
- #endif
- #endif
- INT WaitFor(DWORD dwMillSecond, DWORD dwSecond, BOOL bExceptThreadInterrupted)
- {
- timeval tv {(time_t)dwSecond, (suseconds_t)(dwMillSecond * 1000)};
- if(bExceptThreadInterrupted)
- return NO_EINTR_EXCEPT_THR_INTR_INT(select(0, nullptr, nullptr, nullptr, &tv));
- return NO_EINTR_INT(select(0, nullptr, nullptr, nullptr, &tv));
- }
- INT Sleep(DWORD dwMillSecond, DWORD dwSecond, BOOL bExceptThreadInterrupted)
- {
- timespec ts_req = {(time_t)dwSecond, (long)(dwMillSecond * 1000000)};
- timespec ts_rem = ts_req;
- INT rs = NO_ERROR;
- while(IS_HAS_ERROR(rs = nanosleep(&ts_req, &ts_rem)))
- {
- if(!IS_INTR_ERROR())
- break;
- else
- {
- if(bExceptThreadInterrupted && ::IsThreadInterrupted())
- break;
- }
- ts_req = ts_rem;
- }
- return rs;
- }
- __time64_t _time64(time_t* ptm)
- {
- return (__time64_t)time(ptm);
- }
- __time64_t _mkgmtime64(tm* ptm)
- {
- return (__time64_t)timegm(ptm);
- }
- tm* _gmtime64(tm* ptm, __time64_t* pt)
- {
- time_t t = (time_t)(*pt);
- return gmtime_r(&t, ptm);
- }
- DWORD TimeGetTime()
- {
- return (DWORD)TimeGetTime64();
- }
- ULLONG TimeGetTime64()
- {
- #if !defined(__ANDROID__)
- timeb tb;
- if(ftime(&tb) == NO_ERROR)
- return (((ULLONG)(tb.time)) * 1000 + tb.millitm);
- #else
- timespec ts;
- if(clock_gettime(CLOCK_MONOTONIC, &ts) == NO_ERROR)
- return (((ULLONG)(ts.tv_sec)) * 1000 + ts.tv_nsec / 1000000);
- #endif
- return 0ull;
- }
- DWORD GetTimeGap32(DWORD dwOriginal, DWORD dwCurrent)
- {
- if(dwCurrent == 0)
- dwCurrent = ::TimeGetTime();
- return dwCurrent - dwOriginal;
- }
- ULLONG GetTimeGap64(ULLONG ullOriginal, ULONGLONG ullCurrent)
- {
- if(ullCurrent == 0)
- ullCurrent = ::TimeGetTime64();
- return ullCurrent - ullOriginal;
- }
- LLONG TimevalToMillisecond(const timeval& tv)
- {
- return tv.tv_sec * 1000 + tv.tv_usec / 1000;
- }
- timeval& MillisecondToTimeval(LLONG ms, timeval& tv)
- {
- tv.tv_sec = (time_t)(ms / 1000);
- tv.tv_usec = (suseconds_t)((ms % 1000) * 1000);
- return tv;
- }
- LLONG TimespecToMillisecond(const timespec& ts)
- {
- return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
- }
- timespec& MillisecondToTimespec(LLONG ms, timespec& ts)
- {
- ts.tv_sec = (time_t)(ms / 1000);
- ts.tv_nsec = (long)((ms % 1000) * 1000000);
- return ts;
- }
- timeval& GetFutureTimeval(LLONG ms, timeval& tv, struct timezone* ptz)
- {
- gettimeofday(&tv, ptz);
- tv.tv_sec += (time_t)(ms / 1000);
- tv.tv_usec += (suseconds_t)((ms % 1000) * 1000);
- return tv;
- }
- timespec& GetFutureTimespec(LLONG ms, timespec& ts, clockid_t clkid)
- {
- clock_gettime(clkid, &ts);
- ts.tv_sec += (time_t)(ms / 1000);
- ts.tv_nsec += (long)((ms % 1000) * 1000000);
- return ts;
- }
- FD CreateTimer(LLONG llInterval, LLONG llStart, BOOL bRealTimeClock)
- {
- ASSERT_CHECK_EINVAL(llInterval >= 0L);
- if(llStart < 0)
- llStart = llInterval;
- FD fdTimer = timerfd_create((bRealTimeClock ? CLOCK_REALTIME : CLOCK_MONOTONIC), TFD_NONBLOCK | TFD_CLOEXEC);
- itimerspec its;
- ::MillisecondToTimespec(llStart, its.it_value);
- ::MillisecondToTimespec(llInterval, its.it_interval);
- if(IS_HAS_ERROR(timerfd_settime(fdTimer, 0, &its, nullptr)))
- {
- close(fdTimer);
- fdTimer = INVALID_FD;
- }
- return fdTimer;
- }
- BOOL ReadTimer(FD tmr, ULLONG* pVal, BOOL* pRs)
- {
- static const SSIZE_T SIZE = sizeof(ULLONG);
- if(pVal == nullptr)
- pVal = CreateLocalObject(ULLONG);
- if(pRs == nullptr)
- pRs = CreateLocalObject(BOOL);
- if(read(tmr, pVal, SIZE) == SIZE)
- *pRs = TRUE;
- else
- {
- *pRs = FALSE;
- if(!IS_WOULDBLOCK_ERROR())
- return FALSE;
- }
- return TRUE;
- }
- BOOL fcntl_SETFL(FD fd, INT fl, BOOL bSet)
- {
- int val = fcntl(fd, F_GETFL);
- if(IS_HAS_ERROR(val))
- return FALSE;
- val = bSet ? (val | fl) : (val & (~fl));
- return IS_NO_ERROR(fcntl(fd, F_SETFL , val));
- }
- void PrintStackTrace()
- {
- #if !defined(__ANDROID__)
- const int MAX_SIZE = 51;
- void* arr[MAX_SIZE];
- int size = backtrace(arr, MAX_SIZE);
- char** messages = backtrace_symbols(arr, size);
- for(int i = 1; i < size && messages != nullptr; i++)
- {
- char* mangled_name = nullptr;
- char* offset_end = nullptr;
- const char* offset_begin = nullptr;
- for(char* p = messages[i]; *p; ++p)
- {
- if(*p == '(')
- {
- mangled_name = p;
- }
- else if(*p == '+')
- {
- offset_begin = p;
- }
- else if(*p == ')')
- {
- offset_end = p;
- break;
- }
- }
- if(mangled_name && offset_end && mangled_name < offset_end)
- {
- *mangled_name++ = 0;
- *offset_end++ = 0;
- if(offset_begin == nullptr)
- offset_begin = "";
- else
- *(char*)offset_begin++ = 0;
- while(*offset_end == ' ')
- ++offset_end;
- #ifdef __GNUC__
- int status;
- char* real_name = abi::__cxa_demangle(mangled_name, nullptr, nullptr, &status);
- if(status == 0)
- FPRINTLN(stderr, " -> [%02d] %s : (%s+%s) %s", i, messages[i], real_name, offset_begin, offset_end);
- else
- FPRINTLN(stderr, " -> [%02d] %s : (%s+%s) %s", i, messages[i], mangled_name, offset_begin, offset_end);
- if(real_name != nullptr)
- free(real_name);
- #else
- FPRINTLN(stderr, " -> [%02d] %s : (%s+%s) %s", i, messages[i], mangled_name, offset_begin, offset_end);
- #endif
- }
- else
- {
- FPRINTLN(stderr, " -> [%02d] %s", i, messages[i]);
- }
- }
- free(messages);
- #endif
- }
- void __EXIT_FN_(void (*fn)(int), LPCSTR lpszFnName, int* lpiExitCode, int iErrno, LPCSTR lpszFile, int iLine, LPCSTR lpszFunc, LPCSTR lpszTitle)
- {
- if(iErrno >= 0)
- SetLastError(iErrno);
- else
- iErrno = GetLastError();
- if(!lpszTitle)
- {
- lpszTitle = CreateLocalObjects(char, 64);
- if(lpiExitCode)
- sprintf((LPSTR)lpszTitle, "(#%d, 0x%zX) > %s(%d) [%d]", SELF_PROCESS_ID, (SIZE_T)SELF_THREAD_ID, lpszFnName, *lpiExitCode, iErrno);
- else
- sprintf((LPSTR)lpszTitle, "(#%d, 0x%zX) > %s() [%d]", SELF_PROCESS_ID, (SIZE_T)SELF_THREAD_ID, lpszFnName, iErrno);
- }
- if(lpszFile && iLine > 0)
- FPRINTLN(stderr, "%s : %s\n => %s (%d) : %s", lpszTitle, strerror(iErrno), lpszFile, iLine, lpszFunc ? lpszFunc : "");
- else
- FPRINTLN(stderr, "%s : %s", lpszTitle, strerror(iErrno));
- if(lpiExitCode)
- fn(*lpiExitCode);
- else
- ((void (*)())fn)();
- }
- void EXIT(int iExitCode, int iErrno, LPCSTR lpszFile, int iLine, LPCSTR lpszFunc, LPCSTR lpszTitle)
- {
- __EXIT_FN_(exit, "exit", &iExitCode, iErrno, lpszFile, iLine, lpszFunc, lpszTitle);
- }
- void _EXIT(int iExitCode, int iErrno, LPCSTR lpszFile, int iLine, LPCSTR lpszFunc, LPCSTR lpszTitle)
- {
- __EXIT_FN_(_exit, "_exit", &iExitCode, iErrno, lpszFile, iLine, lpszFunc, lpszTitle);
- }
- void ABORT(int iErrno, LPCSTR lpszFile, int iLine, LPCSTR lpszFunc, LPCSTR lpszTitle)
- {
- __EXIT_FN_((void (*)(int))abort, "abort", nullptr, iErrno, lpszFile, iLine, lpszFunc, lpszTitle);
- }
- BOOL SetSequenceThreadName(THR_ID tid, LPCTSTR lpszPrefix, volatile UINT& vuiSeq)
- {
- UINT uiSequence = InterlockedIncrement(&vuiSeq);
- return SetThreadName(tid, lpszPrefix, uiSequence);
- }
- BOOL SetThreadName(THR_ID tid, LPCTSTR lpszPrefix, UINT uiSequence)
- {
- int iMaxSeqLength = (int)(MAX_THREAD_NAME_LENGTH - lstrlen(lpszPrefix));
- ASSERT(iMaxSeqLength > 0);
- if(iMaxSeqLength <= 0)
- {
- ::SetLastError(ERROR_OUT_OF_RANGE);
- return FALSE;
- }
- ULONGLONG uiDiv = 1;
- for(int i = 0; i < iMaxSeqLength; i++)
- uiDiv *= 10;
- uiSequence = (UINT)(uiSequence % uiDiv);
- CString strName;
- strName.Format(_T("%s%u"), lpszPrefix, uiSequence);
- return SetThreadName(tid, strName);
- }
- BOOL SetThreadName(THR_ID tid, LPCTSTR lpszName)
- {
- ASSERT(lstrlen(lpszName) <= MAX_THREAD_NAME_LENGTH);
- if(tid == 0)
- tid = SELF_THREAD_ID;
- int rs = pthread_setname_np(tid, CT2A(lpszName));
- CHECK_ERROR_CODE(rs)
- return TRUE;
- }
|