1+ #include " DelegateMQ.h"
12#include " Thread.h"
23#include " predef/util/Fault.h"
34
@@ -29,7 +30,7 @@ Thread::~Thread()
2930// ----------------------------------------------------------------------------
3031// CreateThread
3132// ----------------------------------------------------------------------------
32- bool Thread::CreateThread ()
33+ bool Thread::CreateThread (std::optional<dmq::Duration> watchdogTimeout )
3334{
3435 if (!m_thread)
3536 {
@@ -43,6 +44,27 @@ bool Thread::CreateThread()
4344 // Wait for the thread to enter the Process method
4445 m_threadStartFuture.get ();
4546
47+ m_lastAliveTime.store (Timer::GetTime ());
48+
49+ // Caller wants a watchdog timer?
50+ if (watchdogTimeout.has_value ())
51+ {
52+ // Create watchdog timer
53+ m_watchdogTimeout = watchdogTimeout.value ();
54+
55+ // Timer to ensure the Thread instance runs periodically. ThreadCheck invoked
56+ // on this thread instance.
57+ m_threadTimer = std::make_unique<Timer>();
58+ m_threadTimer->Expired = MakeDelegate (this , &Thread::ThreadCheck, *this );
59+ m_threadTimer->Start (m_watchdogTimeout.load () / 4 );
60+
61+ // Timer to check that this Thread instance runs. WatchdogCheck invoked
62+ // on Timer::ProcessTimers() thread.
63+ m_watchdogTimer = std::make_unique<Timer>();
64+ m_watchdogTimer->Expired = MakeDelegate (this , &Thread::WatchdogCheck);
65+ m_watchdogTimer->Start (m_watchdogTimeout.load () / 2 );
66+ }
67+
4668 LOG_INFO (" Thread::CreateThread {}" , THREAD_NAME );
4769 }
4870 return true ;
@@ -100,6 +122,11 @@ void Thread::ExitThread()
100122 if (!m_thread)
101123 return ;
102124
125+ if (m_watchdogTimer)
126+ m_watchdogTimer->Stop ();
127+ if (m_threadTimer)
128+ m_threadTimer->Stop ();
129+
103130 // Create a new ThreadMsg
104131 std::shared_ptr<ThreadMsg> threadMsg (new ThreadMsg (MSG_EXIT_THREAD , 0 ));
105132
@@ -147,6 +174,34 @@ void Thread::DispatchDelegate(std::shared_ptr<dmq::DelegateMsg> msg)
147174 typeid (*threadMsg->GetData ()->GetInvoker ()).name ());
148175}
149176
177+ // ----------------------------------------------------------------------------
178+ // WatchdogCheck
179+ // ----------------------------------------------------------------------------
180+ void Thread::WatchdogCheck ()
181+ {
182+ auto now = Timer::GetTime ();
183+ auto lastAlive = m_lastAliveTime.load ();
184+
185+ auto delta = Timer::Difference (lastAlive, now);
186+
187+ // Watchdog expired?
188+ if (delta > m_watchdogTimeout.load ())
189+ {
190+ LOG_ERROR (" Watchdog detected unresponsive thread: {}" , THREAD_NAME );
191+
192+ // @TODO You can optionally trigger recovery, restart, or further actions here
193+ // For example, throw or notify external system
194+ }
195+ }
196+
197+ // ----------------------------------------------------------------------------
198+ // ThreadCheck
199+ // ----------------------------------------------------------------------------
200+ void Thread::ThreadCheck ()
201+ {
202+ // Do nothing
203+ }
204+
150205// ----------------------------------------------------------------------------
151206// Process
152207// ----------------------------------------------------------------------------
@@ -155,10 +210,12 @@ void Thread::Process()
155210 // Signal that the thread has started processing to notify CreateThread
156211 m_threadStartPromise.set_value ();
157212
158- LOG_INFO (" Thread::Process {}" , THREAD_NAME );
213+ LOG_INFO (" Thread::Process Start {}" , THREAD_NAME );
159214
160215 while (1 )
161216 {
217+ m_lastAliveTime.store (Timer::GetTime ());
218+
162219 std::shared_ptr<ThreadMsg> msg;
163220 {
164221 // Wait for a message to be added to the queue
@@ -193,11 +250,15 @@ void Thread::Process()
193250
194251 case MSG_EXIT_THREAD :
195252 {
253+ LOG_INFO (" Thread::Process Exit Thread {}" , THREAD_NAME );
196254 return ;
197255 }
198256
199257 default :
258+ {
259+ LOG_INFO (" Thread::Process Invalid Message {}" , THREAD_NAME );
200260 throw std::invalid_argument (" Invalid message ID" );
261+ }
201262 }
202263 }
203264}
0 commit comments