//---------------------------------------------------------------------
//
// Copyright (C) 2004 Yingle Jia
//
// Permission to copy, use, modify, sell and distribute this software is
// granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
//
#include "stdafx.h"
namespace Acf {
namespace Threading {
// Constructors
Timer::Timer(TimerCallback* callback, Object* state, int dueTime, int period)
{
if (callback == null)
throw ArgumentNullException();
this->_callback = callback;
this->_state = state;
this->_dueTime = dueTime;
this->_period = period;
this->_startEvent = new AutoResetEvent(false);
this->_waitEvent = new ManualResetEvent(false);
ThreadStartPtr start = new ThreadStart(this, &Timer::ThreadProc);
this->_thread = new Thread(start);
this->_thread->Start();
this->_startEvent->Set();
}
Timer::Timer(void (*callback)(Object*), Object* state, int dueTime, int period)
{
TimerCallbackPtr callback2 = new TimerCallback(callback);
new(this) Timer(callback2, state, dueTime, period);
}
Timer::Timer(TimerCallback* callback, Object* state, const TimeSpan& dueTime, const TimeSpan& period)
{
int dueTime2 = (int)dueTime.TotalMilliseconds;
int period2 = (int)period.TotalMilliseconds;
new(this) Timer(callback, state, dueTime2, period2);
}
Timer::Timer(void (*callback)(Object*), Object* state, const TimeSpan& dueTime, const TimeSpan& period)
{
int dueTime2 = (int)dueTime.TotalMilliseconds;
int period2 = (int)period.TotalMilliseconds;
new(this) Timer(callback, state, dueTime2, period2);
}
// Destructor
/*virtual*/ Timer::~Timer()
{
Dispose();
}
// Methods
void Timer::Change(int dueTime, int period)
{
if (this->_disposed)
throw InvalidOperationException();
if (dueTime < -1)
throw ArgumentOutOfRangeException();
if (period < -1)
throw ArgumentOutOfRangeException();
LOCK (this)
{
// Abort current timer
this->_aborted = true;
this->_waitEvent->Set();
// Record new dueTime and period
this->_dueTime = dueTime;
this->_period = period;
// Re-start the timer
this->_startEvent->Set();
}
}
void Timer::Change(const TimeSpan& dueTime, const TimeSpan& period)
{
int dueTime2 = (int)dueTime.TotalMilliseconds;
int period2 = (int)period.TotalMilliseconds;
Change(dueTime2, period2);
}
void Timer::Dispose()
{
if (!this->_disposed)
{
LOCK (this)
{
if (!this->_disposed)
{
// Set the disposing flag and wait for the thread to die
this->_disposed = true;
this->_waitEvent->Set();
this->_thread->Join();
}
}
}
}
void Timer::ThreadProc()
{
while (this->_startEvent->WaitOne())
{
this->_aborted = false;
//
// Wait for dueTime
//
if (this->_dueTime == Timeout::Infinite)
continue;
bool signaled = false;
this->_waitEvent->Reset();
signaled = this->_waitEvent->WaitOne(this->_dueTime);
if (!signaled)
this->_callback->Invoke(this->_state);
if (this->_disposed)
return;
else if (this->_aborted || this->_period == Timeout::Infinite)
continue;
//
// Wait for period
//
while (true)
{
this->_waitEvent->Reset();
signaled = this->_waitEvent->WaitOne(this->_period);
if (!signaled)
this->_callback->Invoke(this->_state);
if (this->_disposed)
return;
else if (this->_aborted)
break;
}
}
}
} // namespace Threading
} // namespace Acf