Custom sleep, conditional variable sleep instance _c language in C + +

Source: Internet
Author: User
Tags mutex set time sigint signal usleep

The effect of sleep is needless to say, almost every language provides a similar function, the call is very simple. The function of sleep is to let the program wait for some time, and in order to achieve this goal, there are many ways, the simplest is often the most brutal, we will use the following code to illustrate (note: This article refers to the program compiled running environment for Linux)

Copy Code code as follows:

* Filename:test.cpp * *
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>

Class TestServer
{
Public
TestServer (): Run_ (True) {};
~testserver () {};

void Start ()
{
Pthread_create (&thread_, NULL, ThreadProc, (void*) this);
}
void Stop ()
{
Run_ = false;
}
void Wait ()
{
Pthread_join (Thread_, NULL);
}
void Proc ()
{
int count = 0;
while (Run_)
{
printf ("Sleep count:%d\n", ++count);
Sleep (5);
}
}

Private
BOOL Run_;
pthread_t Thread_;

Static void* ThreadProc (void* Arg)
{
testserver* me = static_cast<testserver*> (ARG);
Me->proc ();
return NULL;
}
};

TestServer G_server;

void StopService ()
{
G_server. Stop ();
}

void StartService ()
{
G_server. Start ();
G_server. Wait ();
}

void Signalhandler (int sig)
{
Switch (SIG)
{
Case SIGINT:
StopService ();
Default
Break
}
}

int main (int argc, char* argv[])
{
Signal (SIGINT, Signalhandler);
StartService ();
return 0;
}

This code describes a simple service program, in order to simplify we omit the service processing logic, that is, the proc function of the content, here we only periodically print a statement, in order to achieve cyclical purposes, we use sleep to achieve, every 5 seconds printing. In the main function we capture the SIGINT signal, and when the program is started in the terminal, if you enter the Ctr+c, it sends an interrupt signal to the program, and the program exits, and here we capture the signal, and we handle it according to our own logic, That is, the stop function that calls the server. Execute compile command
Copy Code code as follows:

$ g++ Test.cpp-o Test-lpthread

Then in the terminal input./test run the program, then the program every 5 seconds will print a statement on the screen, press CTL+C, you will find that the program did not exit immediately, but wait for a while before exiting, the reason, when pressed Ctl+c issued interrupt signal, the program to capture and execute their own logic, That is, the stop function of the server is invoked, the run tag bit run_ is set to the False,proc function detects that Run_ is false then exits the loop, the program ends, but it is possible (and should be said in most cases) that proc is performing to the sleep step, And sleep is to suspend the program, because we capture the interrupt signal, so it will not exit, but continue to suspend until the time is satisfied. This sleep is obviously not elegant enough, here are two ways to quickly exit.

Custom Sleep

We can't do anything else inside the function while we call the system-provided sleep, and based on that we have an idea that if you can detect an exit variable in sleep, then you can quit quickly, yes, that's the way it is, by customizing sleep, We split the time slice into smaller fragments, which are detected every other fragment, so that the program's exit latency can be reduced to this smaller fragment, and the custom sleep is as follows

Copy Code code as follows:

void sleep (int seconds, const bool* run)
{
int count = seconds * 10;
while (*run && count > 0)
{
--count;
Usleep (100000);
}
}

Note that the second parameter of this sleep must be a pointer type, because we need to detect its real time value, not just the values it passes in, but the corresponding function calls are slightly modified, and the complete code is as follows
Copy Code code as follows:

* Filename:test2.cpp * *
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>

Class TestServer
{
Public
TestServer (): Run_ (True) {};
~testserver () {};

void Start ()
{
Pthread_create (&thread_, NULL, ThreadProc, (void*) this);
}

void Stop ()
{
Run_ = false;
}

void Wait ()
{
Pthread_join (Thread_, NULL);
}

void Proc ()
{
int count = 0;
while (Run_)
{
printf ("Sleep count:%d\n", ++count);
Sleep (5, &run_);
}
}

Private
BOOL Run_;
pthread_t Thread_;

void sleep (int seconds, const bool* run)
{
int count = seconds * 10;
while (*run && count > 0)
{
--count;
Usleep (100000);

}
}

Static void* ThreadProc (void* Arg)
{
testserver* me = static_cast<testserver*> (ARG);
Me->proc ();
return NULL;
}
};

TestServer G_server;

void StopService ()
{
G_server. Stop ();
}

void StartService ()
{
G_server. Start ();
G_server. Wait ();
}

void Signalhandler (int sig)
{
Switch (SIG)
{
Case SIGINT:
StopService ();
Default
Break
}
}

int main (int argc, char* argv[])
{
Signal (SIGINT, Signalhandler);
StartService ();
return 0;
}

Compile g++ test2.cpp-o test, run./test, when the program is started, press Ctl+c to see if the program will quit soon.

In fact, this exit is not immediately quit, but the sleep of the waiting time into a smaller time slice, the example is 0.1 seconds, that is, after pressing the CTR+C, the program actually will delay 0 to 0.1 seconds to quit, but this time is very short, it looks like immediately quit the same.

Using conditional variables to achieve sleep

The general idea is to wait for a condition variable in the loop, and set the timeout time, if there are other threads within this time trigger the condition variable, the wait will exit immediately, otherwise it will wait until the set time, so you can control the condition variables to achieve sleep, and can immediately exit when needed.

Conditional variables are often used with mutexes, and the logic of the mutex is simple, and if one thread acquires a mutex, the other thread cannot get it, that is, if two threads execute at the same time to the Pthread_mutex_lock statement, only one thread performs the completion and the other thread blocks. It will not continue until the thread calls Pthread_mutex_unlock. So we tend to use mutexes when multithreading accesses the same memory area to prevent multiple threads from modifying a single piece of memory at the same time. The following functions are used in this example, and the mutex-related functions have

Copy Code code as follows:

int Pthread_mutex_init (pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict);
int Pthread_mutex_lock (pthread_mutex_t *mutex);
int Pthread_mutex_unlock (pthread_mutex_t *mutex);
int Pthread_mutex_destroy (pthread_mutex_t *mutex);

The functions of the above function are initialization, lock, unlocking and destroying. The conditional variable correlation function has

Copy Code code as follows:

int Pthread_cond_init (pthread_cond_t *restrict cond, const pthread_condattr_t *RESTRICT);
int pthread_cond_timedwait (pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct TIMESPEC * Restrict abstime);
int pthread_cond_signal (pthread_cond_t *cond);
int Pthread_cond_destroy (pthread_cond_t *cond);

The functions above function are initialization, timeout waiting for condition variables, triggering condition variables, destroying. We need to explain the pthread_cond_timedwait and pthread_cond_signal functions here.

Copy Code code as follows:

Pthread_cond_timedwait

This function call will block, that is, sleep-like function, but it will be awakened in two cases: 1, the condition variable cond is triggered; 2, when the system time arrives abstime, notice here is absolute time, not relative time. It is better than sleep in the 1th place. In addition, it has a parameter is a mutex, when executing this function, its effect is equivalent to at the entrance to the function of the mutex lock, at the exit and then unlock the mutex, when there are multiple threads call this function, you can do this way to understand

Pthread_cond_signal
It has only one parameter cond, the function is very simple, is triggers waits for cond the thread, the note, it only then triggers one, if will trigger all waits for cond county, needs to use the Pthread_cond_broadcast function, the parameter and the usage all are same

With the above background knowledge, you can more gracefully realize sleep, focus on the proc function and stop function, complete code as follows

Copy Code code as follows:

* Filename:test3.cpp * *
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include <sys/time.h>

Class TestServer
{
Public
TestServer (): Run_ (True)
{
Pthread_mutex_init (&mutex_, NULL);
Pthread_cond_init (&cond_, NULL);
};
~testserver ()
{
Pthread_mutex_destroy (&AMP;MUTEX_);
Pthread_cond_destroy (&cond_);
};

void Start ()
{
Pthread_create (&thread_, NULL, ThreadProc, (void*) this);
}

void Stop ()
{
Run_ = false;
Pthread_mutex_lock (&AMP;MUTEX_);
Pthread_cond_signal (&cond_);
Pthread_mutex_unlock (&AMP;MUTEX_);
}

void Wait ()
{
Pthread_join (Thread_, NULL);
}

void Proc ()
{
Pthread_mutex_lock (&AMP;MUTEX_);
struct Timeval now;
int count = 0;
while (Run_)
{
printf ("Sleep count:%d\n", ++count);
Gettimeofday (&now, NULL);
struct Timespec outtime;
Outtime.tv_sec = now.tv_sec + 5;
outtime.tv_nsec = now.tv_usec * 1000;
Pthread_cond_timedwait (&cond_, &mutex_, &outtime);
}
Pthread_mutex_unlock (&AMP;MUTEX_);
}

Private
BOOL Run_;
pthread_t Thread_;
pthread_mutex_t mutex_;
pthread_cond_t Cond_;

Static void* ThreadProc (void* Arg)
{
testserver* me = static_cast<testserver*> (ARG);
Me->proc ();
return NULL;
}
};

TestServer G_server;

void StopService ()
{
G_server. Stop ();
}

void StartService ()
{
G_server. Start ();
G_server. Wait ();
}

void Signalhandler (int sig)
{
Switch (SIG)
{
Case SIGINT:
StopService ();
Default
Break
}
}

int main (int argc, char* argv[])
{
Signal (SIGINT, Signalhandler);
StartService ();
return 0;
}

Like Test2.cpp, after compiling, the program prints a line of output every 5 seconds on the screen, input ctr+c, and the program exits immediately.

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.