\r
\r
#include "complib/cl_timer.h"\r
+ \r
\r
+#define CL_MAX_TIME 0xFFFFFFFF\r
\r
+\r
+/*\r
+ * If timeout_time is 0, the timer has been stopped.\r
+ */\r
static void CALLBACK\r
__timer_callback( \r
IN cl_timer_t* const p_timer,\r
IN BOOLEAN timer_signalled )\r
{\r
- /* timer_signalled is always TRUE, and has no value. */\r
- CL_ASSERT( timer_signalled );\r
+ uint64_t timeout;\r
UNUSED_PARAM( timer_signalled );\r
\r
+ EnterCriticalSection( &p_timer->cb_lock );\r
+ EnterCriticalSection( &p_timer->lock );\r
+ timeout = p_timer->timeout_time;\r
p_timer->timeout_time = 0;\r
- p_timer->thread_id = GetCurrentThreadId();\r
+ LeaveCriticalSection( &p_timer->lock );\r
\r
- (p_timer->pfn_callback)( (void*)p_timer->context );\r
-\r
- p_timer->thread_id = 0;\r
+ if( timeout )\r
+ (p_timer->pfn_callback)( (void*)p_timer->context );\r
+ LeaveCriticalSection( &p_timer->cb_lock );\r
}\r
\r
\r
cl_timer_construct(\r
IN cl_timer_t* const p_timer )\r
{\r
- p_timer->h_timer = NULL;\r
- p_timer->timeout_time = 0;\r
- p_timer->thread_id = 0;\r
+ memset(p_timer, 0, sizeof *p_timer);\r
}\r
\r
\r
\r
p_timer->pfn_callback = pfn_callback;\r
p_timer->context = context;\r
+ InitializeCriticalSection( &p_timer->lock );\r
+ InitializeCriticalSection( &p_timer->cb_lock );\r
+ if( !CreateTimerQueueTimer( &p_timer->h_timer, NULL, __timer_callback,\r
+ p_timer, CL_MAX_TIME, CL_MAX_TIME, WT_EXECUTEINIOTHREAD ) )\r
+ return CL_ERROR;\r
return( CL_SUCCESS );\r
}\r
\r
{\r
CL_ASSERT( p_timer );\r
\r
- cl_timer_stop( p_timer );\r
+ DeleteTimerQueueTimer( NULL, p_timer->h_timer, INVALID_HANDLE_VALUE );\r
+ DeleteCriticalSection( &p_timer->lock );\r
+ DeleteCriticalSection( &p_timer->cb_lock );\r
}\r
\r
\r
IN cl_timer_t* const p_timer,\r
IN const uint32_t time_ms )\r
{\r
- CL_ASSERT( p_timer );\r
-\r
- cl_timer_stop( p_timer );\r
-\r
- p_timer->timeout_time = cl_get_time_stamp() + (((uint64_t)time_ms) * 1000);\r
-\r
- if( !CreateTimerQueueTimer( &p_timer->h_timer, NULL, __timer_callback,\r
- p_timer, time_ms, 0, WT_EXECUTEINIOTHREAD ) )\r
- {\r
- return( CL_ERROR );\r
- }\r
- \r
- return( CL_SUCCESS );\r
+ return cl_timer_trim( p_timer, time_ms );\r
}\r
\r
\r
IN cl_timer_t* const p_timer,\r
IN const uint32_t time_ms )\r
{\r
- uint64_t timeout_time;\r
+ uint64_t timeout;\r
+ cl_status_t status = CL_SUCCESS;\r
\r
CL_ASSERT( p_timer );\r
CL_ASSERT( p_timer->pfn_callback );\r
\r
- /* Calculate the timeout time in the timer object. */\r
- timeout_time = cl_get_time_stamp() + (((uint64_t)time_ms) * 1000);\r
-\r
- /* Only pull in the timeout time. */\r
- if( p_timer->timeout_time && p_timer->timeout_time < timeout_time )\r
- return( CL_SUCCESS );\r
-\r
- return cl_timer_start( p_timer, time_ms );\r
+ EnterCriticalSection( &p_timer->lock );\r
+ timeout = cl_get_time_stamp() + (((uint64_t)time_ms) * 1000);\r
+ if ( !p_timer->timeout_time || timeout < p_timer->timeout_time )\r
+ {\r
+ if( ChangeTimerQueueTimer( NULL, p_timer->h_timer, time_ms, CL_MAX_TIME ) )\r
+ p_timer->timeout_time = timeout;\r
+ else\r
+ status = CL_ERROR;\r
+ }\r
+ LeaveCriticalSection( &p_timer->lock );\r
+ return status;\r
}\r
\r
\r
+/*\r
+ * Acquire cb_lock to ensure that all callbacks have completed.\r
+ */\r
void\r
cl_timer_stop(\r
IN cl_timer_t* const p_timer )\r
{\r
CL_ASSERT( p_timer );\r
\r
- if( p_timer->h_timer && p_timer->thread_id != GetCurrentThreadId() )\r
- {\r
- /* Make sure we block until the timer is cancelled. */\r
- DeleteTimerQueueTimer( NULL, p_timer->h_timer, INVALID_HANDLE_VALUE );\r
- p_timer->h_timer = NULL;\r
- }\r
+ EnterCriticalSection( &p_timer->cb_lock );\r
+ EnterCriticalSection( &p_timer->lock );\r
p_timer->timeout_time = 0;\r
+ ChangeTimerQueueTimer( NULL, p_timer->h_timer, CL_MAX_TIME, CL_MAX_TIME );\r
+ LeaveCriticalSection( &p_timer->lock );\r
+ LeaveCriticalSection( &p_timer->cb_lock );\r
}\r
\r
\r