| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- /*
- * 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 "Thread.h"
- #include <signal.h>
- #include <memory>
- using namespace std;
- template<class T> class CSignalHandler
- {
- public:
- using MT = CSignalHandler<T>;
- using SI = siginfo_t;
- using SS = sigset_t;
- using CHandlerThread = CThread<MT, const SS, VOID>;
- using F = VOID (T::*)(const SI*);
- using SF = VOID (*)(const SI*);
- using SSPTR = unique_ptr<SS>;
- friend CHandlerThread;
- public:
- BOOL Setup(SF pFunc, const SS* pSigSet, BOOL bRestorOnCancel = TRUE)
- {
- return Setup((__CFakeRunnerClass_*)nullptr, *(F*)&pFunc, pSigSet, bRestorOnCancel);
- }
- BOOL Setup(T* pRunner, F pFunc, const SS* pSigSet, BOOL bRestorOnCancel = TRUE)
- {
- ASSERT_CHECK_EINVAL(pSigSet != nullptr);
- m_pssPre = make_unique<SS>();
- int rs = pthread_sigmask(SIG_BLOCK, pSigSet, m_pssPre.get());
- if(rs != NO_ERROR)
- {
- m_pssPre = nullptr;
- ::SetLastError(rs);
- return FALSE;
- }
- m_pRunner = pRunner;
- m_pFunc = pFunc;
- m_pssCur = make_unique<SS>();
- ::CopyPlainObject(m_pssCur.get(), pSigSet);
- BOOL isOK = m_thHandler.Start(this, &MT::ThreadFunc, m_pssCur.get());
- if(isOK && !bRestorOnCancel)
- m_pssPre = nullptr;
- else if(!isOK)
- EXECUTE_RESTORE_ERROR(Reset());
- return isOK;
- }
- BOOL Cancel()
- {
- BOOL isOK = m_thHandler.IsRunning();
- if(isOK)
- {
- isOK = m_thHandler.Interrupt();
- isOK &= m_thHandler.Join();
- }
- isOK &= Reset();
- return isOK;
- }
- BOOL IsRunning () {return m_thHandler.IsRunning();}
- T* GetRunner () {return m_pRunner;}
- F GetFunc () {return m_pFunc;}
- SF GetSFunc () {return *(SF*)&m_pFunc;}
- THR_ID GetThreadID () {return m_thHandler.GetThreadID();}
- NTHR_ID GetNativeID () {return m_thHandler.GetNativeID();}
- private:
- VOID ThreadFunc(const SS* pSigSet)
- {
- ASSERT(pSigSet == m_pssCur.get());
- SI si;
- ZeroObject(si);
- while(!::IsThreadInterrupted())
- {
- #if !defined(__ANDROID__)
- int rs = NO_EINTR_EXCEPT_THR_INTR_INT(sigwaitinfo(pSigSet, &si));
- #else
- int rs = NO_EINTR_EXCEPT_THR_INTR_INT(sigwait(pSigSet, &si.si_signo));
- #endif
- if(IS_HAS_ERROR(rs))
- {
- if(IS_ERROR(EINTR))
- {
- ASSERT(::IsThreadInterrupted());
- break;
- }
-
- ERROR_ABORT();
- }
- Run((T*)nullptr, &si);
- }
- }
- template<typename T_, typename = enable_if_t<!is_same<T_, __CFakeRunnerClass_>::value>>
- VOID Run(T_*, const SI* pSigSet) {(m_pRunner->*m_pFunc)(pSigSet);}
- VOID Run(__CFakeRunnerClass_*, const SI* pSigSet) {(*(SF*)&m_pFunc)(pSigSet);}
- BOOL Reset()
- {
- BOOL isOK = TRUE;
- if(m_pssPre)
- {
- isOK = (pthread_sigmask(SIG_SETMASK, m_pssPre.get(), nullptr) == NO_ERROR);
- m_pssPre = nullptr;
- }
- m_pssCur = nullptr;
- m_pRunner = nullptr;
- m_pFunc = nullptr;
- return isOK;
- }
- public:
- CSignalHandler()
- {
- }
- virtual ~CSignalHandler()
- {
- Cancel();
- }
- DECLARE_NO_COPY_CLASS(CSignalHandler)
- private:
- T* m_pRunner;
- F m_pFunc;
- SSPTR m_pssCur;
- SSPTR m_pssPre;
- CHandlerThread m_thHandler;
- };
- using CStaticSignalHandler = CSignalHandler<__CFakeRunnerClass_>;
|