I think that just an ordinary sleep function would do, no?
For example, using boost::thread (I'm not so familiar with native pthread stuff):
#include <boost/thread/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/bind/bind.hpp>
#include <iostream>
class foo {
public:
void my_delayed_method() {
std::cout << "Hello World!" << std::endl;
};
private:
boost::thread delay_thread;
void call_method_with_delay() {
boost::this_thread::sleep(boost::posix_time::seconds(60));
my_delayed_method();
};
public:
foo() : delay_thread(boost::bind(&foo::call_method_with_delay,this)) { };
~foo() { delay_thread.join(); };
};
If you need the public method to be called from the same thread as the foo object got created on, then you need to use some sort of signal instead of a direct call:
#include <boost/thread/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/bind/bind.hpp>
#include <iostream>
class foo {
public:
void my_delayed_method() {
std::cout << "Hello World!" << std::endl;
};
private:
boost::thread delay_thread;
bool should_call;
void call_method_with_delay() {
boost::this_thread::sleep(boost::posix_time::seconds(60));
should_call = true;
};
public:
foo() : delay_thread(boost::bind(&foo::call_method_with_delay,this)), should_call(false) { };
~foo() { delay_thread.join(); };
void call_if_delay_passed() {
if(should_call) {
my_delayed_method();
should_call = false;
};
};
};
//for sake of example, here is a creator thread:
void create_and_loop() {
foo f;
while(true) {
f.call_if_delay_passed();
boost::this_thread::sleep(boost::posix_time::seconds(1));
};
};
int main() {
std::cout << "About to create several threads... press ctrl-C to stop!" << std::endl;
boost::thread* t[10];
for(int i=0;i<10;++i)
t[i] = new boost::thread(&create_and_loop);
std::cin.get();
return 0;
};
You will observe that there is nothing thread-unsafe in the above.
mike_2000_17
Posting Virtuoso
2,134 posts since Jul 2010
Reputation Points: 1,634
Solved Threads: 457
It seems like you want a subscriber-publisher model. There will be one publisher thread which calls a particular function on all subscribers every 60 seconds. The publisher can be a Singleton and subscribers could just subscribe with a callback function to it. However if there is only 1 publisher then it could be that a new foo object subscribes just a fraction of second before the publisher is going to wake up so the first call can be at any time after you subscribe. All other calls will happen at 60 seconds periods though.
Agni
Practically a Master Poster
655 posts since Dec 2007
Reputation Points: 431
Solved Threads: 116
As Agni suggested, you can group all those delays/timers into one singleton object. The same mechanism applies when it comes to calling from the same thread as foo was created or calling from any thread. I will just make an example for calling from the timer thread (you would just have to replace the callback by setting of a flag to signal the call on the original thread).
#include <boost/thread/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/bind/bind.hpp>
#include <iostream>
#include <map>
class publisher {
private:
typedef std::multimap< boost::posix_time::ptime, boost::function<void()> > CallBackMap;
typedef CallBackMap::iterator CallBackIter;
CallBackMap callbacks;
boost::mutex callbacks_mutex;
boost::thread publishing_thread;
void execute() {
while(true) {
{
boost::unique_lock<boost::mutex> lock(callbacks_mutex);
CallBackIter it_end = callbacks.upper_bound(boost::posix_time::millisec_clock::local_time() + boost::posix_time::milliseconds(20));
for(CallBackIter it = callbacks.begin(); it != it_end; ++it)
it->second(); //call the callbacks that are scheduled.
callbacks.erase(callbacks.begin(), it_end); //erase callbacks that were called.
}; //release lock.
boost::this_thread::sleep(boost::posix_time::milliseconds(20)); //sleep 20ms
};
};
//private constructor. Will start the execution thread.
publisher() : publishing_thread(boost::bind(&publisher::execute,this)) { };
publisher(const publisher&);
publisher& operator=(const publisher&); //non-copyable.
public:
void subscribe(boost::function<void()> f, boost::posix_time::time_duration dt) {
boost::unique_lock<boost::mutex> lock(callbacks_mutex);
callbacks.insert(std::make_pair(boost::posix_time::microsec_clock::local_time() + dt, f));
};
static publisher& getPublisher(); //singleton.
};
publisher& publisher::getPublisher() {
static publisher p; //will be created on first use.
return p;
};
class foo {
public:
void my_delayed_method() {
std::cout << "Hello World!" << std::endl;
};
foo() {
publisher::getPublisher().subscribe(boost::bind(&foo::call_method_with_delay,this), boost::posix_time::seconds(60)); //subscribe for a callback in 60 seconds.
};
};
mike_2000_17
Posting Virtuoso
2,134 posts since Jul 2010
Reputation Points: 1,634
Solved Threads: 457