I checked quite a few posts but could not be sure if answers were related to what I want to do. All I could understand was to use threads.
I want to have a Server object which constantly checks a boolean value in a Client object and in case it is true server should do something and turn the flag to false.
I want this checking process to be done parallel to my main. btw server and client have to do other things too which i dont want to put in the same thread as the function that checks the client's flag
EDIT: I need to have multiple objects of Server and Client
so here is what i mean in C++ code:
main.cpp
#include <iostream>
using namespace std;
class Client
{
public:
bool flag;
void setFlag(bool flagStat)
{
flag = flagStat;
}
bool getFlag()
{
return flag;
}
};
class Server
{
public:
void checkClientFlag(Client *client)
{
while (true)
{
if (client->getFlag())
{
alarmServer();
client->setFlag(false);
}
}
}
void alarmServer()
{
cout << "Client Flag UP!!!" << endl;
}
};
int main()
{
Server *newSrv = new Server;
Client *newCnt = new Client;
newSrv->checkClientFlag(newCnt);
return 0;
}
so help is appreciated.
Thank you in advance.
You can use condition variable that will deal with this checking for you.
The idea is that you have a flag that is set to true/flase depending on whether the work has been done (set up as false and will be set to true when the work method is done).
the wait method means that the program will wait until a certain condition is filled.
you use notify to set this condition to true
Server.h
#include <condition_variable>
#include <mutex>
class CServer
{
std::condition_variable & cv;
std::mutex & mut;
bool & flag;
public:
~CServer(void);
CServer::CServer(std::condition_variable & cv,
std::mutex & mut,
bool & flag);
CServer::CServer(CServer &);
int Notify();
int DisplayNotification();
std::condition_variable & getCondVar(){return cv;}
std::mutex & getMutex(){return mut;}
bool & getFlag(){return flag;}
};
Server.cpp
#include "Server.h"
#include <iostream>
using namespace std;
CServer::~CServer(void)
{
}
CServer::CServer(std::condition_variable & cv_,
std::mutex & mut_,
bool & flag_):
cv(cv_),
mut(mut_),
flag(flag_)
{
}
CServer::CServer(CServer &toCopy):
cv(toCopy.getCondVar()),
mut(toCopy.getMutex()),
flag(toCopy.getFlag())
{
flag=false;
cout<<"Copy constructor"<<std::endl;
}
int CServer::Notify()
{
{
std::lock_guard<std::mutex> lk(mut);
flag=true;
std::cout << "ready for notfication"<<endl;
}
cv.notify_one();
return 0;
}
int CServer::DisplayNotification()
{
// wait for the worker
{
std::unique_lock<std::mutex> lk(mut);
cv.wait(lk, [this]{return this->getFlag();});
}
cout<<"Notification displayed"<<endl;
return 0;
}
Client.h
#include <chrono>
#include "Server.h"
class CClient
{
CServer & serv;
std::chrono::seconds sleepTime;
bool finishedWork;
public:
CClient(CServer & serv,
std::chrono::seconds sleepTime);
~CClient(void);
int work();
};
Client.cpp
#include "Client.h"
#include <thread>
using namespace std;
CClient::CClient(CServer & serv_,
std::chrono::seconds sleepTime_):
serv(serv_),
sleepTime(sleepTime_),
finishedWork(false)
{
}
CClient::~CClient(void)
{
}
int CClient::work()
{
this_thread::sleep_for(sleepTime);
finishedWork=true;
serv.Notify();
return 0;
}
And the main program is
#include "Client.h"
#include <thread>
using namespace std;
int main()
{
std::chrono::seconds sleepTime=std::chrono::seconds(10);
//create client and server
condition_variable cv;
mutex mut;
bool flag=false;
CServer serv(cv,mut, flag);
CClient cli(serv,sleepTime);
//thread with the server
thread thServ(&CServer::DisplayNotification,serv);
////thread with the client
thread thCli (&CClient::work,cli);
////join threads
thServ.join();
thCli.join();
return 0;
}
Hope that helps, ask me if you have any questions
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() {}
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.
I am using an online C++11 compiler, link found here: cpp.sh (C++ Shell).
In my current project, I would like to have a watchdog class, to be able to check somehow the status of a thread or FSM (for example).
After some work (I'm not a C++11 guru), I finally got the code below, that compiles ok.
I also did some basic/trivial tests, but it seems the test program doesn't want to exit.
It says "Program running" and the only way to (force) exit is to hit the "Stop" button... :(
Well, my question : What am I doing wrong?
Any ideas, suggestions you can provide are highly appreciated.
Here is the full code, including my test app:
Watchdog (as MCVE):
#include <thread>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <mutex>
#include <iostream>
using namespace std::chrono;
class Watchdog
{
public:
Watchdog();
~Watchdog();
void Start(unsigned int milliseconds, std::function<void()> callback = 0);
void Stop();
void Pet();
private:
unsigned int m_interval;
std::atomic<bool> m_running;
std::thread m_thread;
std::function<void()> m_callback;
std::mutex m_mutex;
steady_clock::time_point m_lastPetTime;
std::condition_variable m_stopCondition;
void Loop();
};
Watchdog::Watchdog()
{
m_running = false;
}
Watchdog::~Watchdog()
{
Stop();
}
void Watchdog::Start(unsigned int milliseconds, std::function<void()> callback)
{
std::unique_lock<std::mutex> locker(m_mutex);
if(m_running == false)
{
m_lastPetTime = steady_clock::now();
m_interval = milliseconds;
m_callback = callback;
m_running = true;
m_thread = std::thread(&Watchdog::Loop, this);
}
}
void Watchdog::Stop()
{
std::unique_lock<std::mutex> locker(m_mutex);
if(m_running == true)
{
m_running = false;
m_stopCondition.notify_all();
m_thread.join();
}
}
void Watchdog::Pet()
{
std::unique_lock<std::mutex> locker(m_mutex);
m_lastPetTime = steady_clock::now();
m_stopCondition.notify_all();
}
void Watchdog::Loop()
{
std::unique_lock<std::mutex> locker(m_mutex);
while(m_running == true)
{
if(m_stopCondition.wait_for(locker, milliseconds(m_interval)) == std::cv_status::timeout)
{
if(m_callback != nullptr)
m_callback();
}
}
}
int main(int argc, char *argv[])
{
Watchdog wdog;
wdog.Start(3000, [] { std::cout << " WDOG TRIGGERED!!! "; });
for(auto i = 0; i < 10; i++)
{
std::cout << "[+]";
wdog.Pet();
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
}
-
You're doing a deadlock here.
void Watchdog::Stop()
{
std::unique_lock<std::mutex> locker(m_mutex);
if(m_running == true)
{
m_running = false;
m_stopCondition.notify_all();
m_thread.join();
^ ~~~~~~~~~~~~~~
m_mutex is locked; m_thread cannot continue execution
}
}
Some additional suggestion: use simple if conditions, do not compare with true or false.
I'm making a service, which is listening on a logon event. If this event occurs, my application should start a new thread, which will do the work.
My question is, how can i start a new thread every time a logon event occurs, and close it's handle correctly if the thread is done working. My problem is, that i don't know how many logon event will occur, so i can't user WaitForMultipleObjects because it's first parameter is the number of threads it should wait for.
while ( WaitForSingleObject( ghSvcStopEvent, 0 ) != WAIT_OBJECT_0 )
{
DWORD dwEventFlags;
BOOL bRes;
// WTSWaitSystemEvent waits until a logon event ocurs
bRes = WTSWaitSystemEvent( WTS_CURRENT_SERVER_HANDLE, WTS_EVENT_LOGON, &dwEventFlags );
if ( dwEventFlags == WTS_EVENT_NONE )
{
ShowErrorText( "Cancelling waiting for logon event. Service shutting down.", 0, true );
}
if ( bRes )
{
// Someone has logged on
HANDLE hThread = CreateThread( NULL, 0, ServiceWorkerThread, NULL, 0, &dwThreadID );
}
else
{
ShowErrorText( "WTSWaitSystemEvent failed.", GetLastError(), true );
}
}//while
Could someone help me?
Thanks!
If you can use C++11 (starting VS2010), you an use condition variable that will do the job for you
The idea of a condition variable is:
one variable that allows threads to comunicate together.
if you notify it, you send a signal to other threads pluged on it
if you do cv.wait(...) on it, you wait for other threads to signal that sonething has happenend and then you test your condition again.
Here is an example
Server.h
#include <condition_variable>
#include <mutex>
class CServer
{
std::condition_variable & cv;
std::mutex & mut;
bool & flag;
public:
~CServer(void);
CServer::CServer(std::condition_variable & cv,
std::mutex & mut,
bool & flag);
CServer::CServer(CServer &);
int Notify();
int DisplayNotification();
std::condition_variable & getCondVar(){return cv;}
std::mutex & getMutex(){return mut;}
bool & getFlag(){return flag;}
};
Server.cpp
#include "Server.h"
#include <iostream>
using namespace std;
CServer::~CServer(void)
{
}
CServer::CServer(std::condition_variable & cv_,
std::mutex & mut_,
bool & flag_):
cv(cv_),
mut(mut_),
flag(flag_)
{
}
CServer::CServer(CServer &toCopy):
cv(toCopy.getCondVar()),
mut(toCopy.getMutex()),
flag(toCopy.getFlag())
{
flag=false;
cout<<"Copy constructor"<<std::endl;
}
int CServer::Notify()
{
{
std::lock_guard<std::mutex> lk(mut);
flag=true;
std::cout << "ready for notfication"<<endl;
}
cv.notify_one();
return 0;
}
int CServer::DisplayNotification()
{
// wait for the worker
{
std::unique_lock<std::mutex> lk(mut);
cv.wait(lk, [this]{return this->getFlag();});
}
cout<<"Notification displayed"<<endl;
return 0;
}
Client.h
#include <chrono>
#include "Server.h"
class CClient
{
CServer & serv;
std::chrono::seconds sleepTime;
bool finishedWork;
public:
CClient(CServer & serv,
std::chrono::seconds sleepTime);
~CClient(void);
int work();
};
Client.cpp
#include "Client.h"
#include <thread>
using namespace std;
CClient::CClient(CServer & serv_,
std::chrono::seconds sleepTime_):
serv(serv_),
sleepTime(sleepTime_),
finishedWork(false)
{
}
CClient::~CClient(void)
{
}
int CClient::work()
{
this_thread::sleep_for(sleepTime);
finishedWork=true;
serv.Notify();
return 0;
}
Main.cpp
#include "Client.h"
#include <thread>
using namespace std;
int main()
{
std::chrono::seconds sleepTime=std::chrono::seconds(10);
//create client and server
condition_variable cv;
mutex mut;
bool flag=false;
CServer serv(cv,mut, flag);
CClient cli(serv,sleepTime);
//thread with the server
thread thServ(&CServer::DisplayNotification,serv);
////thread with the client
thread thCli (&CClient::work,cli);
////join threads
thServ.join();
thCli.join();
return 0;
}
Ask me if you have any questions,
Hope that helps