At this question, I asked how to unblock a grpc::CompletionQueue::Next() that is waiting on a grpc::Channel::NotifyOnStateChange(..., gpr_inf_future(GPR_CLOCK_MONOTONIC), ...).
That question, specifically, is still unanswered, but I am trying a workaround, where the CompletionQueue is instead waiting on a grpc::Channel::NotifyOnStateChange() with a non-infinite deadline:
// main.cpp
#include <chrono>
#include <iostream>
#include <memory>
#include <thread>
#include <grpcpp/grpcpp.h>
#include <unistd.h>
using namespace std;
using namespace grpc;
void threadFunc(shared_ptr<Channel> ch, CompletionQueue* cq) {
void* tag = NULL;
bool ok = false;
int i = 1;
grpc_connectivity_state state = ch->GetState(false);
std::chrono::time_point<std::chrono::system_clock> now =
std::chrono::system_clock::now();
std::chrono::time_point<std::chrono::system_clock> deadline =
now + std::chrono::seconds(2);
cout << "state " << i++ << " = " << (int)state << endl;
ch->NotifyOnStateChange(state,
//gpr_inf_future(GPR_CLOCK_MONOTONIC),
deadline,
cq,
(void*)1);
while (cq->Next(&tag, &ok)) {
state = ch->GetState(false);
cout << "state " << i++ << " = " << (int)state << endl;
now = std::chrono::system_clock::now();
deadline = now + std::chrono::seconds(2);
ch->NotifyOnStateChange(state,
//gpr_inf_future(GPR_CLOCK_MONOTONIC),
deadline,
cq,
(void*)1);
}
cout << "thread end" << endl;
}
int main(int argc, char* argv[]) {
ChannelArguments channel_args;
CompletionQueue cq;
channel_args.SetInt(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA, 0);
channel_args.SetInt(GRPC_ARG_MIN_RECONNECT_BACKOFF_MS, 2000);
channel_args.SetInt(GRPC_ARG_MAX_RECONNECT_BACKOFF_MS, 2000);
channel_args.SetInt(GRPC_ARG_HTTP2_BDP_PROBE, 0);
channel_args.SetInt(GRPC_ARG_KEEPALIVE_TIME_MS, 60000);
channel_args.SetInt(GRPC_ARG_KEEPALIVE_TIMEOUT_MS, 30000);
channel_args.SetInt(GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS,
60000);
{
shared_ptr<Channel> ch(CreateCustomChannel("my_grpc_server:50051",
InsecureChannelCredentials(),
channel_args));
std::thread my_thread(&threadFunc, ch, &cq);
cout << "sleeping" << endl;
sleep(5);
cout << "slept" << endl;
cq.Shutdown();
cout << "shut down cq" << endl;
my_thread.join();
}
}
Output of the running executable:
$ ./a.out
sleeping
state 1 = 0
state 2 = 0
state 3 = 0
slept
shut down cq
state 4 = 0
E1012 15:29:07.677225824 54 channel_connectivity.cc:234] assertion failed: grpc_cq_begin_op(cq, tag)
Aborted (core dumped)
This version periodically unblocks, as expected, but why does it assert?
My question is ultimately: how do you cleanly exit from a loop/thread that is waiting on a grpc::CompletionQueue that is waiting on a grpc::Channel::NotifyOnStateChange() ?
My experience has been that with an infinite deadline, it's impossible to unblock grpc::CompletionQueue::Next(), and with a non-infinite deadline, shutting down the grpc::CompletionQueue results in an assert, which is presumably a non-clean exit.
The documentation for CompletionQueue::Shutdown()`](https://grpc.github.io/grpc/cpp/classgrpc_1_1_completion_queue.html#a40efddadd9073386fbcb4f46e8325670) says:
Also note that applications must ensure that no work is enqueued on this completion queue after this method is called.
In other words, once you shut down the CQ, it is illegal to call NotifyOnStateChange() again, because that is enqueing new work.
In this case, what you should expect to see after you call CompletionQueue::Shutdown() is that the already-invoked call to CompletionQueue::Next() will return the already-requested NotifyOnStateChange() completion, and the next call to CompletionQueue::Next() will return false, thus indicating that the CQ is shut down. However, your code is not making a call to Next() to see if the CQ is shut down before it calls NotifyOnStateChange() again to request another state change notification, so that is happening after the CQ is shut down, which is why you're seeing this assertion.
In general, the right way to use a CQ is to have a separate, dedicated set of threads that always call Next() in a loop but do not themselves start any new work on the CQs. Starting new work on the CQs should be done in separate thread(s) and should not be done after the CQ is shut down.
I hope this information is helpful.
Related
I'm trying to shutdown properly a gRPC server.
I use the provided async helloworld from gRPC source.
The file is here: https://github.com/grpc/grpc/blob/master/examples/cpp/helloworld/greeter_async_server.cc
I have edited the main like the following:
#include "greeter_async_server.cc"
#include <thread>
#include <iostream>
void stop_task(ServerImpl* server) {
int delay = 10000;
std::cout << "Server will stop after " << delay / 1000 << " seconds" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(delay));
std::cout << "Wait finished" << std::endl;
std::cout << "Stoping server..." << std::endl;
server->Shutdown();
std::cout << "Stop sent" << std::endl;
}
void server_task(ServerImpl* server) {
server->Run();
}
int main(int argc, char** argv) {
ServerImpl server;
std::thread server_thread(server_task, &server);
std::thread stop_thread(stop_task, &server);
stop_thread.join();
server_thread.join();
std::cout << "Server stopped" << std::endl;
return 0;
}
void ServerImpl::Shutdown()
{
server->Shutdown();
// Always shutdown the completion queue after the server.
cq->Shutdown();
}
Server will stop after 10 seconds
Server listening on 0.0.0.0:50051
Wait finished
Stoping server...
E0825 15:08:30.182000000 34960 greeter_async_server.cc:156] assertion failed: ok
Sortie de TestGreeterAsyncServer.exe (processus 37008). Code : -1073740791.
Appuyez sur une touche pour fermer cette fenêtre. . .
I don't understand why the server crashes on assertion failed.
The assertion is at line 156:
GPR_ASSERT(ok);
Anyone has an idea?
Thank you in advance!
You're trying to delete an object (server) that's been created on the stack.
That said, the example code does not showcase any way to cleanly stop the server once it's been started. It is even said in a comment above the Run() method:
There is no shutdown handling in this code.
This question provides good pointers on how to accomplish your goal.
Here is why the assertion is triggered:
cq_->Next(&tag, &ok); is a blocking call, until either
An error occurs (which means ok == false) ;
A task is about to be processed (which means ok == true) ;
cq_->Shutdown() has been called (which also means ok == false).
You can read about all the different scenarios in CompletionQueue::Next() documentation. Since you're shutting down, ok is false which triggers the assertion's failure.
Here is the solution.
I have edited the greeter_async_server.cc like this:
private:
// Adding attrbutes
bool is_shutting_down = false;
std::mutex mutex;
void HandleRpcs() {
new CallData(&service_, cq_.get());
void* tag;
bool ok;
while (true) {
GPR_ASSERT(cq_->Next(&tag, &ok));
// Here, added exit condition
mutex.lock();
if (true == is_shutting_down) {
mutex.unlock();
std::cout << "stop reading" << std::endl;
break;
}
else mutex.unlock();
GPR_ASSERT(ok);
static_cast<CallData*>(tag)->Proceed();
}
}
public:
// Adding Shutdown public method
void Shutdown() {
mutex.lock();
is_shutting_down = true;
mutex.unlock();
const std::chrono::milliseconds WaitDuration = std::chrono::milliseconds(50);
const std::chrono::time_point<std::chrono::system_clock> Deadline = std::chrono::system_clock::now() + WaitDuration;
server_->Shutdown(Deadline);
cq_->Shutdown();
}
Currently I'm working on server development for an online game and decided to implement it as multithreaded application.
I have a main thread which implements while loop which abstractly gets data from the socket.
std::vector<std::thread> games_threads;
int start(int game_id) {
std::this_thread::sleep_for(std::chrono::seconds(10));
return end(game_id);
}
int end(int game_id) {
// some other conditions for turn end
return start(game_id);
}
int main() {
// socket implmementation
while(1) {
Message msg = socket.get_data();
switch(msg->action) {
case GAME_START:
std::thread game_thread(start, create_game());
game_thread.detach();
games_threads.push_back(game_thread);
break;
case TURN_END:
std::thread game_thread(end, msg->get_game());
game_thread.detach();
games_threads.push_back(game_thread);
break;
}
}
}
Game creates with turn start() method. And then after waiting 10 secs in call end() method which implements turn end.
After than turn end() method calls start().
But I need also implement force turn end method so I have race condition with 2 cases:
Start -> End normal workflow with 10s timeout (which makes game
thread unavailable for 10 secs)
Forced turn end command (TURN_END).
So I need somehow end the current game thread and replace with one user thread. Or just catch signals somehow with conditional variable but I have already freeze for 10sec and as far as I know I can't wait both things at the same time (conditional variable and sleep ending).
Maybe multithreading is not a good solution at all. Please share your approach in this case.
Thanks
Its not so much that multi-threading is a bad approach as your specific implementation is not right.
A call to the start() function or end() function will never return because they each call each other in a never ending recursion. This is already bad since your stack will be filling up as you enter deeper into function calls.
But that aside, your main loop starts a new thread when you call GAME_START and this new thread goes into its "forever" start()<-->end() loop. "OK" so far, but then when the TURN_END is called your main loop calls end() directly and therefore your main loop also now enters a forever start()<-->end() loop. This now means both your main and your "worker" thread are locked up in these loops that don't return - so no more messages can be processed from your socket.
I would suggest that your main loop uses a condition variable to signal your worker loop to force a new turn.
I am not quite sure what to suggest to replace your start()<-->end() recursion loop because its not clear to me what this is trying to achieve. But possibly a timer class might work here (the example is the first one I found in google)
Complete Example Using Stdin
Here the start function implements a thread loop instead of calling end/start repeatedly... Also the game ID 1 gets ended when you enter end the other games continue as normal. All games exit when you enter exit
#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
#include <algorithm>
#include <atomic>
#include <chrono>
#include <condition_variable>
std::vector<std::thread> games_threads;
std::condition_variable cv;
std::mutex cv_m;
int the_game_id = 0;
int start(int id) {
int game_id = id;
bool running = true;
while (running)
{
std::unique_lock<std::mutex> lk(cv_m);
auto now = std::chrono::system_clock::now();
std::cout << "THREAD " << game_id << ": Waiting for turn..." << std::endl;
// Wait for the signal to end turn only if the game ID is for us.
if(cv.wait_until(lk, now + std::chrono::seconds(10), [&game_id](){return (the_game_id == game_id || the_game_id == -1);}))
{
// Condition var signalled
if (the_game_id == -1)
{
std::cout << "THREAD" << game_id << ": end game - exit" << std::endl;
running = false;
}
else
{
std::cout << "THREAD" << game_id << ": turn end forced" << std::endl;
// Reset the game ID so we don't keep triggering
the_game_id = 0;
}
}
else
{
// 10 second timeout occured
std::cout << "THREAD" << game_id << ": 10 seconds is up, end turn" << std::endl;
}
}
std::cout << "THREAD" << game_id << ": ended" << std::endl;
return 1;
}
int main() {
// pretend socket implmementation - using stdin
int id = 1;
bool done = false;
while(!done) {
std::string cmd;
std::getline(std::cin, cmd);
if (cmd == "start")
{
std::cout << "starting..." << std::endl;
games_threads.push_back({ std::thread( [&id](){ return start(id++); } ) });
}
else if (cmd == "end")
{
std::cout << "ending..." << std::endl;
// Notify game ID 1 to end turn - (but in reality get the ID from the message)
the_game_id = 1;
cv.notify_all();
}
else if (cmd == "exit")
{
std::cout << "exiting all threads..." << std::endl;
// Notify game ID 1 to end turn
the_game_id = -1;
cv.notify_all();
done = true;
}
}
// Tidyup threads
for (auto &th : games_threads)
{
if (th.joinable())
{
th.join();
}
}
}
Output:
> start
starting...
THREAD 1: Waiting for turn...
> start
starting...
THREAD 2: Waiting for turn...
> start
starting...
THREAD 3: Waiting for turn...
> end
ending...
THREAD1: turn end forced
THREAD 1: Waiting for turn...
THREAD2: 10 seconds is up, end turn
THREAD 2: Waiting for turn...
THREAD3: 10 seconds is up, end turn
THREAD 3: Waiting for turn...
THREAD1: 10 seconds is up, end turn
THREAD 1: Waiting for turn...
> exit
exiting all threads...
THREAD1: end game - exit
THREAD1: ended
THREAD2: end game - exit
THREAD2: ended
THREAD3: end game - exit
THREAD3: ended
I encountered some problems with MHD_suspend_connection() and MHD_resume_connection() in libmicrohttpd while using the external event loop. Afterwards I have wrote a small example (without error handling) below. My question is: What am I doing wrong? Or is it a bug in the library? It should work as far as I understand the manual. Using external select with suspend/resume is allowed explicitly.
The problem is that connections are not resumed correctly. Processing the connection does not continue right after calling MHD_resume_connection(). In some versions of my program, it did continue after another request was incomming. In other versions later requests was not handled at all (access_handler() was never called). In some of this versions I got a response for the first request while stopping libmicrohttpd. When I enable MHD_USE_SELECT_INTERNALLY and remove my external loop (let it sleep), everything works.
I tested it on Debian (libmicrohttpd 0.9.37) and Arch (libmicrohttpd 0.9.50). The problem exists on both systems but maybe the behavior was a little bit different.
#include <algorithm>
#include <csignal>
#include <cstring>
#include <iostream>
#include <vector>
#include <sys/select.h>
#include <microhttpd.h>
using std::cerr;
using std::cout;
using std::endl;
static volatile bool run_loop = true;
static MHD_Daemon *ctx = nullptr;
static MHD_Response *response = nullptr;
static std::vector<MHD_Connection*> susspended;
void sighandler(int)
{
run_loop = false;
}
int handle_access(void *cls, struct MHD_Connection *connection,
const char *url, const char *method, const char *version,
const char *upload_data, size_t *upload_data_size,
void **con_cls)
{
static int second_call_marker;
static int third_call_marker;
if (*con_cls == nullptr) {
cout << "New connection" << endl;
*con_cls = &second_call_marker;
return MHD_YES;
} else if (*con_cls == &second_call_marker) {
cout << "Suspending connection" << endl;
MHD_suspend_connection(connection);
susspended.push_back(connection);
*con_cls = &third_call_marker;
return MHD_YES;
} else {
cout << "Send response" << endl;
return MHD_queue_response(connection, 200, response);
}
}
void myapp()
{
std::signal(SIGINT, &sighandler);
std::signal(SIGINT, &sighandler);
ctx = MHD_start_daemon(MHD_USE_DUAL_STACK //| MHD_USE_EPOLL
| MHD_USE_SUSPEND_RESUME | MHD_USE_DEBUG,
8080, nullptr, nullptr,
&handle_access, nullptr,
MHD_OPTION_END);
response = MHD_create_response_from_buffer(4, const_cast<char*>("TEST"),
MHD_RESPMEM_PERSISTENT);
while (run_loop) {
int max;
fd_set rs, ws, es;
struct timeval tv;
struct timeval *tvp;
max = 0;
FD_ZERO(&rs);
FD_ZERO(&ws);
FD_ZERO(&es);
cout << "Wait for IO activity" << endl;
MHD_UNSIGNED_LONG_LONG mhd_timeout;
MHD_get_fdset(ctx, &rs, &ws, &es, &max);
if (MHD_get_timeout(ctx, &mhd_timeout) == MHD_YES) {
//tv.tv_sec = std::min(mhd_timeout / 1000, 1ull);
tv.tv_sec = mhd_timeout / 1000;
tv.tv_usec = (mhd_timeout % 1000) * 1000;
tvp = &tv;
} else {
//tv.tv_sec = 2;
//tv.tv_usec = 0;
//tvp = &tv;
tvp = nullptr;
}
if (select(max + 1, &rs, &ws, &es, tvp) < 0 && errno != EINTR)
throw "select() failed";
cout << "Handle IO activity" << endl;
if (MHD_run_from_select(ctx, &rs, &ws, &es) != MHD_YES)
throw "MHD_run_from_select() failed";
for (MHD_Connection *connection : susspended) {
cout << "Resume connection" << endl;
MHD_resume_connection(connection);
}
susspended.clear();
}
cout << "Stop server" << endl;
MHD_stop_daemon(ctx);
}
int main(int argc, char *argv[])
{
try {
myapp();
} catch (const char *str) {
cerr << "Error: " << str << endl;
cerr << "Errno: " << errno << " (" << strerror(errno) << ")" << endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
I've compiled and run your sample on Windows and am seeing the same behavior w/ 0.9.51.
It's not a bug in microhttpd. The problem is that you are resuming a connection before queuing a response on it. The only code you have that creates a response relies on more activity on the connection so it's a catch-22.
The point of MHD_suspend_connection/MHD_resume_connection is to not block new connections while long-running work is going on. Thus typically after suspending the connection you need to kick off that work on another thread to continue while the listening socket is maintained. When that thread has queued the response it can resume the connection and the event loop will know it is ready to send back to the client.
I'm not sure of your other design requirements but you may not need to be implementing external select. That is to say, suspend/resume does not require it (I've used suspend/resume just fine with MHD_USE_SELECT_INTERNALLY, e.g.).
I dont know if it's mentioned. But you have a multi-threading bug, and perhaps, "intent bug". As the lib, may or may not use threads, depending on other factors. You can see if you are using threads, by printing the thread id, from the functions. But, your answerToConnection function, sets your vector (without mutex protection), and then you are immediately looking at it, and retrying potentially from another thread. this goes against the intent/purpose of suspend/retry, since suspend is really for something taking "a long time". The gotcha, is that you dont own the calling code, so, you dont know when it's totally done. however, you can age your retry, with a timeval, so, you dont retry too soon. at least a value of tv_usec +1. you need to note, that you are using the vector from two or more threads, without mutex protection.
I'm using a deadline_timer as an asynchronous event and I'm running into a situation where, after some time, the thread waiting on the event never seems to be woken up (despite more calls to cancel()). I've been able to reproduce this using some sample code that I've pasted below; it's not exactly consistent but I have seen what I think is the same issue I'm experiencing.
boost::asio::io_service io_service;
boost::asio::deadline_timer timer(io_service);
timer.expires_at(boost::posix_time::pos_infin);
int num_events = 0;
auto waiter = [&timer, &num_events](boost::asio::yield_context context) {
while (true) {
std::cout << "waiting on event" << std::endl;
boost::system::error_code e;
timer.async_wait(context[e]);
std::cout << "got event (" << e << ")" << std::endl;
++num_events;
}
};
boost::asio::spawn(io_service, std::move(waiter));
boost::thread thread(boost::bind(&boost::asio::io_service::run, &io_service));
for (auto i = 0; i < 500000; ++i) {
timer.cancel();
std::cout << i << std::endl;
}
Am I doing something here that's unsupported and inadvertently hitting some race condition? The error code from the wait() never looks troublesome (even on the very last time it's woken up before it never seems to again). EDIT: I've also noticed the original bug on 3 different platforms (Windows, Mac and Linux) but the above test I've been using to reproduce has been on Windows.
The deadline_timer object is not threadsafe.
You're canceling it from another thread than the one that's posting the async_wait. This means the calls can race.
I'm not sure how this can completely inhibit the callback, in your sample. It seems to me that the program should /just/ quit because the tight loop to 500000 finishes quickly (doing many redundant cancels that never get processed, because the coroutine would e.g. not even have posted the new async_wait).
So maybe you mean, "why don't I get 500000 events".
UPDATE
After the comment, here's a trivial transformation that shows how you are gonna be fine calling members on the timer from within an actor. Note: this critically hinges on the idea that the io_service is run from a single thread only!
#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/make_shared.hpp>
#include <boost/thread.hpp>
#include <iostream>
using boost::thread;
using boost::asio::io_service;
int main() {
boost::asio::io_service io_service;
boost::asio::deadline_timer timer(io_service);
timer.expires_at(boost::posix_time::pos_infin);
boost::atomic_bool shutdown(false);
int num_events = 0;
auto waiter = [&timer, &num_events, &shutdown](boost::asio::yield_context context) {
while (!shutdown) {
std::cout << "waiting on event" << std::endl;
boost::system::error_code e;
timer.async_wait(context[e]);
std::cout << "got event (" << e.message() << ")" << std::endl;
++num_events;
}
};
boost::asio::spawn(io_service, std::move(waiter));
boost::thread thread(boost::bind(&boost::asio::io_service::run, &io_service));
for (auto i = 0; i < 5000; ++i) {
io_service.post([&timer, i]{
std::cout << i << std::endl;
timer.cancel();
});
}
io_service.post([&]{
shutdown = true;
timer.cancel();
});
thread.join();
std::cout << "Check: " << num_events << " events counted\n";
}
Also, it looks like you just wanted to signal a background task. As given you can simplify the program like:
See it Live On Coliru
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/make_shared.hpp>
#include <iostream>
using boost::thread;
using boost::asio::io_service;
int main() {
io_service svc;
int num_events = 0;
auto work = boost::make_shared<io_service::work>(svc); // keep svc running
boost::thread thread(boost::bind(&io_service::run, &svc));
for (auto i = 0; i < 500000; ++i) {
svc.post([&num_events,i]{
std::cout << "got event (" << i << ")" << std::endl;
++num_events;
});
}
work.reset();
thread.join();
std::cout << "Check: " << num_events << " events counted\n";
}
This does print all 500000 events:
got event (0)
got event (1)
got event (3)
...
got event (499998)
got event (499999)
Check: 500000 events counted
I require a heartbeat signal every 10 seconds or so. To implement this I have produced a class with the following constructor:
HeartBeat::HeartBeat (int Seconds, MessageQueue * MsgQueue)
{
TimerSeconds = Seconds;
pQueue = MsgQueue;
isRunning = true;
assert(!m_pHBThread);
m_pHBThread = shared_ptr<thread>(new thread(boost::bind(&HeartBeat::TimerStart,this)));
}
Which calls the following method in a new thread:
void HeartBeat::TimerStart ()
{
while (1)
{
cout << "heartbeat..." << endl;
boost::this_thread::sleep(boost::posix_time::seconds (TimerSeconds));
addHeartBeat();
}
}
This produces a heartbeat with out any issues. However I would like to be able to reset the sleep timer back to zero. Is there a simple way of doing this, or should I use something other than
boost::this_thread::sleep
for my sleep?
OS: Redhat
IDE: Eclipse
Code language: C++
EDIT:
I have looked at using
m_pHBThread->interrupt();
And it seems to be what I'm after, so thank you!
This sounds exactly like what asynchronous timer does. Since you're using boost already, perhaps it makes sense to use boost's own async timers in the long run?
#include <iostream>
#include <boost/thread.hpp>
#include <boost/date_time.hpp>
#include <boost/asio.hpp>
boost::posix_time::ptime now()
{
return boost::posix_time::microsec_clock::local_time();
}
class HeartBeat {
boost::asio::io_service ios;
boost::asio::deadline_timer timer;
boost::posix_time::time_duration TimerSeconds;
boost::thread thread;
public:
HeartBeat(int Seconds) : ios(), timer(ios),
TimerSeconds(boost::posix_time::seconds(Seconds))
{
reset(); // has to start timer before starting the thread
thread = boost::thread(boost::bind(&boost::asio::io_service::run,
&ios));
}
~HeartBeat() {
ios.stop();
thread.join();
}
void reset()
{
timer.expires_from_now(TimerSeconds);
timer.async_wait(boost::bind(&HeartBeat::TimerExpired,
this, boost::asio::placeholders::error));
}
void TimerExpired(const boost::system::error_code& ec)
{
if (ec == boost::asio::error::operation_aborted) {
std::cout << "[" << now() << "] timer was reset" << std::endl;
} else {
std::cout << "[" << now() << "] heartbeat..." << std::endl;
reset();
}
}
};
int main()
{
std::cout << "[" << now() << "] starting up.\n";
HeartBeat hb(10);
sleep(15);
std::cout << "[" << now() << "] Resetting the timer\n";
hb.reset();
sleep(15);
}
test run:
~ $ ./test
[2011-Sep-07 12:08:17.348625] starting up.
[2011-Sep-07 12:08:27.348944] heartbeat...
[2011-Sep-07 12:08:32.349002] Resetting the timer
[2011-Sep-07 12:08:32.349108] timer was reset
[2011-Sep-07 12:08:42.349160] heartbeat...
Perhaps you can use interrupt() to do this.
Well, it is not very efficient to launch a new thread every time you have an heart beat...
I'd do it instead with a single thread and a sleep inside it.
If you need to change the heart beat frequency then you can kill the current thread and start a new one with a new sleep time. You can use the boost::thread and the interrupt signal for this.
EDIT: look here for info on boost threads: boost thread management
if you want to reset the time to zero and execute your code immediately then call it inside the catch for boost::thread_interrupted...
EDIT2: I didn't look properly to the code and I assumed that the common error of launching a new thread for each heart beat was there... sorry, my mistake... I guess I don't like the fact that the thread's name is: TimerStart()
Anyway I think that using the interrupt() and catching it should work if you need to execute the heart beat right away.