C++11 Timer Function?
the comment thomas posted it good so that's clearly the best link
Apart from it I have made an example that can help.
#include <iostream>
#include <stdio.h>
#include <thread>
using namespace std;
int main()
{
std::thread([]() {std::this_thread::sleep_for(std::chrono::milliseconds(1000));
cout<<"end of the thread\n";
}).detach();
for (int i=0;i<20;++i)
{
std::this_thread::sleep_for(std::chrono::milliseconds(100));
cout<<i<<std::endl;
}
return 0;
}
And my output is:
0
1
2
3
4
5
6
7
8
end of the thread
9
10
11
12
13
14
15
16
17
18
19
Hope that helps :-)
C++ 11: Calling a C++ function periodically
The problem in your code is that your lambda expression inside your "start" function captures the local variables by reference, using the [&]
syntax. This means that the lambda captures the interval
and func
variables by reference, which are both local variables to the start()
function, and thus, they disappear after returning from that function. But, after returning from that function, the lambda is still alive inside the detached thread. That's when you get the "bad-function-call" exception because it tries to call func
by reference to an object that no longer exists.
What you need to do is capture the local variables by value, with the [=]
syntax on the lambda, as so:
void start(int interval, std::function<void(void)> func)
{
_execute = true;
std::thread([=]()
{
while (_execute) {
func();
std::this_thread::sleep_for(
std::chrono::milliseconds(interval));
}
}).detach();
}
This works when I try it.
Or, you could also list out the values you want to capture more explicitly (which I generally recommend for lambdas):
void start(int interval, std::function<void(void)> func)
{
_execute = true;
std::thread([this, interval, func]()
{
while (_execute) {
func();
std::this_thread::sleep_for(
std::chrono::milliseconds(interval));
}
}).detach();
}
EDIT
As others have pointed out, the use of a detached thread is not a great solution because you could easily forget to stop the thread and you have no way to check if it's already running. Also, you should probably make the _execute
flag atomic, just to be sure it doesn't get optimized out and that the reads / writes are thread-safe. You could do this instead:
class CallBackTimer
{
public:
CallBackTimer()
:_execute(false)
{}
~CallBackTimer() {
if( _execute.load(std::memory_order_acquire) ) {
stop();
};
}
void stop()
{
_execute.store(false, std::memory_order_release);
if( _thd.joinable() )
_thd.join();
}
void start(int interval, std::function<void(void)> func)
{
if( _execute.load(std::memory_order_acquire) ) {
stop();
};
_execute.store(true, std::memory_order_release);
_thd = std::thread([this, interval, func]()
{
while (_execute.load(std::memory_order_acquire)) {
func();
std::this_thread::sleep_for(
std::chrono::milliseconds(interval));
}
});
}
bool is_running() const noexcept {
return ( _execute.load(std::memory_order_acquire) &&
_thd.joinable() );
}
private:
std::atomic<bool> _execute;
std::thread _thd;
};
How to time event in C++?
The <chrono>
library in standard C++ provides the best way to do this. This library provides a standard, type safe, generic API for clocks.
#include <chrono>
#include <iostream>
int main() {
using std::chrono::duration_cast;
using std::chrono::nanoseconds;
typedef std::chrono::high_resolution_clock clock;
auto start = clock::now();
// stuff
auto end = clock::now();
std::cout << duration_cast<nanoseconds>(end-start).count() << "ns\n";
}
The actual resolution of the clock will vary between implementations, but this code will always show results in nanoseconds, as accurately as possible given the implementation's tick period.
Can you implement a timer without a sleep in it using standard c++/c++11 only?
C++11 provides us with std::condition_variable
. In your timer you can wait until your condition has been met:
// Somewhere else, e.g. in a header:
std::mutex mutex;
bool condition_to_be_met{false};
std::condition_variable cv;
// In your timer:
// ...
std::unique_lock<std::mutex> lock{mutex};
if(!cv.wait_for(lock, std::chrono::milliseconds{timeout_ms}, [this]{return condition_to_be_met;}))
std::cout << "timed out!" << std::endl;
You can find more information here: https://en.cppreference.com/w/cpp/thread/condition_variable
To signal that the condition has been met do this in another thread:
{
std::lock_guard<std::mutex> lock{mutex}; // Same instance as above!
condition_to_be_met = true;
}
cv.notify_one();
How to use timer in C?
You can use a time_t
struct and clock()
function from time.h.
Store the start time in a time_t
struct by using clock()
and check the elapsed time by comparing the difference between stored time and current time.
Related Topics
Int to Unsigned Int Conversion
Opencv 2.3 Compiling Issue - Undefined Refence - Ubuntu 11.10
Why User-Defined Move-Constructor Disables the Implicit Copy-Constructor
C++14 Variable Templates: What Is Their Purpose? Any Usage Example
What Are Primitive Types Default-Initialized to in C++
How to Achieve "Virtual Template Function" in C++
Why Are Null Pointers Defined Differently in C and C++
Returning Large Objects in Functions
Moving Elements from Std::Vector to Another One
How to Raise Warning If Return Value Is Disregarded
Nonstatic Member as a Default Argument of a Nonstatic Member Function
How to Get List of Files with a Specific Extension in a Given Folder
Force C++ Structure to Pack Tightly
Check Traits for All Variadic Template Arguments
Is Storing an Invalid Pointer Automatically Undefined Behavior