Multi-thread timer implementation in Linux

Source: Internet
Author: User

I. functions:

Compile a library to implement the timer function. It can provide users with the timer used multiple times in the same process.

II. Implementation

# Include <unistd. h> # include <stdio. h> # include <stdlib. h> # include <time. h> # include <sys/queue. h> # include <sys/time. h> # include <pthread. h> # include <errno. h> # define default_interval 1int timer_cnt = 0; Class timer; // Timer class timermanager; // timer manager class timermanager {friend class timer; // youyuan class, timer class: public: typedef Enum {timer_manager_stop = 0, timer_manager_start} timermanagerstate; static time Rmanager * instance (); // the current instance void start (); // start the current thread and run the process function void stop (); // terminate the current thread void dump (); // clear the remaining useless timer void add_timer (timer * vtimer); // thread security increase timer void remove_timer (timer * vtimer); // thread-safe remove timer protected: static void * process (void *); Private: timermanager (); void add_timer_unsafe (timer * vtimer); // adds a timer for non-thread security, this class uses void remove_timer_unsafe (timer * vtimer); // thread-safe remove timer. This class uses static timerman Ager * m_instance; static pthread_mutex_t workmutex; timermanagerstate m_state; list_head (, timer) LIST _; // static int mark;}; Class timer {friend class timermanager; public: typedef Enum {timer_idle = 0, timer_alive, timer_timeout} timerstate; timer (INT vinterval, void (* vfunc) (void *), void * vdata); void start (); // Add yourself to the linked list of the timer manager void stop (); // remove yourself from the linked list of the timer manager void reset (INT vinterval); // Reset ~ Timer (); Private: int ID; // the ID of the current timer int m_interval; // The timer time of the timer, in the unit of seconds int m_counter; // the remaining time, the Unit is microsecond timerstate m_state; // The status void (* m_func) (void *) of the current timer; void * m_data; list_entry (timer) entry _; // address of the current Timer In the linked list}; timermanager * timermanager: m_instance; pthread_mutex_t timermanager: workmutex; timermanager: timermanager () {pthread_mutex_init (& workmutex, null );} timermanager * timermanager: instance () {if (M_instance = NULL) {pthread_mutex_lock (& workmutex); If (m_instance = NULL) m_instance = new timermanager (); pthread_mutex_unlock (& workmutex);} return m_instance ;} void timermanager: Start () {If (m_state = timer_manager_stop) {m_state = timer_manager_start; pthread_t PID; int res = pthread_create (& pid, null, process, this ); if (res! = 0) {printf ("pthread_create is failed \ n"); exit (exit_failure) ;}} void timermanager: Stop () {This-> m_state = timer_manager_stop ;} void timermanager: dump () {timer * item; pthread_mutex_lock (& workmutex); list_foreach (item, & (this-> LIST _), entry _) {If (item-> m_counter = 0) {printf ("timer % d will be dumped! \ N ", (INT) item-> m_data); item-> stop () ;}} pthread_mutex_unlock (& workmutex);} void * timermanager: Process (void * Arg) {pthread_detach (pthread_self (); timermanager * manage = (timermanager *) ARG; timer * item; struct timeval start, end; int delay; struct timeval TM; gettimeofday (& end, 0); While (manage-> m_state = timer_manager_start) {TM. TV _sec = 0; TM. TV _usec = default_interval * 1000; start. TV _sec = end. TV _sec; start. TV _usec = end. TV _usec; while (select (0, 0, 0, & TM) <0 & errno = eintr); gettimeofday (& End, 0); delay = (end. TV _sec-start. TV _sec) * 1000; delay + = (end. TV _usec-start. TV _usec); pthread_mutex_lock (& Manage-> workmutex); list_foreach (item, & (manage-> LIST _), entry _) {// printf ("m_data = % d m_counter = % d", item-> m_data, item-> m_counter); If (item-> m_counter <delay) item-> m_counter = 0; else item-> m_counter-= delay; // printf ("m_data = % d m_counter = % d \ n", item-> m_data, item-> m_counter); If (item-> m_counter = 0) {If (item-> m_func) item-> m_func (item-> m_data ); manage-> remove_timer_unsafe (item); item-> m_state = Timer: timer_timeout ;}} pthread_mutex_unlock (& Manage-> workmutex) ;}} void timermanager :: add_timer (timer * vtimer) {pthread_mutex_lock (& workmutex); list_insert_head (& (this-> LIST _), vtimer, entry _); worker (& workmutex);} void timermanager:: remove_timer (timer * vtimer) {pthread_mutex_lock (& workmutex); list_remove (vtimer, entry _); worker (& workmutex);} void timermanager: worker (timer * vtimer) {list_insert_head (& (this-> LIST _), vtimer, entry _);} void timermanager: remove_timer_unsafe (timer * vtimer) {list_remove (vtimer, entry _);}

Another class of code is not uploaded first. This is a Linux experiment we are learning. If uploaded, tens of thousands of people will submit the code to the teacher.

Iii. Summary:

1. According to the habit of writing code before, I declare a Class A first, then implement the method in sequence, then declare a Class B, and then implement the B method in sequence.

According to this habit, if Class A is declared before class B, if Class A wants to call the method in Class B, Class A and Class B must be declared before definition, then, declare Class A as a membership class of Class B, and put the implementation behind the definition of two classes to avoid errors.

According to this habit, what should I do if Class A wants to call the method of class B and class B wants to call the method of Class? Which class is placed in front? Similar to the above. We must ensure that a class is calling the object of another class, and the methods of the other class have been implemented. Otherwise, an error similar to invalid use of incomplete type 'struct timer' may occur.

2. When static variables are declared in the class, they are not initialized. At this time, the static variables must be declared separately outside the class, so that the system will automatically allocate global memory space to these variables. In this way, you can safely assign values to static variables. Otherwise, an error similar to undefined reference to 'timermanager: m_instance' may occur.

3. A deadlock occurs in the program. Lock and unlock are used in the process to lock a piece of code. The Code also uses lock and unlock to lock a piece of code, in this case, the switch program cannot be executed in the wait state.

4. My implementation is to continuously check the time through select, but the select function call takes some time, resulting in accuracy errors. If I try to call the select function as little as possible, the real-time performance is not enough. If there are many calls, the accuracy is not enough. In my code, select 1 s as the interval to call select.

5. When the timermanager class calls its own add_timer _ to remove_timer _, some errors may occur because no locks are applied, but the lock will immediately cause a deadlock. This problem remains to be solved.

This article is original in zeroclock, but it can be reproduced, because we are brothers.

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.