Cross platform Sleep function for C++
Asked Answered
E

7

48

Is it possible with macros make cross platform Sleep code? For example

#ifdef LINUX
#include <header_for_linux_sleep_function.h>
#endif
#ifdef WINDOWS
#include <header_for_windows_sleep_function.h>
#endif
...
Sleep(miliseconds);
...
Edva answered 6/6, 2012 at 16:23 Comment(5)
If you don't mind the processor whirring away and have C++11, you can use <chrono>.Araroba
Why would you have the processor whirring away? If you have C++11 you can use something like std::this_thread::sleep_for(std::chrono::milliseconds(n)) which should not consume any CPU.Hinson
@KamilKrzyszczuk that's an almost worthless description. I doubt there is much "pure C++" code out there, since no compiler in existence can handle "pure C++". For what is worth, C++11 is not an extension, it's actually the real "pure C++".Hinson
@R.MartinhoFernandes, I never realized that existed; I just started with chrono yesterday. That saves me a lot of trouble, thanks.Araroba
In my programs, I use <time.h>. It's very reliable.Troat
C
48

Yes there is. What you do is wrap the different system sleeps calls in your own function as well as the include statements like below:

#ifdef LINUX
#include <unistd.h>
#endif
#ifdef WINDOWS
#include <windows.h>
#endif

void mySleep(int sleepMs)
{
#ifdef LINUX
    usleep(sleepMs * 1000);   // usleep takes sleep time in us (1 millionth of a second)
#endif
#ifdef WINDOWS
    Sleep(sleepMs);
#endif
}

Then your code calls mySleep to sleep rather than making direct system calls.

Chenay answered 6/6, 2012 at 16:38 Comment(10)
#ifdef LINUX int Sleep(int sleepMs) { return usleep(sleepMs * 1000); } #endifCopperhead
ya, that would be great, but usleep doesnt stop consuming CPU. For example: while(1) { usleep(1000*1000);/*1sec?*/ cout << 1; } Then after this one sec, output is many of "1" characters.Edva
@KamilKrzyszczuk: No, usleep does not consume CPU, it stops the process entirely for a while.Annunciata
so why output for code above is many of 1 characters instead of just one? I understand that is not related. But how to fix it?Edva
@KamilKrzyszczuk: because you made some other mistake. The code you posted should print one 1 character per second.Annunciata
There is no mistake in while(true) codeblock, as u can see there is just sleep and cout, and this code I compiled. Btw. I used usleep(1000) and it work for 1 sec. :)Edva
Why take an int for mySleep? Wouldn't an unsigned int be a better choice? After all, it's not like you can sleep for negative seconds! :PCodification
If anyone tries this with MinGW derivative (ie gcc g++) on Windows, there is a problem with the macros. If you add -DWINDOWS to your compilation parameters (like g++ xx.cpp -DWINDOWS), the CPU consumption is over.Vicinage
Note that "POSIX.1-2001 declares this function obsolete; use nanosleep(2) instead. POSIX.1-2008 removes the specification of usleep()." sourceKymberlykymograph
The macros don't work. See here on how to reliably detect the platform: #5920496Reside
T
84

Yup. But this only works in C++11 and later.

#include <chrono>
#include <thread>
...
std::this_thread::sleep_for(std::chrono::milliseconds(ms));

where ms is the amount of time you want to sleep in milliseconds.

You can also replace milliseconds with nanoseconds, microseconds, seconds, minutes, or hours. (These are specializations of the type std::chrono::duration.)

Update: In C++14, if you're sleeping for a set amount of time, for instance 100 milliseconds, std::chrono::milliseconds(100) can be written as 100ms. This is due to user defined literals, which were introduced in C++11. In C++14 the chrono library has been extended to include the following user defined literals:

Effectively this means that you can write something like this.

#include <chrono>
#include <thread>
using namespace std::literals::chrono_literals;

std::this_thread::sleep_for(100ms);

Note that, while using namespace std::literals::chrono_literals provides the least amount of namespace pollution, these operators are also available when using namespace std::literals, or using namespace std::chrono.

Telescopium answered 30/6, 2012 at 18:18 Comment(1)
@ThePirate42 haha thanks. At the time it was posted though, most people were not yet using C++11, so the accepted answer was more generally useful.Telescopium
C
48

Yes there is. What you do is wrap the different system sleeps calls in your own function as well as the include statements like below:

#ifdef LINUX
#include <unistd.h>
#endif
#ifdef WINDOWS
#include <windows.h>
#endif

void mySleep(int sleepMs)
{
#ifdef LINUX
    usleep(sleepMs * 1000);   // usleep takes sleep time in us (1 millionth of a second)
#endif
#ifdef WINDOWS
    Sleep(sleepMs);
#endif
}

Then your code calls mySleep to sleep rather than making direct system calls.

Chenay answered 6/6, 2012 at 16:38 Comment(10)
#ifdef LINUX int Sleep(int sleepMs) { return usleep(sleepMs * 1000); } #endifCopperhead
ya, that would be great, but usleep doesnt stop consuming CPU. For example: while(1) { usleep(1000*1000);/*1sec?*/ cout << 1; } Then after this one sec, output is many of "1" characters.Edva
@KamilKrzyszczuk: No, usleep does not consume CPU, it stops the process entirely for a while.Annunciata
so why output for code above is many of 1 characters instead of just one? I understand that is not related. But how to fix it?Edva
@KamilKrzyszczuk: because you made some other mistake. The code you posted should print one 1 character per second.Annunciata
There is no mistake in while(true) codeblock, as u can see there is just sleep and cout, and this code I compiled. Btw. I used usleep(1000) and it work for 1 sec. :)Edva
Why take an int for mySleep? Wouldn't an unsigned int be a better choice? After all, it's not like you can sleep for negative seconds! :PCodification
If anyone tries this with MinGW derivative (ie gcc g++) on Windows, there is a problem with the macros. If you add -DWINDOWS to your compilation parameters (like g++ xx.cpp -DWINDOWS), the CPU consumption is over.Vicinage
Note that "POSIX.1-2001 declares this function obsolete; use nanosleep(2) instead. POSIX.1-2008 removes the specification of usleep()." sourceKymberlykymograph
The macros don't work. See here on how to reliably detect the platform: #5920496Reside
C
30

shf301 had a good idea, but this way is better:

#ifdef _WINDOWS
#include <windows.h>
#else
#include <unistd.h>
#define Sleep(x) usleep((x)*1000)
#endif

Then use like this:

Sleep(how_many_milliseconds);
Circumvolution answered 7/4, 2013 at 10:46 Comment(1)
Convenient! Thank you! :)Obstetrics
A
19

Get Boost.

#include <boost/thread/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
...
boost::this_thread::sleep(boost::posix_time::millisec(milliseconds));
Amends answered 6/6, 2012 at 16:33 Comment(1)
this is now in C++11. posix_time is called chrono though.Telescopium
C
8

The stock solution is the select() call (requires Winsock). This particular call has exactly the same behavior on Linux and Windows.

long value; /* time in microseconds */

struct timeval tv;
tv.tv_sec = value / 1000000;
tv.tv_usec = value % 1000000;
select(0, NULL, NULL, NULL, &tf);
Copperhead answered 6/6, 2012 at 16:41 Comment(2)
interesting solution, but I liked your comment on shf301's answer better.Annunciata
this doesn't work on Windows, it returns immediately, regardless of the requested timeoutEastman
G
1

In linux remember that usleep has a limit. You can't 'sleep' more than 1000 seconds.

I would write like this

struct timespec req={0},rem={0};
req.tv_sec=(milisec/1000);
req.tv_nsec=(milisec - req.tv_sec*1000)*1000000;
nanosleep(&req,&rem);
Greenland answered 7/6, 2012 at 8:50 Comment(0)
B
1

since c++ 11 you could just do this.

#include<chrono>
#include<thread>
int main(){
    std::this_thread::sleep_for(std::chrono::milliseconds(x));//sleeps for x milliseconds
    std::this_thread::sleep_for(std::chrono::seconds(x));//sleeps for x seconds  
    std::this_thread::sleep_for(std::chrono::minutes(x));//sleeps for x minutes
    std::this_thread::sleep_for(std::chrono::hours(x));//sleeps for x hours.
  return 0;  
}

I don't know why would you want to use messy macros when you can do this, this method is great, cross platform and is included in the c++ standard.

Bruin answered 15/6, 2020 at 10:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.