Explorar o código

simplify timer

remove duplicated timestamp; refactor deadline processing to call cb
with released internal locks
alexey %!s(int64=3) %!d(string=hai) anos
pai
achega
3e257e5e40
Modificáronse 5 ficheiros con 40 adicións e 44 borrados
  1. 2 2
      src/coroutine.cpp
  2. 1 1
      src/coroutine.h
  3. 28 30
      src/mini_timer.cpp
  4. 6 2
      src/mini_timer.h
  5. 3 9
      src/searchdtask.cpp

+ 2 - 2
src/coroutine.cpp

@@ -843,7 +843,7 @@ void SleepMsec ( int iMsec )
 
 	struct Sleeper_t final: public MiniTimer_c
 	{
-		Sleeper_t () { m_szName = "SleepMsec"; }
+		Sleeper_t () : MiniTimer_c { "SleepMsec" } {}
 		Waker_c m_tWaker = Worker()->CreateWaker();
 		void OnTimer() final { m_tWaker.Wake(); }
 	} tWait;
@@ -929,7 +929,7 @@ struct ScheduledWait_t final: public MiniTimer_c
 {
 	Waker_c& m_tWaker;
 	void OnTimer() final { m_tWaker.Wake(); }
-	ScheduledWait_t ( Waker_c& tWaker, const char* szName ) : m_tWaker { tWaker } { m_szName = szName; }
+	ScheduledWait_t ( Waker_c& tWaker, const char* szName ) : MiniTimer_c { szName }, m_tWaker { tWaker } {}
 };
 
 // returns true if signalled, false if timed-out

+ 1 - 1
src/coroutine.h

@@ -249,7 +249,7 @@ class Throttler_c
 	int64_t m_tmNextThrottleTimestamp;
 	int m_tmThrottlePeriodMs;
 
-	MiniTimer_c m_dTimerGuard;
+	MiniTimer_c m_dTimerGuard { "throttler" };
 	bool m_bSameThread = true;
 
 	bool MaybeThrottle ();

+ 28 - 30
src/mini_timer.cpp

@@ -71,7 +71,7 @@ class TinyTimer_c
 	mutable CSphMutex m_tTimeoutsGuard; // guard is need as we can remove elems from any thread. That is short-live.
 	TimeoutQueue_c m_dTimeouts GUARDED_BY ( m_tTimeoutsGuard );
 
-	int64_t m_iNextTimeoutUS = -1;
+	// time
 	std::atomic<int64_t> m_tmLastTimestamp { sphMicroTimer() };
 
 	// management
@@ -117,43 +117,42 @@ private:
 		return &tScheduled;
 	}
 
-	int EnqueueStagingTasks() REQUIRES ( TimerThread ) EXCLUDES ( m_tTimeoutsGuard )
+	int AbandonStagingAndGetWaitPeriodMs() REQUIRES ( TimerThread ) EXCLUDES ( m_tTimeoutsGuard )
 	{
 		ScopedMutex_t tTimeoutsLock { m_tTimeoutsGuard };
 		while ( MiniTimer_c * pStagingTask = PopStagingTask() )
 			m_dTimeouts.Change ( pStagingTask );
 		if ( m_dTimeouts.IsEmpty() )
-		{
-			m_iNextTimeoutUS = 0;
 			return -1;
-		}
 
 		auto* pTask = (MiniTimer_c*)m_dTimeouts.Root();
-		m_iNextTimeoutUS = pTask->m_iTimeoutTimeUS;
-		return (int)( ( m_iNextTimeoutUS - MicroTimer() ) / sph::TICKS_GRANULARITY );
+		return (int)( ( pTask->m_iTimeoutTimeUS - MicroTimer() ) / sph::TICKS_GRANULARITY );
 	}
 
-	void ProcessTimerActions() REQUIRES ( TimerThread ) EXCLUDES ( m_tTimeoutsGuard )
+	MiniTimer_c* PopNextDeadlinedAction() EXCLUDES ( m_tTimeoutsGuard )
 	{
-		if ( !sph::TimeExceeded ( m_iNextTimeoutUS, MicroTimer() ) )
-			return;
-
 		ScopedMutex_t tTimeoutsLock { m_tTimeoutsGuard };
-		auto tmTimestamp = MicroTimer();
-		while ( !m_dTimeouts.IsEmpty() )
-		{
-			auto* pRoot = (MiniTimer_c*)m_dTimeouts.Root();
-			assert ( pRoot->m_iTimeoutTimeUS > 0 );
-			if ( !sph::TimeExceeded ( pRoot->m_iTimeoutTimeUS, tmTimestamp ) )
-				return;
-
-			// timeout reached; have to do an action
-			DEBUGT << "timeout happens for " << pRoot << " deadline " << timestamp_t (pRoot->m_iTimeoutTimeUS);
-			DEBUGT << m_dTimeouts.DebugDump ( "heap:" );
-			m_dTimeouts.Pop();
-			DEBUGT << "Oneshot task removed: " << pRoot;
+		if ( m_dTimeouts.IsEmpty() )
+			return nullptr;
+
+		auto pRoot = (MiniTimer_c*)m_dTimeouts.Root();
+		assert ( pRoot->m_iTimeoutTimeUS > 0 );
+		if ( !sph::TimeExceeded ( pRoot->m_iTimeoutTimeUS, MicroTimer() ) )
+			return nullptr;
+
+		// timeout reached; have to do an action
+		DEBUGT << "timeout happens for " << pRoot << " deadline " << timestamp_t ( pRoot->m_iTimeoutTimeUS );
+		DEBUGT << m_dTimeouts.DebugDump ( "heap:" );
+		m_dTimeouts.Pop();
+		DEBUGT << "Oneshot task removed: " << pRoot;
+
+		return pRoot;
+	}
+
+	void ProcessTimerActions() REQUIRES ( TimerThread ) EXCLUDES ( m_tTimeoutsGuard )
+	{
+		for ( MiniTimer_c* pRoot = PopNextDeadlinedAction(); pRoot; pRoot = PopNextDeadlinedAction() )
 			pRoot->OnTimer();
-		}
 	}
 
 	void Loop()
@@ -164,13 +163,13 @@ private:
 		{
 			DEBUGT << "---------------------------- Loop() tick";
 			ProcessTimerActions();
-			int iWait = EnqueueStagingTasks();
+			int iWait = AbandonStagingAndGetWaitPeriodMs();
 			if ( !iWait )
 			{
-				DEBUGT << "no sleep since timeout is 0; (" << timestamp_t ( m_iNextTimeoutUS ) << ")";
+				DEBUGT << "no sleep since timeout is 0; (" << timestamp_t ( iWait ) << ")";
 				continue;
 			}
-			DEBUGT << "calculated timeout is " << iWait << " ms (" << timestamp_t ( m_iNextTimeoutUS ) << ")";
+			DEBUGT << "calculated timeout is " << iWait << " ms (" << timestamp_t ( iWait ) << ")";
 			bool VARIABLE_IS_NOT_USED bWasKicked = m_tSignal.WaitEvent ( iWait );
 			DEBUGT << "awakened, reason=" << ( bWasKicked ? "kicked" : "timeout or error" );
 		}
@@ -305,8 +304,7 @@ void MiniTimer_c::UnEngage()
 
 MiniTimer_c::~MiniTimer_c()
 {
-	if ( m_szName )
-		UnEngage();
+	UnEngage();
 }
 
 /// returns true if provided timestamp is already reached or not

+ 6 - 2
src/mini_timer.h

@@ -49,13 +49,17 @@ namespace sph
 class MiniTimer_c: public EnqueuedTimeout_t
 {
 	friend class TinyTimer_c;
-	virtual void OnTimer() {};
+	virtual void OnTimer() {}; // notice, will be called from naked thread, not coroutine ctx!
+	const char* m_szName; // used as display name in 'debug sched', or '@@system.shed'.
 
 public:
 	sph::TimerHook_t m_tLink; // used to link timer in the queue
-	const char* m_szName = "mini-timer"; // hack! name and also flag that timer should be unlinked on destroy (if nullptr - dtr will do nothing)
 
 public:
+	explicit MiniTimer_c ( const char* szName = "mini-timer" )
+		: m_szName ( szName )
+	{}
+
 	/// on period<=0 does nothing, returns 0. On positive - engage tick after given period; returns timestamp where it should tick.
 	int64_t Engage ( int64_t iTimePeriodMS );
 	int64_t EngageUS ( int64_t iTimePeriodUS ); // same, but period is in microseconds

+ 3 - 9
src/searchdtask.cpp

@@ -114,17 +114,11 @@ private:
 		delete this;
 	}
 
-	~ScheduledTask_c() final
-	{
-		m_szName = nullptr; // signal to not call remove() in MiniTimer_c dtr
-	}
-
 	ScheduledTask_c ( TaskID iTask, Threads::Handler fnTask )
-		: m_iTask ( iTask )
+		: MiniTimer_c ( g_Tasks[iTask].m_sName.cstr() )
+		, m_iTask ( iTask )
 		, m_fnJob { std::move ( fnTask ) }
-	{
-		m_szName = g_Tasks[iTask].m_sName.cstr();
-	}
+	{}
 
 public:
 	static void EngageJob ( TaskID iTask, int64_t iTimeStampUS, Threads::Handler fnJob )