I wanted to redo a Conway's Game of Life thing I did in Java, but this time use ncurses and C++. Obviously I need a timed event so I can run out the simulation at a rate which it can be viewed. Turns out it is a hell of a lot harder to make a timed event in C++ than it is in Java. I am not as experienced in C++ than I am in Java. I have already looked around online, and what I found led me to the code I have below. Upon executing it produces no result in the terminal. What exactly am I doing wrong?
main.cpp:
#include <iostream>
#include <functional>
#include <chrono>
#include <future>
#include <cstdio>
using namespace std;
class callBackTimer //no idea how this works, got it from Stack Overflow thread
{
public:
callBackTimer()
:_execute(false)
{}
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();
}
void stop()
{
_execute = false;
}
private:
bool _execute;
};
void timerExec()
{
cout << "SNAFU" << endl;
}
int main(int argc, const char * argv[])
{
callBackTimer timer; //declare the timer
std::function<void(void)> exec = timerExec; //declare a pointer to timerExec
timer.start(25, std::bind(exec)); //start the timer
return 0;
}
You need to wait for the thread to finish what it is doing, which is usually accomplished by calling join(). So maybe something like this:
#include <iostream>
#include <functional>
#include <chrono>
#include <future>
#include <cstdio>
using namespace std;
class callBackTimer //no idea how this works, got it from Stack Overflow thread
{
public:
callBackTimer()
:_execute(false)
{}
void setup(int interval, std::function<void(void)> func)
{
_execute = true;
thread = std::thread([=]()
{
// while (_execute)
for (int steps = 0; steps < 100; ++steps)
{
func();
std::this_thread::sleep_for(std::chrono::milliseconds(interval));
}
});
}
void stop()
{
_execute = false;
}
void run()
{
thread.join();
}
private:
bool _execute;
std::thread thread;
};
void timerExec()
{
cout << "SNAFU" << endl;
}
int main(int argc, const char * argv[])
{
callBackTimer timer; //declare the timer
std::function<void(void)> exec = timerExec; //declare a pointer to timerExec
timer.setup(25, std::bind(exec)); //start the timer
timer.run();
return 0;
}
Calling detach() is OK, but you have to make main() wait for the thread manually. You also need a condition to break out of the while loop, otherwise it will go on forever. Hope that helps!
Related
I've written a little program which counts back from 5 to 0 and does a println afterwards. I've wrapped this a little bit, but please let me show my code:
Main.ino
#include "MyObject.h"
#include <string>
using namespace std;
MyObjekt *myObject;
void setup() {
Serial.begin(115200);
string trigger = "triggering";
myObject = new MyObject(trigger);
}
void loop(){}
MyObject.h
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <string>
using namespace std;
class MyObject{
public:
string field;
MyObject(string trigger);
string GetField(){ return field; }
void SetField(string trigger);
};
#endif
MyObject.cpp
#include "MyObject.h"
#include <string>
using namespace std;
#include "Timer.h"
MyObject::MyObject(string trigger){
SetField(trigger);
}
void MyObject::SetField(string trigger){
field = trigger;
auto f = []() {std::cout << "---------------- I waited to print! ----------------\n"; };
Timer t1{10000,f};
}
Timer.h
#include <iostream>
#include <chrono>
#include <thread>
#include <functional>
#include <mutex>
#include <condition_variable>
class Timer {
public:
Timer(size_t time, const std::function<void(void)>& f) : time{std::chrono::milliseconds{time}}, f{f} {}
~Timer() {wait_thread.join();}
private:
void wait_then_call()
{
std::unique_lock<std::mutex> lck{mtx};
for(int i{5}; i > 0; --i) {
//std::cout << "Thread " << wait_thread.get_id() << " countdown at: " << '\t' << i << '\n';
cv.wait_for(lck, time / 10);
}
f();
}
std::mutex mtx;
std::condition_variable cv{};
std::chrono::milliseconds time;
std::function <void(void)> f;
std::thread wait_thread{[this]() {wait_then_call();}};
};
Unfortately this blocks the main thread, so nothing other (like another println) is done during this. Is it somehow possible to do this countdown in the background and only do the println (f ) in the foreground (in other words: listening while doing work, if background-println is detected/sent to listener, execute, then listen again and continue with work)?
Would be really happy about every answer and help effort. Sorry if for my Problems expressing myself, i hope it became somehow clear what I am trying to achieve^^
Best regards
It looks like you're on Arduino. Using the arduino-timer library, the code should look something similar:
#include <arduino-timer.h>
const size_t TIMER_INTERVAL_MS = 1000;
volatile int counter = 5;
auto timer = timer_create_default();
void setup() {
timer.every(TIMER_INTERVAL_MS, [](void*) -> bool { counter--; return true; });
}
void loop() {
timer.tick();
if (counter <= 0) {
Serial.println("Counter is 0");
counter = 5; // Reset counter
}
Sorry, can't validate or run the code as I don't have an Arduino setup ready to go. But you should get the point.
You can also do more complex solutions like ask the timer peripheral for an interrupt; or set up timer service in the RTOS (assuming you've upgraded to one). The basic principle is the same.
First of all, don't use keyword new if you never call delete, as it would cause memory leak. What do you want can be achieved with two ways:
1. Use Counter
This is still run on the loopTask, but it is let other code to run.
long lastMillis = 0;
long interval = 1000;
long counter = 5;
void setup() {
Serial.begin(115200);
}
void loop() {
if (millis() - lastMillis > interval && counter >= 0) {
lastMillis = millis();
Serial.println(counter--);
}
//Other code would still run
}
2. Create Another Task
This would be completely asynchronous, even if you are calling delay() on the other task, the code on the loopTask would still run.
int counter = 5;
int interval = 1000;
void vTask(void *param) {
while (counter >= 0) {
delay(1000);
Serial.println(counter--);
}
vTaskDelete(NULL);
}
void setup() {
Serial.begin(115200);
xTaskCreate(vTask, "vTask", 4096, NULL, 1, NULL);
}
void loop() {}
Sorry for my english, if something is not clear, please ask me. I am having trouble to make that application for WindowsForms ("ThreadTeste" is a representation of "MyForm1"):
#include <chrono>
#include <iostream>
#include <thread>
using namespace std;
using namespace std::chrono;
class ThreadTeste
{
public:
void loop()
{
for(int i = 0 ; i < 5 ; i++)
{
cout << i << endl;
this_thread::sleep_for(seconds(1));
}
}
thread getThread()
{
return thread(&ThreadTeste::loop, this);
}
ThreadTeste()
{
thread myThread = getThread();
myThread.detach();
}
};
int main(int argc, char *argv[])
{
ThreadTeste* t = new ThreadTeste();
while(true)
{
cout << "Working" << endl;
this_thread::sleep_for(seconds(1));
}
}
//That works!!
D:
If you want to output from 0 to 4 and then output working, then you could not use detach. Because detach means that the main thread does not need to wait for the execution of the child thread to complete and the two are out of relationship,then it will run by itself.
You could use join.
ThreadTeste()
{
thread myThread = getThread();
myThread.join();
}
I've implemented thread pooling following the answer of Kerrek SB in this question.
I've implemented MPMC queue for the functions and vector threads for the threads.
Everything worked perfectly, except that I don't know how to terminate the program, in the end if I just do thread.join since the thread is still waiting for more tasks to do, it will not join and the main thread will not continue.
Any idea how to end the program correctly?
For completeness, this is my code:
function_pool.h
#pragma once
#include <queue>
#include <functional>
#include <mutex>
#include <condition_variable>
class Function_pool
{
private:
std::queue<std::function<void()>> m_function_queue;
std::mutex m_lock;
std::condition_variable m_data_condition;
public:
Function_pool();
~Function_pool();
void push(std::function<void()> func);
std::function<void()> pop();
};
function_pool.cpp
#include "function_pool.h"
Function_pool::Function_pool() : m_function_queue(), m_lock(), m_data_condition()
{
}
Function_pool::~Function_pool()
{
}
void Function_pool::push(std::function<void()> func)
{
std::unique_lock<std::mutex> lock(m_lock);
m_function_queue.push(func);
// when we send the notification immediately, the consumer will try to
get the lock , so unlock asap
lock.unlock();
m_data_condition.notify_one();
}
std::function<void()> Function_pool::pop()
{
std::unique_lock<std::mutex> lock(m_lock);
m_data_condition.wait(lock, [this]() {return !m_function_queue.empty();
});
auto func = m_function_queue.front();
m_function_queue.pop();
return func;
// Lock will be released
}
main.cpp
#include "function_pool.h"
#include <string>
#include <iostream>
#include <mutex>
#include <functional>
#include <thread>
#include <vector>
Function_pool func_pool;
void example_function()
{
std::cout << "bla" << std::endl;
}
void infinite_loop_func()
{
while (true)
{
std::function<void()> func = func_pool.pop();
func();
}
}
int main()
{
std::cout << "stating operation" << std::endl;
int num_threads = std::thread::hardware_concurrency();
std::cout << "number of threads = " << num_threads << std::endl;
std::vector<std::thread> thread_pool;
for (int i = 0; i < num_threads; i++)
{
thread_pool.push_back(std::thread(infinite_loop_func));
}
//here we should send our functions
func_pool.push(example_function);
for (int i = 0; i < thread_pool.size(); i++)
{
thread_pool.at(i).join();
}
int i;
std::cin >> i;
}
Your problem is located in infinite_loop_func, which is an infinite loop and by result doesn't terminate. I've read the previous answer which suggests throwing an exception, however, I don't like it since exceptions should not be used for the regular control flow.
The best way to solve this is to explicitly deal with the stop condition. For example:
std::atomic<bool> acceptsFunctions;
Adding this to the function pool allows you to clearly have state and to assert that no new functions being added when you destruct.
std::optional<std::function<void()>> Function_pool::pop()
Returning an empty optional (or function in C++14 and before), allows you to deal with an empty queue. You have to, as condition_variable can do spurious wakeups.
With this, m_data_condition.notify_all() can be used to wake all threads.
Finally we have to fix the infinite loop as it doesn't cover overcommitment and at the same time allows you to execute all functions still in the queue:
while (func_pool.acceptsFunctions || func_pool.containsFunctions())
{
auto f = func_pool.pop();
If (!f)
{
func_pool.m_data_condition.wait_for(1s);
continue;
}
auto &function = *f;
function ();
}
I'll leave it up to you to implement containsFunctions() and clean up the code (infinite_loop_func as member function?) Note that with a counter, you could even deal with background task being spawned.
You can always use a specific exception type to signal to infinite_loop_func that it should return...
class quit_worker_exception: public std::exception {};
Then change infinite_loop_func to...
void infinite_loop_func ()
{
while (true) {
std::function<void()> func = func_pool.pop();
try {
func();
}
catch (quit_worker_exception &ex) {
return;
}
}
}
With the above changes you could then use (in main)...
/*
* Enqueue `thread_pool.size()' function objects whose sole job is
* to throw an instance of `quit_worker_exception' when invoked.
*/
for (int i = 0; i < thread_pool.size(); i++)
func_pool.push([](){ throw quit_worker_exception(); });
/*
* Now just wait for each worker to terminate having received its
* quit_worker_exception.
*/
for (int i = 0; i < thread_pool.size(); i++)
thread_pool.at(i).join();
Each instance of infinite_loop_func will dequeue one function object which, when called, throws a quit_worker_exception causing it to return.
Follwoing [JVApen](https://stackoverflow.com/posts/51382714/revisions) suggestion, I copy my code in case anyone will want a working code:
function_pool.h
#pragma once
#include <queue>
#include <functional>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <cassert>
class Function_pool
{
private:
std::queue<std::function<void()>> m_function_queue;
std::mutex m_lock;
std::condition_variable m_data_condition;
std::atomic<bool> m_accept_functions;
public:
Function_pool();
~Function_pool();
void push(std::function<void()> func);
void done();
void infinite_loop_func();
};
function_pool.cpp
#include "function_pool.h"
Function_pool::Function_pool() : m_function_queue(), m_lock(), m_data_condition(), m_accept_functions(true)
{
}
Function_pool::~Function_pool()
{
}
void Function_pool::push(std::function<void()> func)
{
std::unique_lock<std::mutex> lock(m_lock);
m_function_queue.push(func);
// when we send the notification immediately, the consumer will try to get the lock , so unlock asap
lock.unlock();
m_data_condition.notify_one();
}
void Function_pool::done()
{
std::unique_lock<std::mutex> lock(m_lock);
m_accept_functions = false;
lock.unlock();
// when we send the notification immediately, the consumer will try to get the lock , so unlock asap
m_data_condition.notify_all();
//notify all waiting threads.
}
void Function_pool::infinite_loop_func()
{
std::function<void()> func;
while (true)
{
{
std::unique_lock<std::mutex> lock(m_lock);
m_data_condition.wait(lock, [this]() {return !m_function_queue.empty() || !m_accept_functions; });
if (!m_accept_functions && m_function_queue.empty())
{
//lock will be release automatically.
//finish the thread loop and let it join in the main thread.
return;
}
func = m_function_queue.front();
m_function_queue.pop();
//release the lock
}
func();
}
}
main.cpp
#include "function_pool.h"
#include <string>
#include <iostream>
#include <mutex>
#include <functional>
#include <thread>
#include <vector>
Function_pool func_pool;
class quit_worker_exception : public std::exception {};
void example_function()
{
std::cout << "bla" << std::endl;
}
int main()
{
std::cout << "stating operation" << std::endl;
int num_threads = std::thread::hardware_concurrency();
std::cout << "number of threads = " << num_threads << std::endl;
std::vector<std::thread> thread_pool;
for (int i = 0; i < num_threads; i++)
{
thread_pool.push_back(std::thread(&Function_pool::infinite_loop_func, &func_pool));
}
//here we should send our functions
for (int i = 0; i < 50; i++)
{
func_pool.push(example_function);
}
func_pool.done();
for (unsigned int i = 0; i < thread_pool.size(); i++)
{
thread_pool.at(i).join();
}
}
I want this program run every start(call) 10min.
But I did not find a solution how-to call(start) Program every 10 minutes, on c++ code (man.exe).
I would like to use the code in visual studio 2013
int runevery() {
system("start man.exe");
return true;
}
Call:
#ifdef MAN_RUN
runevery();
#endif
Thank you for your help in advance!
You can create another thread that executes that function periodically until stopped. Example:
#include <mutex>
#include <chrono>
#include <thread>
#include <iostream>
#include <functional>
#include <condition_variable>
class PeriodicAction {
std::mutex m_;
std::condition_variable c_;
bool stop_ = false;
std::function<void()> const f_;
std::chrono::seconds const initial_delay_;
std::chrono::seconds const delay_;
std::thread thread_;
bool wait(std::chrono::seconds delay) {
std::unique_lock<std::mutex> lock(m_);
c_.wait_for(lock, delay, [this]() { return stop_; });
return !stop_;
}
void thread_fn() {
for(auto delay = initial_delay_; this->wait(delay); delay = delay_)
f_();
}
public:
PeriodicAction(std::chrono::seconds initial_delay,
std::chrono::seconds delay,
std::function<void()> f)
: f_(move(f))
, initial_delay_(initial_delay)
, delay_(delay)
, thread_(&PeriodicAction::thread_fn, this)
{}
~PeriodicAction() {
this->stop();
thread_.join();
}
void stop() {
{
std::unique_lock<std::mutex> lock(m_);
stop_ = true;
}
c_.notify_one();
}
};
char const* now_c_str() {
auto time_t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
return std::ctime(&time_t);
}
int main(int ac, char**) {
using namespace std::literals::chrono_literals;
// Print current time for the next 5 seconds and then terminate.
PeriodicAction a(0s, 1s, []() { std::cout << now_c_str(); });
std::this_thread::sleep_for(5s);
}
Applying to your case:
PeriodicAction a(0s, 600s, [](){ system("start man.exe"); });
I don't think this is a good idea, but it's easy to achieve like this:
#include <thread>
#include <chrono>
int main()
{
while (true)
{
std::this_thread::sleep_for(std::chrono::minutes(10));
system("man.exe");
}
}
I still think as per my earlier comment that a scheduled task on Windows would be better behaved and easier configurable.
As I came to know creating and terminating thread abruptly
using pthread_kill() everytime is not a good way to do, so I am going
with suspend and resume method for a thread using thread1.suspend() and
thread1.resume(), whenever needed. How to do/implement this?
Take below LED blinking code for reference. During thread1.start() creating thread with suspended = false; is continuing as it is stuck in a while loop.
Calling thread1.suspend() has no effect.
#define on 1
#define off 0
void gpio_write(int fd, int value);
void* led_Flash(void* args);
class PThread {
public:
pthread_t threadID;
bool suspended;
int fd;
pthread_mutex_t m_SuspendMutex;
pthread_cond_t m_ResumeCond;
void start() {
suspended = false;
pthread_create(&threadID, NULL, led_Flash, (void*)this );
}
PThread(int fd1) { this->fd=fd1; }
~PThread() { }
void suspend() {
pthread_mutex_lock(&m_SuspendMutex);
suspended = true;
printf("suspended\n");
do {
pthread_cond_wait(&m_ResumeCond, &m_SuspendMutex);
} while (suspended);
pthread_mutex_unlock(&m_SuspendMutex);
}
void resume() {
/* The shared state 'suspended' must be updated with the mutex held. */
pthread_mutex_lock(&m_SuspendMutex);
suspended = false;
printf("Resumed\n");
pthread_cond_signal(&m_ResumeCond);
pthread_mutex_unlock(&m_SuspendMutex);
}
};
void* led_Flash(void* args)
{
PThread* pt= (PThread*) args;
int ret=0;
int fd= pt->fd;
while(pt->suspended == false)
{
gpio_write(fd,on);
usleep(1);
gpio_write(fd,off);
usleep(1);
}
return NULL;
}
int main()
{
int fd1=1,fd2=2, fd3=3;
class PThread redLED(fd1);
class PThread amberLED(fd2);
class PThread greenLED(fd3);
redLED.start();
amberLED.start();
greenLED.start();
sleep(1);
redLED.suspend();
return 0;
}
Could some body help me, please?
After a little modification of above code , it seems working . Thanks guy for pointing out issues on above code, the changes are as follow.
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<iostream>
#define on 1
#define off 0
void gpio_write(int fd, int value);
void* led_Flash(void* args);
class PThread {
public:
pthread_t threadID;
volatile int suspended;
int fd;
pthread_mutex_t lock;
PThread(int fd1)
{
this->fd=fd1;
this->suspended =1; //Initial state: suspend blinking untill resume call
pthread_mutex_init(&this->lock,NULL);
pthread_create(&this->threadID, NULL, led_Flash, (void*)this );
}
~PThread()
{
pthread_join(this->threadID , NULL);
pthread_mutex_destroy(&this->lock);
}
void suspendBlink() {
pthread_mutex_lock(&this->lock);
this->suspended = 1;
pthread_mutex_unlock(&this->lock);
}
void resumeBlink() {
pthread_mutex_lock(&this->lock);
this->suspended = 0;
pthread_mutex_unlock(&this->lock);
}
};
void gpio_write(int fd, int value)
{
if(value!=0)
printf("%d: on\n", fd);
else
printf("%d: off\n", fd);
}
void* led_Flash(void* args)
{
PThread* pt= (PThread*) args;
int fd= pt->fd;
while(1)
{
if(!(pt->suspended))
{
gpio_write(fd,on);
usleep(1);
gpio_write(fd,off);
usleep(1);
}
}
return NULL;
}
int main()
{
//Create threads with Initial state: suspend/stop blinking untill resume call
class PThread redLED(1);
class PThread amberLED(2);
class PThread greenLED(3);
// Start blinking
redLED.resumeBlink();
amberLED.resumeBlink();
greenLED.resumeBlink();
sleep(5);
// suspend/stop blinking
amberLED.suspendBlink();
sleep(5);
redLED.suspendBlink();
sleep(5);
amberLED.suspendBlink();
sleep(5);
redLED.resumeBlink();
pthread_exit(NULL);
return 0;
}