eapol/eapol_framework/eapol_common/am/common/eap_timer_queue.cpp
changeset 0 c8830336c852
child 2 1c7bc153c08e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eapol/eapol_framework/eapol_common/am/common/eap_timer_queue.cpp	Thu Dec 17 08:47:43 2009 +0200
@@ -0,0 +1,1721 @@
+/*
+* Copyright (c) 2001-2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  EAP and WLAN authentication protocols.
+*
+*/
+
+
+// This is enumeration of EAPOL source code.
+#if defined(USE_EAP_MINIMUM_RELEASE_TRACES)
+	#undef EAP_FILE_NUMBER_ENUM
+	#define EAP_FILE_NUMBER_ENUM 15 
+	#undef EAP_FILE_NUMBER_DATE 
+	#define EAP_FILE_NUMBER_DATE 1127594498 
+#endif //#if defined(USE_EAP_MINIMUM_RELEASE_TRACES)
+
+
+#include "eap_am_memory.h"
+#include "eap_timer_queue.h"
+
+//--------------------------------------------------
+
+#if defined(USE_EAP_TIMER_QUEUE_TRACE)
+	#define EAP_TRACE_TIMER EAP_TRACE_DEBUG
+#else
+	#define EAP_TRACE_TIMER(object, flags, parameters)
+#endif //#if defined(USE_EAP_TIMER_QUEUE_TRACE)
+
+//--------------------------------------------------
+
+// 
+eap_timer_queue_event_c::~eap_timer_queue_event_c()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	m_initializer->timer_delete_data(m_id, m_data);
+	m_initializer = 0;
+	m_id = 0;
+	m_data = 0;
+	m_hash = 0;
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+
+// 
+eap_timer_queue_event_c::eap_timer_queue_event_c(
+	abs_eap_am_tools_c * const tools, 
+	abs_eap_base_timer_c * const initializer, 
+	const u32_t id, 
+	void * const data,
+	const u32_t p_time_ms)
+	: m_am_tools(tools)
+	, m_initializer(initializer)
+	, m_id(id)
+	, m_data(data)
+	, m_time_ms(p_time_ms)
+	, m_original_time_ms(p_time_ms)
+	, m_prev(0)
+	, m_next(0)
+	, m_hash(0)
+	, m_prev_same_time(0)
+	, m_next_same_time(0)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+
+// 
+u32_t eap_timer_queue_event_c::get_time() const
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return m_time_ms;
+}
+
+//--------------------------------------------------
+
+// 
+u32_t eap_timer_queue_event_c::get_original_time() const
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return m_original_time_ms;
+}
+
+//--------------------------------------------------
+
+// 
+eap_timer_queue_event_c *eap_timer_queue_event_c::get_prev() const
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return m_prev;
+}
+
+//--------------------------------------------------
+
+// 
+eap_timer_queue_event_c *eap_timer_queue_event_c::get_next() const
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return m_next;
+}
+
+//--------------------------------------------------
+
+// 
+eap_timer_queue_event_c *eap_timer_queue_event_c::get_prev_same_time() const
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return m_prev_same_time;
+}
+
+//--------------------------------------------------
+
+// 
+eap_timer_queue_event_c *eap_timer_queue_event_c::get_next_same_time() const
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return m_next_same_time;
+}
+
+//--------------------------------------------------
+
+// 
+eap_timer_queue_hash_c * eap_timer_queue_event_c::get_hash() const
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return m_hash;
+}
+
+//--------------------------------------------------
+
+// 
+u32_t eap_timer_queue_event_c::pulse_time(const u32_t resolution)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	if (m_time_ms >= resolution)
+	{
+		m_time_ms -= resolution;
+		
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return 0u;
+	}
+	else
+	{
+		u32_t remainder = resolution - m_time_ms;
+		m_time_ms = 0u;
+		
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return remainder;
+	}
+}
+
+//--------------------------------------------------
+
+// 
+void eap_timer_queue_event_c::decrease_time_left(const u32_t decrease_time)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	if (m_time_ms > decrease_time)
+	{
+		m_time_ms -= decrease_time;
+	}
+	else
+	{
+		m_time_ms = 0u;
+	}
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+
+// 
+void eap_timer_queue_event_c::increase_time_left(const u32_t increase_time)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	m_time_ms += increase_time;
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+
+// 
+void eap_timer_queue_event_c::set_prev(eap_timer_queue_event_c * const prev)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	m_prev = prev;
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+
+// 
+void eap_timer_queue_event_c::set_next(eap_timer_queue_event_c * const next)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	m_next = next;
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+
+// 
+void eap_timer_queue_event_c::set_prev_same_time(eap_timer_queue_event_c * const prev_same_time)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	m_prev_same_time = prev_same_time;
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+
+// 
+void eap_timer_queue_event_c::set_next_same_time(eap_timer_queue_event_c * const next_same_time)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	m_next_same_time = next_same_time;
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+
+// 
+void eap_timer_queue_event_c::set_hash(eap_timer_queue_hash_c * const hash)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	m_hash = hash;
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+
+// 
+abs_eap_base_timer_c * eap_timer_queue_event_c::get_initializer() const
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return m_initializer;
+}
+
+//--------------------------------------------------
+
+// 
+u32_t eap_timer_queue_event_c::get_id() const
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return m_id;
+}
+
+//--------------------------------------------------
+
+// 
+void * eap_timer_queue_event_c::get_data() const
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return m_data;
+}
+
+//--------------------------------------------------
+
+// 
+u32_t eap_timer_queue_event_c::get_time_ms()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return m_time_ms;
+}
+
+//--------------------------------------------------
+//--------------------------------------------------
+//--------------------------------------------------
+
+// 
+eap_timer_queue_hash_c::~eap_timer_queue_hash_c()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	m_atom = 0;
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+	//--------------------------------------------------
+
+// 
+eap_timer_queue_hash_c::eap_timer_queue_hash_c(
+	abs_eap_am_tools_c * const tools, 
+	eap_timer_queue_event_c * const atom,
+	const u32_t index)
+	: m_am_tools(tools)
+	, m_index(index)
+	, m_atom(atom)
+	, m_prev(0)
+	, m_next(0)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+
+// 
+eap_timer_queue_hash_c *eap_timer_queue_hash_c::get_next() const
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return m_next;
+}
+
+//--------------------------------------------------
+
+// 
+eap_timer_queue_hash_c *eap_timer_queue_hash_c::get_prev() const
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return m_prev;
+}
+
+//--------------------------------------------------
+
+// 
+u32_t eap_timer_queue_hash_c::get_index() const
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return m_index;
+}
+
+//--------------------------------------------------
+
+// 
+void eap_timer_queue_hash_c::set_next(eap_timer_queue_hash_c * const next)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	m_next = next;
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+
+// 
+void eap_timer_queue_hash_c::set_prev(eap_timer_queue_hash_c * const prev)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	m_prev = prev;
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+
+eap_timer_queue_event_c * eap_timer_queue_hash_c::get_atom()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return m_atom;
+}
+
+//--------------------------------------------------
+
+i32_t eap_timer_queue_hash_c::compare(
+	const abs_eap_base_timer_c * const a_initializer, 
+	const u32_t a_id,
+	const abs_eap_base_timer_c * const b_initializer, 
+	const u32_t b_id)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	if (a_id < b_id)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return -1;
+	}
+	else if (a_id > b_id)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return 1;
+	}
+	else if (a_initializer < b_initializer)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return -1;
+	}
+	else if (a_initializer > b_initializer)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return 1;
+	}
+	else
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return 0;
+	}
+}
+
+//--------------------------------------------------
+//--------------------------------------------------
+//--------------------------------------------------
+
+eap_timer_queue_c::~eap_timer_queue_c()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	deactivate_timer_queue();
+
+	// cancel_all_timers() must be called before destructor.
+	EAP_ASSERT_TOOLS(m_am_tools, m_timer_queue == 0);
+	EAP_ASSERT_TOOLS(m_am_tools, m_new_event_begin == 0);
+	EAP_ASSERT_TOOLS(m_am_tools, m_new_event_end == 0);
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+
+eap_timer_queue_c::eap_timer_queue_c(
+	abs_eap_am_tools_c * const tools, 
+	const u32_t timer_resolution_ms)
+	: m_am_tools(tools)
+	, m_timer_queue(0)
+	, m_new_event_begin(0)
+	, m_new_event_end(0)
+	, m_timer_resolution_ms(timer_resolution_ms)
+	, m_is_active(false)
+	, m_is_valid(false)
+	, m_use_eap_millisecond_timer(false)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	for(u32_t ind = 0; ind < EAP_TIMER_QUEUE_HASH_SIZE; ind++)
+	{
+		m_map[ind] = 0;
+	}
+	
+	m_is_active = true;
+	m_is_valid = true;
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+
+bool eap_timer_queue_c::get_use_eap_milli_second_timer()
+{
+	return m_use_eap_millisecond_timer;
+}
+
+//--------------------------------------------------
+
+void eap_timer_queue_c::set_use_eap_milli_second_timer(const bool use_eap_millisecond_timer)
+{
+	m_use_eap_millisecond_timer = use_eap_millisecond_timer;
+}
+
+//--------------------------------------------------
+
+u32_t eap_timer_queue_c::get_timer_resolution_ms()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return m_timer_resolution_ms;
+}
+
+//--------------------------------------------------
+
+void eap_timer_queue_c::set_timer_resolution_ms(const u32_t timer_resolution_ms)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	m_timer_resolution_ms = timer_resolution_ms;
+}
+
+//--------------------------------------------------
+
+void eap_timer_queue_c::deactivate_timer_queue()
+{
+	m_is_active = false;
+}
+
+//--------------------------------------------------
+
+// This is used in Symbian AM.
+eap_status_e eap_timer_queue_c::re_activate_timer_queue()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	m_is_active = true;
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+//--------------------------------------------------
+
+void eap_timer_queue_c::trace_timer_event(
+	const eap_const_string prefix, 
+	const eap_timer_queue_event_c * const event)
+{
+
+	EAP_UNREFERENCED_PARAMETER(prefix);
+	EAP_UNREFERENCED_PARAMETER(event);
+
+#if defined(USE_EAP_TIMER_QUEUE_TRACE)
+#if !defined(NO_EAP_TIMER_QUEUE)
+
+	EAP_TRACE_TIMER(
+		m_am_tools,
+		TRACE_FLAGS_TIMER_QUEUE,
+		(EAPL("TIMER: queue: %s, %s[0x%08x], original time %8d, ")
+		 EAPL("time left %8d, initializer 0x%08x, ")
+		 EAPL("id 0x%02x, data 0x%08x, prev 0x%08x, ")
+		 EAPL("next 0x%08x, prev same time 0x%08x, next same time 0x%08x\n"),
+		 prefix,
+		 ((event == m_timer_queue || event->get_time() != 0) ? "-> ": "   "),
+		 event, 
+		 event->get_original_time(),
+		 event->get_time(), 
+		 event->get_initializer(), 
+		 event->get_id(), 
+		 event->get_data(), 
+		 event->get_prev(), 
+		 event->get_next(), 
+		 event->get_prev_same_time(), 
+		 event->get_next_same_time()));
+
+#endif //#if !defined(NO_EAP_TIMER_QUEUE)
+#endif //#if defined(USE_EAP_TIMER_QUEUE_TRACE)
+}
+
+//--------------------------------------------------
+
+void eap_timer_queue_c::trace_timer()
+{
+#if defined(USE_EAP_TIMER_QUEUE_TRACE)
+#if !defined(NO_EAP_TIMER_QUEUE)
+
+	if ( ! (m_am_tools->get_trace_mask() & (TRACE_FLAGS_TIMER_QUEUE)))
+	{
+		return;
+	}
+
+	eap_timer_queue_event_c *cursor = m_timer_queue;
+	eap_timer_queue_event_c *prev = 0;
+	EAP_UNREFERENCED_PARAMETER(prev);
+
+	EAP_TRACE_TIMER(
+		m_am_tools,
+		TRACE_FLAGS_TIMER_QUEUE,
+		(EAPL("-------------------------------------------------------------------------\n")));
+	EAP_TRACE_TIMER(
+		m_am_tools,
+		TRACE_FLAGS_TIMER_QUEUE,
+		(EAPL("TIMER: current timer queue:\n")));
+
+	if (cursor == 0
+		&& m_new_event_begin == 0)
+	{
+		EAP_TRACE_TIMER(
+			m_am_tools,
+			TRACE_FLAGS_TIMER_QUEUE,
+			(EAPL("TIMER: queue: is empty\n")));
+	}
+
+
+	{
+		eap_timer_queue_event_c *pending = m_new_event_begin;
+		
+		while(pending != 0)
+		{
+			trace_timer_event("new", pending);
+			
+			pending = pending->get_next();
+		}
+	}
+
+
+	while(cursor != 0)
+	{
+		EAP_ASSERT(prev == cursor->get_prev());
+
+		{
+			eap_timer_queue_event_c *vertical = cursor;
+			
+			while(vertical != 0)
+			{
+				trace_timer_event("old", vertical);
+
+				vertical = vertical->get_next_same_time();
+			}
+		}
+
+		prev = cursor;
+		cursor = cursor->get_next();
+
+		EAP_ASSERT(prev->get_next() == cursor);
+	}
+
+	EAP_TRACE_TIMER(
+		m_am_tools,
+		TRACE_FLAGS_TIMER_QUEUE,
+		(EAPL("-------------------------------------------------------------------------\n")));
+
+#endif //#if !defined(NO_EAP_TIMER_QUEUE)
+#endif //#if defined(USE_EAP_TIMER_QUEUE_TRACE)
+}
+
+//--------------------------------------------------
+
+u32_t eap_timer_queue_c::pulse_timer(
+	const u32_t elapsed_time_in_ms,
+	const bool can_call_timer_expired_when_true)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	u32_t next_sleep_time = get_timer_resolution_ms();
+
+#if !defined(NO_EAP_TIMER_QUEUE)
+
+	EAP_TRACE_TIMER(
+		m_am_tools,
+		TRACE_FLAGS_TIMER,
+		(EAPL("TIMER: pulse_timer(%u), can_call_timer_expired_when_true %d\n"),
+		 elapsed_time_in_ms,
+		 can_call_timer_expired_when_true));
+
+	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
+
+	trace_timer();
+
+	if (m_timer_queue != 0)
+	{
+		u32_t remainder_time = m_timer_queue->pulse_time(elapsed_time_in_ms);
+
+		if (can_call_timer_expired_when_true == true)
+		{
+			while (m_timer_queue != 0
+				&& m_timer_queue->get_time() == 0)
+			{
+				eap_timer_queue_event_c *current = m_timer_queue;
+
+				EAP_ASSERT(m_timer_queue->get_prev() == 0);
+				EAP_ASSERT(current->get_time() == 0);
+
+				if (current->get_next_same_time() != 0)
+				{
+					eap_timer_queue_event_c *next = current->get_next_same_time();
+
+					EAP_ASSERT(next->get_prev() == 0 && next->get_next() == 0);
+
+					next->set_prev_same_time(0);
+					next->set_next(m_timer_queue->get_next());
+
+					if (m_timer_queue->get_next() != 0)
+					{
+						m_timer_queue->get_next()->set_prev(next);
+					}
+
+					m_timer_queue = next;
+				}
+				else
+				{
+					m_timer_queue = m_timer_queue->get_next();
+					if (m_timer_queue != 0)
+					{
+						m_timer_queue->set_prev(0);
+					}
+				}
+
+				if (current != 0)
+				{
+					EAP_TRACE_TIMER(
+						m_am_tools,
+						TRACE_FLAGS_DEFAULT,
+						(EAPL("TIMER: timer_expired(): [0x%08x]->initializer(0x%08x)->timer_expired(")
+						 EAPL("id 0x%02x, data 0x%08x, original time %8d)\n"),
+						 current,
+						 current->get_initializer(),
+						 current->get_id(),
+						 current->get_data(),
+						 current->get_original_time()));
+
+					remove_hash_of_timer_event(current);
+
+					current->set_prev_same_time(0);
+					current->set_next_same_time(0);
+					current->set_prev(0);
+					current->set_next(0);
+
+					current->get_initializer()->timer_expired(
+						current->get_id(),
+						current->get_data());
+
+					delete current;
+				}
+			
+				if (remainder_time != 0u
+					&& m_timer_queue != 0)
+				{
+					remainder_time = m_timer_queue->pulse_time(remainder_time);
+				}
+			} // while(m_timer_queue != 0
+			  //	&& m_timer_queue->get_time() == 0)
+		} // if (can_call_timer_expired_when_true == true)
+	}
+
+
+	if (m_use_eap_millisecond_timer == true)
+	{
+		// New timer events are added here because the current
+		// pulse might be very long, and the long pulse will
+		// cause the new event expire immediately.
+		// By using this function the shortest timer events in the
+		// timer queue are handled and after that the new timer events
+		// are added to timer queue.
+		eap_status_e status = add_pending_timer();
+		if (status != eap_status_ok)
+		{
+			next_sleep_time = get_timer_resolution_ms();
+
+			EAP_TRACE_TIMER(
+				m_am_tools,
+				TRACE_FLAGS_TIMER,
+				(EAPL("ERROR: TIMER: add_pending_timer() status=%d, next_sleep_time=%d\n"),
+				 status,
+				 next_sleep_time));
+	
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			(void) EAP_STATUS_RETURN(m_am_tools, status);
+			return next_sleep_time;
+		}
+	}
+
+
+	if (m_timer_queue != 0)
+	{
+		next_sleep_time = m_timer_queue->get_time();
+	}
+	else
+	{
+		if (m_use_eap_millisecond_timer == true)
+		{
+			next_sleep_time = EAP_TIMER_QUEUE_LONG_SLEEP_TIME;
+		}
+	}
+
+	trace_timer();
+
+	if (m_use_eap_millisecond_timer == false)
+	{
+		next_sleep_time = get_timer_resolution_ms();
+	}
+
+	EAP_TRACE_TIMER(
+		m_am_tools,
+		TRACE_FLAGS_TIMER,
+		(EAPL("TIMER: next_sleep_time=%d\n"),
+		 next_sleep_time));
+	
+#endif //#if !defined(NO_EAP_TIMER_QUEUE)
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return next_sleep_time;
+}
+
+
+//--------------------------------------------------
+
+bool eap_timer_queue_c::get_timer_queue_is_empty()
+{
+
+#if !defined(NO_EAP_TIMER_QUEUE)
+
+	EAP_TRACE_TIMER(
+		m_am_tools,
+		TRACE_FLAGS_TIMER,
+		(EAPL("TIMER: get_timer_queue_is_empty(): m_timer_queue=0x%08x, m_new_event_begin=0x%08x\n"),
+		 m_timer_queue,
+		 m_new_event_begin));
+
+	return (m_timer_queue == 0 && m_new_event_begin == 0);
+
+#else
+
+	return true;
+
+#endif //#if !defined(NO_EAP_TIMER_QUEUE)
+
+}
+
+//--------------------------------------------------
+
+#if !defined(NO_EAP_TIMER_QUEUE)
+
+eap_status_e eap_timer_queue_c::add_hash_of_timer_event(
+	eap_timer_queue_event_c * const event,
+	const abs_eap_base_timer_c * const initializer, 
+	const u32_t id)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	const u32_t index = hash(EAP_TIMER_QUEUE_HASH_SIZE, initializer, id);
+
+	if (index >= EAP_TIMER_QUEUE_HASH_SIZE)
+	{
+		EAP_TRACE_TIMER(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("ERROR: TIMER HASH: add_handler(): initializer 0x%08x, ")
+			 EAPL("id 0x%02x,  index %d >= EAP_TIMER_QUEUE_HASH_SIZE %d\n"),
+			 initializer,
+			 id,
+			 index,
+			 EAP_TIMER_QUEUE_HASH_SIZE));
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_hashed_index);
+	}
+
+	eap_timer_queue_hash_c *hash = new eap_timer_queue_hash_c(m_am_tools, event, index);
+
+	if (hash == 0)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	event->set_hash(hash);
+
+	eap_timer_queue_hash_c *cursor = m_map[index];
+	eap_timer_queue_hash_c *last_cursor = 0;
+
+	EAP_TRACE_TIMER(
+		m_am_tools,
+		TRACE_FLAGS_TIMER,
+		(EAPL("TIMER HASH: add_handler(): initializer 0x%08x, id 0x%02x,  index %d\n"),
+		 initializer,
+		 id,
+		 index));
+
+	while (cursor != 0)
+	{
+		if (hash->compare(hash->get_atom()->get_initializer(),
+			hash->get_atom()->get_id(),
+			cursor->get_atom()->get_initializer(),
+			cursor->get_atom()->get_id()) == 0)
+		{
+			// match
+			break;
+		}
+		last_cursor = cursor;
+		cursor = cursor->get_next();
+	}
+
+	EAP_TRACE_TIMER(
+		m_am_tools,
+		TRACE_FLAGS_TIMER,
+		(EAPL("TIMER HASH: add_hash_of_timer_event(): hash 0x%08x\n"),
+		 hash));
+
+	EAP_ASSERT(hash->get_index() == index);
+
+	if (last_cursor != 0)
+	{
+		if (last_cursor->get_next() != 0)
+		{
+			last_cursor->get_next()->set_prev(hash);
+		}
+		hash->set_next(last_cursor->get_next());
+		last_cursor->set_next(hash);
+		hash->set_prev(last_cursor);
+	}
+	else
+	{
+		if (m_map[index] != 0)
+		{
+			m_map[index]->set_prev(hash);
+		}
+		hash->set_next(m_map[index]);
+		m_map[index] = hash;
+		hash->set_prev(0);
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+#endif //#if !defined(NO_EAP_TIMER_QUEUE)
+
+//--------------------------------------------------
+
+#if !defined(NO_EAP_TIMER_QUEUE)
+
+eap_timer_queue_event_c * eap_timer_queue_c::get_hashed_timer_event(
+	const abs_eap_base_timer_c * const initializer, 
+	const u32_t id)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	const u32_t index = hash(EAP_TIMER_QUEUE_HASH_SIZE, initializer, id);
+
+	if (index >= EAP_TIMER_QUEUE_HASH_SIZE)
+	{
+		EAP_TRACE_TIMER(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("ERROR: TIMER HASH: get_handler(): initializer 0x%08x, ")
+			 EAPL("id 0x%02x,  index %d >= EAP_TIMER_QUEUE_HASH_SIZE %d\n"),
+			 initializer,
+			 id,
+			 index,
+			 EAP_TIMER_QUEUE_HASH_SIZE));
+		return 0;
+	}
+
+	eap_timer_queue_hash_c *cursor = m_map[index];
+
+	EAP_TRACE_TIMER(
+		m_am_tools,
+		TRACE_FLAGS_TIMER,
+		(EAPL("TIMER HASH: get_handler(): initializer 0x%08x, id 0x%02x,  index %d\n"),
+		 initializer,
+		 id,
+		 index));
+
+	while (cursor != 0)
+	{
+		eap_timer_queue_event_c * const event = cursor->get_atom();
+
+		if (cursor->compare(initializer,
+			id,
+			event->get_initializer(),
+			event->get_id()) == 0)
+		{
+			// match
+			EAP_TRACE_TIMER(
+				m_am_tools,
+				TRACE_FLAGS_TIMER,
+				(EAPL("TIMER HASH: match: get_handler(): initializer 0x%08x, ")
+				 EAPL("id 0x%02x,  index %d, atom 0x%08x\n"),
+				 initializer,
+				 id,
+				 index,
+				 cursor->get_atom()));
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return cursor->get_atom();
+		}
+
+		cursor = cursor->get_next();
+	}
+
+	EAP_TRACE_TIMER(
+		m_am_tools,
+		TRACE_FLAGS_TIMER,
+		(EAPL("WARNING: TIMER HASH: not found: get_handler(): ")
+		 EAPL("initializer 0x%08x, id 0x%02x,  index %d\n"),
+		 initializer,
+		 id,
+		 index));
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return 0;
+}
+
+#endif //#if !defined(NO_EAP_TIMER_QUEUE)
+
+//--------------------------------------------------
+
+#if !defined(NO_EAP_TIMER_QUEUE)
+
+eap_status_e eap_timer_queue_c::remove_hash_of_timer_event(
+	eap_timer_queue_event_c * const event)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	if (event == 0
+		|| event->get_hash() == 0)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
+	}
+
+	eap_timer_queue_hash_c *hash = event->get_hash();
+	event->set_hash(0);
+
+	if (hash->get_prev() != 0)
+	{
+		// Remove from middle.
+		EAP_ASSERT(m_map[hash->get_index()] != hash);
+
+		if (hash->get_next() != 0)
+		{
+			hash->get_next()->set_prev(hash->get_prev());
+		}
+		hash->get_prev()->set_next(hash->get_next());
+	}
+	else
+	{
+		// Remove the first item.
+		EAP_ASSERT(m_map[hash->get_index()] == hash);
+		EAP_ASSERT(hash->get_prev() == 0);
+
+		if (hash->get_next() != 0)
+		{
+			hash->get_next()->set_prev(hash->get_prev());
+		}
+		m_map[hash->get_index()] = hash->get_next();
+		EAP_ASSERT(m_map[hash->get_index()] == 0
+			|| m_map[hash->get_index()]->get_prev() == 0);
+	}
+
+	delete hash;
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+#endif //#if !defined(NO_EAP_TIMER_QUEUE)
+
+//--------------------------------------------------
+
+// 
+u32_t eap_timer_queue_c::hash(
+	const u32_t size,
+	const abs_eap_base_timer_c * const initializer, 
+	const u32_t id) const
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	u32_t ihash = 0x55555555;
+
+	ihash += static_cast<u32_t>(id);
+	ihash += reinterpret_cast<u32_t>(initializer);
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return ihash % size;
+}
+
+//--------------------------------------------------
+
+void eap_timer_queue_c::add_end_of_vertical_list(
+	eap_timer_queue_event_c * const begin,
+	eap_timer_queue_event_c * const event)
+{
+	EAP_ASSERT(begin != 0 && event != 0);
+
+	eap_timer_queue_event_c * previous = 0;
+	eap_timer_queue_event_c * current = begin;
+
+	while (current != 0)
+	{
+		previous = current;
+		current = current->get_next_same_time();
+	}
+
+	// Add to the vertical list of previous time.
+	event->set_next_same_time(previous->get_next_same_time());
+	if (previous->get_next_same_time() != 0)
+	{
+		previous->get_next_same_time()->set_prev_same_time(event);
+	}
+	previous->set_next_same_time(event);
+	event->set_prev_same_time(previous);
+}
+
+//--------------------------------------------------
+
+eap_status_e eap_timer_queue_c::add_timer(
+	eap_timer_queue_event_c *event)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+#if !defined(NO_EAP_TIMER_QUEUE)
+
+	eap_status_e status = add_hash_of_timer_event(
+		event,
+		event->get_initializer(),
+		event->get_id());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+
+	if (m_timer_queue == 0)
+	{
+		m_timer_queue = event;
+
+		EAP_TRACE_TIMER(
+			m_am_tools,
+			TRACE_FLAGS_TIMER,
+			(EAPL("TIMER: [0x%08x] add_timer(initializer 0x%08x, ")
+			 EAPL("id 0x%02x, data 0x%08x, time %d)\n"),
+			 m_timer_queue,
+			 event->get_initializer(),
+			 event->get_id(),
+			 event->get_data(),
+			 event->get_time_ms()));
+	}
+	else
+	{
+		EAP_TRACE_TIMER(
+			m_am_tools,
+			TRACE_FLAGS_TIMER,
+			(EAPL("TIMER: [0x%08x]\n"),
+			 event));
+
+		EAP_TRACE_TIMER(
+			m_am_tools,
+			TRACE_FLAGS_TIMER,
+			(EAPL("TIMER: initializer 0x%08x\n"),
+			 event->get_initializer()));
+
+		EAP_TRACE_TIMER(
+			m_am_tools,
+			TRACE_FLAGS_TIMER,
+			(EAPL("TIMER: id 0x%02x\n"),
+			 event->get_id()));
+
+		EAP_TRACE_TIMER(
+			m_am_tools,
+			TRACE_FLAGS_TIMER,
+			(EAPL("TIMER: data 0x%08x\n"),
+			 event->get_data()));
+
+		EAP_TRACE_TIMER(
+			m_am_tools,
+			TRACE_FLAGS_TIMER,
+			(EAPL("TIMER: time %d\n"),
+			 event->get_time_ms()));
+
+		EAP_TRACE_TIMER(
+			m_am_tools,
+			TRACE_FLAGS_TIMER,
+			(EAPL("TIMER: [0x%08x] add_timer(initializer 0x%08x, ")
+			 EAPL("id 0x%02x, data 0x%08x, time %d)\n"),
+			 event,
+			 event->get_initializer(),
+			 event->get_id(),
+			 event->get_data(),
+			 event->get_time_ms()));
+
+		eap_timer_queue_event_c *current = m_timer_queue;
+		eap_timer_queue_event_c *prev = 0;
+		u32_t time_ms_sum = 0u;
+		u32_t tmp_time_ms = 0u;
+
+
+		while(current != 0)
+		{
+			tmp_time_ms = current->get_time();
+
+			time_ms_sum += tmp_time_ms;
+
+			if (time_ms_sum >= event->get_time())
+			{
+				// Time segment found.
+				// tmp_time_ms is decremented from time_ms_sum
+				// because of we need time sum before current.
+				// New event is added before current.
+				if (time_ms_sum > event->get_time())
+				{
+					time_ms_sum -= tmp_time_ms;
+				}
+				else
+				{
+					// current points to the same time sum.
+				}
+				break;
+			}
+
+			prev = current;
+			current = current->get_next();
+		} // while(current != 0)
+
+
+		if (prev == 0
+			&& time_ms_sum == 0)
+		{
+			// Add to first.
+
+			if (m_timer_queue != 0
+				&& m_timer_queue->get_time() == event->get_time())
+			{
+				// Add to the first vertical list, in the end of the vertical list.
+				m_timer_queue->decrease_time_left(event->get_time()); // event->get_time() == 0.
+				add_end_of_vertical_list(m_timer_queue, event);
+			}
+			else
+			{
+				if (m_timer_queue != 0)
+				{
+					m_timer_queue->decrease_time_left(event->get_time());
+				}
+				event->set_next(m_timer_queue);
+				m_timer_queue->set_prev(event);
+				m_timer_queue = event;
+			}
+		}
+		else if (current != 0
+			&& time_ms_sum == event->get_time())
+		{
+			add_end_of_vertical_list(current, event);
+			event->decrease_time_left(event->get_time()); // event->get_time() == 0.
+		}
+		else
+		{
+			// Add new vertical list to middle.
+			EAP_ASSERT(prev != 0);
+
+			event->decrease_time_left(time_ms_sum);
+
+			if (prev != 0)
+			{
+				event->set_next(prev->get_next());
+				if (prev->get_next() != 0)
+				{
+					prev->get_next()->set_prev(event);
+					prev->get_next()->decrease_time_left(event->get_time());
+				}
+				prev->set_next(event);
+				event->set_prev(prev);
+			}
+		}
+	}
+
+	trace_timer();
+
+#endif //#if !defined(NO_EAP_TIMER_QUEUE)
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+//--------------------------------------------------
+
+eap_status_e eap_timer_queue_c::add_new_pending_timer(
+	eap_timer_queue_event_c *event)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_TIMER(
+		m_am_tools,
+		TRACE_FLAGS_TIMER,
+		(EAPL("TIMER: [0x%08x] add_new_pending_timer(initializer 0x%08x, ")
+		 EAPL("id 0x%02x, data 0x%08x, time %d)\n"),
+		 m_timer_queue,
+		 event->get_initializer(),
+		 event->get_id(),
+		 event->get_data(),
+		 event->get_time_ms()));
+
+	// Adds the new event to the end of the list to keep the order of events correct.
+	EAP_ASSERT(m_new_event_begin == 0
+		&& m_new_event_end == 0
+		|| m_new_event_begin != 0
+		&& m_new_event_end != 0);
+
+	if (m_new_event_begin == 0
+		&& m_new_event_end == 0)
+	{
+		// Adds to the begin.
+		m_new_event_begin = event;
+		m_new_event_end = event;
+	}
+	else
+	{
+		// Adds to the end.
+		m_new_event_end->set_next(event);
+		m_new_event_end = event;
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+//--------------------------------------------------
+
+eap_status_e eap_timer_queue_c::set_timer(
+	abs_eap_base_timer_c * const initializer, 
+	const u32_t id, 
+	void * const data,
+	const u32_t time_ms)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_STACK_TRACE(initializer);
+
+	if (m_is_active == false)
+	{
+		initializer->timer_delete_data(id, data);
+		EAP_TRACE_TIMER(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("WARNING: TIMER: not accepted, timer queue is inactive: ")
+			 EAPL("[0x%08x] set_timer(initializer 0x%08x, id 0x%02x, data 0x%08x, time %d)\n"),
+			 m_timer_queue,
+			 initializer,
+			 id,
+			 data,
+			 time_ms));
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_not_supported);
+	}
+
+#if !defined(NO_EAP_TIMER_QUEUE)
+
+	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
+
+	trace_timer();
+
+	eap_timer_queue_event_c *event = new eap_timer_queue_event_c(
+		m_am_tools,
+		initializer,
+		id,
+		data,
+		time_ms);
+
+	if (event == 0)
+	{
+		initializer->timer_delete_data(id, data);
+
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+
+	if (m_use_eap_millisecond_timer == true)
+	{
+		// The next pulse_timer() function call will add the event to timer queue.
+		eap_status_e status = add_new_pending_timer(event);
+		if (status != eap_status_ok)
+		{
+			delete event;
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+	else
+	{
+		eap_status_e status = add_timer(event);
+		if (status != eap_status_ok)
+		{
+			delete event;
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+#endif //#if !defined(NO_EAP_TIMER_QUEUE)
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+//--------------------------------------------------
+
+eap_status_e eap_timer_queue_c::add_pending_timer()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	eap_status_e status(eap_status_ok);
+
+	while (m_new_event_begin != 0)
+	{
+		eap_timer_queue_event_c *event = m_new_event_begin;
+
+		m_new_event_begin = m_new_event_begin->get_next();
+
+		if (m_new_event_begin == 0)
+		{
+			m_new_event_end = 0;
+		}
+
+		event->set_next(0);
+
+		eap_status_e status = add_timer(event);
+		if (status != eap_status_ok)
+		{
+			event->get_initializer()->timer_expired(
+				event->get_id(),
+				event->get_data());
+
+			delete event;
+
+			// Read all pending events. Even the addition failed.
+			// We might have too less mamory.
+		}
+	} // while()
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+eap_status_e eap_timer_queue_c::cancel_pending_timer(
+	abs_eap_base_timer_c * const initializer, 
+	const u32_t id)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_STACK_TRACE(initializer);
+
+	eap_timer_queue_event_c *previous = 0;
+	eap_timer_queue_event_c *event = m_new_event_begin;
+
+	while (event != 0)
+	{
+		if (initializer == event->get_initializer()
+			&& id == event->get_id())
+		{
+			// Remove this pending event.
+			eap_timer_queue_event_c *remove = event;
+			event = event->get_next();
+
+			if (remove == m_new_event_end)
+			{
+				m_new_event_end = previous;
+			}
+
+			remove->set_next(0);
+			delete remove;
+
+			if (previous != 0)
+			{
+				previous->set_next(event);
+			}
+			else
+			{
+				m_new_event_begin = event;
+			}
+		}
+		else
+		{
+			previous = event;
+			event = event->get_next();
+		}
+	} // while()
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+//--------------------------------------------------
+
+eap_status_e eap_timer_queue_c::cancel_timer(
+	abs_eap_base_timer_c * const initializer, 
+	const u32_t id)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_STACK_TRACE(initializer);
+
+#if !defined(NO_EAP_TIMER_QUEUE)
+
+	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
+
+
+	trace_timer();
+
+
+	eap_status_e status = cancel_pending_timer(
+		initializer, 
+		id);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+
+	if (m_timer_queue == 0)
+	{
+		EAP_TRACE_TIMER(
+			m_am_tools,
+			TRACE_FLAGS_TIMER,
+			(EAPL("TIMER: empty queue, [0x%08x] cancel_timer(initializer 0x%08x, id 0x%02x)\n"),
+			 m_timer_queue,
+			 initializer,
+			 id));
+	}
+	else
+	{
+		eap_timer_queue_event_c * cursor = get_hashed_timer_event(initializer, id);
+
+		while(cursor != 0)
+		{
+			EAP_TRACE_TIMER(
+				m_am_tools,
+				TRACE_FLAGS_TIMER,
+				(EAPL("TIMER: [0x%08x] cancel_timer(initializer 0x%08x, ")
+				 EAPL("id 0x%02x, original time %8d)\n"),
+				 cursor,
+				 initializer,
+				 id,
+				 cursor->get_original_time()));
+
+			if (cursor == m_timer_queue)
+			{
+				// The first event will be removed.
+				EAP_ASSERT(cursor->get_prev() == 0);
+
+				if (m_timer_queue->get_next_same_time() != 0)
+				{
+					eap_timer_queue_event_c * new_first = m_timer_queue->get_next_same_time();
+					EAP_ASSERT(new_first->get_next() == 0 && new_first->get_prev() == 0);
+					new_first->set_prev_same_time(0);
+					new_first->set_next(m_timer_queue->get_next());
+					if (m_timer_queue->get_next() != 0)
+					{
+						m_timer_queue->get_next()->set_prev(new_first);
+					}
+					m_timer_queue = new_first;
+					m_timer_queue->increase_time_left(cursor->get_time());
+				}
+				else
+				{
+					if (cursor->get_next() != 0)
+					{
+						cursor->get_next()->increase_time_left(cursor->get_time());
+						cursor->get_next()->set_prev(0);
+					}
+					m_timer_queue = cursor->get_next();
+				}
+
+				cursor->set_prev(0);
+				cursor->set_next(0);
+				cursor->set_prev_same_time(0);
+				cursor->set_next_same_time(0);
+				remove_hash_of_timer_event(cursor);
+				delete cursor;
+			}
+			else if (cursor->get_prev_same_time() != 0)
+			{
+				// Event from the vertical time list will be removed.
+				EAP_ASSERT(cursor->get_next() == 0 && cursor->get_prev() == 0);
+				cursor->get_prev_same_time()->set_next_same_time(cursor->get_next_same_time());
+				if (cursor->get_next_same_time() != 0)
+				{
+					cursor->get_next_same_time()->set_prev_same_time(cursor->get_prev_same_time());
+				}
+				cursor->set_prev(0);
+				cursor->set_next(0);
+				cursor->set_prev_same_time(0);
+				cursor->set_next_same_time(0);
+				remove_hash_of_timer_event(cursor);
+				delete cursor;
+			}
+			else // if (cursor->get_prev_same_time() == 0)
+			{
+				EAP_ASSERT(cursor->get_prev() != 0);
+
+				// Event from middle or end of the horizontal queue will be removed.
+				if (cursor->get_next_same_time() != 0)
+				{
+					// Next on the vertical list will replace the removed timer event.
+					eap_timer_queue_event_c * new_first = cursor->get_next_same_time();
+
+					new_first->increase_time_left(cursor->get_time());
+
+					new_first->set_next(cursor->get_next());
+					if (cursor->get_next() != 0)
+					{
+						cursor->get_next()->set_prev(new_first);
+					}
+					new_first->set_prev(cursor->get_prev());
+					if (cursor->get_prev() != 0)
+					{
+						cursor->get_prev()->set_next(new_first);
+					}
+					new_first->set_prev_same_time(0);
+				}
+				else
+				{
+					// No other timer events are in the vertical list.
+					cursor->get_prev()->set_next(cursor->get_next());
+					if (cursor->get_next() != 0)
+					{
+						cursor->get_next()->set_prev(cursor->get_prev());
+						cursor->get_next()->increase_time_left(cursor->get_time());
+					}
+				}
+				cursor->set_prev(0);
+				cursor->set_next(0);
+				cursor->set_prev_same_time(0);
+				cursor->set_next_same_time(0);
+				remove_hash_of_timer_event(cursor);
+				delete cursor;
+			}
+			cursor = get_hashed_timer_event(initializer, id);
+		} // while()
+	}
+
+	trace_timer();
+
+#endif //#if !defined(NO_EAP_TIMER_QUEUE)
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+//--------------------------------------------------
+
+eap_status_e eap_timer_queue_c::cancel_all_timers()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_STACK_TRACE(0);
+
+	deactivate_timer_queue();
+
+	while (m_new_event_begin != 0)
+	{
+		eap_timer_queue_event_c *event = m_new_event_begin;
+
+		m_new_event_begin = m_new_event_begin->get_next();
+
+		event->set_next(0);
+
+		delete event;
+		event = 0;
+	} // while()
+
+	m_new_event_end = 0;
+
+#if !defined(NO_EAP_TIMER_QUEUE)
+
+	EAP_TRACE_TIMER(
+		m_am_tools,
+		TRACE_FLAGS_TIMER,
+		(EAPL("TIMER: [0x%08x] cancel_all_timers()\n"),
+		 m_timer_queue));
+
+	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
+
+	eap_status_e status = add_pending_timer();
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	trace_timer();
+
+	if (m_timer_queue == 0)
+	{
+		// Nothing to do.
+	}
+	else
+	{
+		eap_timer_queue_event_c *cursor = m_timer_queue;
+
+		while (cursor != 0)
+		{
+			// The first event will be removed.
+			m_timer_queue = m_timer_queue->get_next();
+
+			while (cursor != 0)
+			{
+				EAP_TRACE_TIMER(
+					m_am_tools,
+					TRACE_FLAGS_TIMER,
+					(EAPL("TIMER: [0x%08x] cancel_all_timers()\n"),
+					cursor));
+
+				eap_timer_queue_event_c *next = cursor->get_next_same_time();
+
+				cursor->set_prev(0);
+				cursor->set_next(0);
+
+				remove_hash_of_timer_event(cursor);
+
+				delete cursor;
+
+				cursor = next;
+			} // while()
+
+			cursor = m_timer_queue;
+		} // while()
+	}
+
+	trace_timer();
+
+#endif //#if !defined(NO_EAP_TIMER_QUEUE)
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+//--------------------------------------------------
+
+bool eap_timer_queue_c::get_is_valid() const
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return m_is_valid;
+}
+
+//--------------------------------------------------
+
+
+
+
+// End.