nico@207: nico@207: nico@207: CanFestival: /home/epimerde/documents/tc11/CanFestival-3/drivers/win32/timers_win32.cpp Source File nico@207: nico@207: nico@207: nico@207: nico@207:
nico@207:
nico@207:
nico@207:
nico@207:

/home/epimerde/documents/tc11/CanFestival-3/drivers/win32/timers_win32.cpp

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

Generated on Mon Jun 4 16:29:06 2007 for CanFestival by  nico@207: nico@207: doxygen 1.5.1
nico@207: nico@207: