diff -r 003cc3c63855 -r f49e5a6b7804 doc/doxygen/html/timers__win32_8cpp-source.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/doxygen/html/timers__win32_8cpp-source.html Fri Jun 08 09:23:56 2007 +0200 @@ -0,0 +1,267 @@ + +
+00001 /* +00002 This file is part of CanFestival, a library implementing CanOpen Stack. +00003 +00004 Copyright (C): Edouard TISSERANT and Francis DUPIN +00005 Copyright (C) Win32 Port Leonid Tochinski +00006 +00007 See COPYING file for copyrights details. +00008 +00009 This library is free software; you can redistribute it and/or +00010 modify it under the terms of the GNU Lesser General Public +00011 License as published by the Free Software Foundation; either +00012 version 2.1 of the License, or (at your option) any later version. +00013 +00014 This library is distributed in the hope that it will be useful, +00015 but WITHOUT ANY WARRANTY; without even the implied warranty of +00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +00017 Lesser General Public License for more details. +00018 +00019 You should have received a copy of the GNU Lesser General Public +00020 License along with this library; if not, write to the Free Software +00021 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +00022 */ +00023 +00024 +00025 +00026 #include <windows.h> +00027 #include <stdlib.h> +00028 +00029 extern "C" +00030 { +00031 #include "applicfg.h" +00032 #include "can_driver.h" +00033 #include "timer.h" +00034 #include "timers_driver.h" +00035 }; +00036 +00037 // --------------- Synchronization Object Implementation --------------- +00038 class ccritical_section +00039 { +00040 public: +00041 ccritical_section() +00042 { +00043 ::InitializeCriticalSection(&m_cs); +00044 } +00045 ~ccritical_section() +00046 { +00047 ::DeleteCriticalSection(&m_cs); +00048 } +00049 void enter() +00050 { +00051 ::EnterCriticalSection(&m_cs); +00052 } +00053 void leave() +00054 { +00055 ::LeaveCriticalSection(&m_cs); +00056 } +00057 private: +00058 CRITICAL_SECTION m_cs; +00059 }; +00060 +00061 static ccritical_section g_cs; +00062 +00063 +00064 void EnterMutex(void) +00065 { +00066 g_cs.enter(); +00067 } +00068 +00069 void LeaveMutex(void) +00070 { +00071 g_cs.leave(); +00072 } +00073 // --------------- Synchronization Object Implementation --------------- +00074 +00075 +00076 // --------------- CAN Receive Thread Implementation --------------- +00077 +00078 void CreateReceiveTask(CAN_HANDLE fd0, TASK_HANDLE* Thread, void* ReceiveLoopPtr) +00079 { +00080 unsigned long thread_id = 0; +00081 *Thread = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ReceiveLoopPtr, fd0, 0, &thread_id); +00082 } +00083 +00084 void WaitReceiveTaskEnd(TASK_HANDLE Thread) +00085 { +00086 ::WaitForSingleObject(Thread, INFINITE); +00087 ::CloseHandle(Thread); +00088 //*Thread = NULL; +00089 } +00090 // --------------- CAN Receive Thread Implementation --------------- +00091 +00092 +00093 // --------------- Timer Thread Implementation --------------- +00094 class class_timers +00095 { +00096 public: +00097 class_timers(); +00098 ~class_timers(); +00099 void start_timer_thread(); +00100 void resume_timer_thread(); +00101 void stop_timer_thread(); +00102 void set_timer(TIMEVAL value); +00103 TIMEVAL get_elapsed_time(); +00104 private: +00105 TIMEVAL get_timer() const; +00106 static DWORD WINAPI timer_loop_thread_proc(void* arg); +00107 private: +00108 TIMEVAL m_last_occured_alarm_time; +00109 volatile TIMEVAL m_last_alarm_set_time; +00110 HANDLE m_timer_thread; +00111 volatile bool m_continue_timer_loop; +00112 bool m_use_hi_res_timer; +00113 double m_counts_per_usec; +00114 }; +00115 +00116 class_timers::class_timers() : m_last_occured_alarm_time(TIMEVAL_MAX), +00117 m_last_alarm_set_time(TIMEVAL_MAX), +00118 m_timer_thread(0), +00119 m_continue_timer_loop(false), +00120 m_use_hi_res_timer(false), +00121 m_counts_per_usec(0.) +00122 { +00123 // initialize hi resolution timer +00124 LARGE_INTEGER counts_per_sec = {0, 0}; +00125 if (::QueryPerformanceFrequency(&counts_per_sec) && counts_per_sec.QuadPart > 0) +00126 { +00127 m_use_hi_res_timer = true; +00128 m_counts_per_usec = counts_per_sec.QuadPart / 1000000.; +00129 } +00130 m_use_hi_res_timer = true; +00131 } +00132 +00133 class_timers::~class_timers() +00134 { +00135 stop_timer_thread(); +00136 } +00137 +00138 // time is in micro seconds +00139 TIMEVAL class_timers::get_timer() const +00140 { +00141 if (m_use_hi_res_timer) +00142 { +00143 LARGE_INTEGER performance_count = {0, 0}; +00144 ::QueryPerformanceCounter(&performance_count); +00145 return (TIMEVAL)(performance_count.QuadPart / m_counts_per_usec); +00146 } +00147 // hi-res timer is unavailable +00148 return 1000 * ::GetTickCount(); +00149 } +00150 +00151 DWORD WINAPI class_timers::timer_loop_thread_proc(void* arg) +00152 { +00153 class_timers* This = reinterpret_cast<class_timers*>(arg); +00154 while (This->m_continue_timer_loop) +00155 { +00156 TIMEVAL cur_time = This->get_timer(); +00157 if (cur_time >= This->m_last_alarm_set_time) +00158 { +00159 This->m_last_occured_alarm_time = cur_time; +00160 This->m_last_alarm_set_time = TIMEVAL_MAX; +00161 EnterMutex(); +00162 TimeDispatch(); +00163 LeaveMutex(); +00164 } +00165 else +00166 { +00167 ::Sleep(1); +00168 } +00169 } +00170 return 0; +00171 } +00172 +00173 void class_timers::start_timer_thread() +00174 { +00175 if (m_timer_thread == 0) +00176 { +00177 unsigned long thread_id = 0; +00178 m_timer_thread = ::CreateThread(NULL, 0, &timer_loop_thread_proc, this, CREATE_SUSPENDED, &thread_id); +00179 m_last_alarm_set_time = TIMEVAL_MAX; +00180 m_last_occured_alarm_time = get_timer(); +00181 } +00182 } +00183 +00184 void class_timers::resume_timer_thread() +00185 { +00186 if (m_timer_thread) +00187 { +00188 m_continue_timer_loop = true; +00189 ::ResumeThread(m_timer_thread); +00190 } +00191 } +00192 +00193 void class_timers::stop_timer_thread() +00194 { +00195 if (m_timer_thread) +00196 { +00197 m_continue_timer_loop = false; +00198 ::WaitForSingleObject(m_timer_thread, INFINITE); +00199 ::CloseHandle(m_timer_thread); +00200 m_timer_thread = 0; +00201 } +00202 } +00203 +00204 void class_timers::set_timer(TIMEVAL value) +00205 { +00206 m_last_alarm_set_time = (value == TIMEVAL_MAX) ? TIMEVAL_MAX : get_timer() + value; +00207 } +00208 +00209 // elapsed time since last occured alarm +00210 TIMEVAL class_timers::get_elapsed_time() +00211 { +00212 return get_timer() - m_last_occured_alarm_time; +00213 } +00214 +00215 // ---------------------------------------------------------- +00216 +00217 static class_timers s_timers; +00218 +00219 void StartTimerLoop(TimerCallback_t init_callback) +00220 { +00221 s_timers.start_timer_thread(); +00222 // At first, TimeDispatch will call init_callback. +00223 if (init_callback != NULL) +00224 SetAlarm(NULL, 0, init_callback, (TIMEVAL)0, (TIMEVAL)0); +00225 s_timers.resume_timer_thread(); +00226 } +00227 +00228 void StopTimerLoop(void) +00229 { +00230 s_timers.stop_timer_thread(); +00231 } +00232 +00233 void setTimer(TIMEVAL value) +00234 { +00235 s_timers.set_timer(value); +00236 } +00237 +00238 TIMEVAL getElapsedTime(void) +00239 { +00240 return s_timers.get_elapsed_time(); +00241 } +