| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530 |
- /*
- * 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.
- */
- #pragma once
- #include "../hpsocket/GlobalDef.h"
- #include "Singleton.h"
- #include "FuncHelper.h"
- #include "PollHelper.h"
- #include <errno.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <sys/eventfd.h>
- #include <sys/timerfd.h>
- #include <sys/signalfd.h>
- class CPipeEvent
- {
- public:
- enum
- {
- EVT_1 = 0x01,
- EVT_WAKEUP = EVT_1,
- EVT_EXIT = 0x7F,
- EVT_SIG_0 = 0x80,
- EVT_SIG_MAX = EVT_SIG_0 + _NSIG,
- };
- public:
- int Wait(long lTimeout = INFINITE, const sigset_t* pSigSet = nullptr)
- {
- pollfd pfd = {m_fd[0], POLLIN};
- while(TRUE)
- {
- int rs = (int)::PollForSingleObject(pfd, lTimeout, pSigSet);
- if(rs <= TIMEOUT) return rs;
- if(pfd.revents & POLLIN)
- {
- BYTE v;
- if(!Get(v))
- return HAS_ERROR;
- if(v == 0)
- continue;
- return (int)v;
- }
- if(pfd.revents & _POLL_ALL_ERROR_EVENTS)
- {
- ::SetLastError(ERROR_BROKEN_PIPE);
- return HAS_ERROR;
- }
- ASSERT(FALSE);
- }
- }
- BOOL Set(BYTE bVal = EVT_WAKEUP)
- {
- ASSERT_CHECK_EINVAL(bVal != 0);
- return VERIFY(write(m_fd[1], &bVal, 1) > 0);
- }
- BOOL Get(BYTE& v)
- {
- ASSERT(IsValid());
- int rs = (int)read(m_fd[0], &v, 1);
- if(IS_HAS_ERROR(rs))
- {
- if(IS_WOULDBLOCK_ERROR())
- v = 0;
- else
- return FALSE;
- }
- else if(rs == 0)
- {
- ::SetLastError(ERROR_BROKEN_PIPE);
- return FALSE;
- }
- return TRUE;
- }
- BOOL Reset()
- {
- BYTE v;
- while(TRUE)
- {
- if(!Get(v))
- return FALSE;
- if(v == 0)
- break;
- }
- return TRUE;
- }
- BOOL SetSignal(BYTE bSigVal)
- {
- ASSERT_CHECK_EINVAL(bSigVal > 0 && bSigVal < _NSIG);
- return Set((BYTE)(EVT_SIG_0 + bSigVal));
- }
- static inline BYTE ToSignalValue(int iWaitResult)
- {
- if(iWaitResult <= EVT_SIG_0 || iWaitResult >= EVT_SIG_MAX)
- return 0;
- return (BYTE)(iWaitResult - EVT_SIG_0);
- }
- BOOL IsValid() {return IS_VALID_FD(m_fd[0]) && IS_VALID_FD(m_fd[1]);}
- operator FD () {return m_fd[0];}
- FD GetFD () {return m_fd[0];}
- public:
- CPipeEvent()
- {
- VERIFY_IS_NO_ERROR(pipe2(m_fd, O_NONBLOCK | O_CLOEXEC));
- VERIFY(::fcntl_SETFL(m_fd[0], O_NOATIME));
- VERIFY(::fcntl_SETFL(m_fd[1], O_NOATIME));
- }
- ~CPipeEvent()
- {
- close(m_fd[1]);
- close(m_fd[0]);
- }
- DECLARE_NO_COPY_CLASS(CPipeEvent)
- private:
- FD m_fd[2] = {INVALID_FD, INVALID_FD};
- };
- template<bool is_sem_mode = false> class CCounterEvent
- {
- public:
- eventfd_t Wait(long lTimeout = INFINITE, const sigset_t* pSigSet = nullptr)
- {
- pollfd pfd = {m_evt, POLLIN};
- while(TRUE)
- {
- long rs = ::PollForSingleObject(pfd, lTimeout, pSigSet);
- if(rs <= TIMEOUT) return (eventfd_t)rs;
- if(pfd.revents & POLLIN)
- {
- eventfd_t v;
- if(!Get(v))
- return HAS_ERROR;
- if(v == 0)
- continue;
- return v;
- }
- if(pfd.revents & _POLL_ALL_ERROR_EVENTS)
- {
- ::SetLastError(ERROR_HANDLES_CLOSED);
- return HAS_ERROR;
- }
- ASSERT(FALSE);
- }
- }
- BOOL Set(eventfd_t val = 1)
- {
- ASSERT_CHECK_EINVAL(val > 0);
- int rs = eventfd_write(m_evt, val);
- return VERIFY_IS_NO_ERROR(rs);
- }
- BOOL Get(eventfd_t& v)
- {
- ASSERT(IsValid());
- if(IS_HAS_ERROR(eventfd_read(m_evt, &v)))
- {
- if(IS_WOULDBLOCK_ERROR())
- v = 0;
- else
- return FALSE;
- }
-
- return TRUE;
- }
- BOOL Reset()
- {
- eventfd_t v;
- while(TRUE)
- {
- if(!Get(v))
- return FALSE;
- if(v == 0)
- break;
- }
- return TRUE;
- }
- BOOL IsValid() {return IS_VALID_FD(m_evt);}
- operator FD () {return m_evt;}
- FD GetFD () {return m_evt;}
- public:
- CCounterEvent(int iInitCount = 0)
- {
- int iFlag = EFD_NONBLOCK | EFD_CLOEXEC | (is_sem_mode ? EFD_SEMAPHORE : 0);
- m_evt = eventfd(iInitCount, iFlag);
- VERIFY(IsValid());
- }
- ~CCounterEvent()
- {
- if(IsValid()) close(m_evt);
- }
- DECLARE_NO_COPY_CLASS(CCounterEvent)
- private:
- FD m_evt = INVALID_FD;
- };
- using CSimpleEvent = CCounterEvent<false>;
- using CSemaphoreEvent = CCounterEvent<true>;
- using CEvt = CSimpleEvent;
- class CTimerEvent
- {
- public:
- ULLONG Wait(long lTimeout = INFINITE, const sigset_t* pSigSet = nullptr)
- {
- pollfd pfd = {m_tmr, POLLIN};
- while(TRUE)
- {
- SSIZE_T rs = ::PollForSingleObject(pfd, lTimeout, pSigSet);
- if(rs <= TIMEOUT) return (ULLONG)rs;
- if(pfd.revents & POLLIN)
- {
- BOOL ok;
- ULLONG v;
- if(!Get(v, ok))
- return HAS_ERROR;
- if(!ok)
- continue;
- return v;
- }
- if(pfd.revents & _POLL_ALL_ERROR_EVENTS)
- {
- ::SetLastError(ERROR_HANDLES_CLOSED);
- return HAS_ERROR;
- }
- ASSERT(FALSE);
- }
- }
- BOOL Set(LLONG llInterval, LLONG llStart = -1)
- {
- ASSERT_CHECK_EINVAL(llInterval >= 0L);
- if(llStart < 0)
- llStart = llInterval;
- itimerspec its;
- ::MillisecondToTimespec(llStart, its.it_value);
- ::MillisecondToTimespec(llInterval, its.it_interval);
- int rs = timerfd_settime(m_tmr, 0, &its, nullptr);
- return VERIFY_IS_NO_ERROR(rs);
- }
- BOOL Get(ULLONG &v, BOOL& ok)
- {
- ASSERT(IsValid());
- return ::ReadTimer(m_tmr, &v, &ok);
- }
- BOOL Reset()
- {
- BOOL ok;
- ULLONG v;
- while(TRUE)
- {
- if(!Get(v, ok))
- return FALSE;
- if(!ok)
- break;
- }
- return TRUE;
- }
- BOOL GetTime(LLONG& lStart, LLONG& lInterval)
- {
- itimerspec its;
- if(IS_HAS_ERROR(timerfd_gettime(m_tmr, &its)))
- return FALSE;
- lStart = ::TimespecToMillisecond(its.it_value);
- lInterval = ::TimespecToMillisecond(its.it_interval);
- return TRUE;
- }
- BOOL IsValid() {return IS_VALID_FD(m_tmr);}
- operator FD () {return m_tmr;}
- FD GetFD () {return m_tmr;}
- public:
- CTimerEvent(bool bRealTimeClock = FALSE)
- {
- int iCID = (bRealTimeClock ? CLOCK_REALTIME : CLOCK_MONOTONIC);
- m_tmr = timerfd_create(iCID, TFD_NONBLOCK | TFD_CLOEXEC);
- VERIFY(IsValid());
- }
- ~CTimerEvent()
- {
- if(IsValid()) close(m_tmr);
- }
- DECLARE_NO_COPY_CLASS(CTimerEvent)
- private:
- FD m_tmr = INVALID_FD;
- };
- class CSignalEvent
- {
- public:
- int Wait(signalfd_siginfo& sgInfo, long lTimeout = INFINITE, const sigset_t* pSigSet = nullptr)
- {
- m_dwTID = SELF_THREAD_ID;
- pollfd pfd = {m_sig, POLLIN};
- while(TRUE)
- {
- long rs = ::PollForSingleObject(pfd, lTimeout, pSigSet);
- if(rs <= TIMEOUT) return (int)rs;
- if(pfd.revents & POLLIN)
- {
- BOOL ok;
- if(!Get(sgInfo, ok))
- return HAS_ERROR;
- if(!ok)
- continue;
- return sgInfo.ssi_signo;
- }
- if(pfd.revents & _POLL_ALL_ERROR_EVENTS)
- {
- ::SetLastError(ERROR_HANDLES_CLOSED);
- return HAS_ERROR;
- }
- ASSERT(FALSE);
- }
- m_dwTID = 0;
- }
- BOOL Set(int iSig, const sigval sgVal, THR_ID dwTID = 0)
- {
- if(dwTID == 0)
- {
- dwTID = m_dwTID;
- if(dwTID == 0)
- {
- ::SetLastError(ERROR_INVALID_STATE);
- return FALSE;
- }
- }
- #if !defined(__ANDROID__)
- int rs = pthread_sigqueue(dwTID, iSig, sgVal);
- #else
- int rs = pthread_kill(dwTID, iSig);
- #endif
- return IS_NO_ERROR(rs);
- }
- BOOL Get(signalfd_siginfo& v, BOOL& ok)
- {
- ASSERT(IsValid());
- static const SSIZE_T SIZE = sizeof(signalfd_siginfo);
- if(read(m_sig, &v, SIZE) == SIZE)
- ok = TRUE;
- {
- if(IS_WOULDBLOCK_ERROR())
- ok = FALSE;
- else
- return FALSE;
- }
- return ok;
- }
- BOOL Reset()
- {
- BOOL ok;
- signalfd_siginfo v;
- while(TRUE)
- {
- if(!Get(v, ok))
- return FALSE;
- if(!ok)
- break;
- }
- return TRUE;
- }
- BOOL Mask(const sigset_t* pSigMask)
- {
- if(!pSigMask)
- {
- if(!IsValid()) return TRUE;
- return IS_NO_ERROR(close(m_sig));
- }
- FD sig = signalfd(m_sig, pSigMask, SFD_NONBLOCK | SFD_CLOEXEC);
- if(IS_VALID_FD(sig))
- {
- m_sig = sig;
- return TRUE;
- }
- return FALSE;
- }
- BOOL IsValid() {return IS_VALID_FD(m_sig);}
- operator FD () {return m_sig;}
- FD GetFD () {return m_sig;}
- public:
- CSignalEvent(const sigset_t* pSigMask = nullptr)
- {
- if(pSigMask) VERIFY(Mask(pSigMask));
- }
- ~CSignalEvent()
- {
- if(IsValid()) close(m_sig);
- }
- DECLARE_NO_COPY_CLASS(CSignalEvent)
- private:
- FD m_sig = INVALID_FD;
- THR_ID m_dwTID = 0;
- };
|