C ++ custom timer implementation (multi-object multi-timer)

Source: Internet
Author: User

: This article discusses the timer implementation in the previous article "data retransmission mechanism Scheme Design Based on selection retransmission ARQ transmission protocol ".

Error Correction:

1. Background

In this project, each hardware sensor corresponds to a sensor object in the software system, and data transmission and retransmission operations are for each sensor object. Therefore, each object should correspond to a timer (this timer is for each object's retransmission queue, not for the next packet to be received, this is very important, this is two different ways of thinking. I personally think the first solution is better ). The timer for the retransmission queue sends the retransmission queue to the corresponding sensor after the timeout, and resets the timer after receiving the data (that is, the retransmission queue will be postponed ), after receiving all the packets collected at a time (assuming a few packets are dropped in the middle, the current timer will be immediately canceled and the retransmission queue will be issued if no packet is dropped), the timer will not be reset. In this way, after a while, the timer times out and sends the retransmission queue to the sender. After receiving the retransmission queue, the sender detects the bite bit and retransmits the packet data.

2. Key Issues

1. The data retransmission module is working behind the scenes and is not associated with the window. Therefore, it is impossible to use the ontimer timer provided by MFC.

2. Because each sensor object has different latency during retransmission, a unified timer cannot be used. A separate Timer must be set for each object.

3. The thread processing function in the C ++ class must be static, so that the thread processing function cannot use non-static member variables in the class. The reason why thread processing functions need to be static is that the prototype of a function is lresult threadproc (lpvoid PV). If it is a non-static member function, it is automatically expanded to threadproc (Pclass-> This, PV); does not match the thread function call. Therefore, global functions or static member functions must be used.

4. The timer timeout processing function must also be static, so no matter how many timers you set, the final timer processing function is the same.

3. Solution

First, for the first problem, we use the Windows API settimer () to customize the timer.

Second, when a thread is enabled, this pointer of the current object is passed to the thread processing function, use the this pointer in the thread processing function to call a non-static function and set a timer for this object.

Finally, we create a map in the timeout processing function to record the relationship between the timer ID and the corresponding object. In this way, when a timer times out, we can find the corresponding object based on the ID to operate the object.

Let's take a look at the specific implementation code:

Engineering: http://download.csdn.net/detail/pinghegood/4898817

// Mytimer. h: interface for the mytimer class. /*************************************** ********************************* // Author: pinghegood/* 2012.8.19 20:56 *//******************************** **************************************** //////////////////////////////////////// /// // If! Defined (partition _) # define partition _ # If _ msc_ver> 1000 # pragma once # endif // _ msc_ver> 1000 # include "windows. H "# pragma warning (Disable: 4786) // shield warnings in map # include" map "using namespace STD; Class test; // Save the ing between the timer ID and the corresponding object this pointer. typedef Map <uint, test *> cownermap; Class cmytimer {public: static void d Ataproc (hwnd, uint umsg, uint idevent, DWORD dwtime); cmytimer (void (* ptimeproc) (hwnd, uint umsg, uint idevent, DWORD dwtime) = NULL ); virtual ~ Cmytimer (); void setmytimer (uint nelapse, test * pcombodata); void trim (bool flag = true); uint gettimerid (); static DWORD winapi threadrun (lpvoid lpparameter); Private: DWORD m_idthread; // Save the timer value uint m_ntimerid; bool m_realclose; // ptimer m_ptimerproc; // pointer to the processing function ///static cownermap m_ownermap; static cmytimer * pthistmer; test * m_combodata; handle m_handle; uint m_tim Eouttime; bool m_isrunning; bool m_setorkill; m_critivaltime; critical_section m_critivalthread; static critical_section m_critivalmap; bool settimerproc () ;};# endif //! Defined (afx_mytimer_h000083eef423_262a_4a4f_82a0_094336feac5700000000ded _)

// Mytimer. CPP: Implementation of the mytimer class. //////////////////////////////////////// //// // # pragma warning (Disable: 4786) // block warnings in map # include "mytimer. H "# include" test. H "////////////////////////////////////// /// // construction/destruction /// //////////////////////////////////////// /// // cownermap cmytimer:: m_ownermap; Optional * cmytimer: pthisttimer = NULL; required cmytimer: timer; cmytimer: cmytimer (void (* ptimeproc) (hwnd, uint umsg, uint idevent, DWORD dwtime )): m_ntimerid (-1) {response (& m_critivaltime); initializecriticalsection (& m_critivalthread); Response (& m_critivalmap); // m_ptimerproc = ptimeproc; m_handle = NULL; /// // m_isrunning = true; m_setork Ill = true; pthist.pdf = This;}; cmytimer ::~ Cmytimer () {// If (null! = M_combodata) // {// Delete m_combodata; //} // sets the timer. nelapse indicates the time interval void cmytimer: setmytimer (uint nelapse, test * pcombodata) {// Save the call Object Pointer m_combodata = pcombodata; // Save the set timeout time m_timeouttime = nelapse; m_isrunning = true; m_setorkill = true; If (null = m_handle) {// start time setting thread m_handle = createthread (null, 0, threadrun, (lpvoid) This, 0, & m_idthread );}}; // destroy the timer void cmytimer: killmytimer (bool flag) {entercriticalsection (& m_cri Tivaltime); m_setorkill = false; m_timeouttime =-1; if (true = Flag) {uint MSG = wm_quit; entercriticalsection (& m_critivalthread); m_isrunning = false; # ifdef mytimerdebugouttrace0 ("=============== killmytimer1 ============== "); # define (& m_critivalthread); postthreadmessage (m_idthread, MSG,); // waitforsingleobject (m_handle, infinite); // closehandle (m_handle); m_handle = NULL;} # ifdef complete Ace0 ("= cmytimerkillmytimer ="); # timer (& m_critivaltime); m_ntimerid =-1 ;}; // obtain the timer ID uint cmytimer: gettimerid () {return m_ntimerid;}; // set the timer thread DWORD winapi cmytimer: threadrun (lpvoid lpparameter) {cmytimer * pthis = reinterpret_cast <cmytimer *> (lpparameter ); if (pthis-> settimerproc () {# ifdef mytimerdebugout // trace ("start thread"); // trace0 ("threadrun exit safely! (0xcc66) \ n "); # endifreturn 0xcc66;} else {// trace0 (" threadrun exit unsafely! (0xcc77) \ n "); Return 0xcc77 ;}}; void cmytimer: dataproc (hwnd, uint umsg, uint idevent, DWORD dwtime) {entercriticalsection (& (pthistimer-> m_critivalmap); test * tempcr = m_ownermap [idevent]; leavecriticalsection (& (pthistimer-> m_critivalmap); If (null! = Tempcr) {tempcr-> testsettime () ;}} bool cmytimer: settimerproc () {bool isrunning = true; entercriticalsection (& m_critivalthread); isrunning = m_isrunning; trim (& m_critivalthread); While (isrunning) {bool openflag = true; uint timeouttime =-1; entercriticalsection (& m_critivaltime); openflag = m_setorkill; timeouttime = m_timeouttime; leavecriticalsection (& m_critivaltime); If (true = openflag) {MSG; uint_ptr Id = settimer (null, null, m_timeouttime, (timerproc) (dataproc); If (m_ownermap.end ()! = M_ownermap.find (ID) {// trace1 ("the two generated timer IDs are the same: % u \ n", ID);} m_ownermap [ID] = m_combodata; m_combodata = NULL; while (-1! = Getmessage (& MSG, null, 0, 0) & getmessage (& MSG, null )! = 0) {entercriticalsection (& m_critivaltime); openflag = m_setorkill; then (& m_critivaltime); If (false = openflag) {entercriticalsection (& m_critivalmap); If (! M_ownermap.empty () & m_ownermap.end ()! = M_ownermap.find (ID) {m_ownermap.erase (ID);} leavecriticalsection (& m_critivalmap); killtimer (null, ID); // trace ("killtimertrue"); break ;} translatemessage (& MSG); // translates virtual-key codes dispatchmessage (& MSG); // dispatches message to window sleep (20);} Sleep (30 ); entercriticalsection (& m_critivalthread); isrunning = m_isrunning; leavecriticalsection (& m_critivalthread);} return true ;}

 

4. Analysis of running results

As shown in: the timer latency of the test object is 1 s, Test2 corresponds to 3 s, and test3 corresponds to 5 s. Since the test Timer and the Test2 timer time out at the third time, their output is mixed together. The same is true in the 5S. The output shows that the timer of each object works independently and does not interfere with each other.

4. Related Knowledge


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.