I am trying to understand how the AsyncSpinner from ROS really works because I may have something misunderstood. You can find a similar question here.
As seen here its definition mentions:
Asynchronous spinner: spawns a couple of threads (configurable) that
will execute callbacks in parallel while not blocking the thread that
called it. The start/stop method allows to control when the callbacks
start being processed and when it should stop.
And in the official documentation here the AsyncSpinning is also remarked as a type of multi-threading Spinning.
So, said that, I have a very simple example with a publisher and subscriber with an AsyncSpinner to test the multi-threading behavior.
#include "ros/ros.h"
#include "std_msgs/String.h"
int main(int argc, char **argv)
{
ros::init(argc, argv, "publisher");
ros::NodeHandle nh;
ros::Publisher chatter_pub = nh.advertise<std_msgs::String>("chatter", 1000);
ros::Rate loop_rate(10);
while (ros::ok())
{
std_msgs::String msg;
msg.data = "hello world";
chatter_pub.publish(msg);
ros::spinOnce();
loop_rate.sleep();
}
return 0;
}
And the subscriber where the spinner is defined and used:
#include "ros/ros.h"
#include "std_msgs/String.h"
#include <boost/thread.hpp>
int count = 0;
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
count++;
ROS_INFO("Subscriber %i callback: I heard %s", count, msg->data.c_str());
sleep(1);
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "subscriber");
ros::NodeHandle nh;
ros::Subscriber sub = nh.subscribe("chatter", 1000, chatterCallback);
ros::AsyncSpinner spinner(boost::thread::hardware_concurrency());
ros::Rate r(10);
spinner.start();
ros::waitForShutdown();
return 0;
}
When I run both programs I get the following output:
[ INFO] [1517215527.481856914]: Subscriber 1 callback: I heard hello world
[ INFO] [1517215528.482005146]: Subscriber 2 callback: I heard hello world
[ INFO] [1517215529.482204798]: Subscriber 3 callback: I heard hello world
As you can see the callback runs every second and no other callbacks are being called in parallel. I know that the global callback queue is being fulfilled because if I stop the publisher, the subscriber will keep popping the accumulated messages from the queue.
I know I should not block a callback but in the definition above is remarked that this will not stop the thread where it was called and I guess neither the others created by the spinner. Am I blocking the next callbacks just because I'm blocking the callback? Is there something I did misunderstood? I am bit confused and not able to demonstrate that the callbacks are running in parallel. Maybe you have another example?
Short answer:
ROS callbacks are threadsafe by default. This means a registered callback can only be processed by one thread and concurrent calls are disabled. A second thread is not able to access the same callback at the same time.
If you register a second callback, you will see the spinner working like expected and multiple threads are calling your callbacks at the same time.
ros::Subscriber sub1 = nh.subscribe("chatter", 1000, chatterCallback);
ros::Subscriber sub2 = nh.subscribe("chatter", 1000, chatterCallback);
Extended answer:
An async spinner tries to call available callbacks in the callback queue as fast as the rate allows. If the callback is already in process (by an other thread) the CallResult is TryAgain. This means a new attempt will be started later on.
The implementation of this lock uses the variable allow_concurrent_callbacks_ which means this behaviour is optional.
Solution:
It is possible to allow concurrent calls by setting the correct SubscribeOptions.allow_concurrent_callbacks which is false by default. Therefore you need to define your own SubscribeOptions. Here is the code you need to subscribe and allow concurrent callback calls:
ros::SubscribeOptions ops;
ops.template init<std_msgs::String>("chatter", 1000, chatterCallback);
ops.transport_hints = ros::TransportHints();
ops.allow_concurrent_callbacks = true;
ros::Subscriber sub = nh.subscribe(ops);
Related
So I am trying to add a subscriber to a specific topic.
The purpose of the subscriber is to get range messages from the pi_sonar topic and use it in the code.
This is the code here:
line Follower code
so, if I wanted to add the sonar messages, should it look like this:
void turtlebot::range_sub('pacakge name of sonars'::range msg){
turtlebot::rng = msg.range;
}
based on what I was able to understand here I mean…
Is that correct?
I am gonna try it once I have my hands on the robot
You can follow this tutorial, it explains exactly what you are looking for,
#include <ros/ros.h>
#include <sensor_msgs/Range.h>
void sonarCallback(const sensor_msgs::Range::ConstPtr& msg)
{
ROS_INFO("Sonar Seq: [%d]", msg->header.seq);
ROS_INFO("Sonar Range: [%f]", msg->range);
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "infrared_listener");
ros::NodeHandle n;
ros::Subscriber sub = n.subscribe("sensor/sonar0", 1000, sonarCallback);
ros::spin();
return 0;
}
Basically, you have to create ros::Subscriber whose callback, i.e., sonarCallback, is listening to incoming messages where you can implement your logic what to do with the sonar sensor reading, Please go through the link I shared and if something not clear, update the question accordingly
I want to run boost::asio::io_service.run() in a background thread. So when I need it post() func into.
This is main func:
int main(int /*argc*/, char** /*argv*/)
{
std::string message = "hello";
logg = new logger_client(filename,ip,13666);
logg->start();
while (true)
logg->add_string(message);
return 0;
}
And some relevant funcs from logger_client:
std::auto_ptr<boost::asio::io_service::work> work;
logger_client::logger_client(std::string& filename,std::string& ip, uint16_t port) : work(new boost::asio::io_service::work(io_service))
{
}
void logger_client::start()
{
ios_thread = new boost::thread(boost::bind(&io_service.run,&io_service));
}
void print_nothing()
{
printf("%s\n","lie");
}
void logger_client::add_string(std::string& message)
{
io_service.post(boost::bind(print_nothing));
//io_service.post(strand->wrap(boost::bind(&logger_client::add_string_imp,this,message)));
//io_service.run();
}
When i run this, my program eats 2Gb less than a minute. If i remove endless work and change to this:
void logger_client::add_string(std::string& message)
{
io_service.post(boost::bind(print_nothing));
//io_service.post(strand->wrap(boost::bind(&logger_client::add_string_imp,this,message)));
io_service.run();
}
Program works just fine. But I don't want to invoke async operations on this (main) thread. What am i doing wrong?
UPDATE
I added sleep(1sec) in while(true) loop and memory is no longer growing. But this is not a solution. Because if I call run() after post() (i.e. use main thread for processing handles) and even add five more threads with while(true) loops memory is not growing. So why main thread is so much better than newly created? I also tried thread pool for io_service::run - did not help.
io_service.run will exit unless there are pending operations.
Therefore, your ios_thread will exit immediately.
The solution is to use io_service::work.
In addition, endless loop spam like this
while (true)
logg->add_string(message);
is not a good idea, maybe add some sleep(), to slow it down a bit and keep it under control.
I am trying to use Gtk 3.0 to visualize a network of nodes in real-time. The network of nodes will make new nodes and new connections will be formed between the nodes in real-time. I'm thinking of using one thread to configure Gtk and begin Gtk's main loop, and another for the development of the nodal network. The variables of the network will be global so that both the network developing thread and the Gtk thread can see the network variables. I will use a mutex on both sides to ensure synchronization.
My Gtk event-handler function will draw the current network, and idealistically, it should get called every time the network changes (eg new nodes, new connections). Therefore I would like to know if there is a solution in Gtk 3.0 where the event-handler function gets signaled every time a variable changes, say a change in vector's size, because I am using vector to store the nodes and connections.
I wrote a simple test program just to see if what I'm trying to do is possible. I have a thread which keeps incrementing an integer whereas another thread does all the Gtk configurations and initiates the main loop. In this code below, the Gtk thread draws the current value of the integer which keeps getting incremented. This code however is a modification of another and it does not draw the current value only at times when the value changes. Moreover, this code doesn't compile in Gtk 3.0. Is there any way to make this code compile in Gtk 3.0? In addition, is it possible to make it signal the drawing function only when the integer's value change?
#include <gtk/gtk.h>
#include <math.h>
#include <thread>
#include <mutex>
#include <string>
unsigned long long counter;
std::mutex mtx;
gboolean timeout(gpointer data) {
GtkWidget *widget = GTK_WIDGET(data);
if (!widget->window) return TRUE;
gtk_widget_queue_draw(widget);
}
gboolean expose(GtkWidget *widget, GdkEventExpose *event, gpointer data) {
cairo_t *cr = gdk_cairo_create(widget->window);
cairo_rectangle(cr, event->area.x, event->area.y, event->area.width, event- >area.height);
cairo_clip(cr);
cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);
cairo_select_font_face(cr, "Purisa", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
std::string str;
mtx.lock();
str = std::to_string(counter);
cairo_move_to(cr, 20, 30);
cairo_show_text(cr, str.c_str());
mtx.unlock();
return FALSE;
}
void setupGtk() {
gtk_init(NULL,NULL);
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(GTK_WINDOW(window), "destroy",G_CALLBACK(gtk_main_quit), NULL);
GtkWidget *drawing_area = gtk_drawing_area_new();
g_signal_connect(drawing_area,"expose_event",G_CALLBACK(expose),NULL);
gtk_container_add(GTK_CONTAINER(window), drawing_area);
gtk_widget_show(drawing_area);
g_timeout_add(10, timeout, window);
if (!GTK_WIDGET_VISIBLE (window))
gtk_widget_show_all(window);
else {
gtk_widget_destroy (window);
window = NULL;
}
gtk_main();
}
void count() {
while(counter<100000000) {
mtx.lock();
counter++;
mtx.unlock();
}
}
int main(int argc, char *argv[]) {
std::thread gtk(setupGtk);
std::thread process(count);
gtk.join();
process.join();
return 1;
}
You will need to create your own GObject class and either add a signal to that that you can emit when the value changes or add a property to represent the variable and use the notify signal.
Note that signal emission is not guaranteed to cross thread boundaries properly. You will need to use gdk_threads_idle_add() to ensure the signal gets sent on he main thread.
If your goal is simply to redraw a control, you can call gtk_widget_queue_draw() or related in the idle callback instead of emitting a signal.
Note that an idle callback runs asynchronously. If you want the callback to complete before your other thread continues, you will need to write the synchronization method yourself.
(Sorry for the terse answer; I'm in a rush.)
I want to use libev with multiple threads for the handling of tcp connections. What I want to is:
The main thread listen on incoming connections, accept the
connections and forward the connection to a workerthread.
I have a pool of workerthreads. The number of threads depends on the
number of cpu's. Each worker-thread has an event loop. The worker-thread listen if I can write on the tcp socket or if
somethings available for reading.
I looked into the documentation of libev and I known this can be done with libev, but I can't find any example how I have to do that.
Does someone has an example?
I think that I have to use the ev_loop_new() api, for the worker-threads and for the main thread I have to use the ev_default_loop() ?
Regards
The following code can be extended to multiple threads
//This program is demo for using pthreads with libev.
//Try using Timeout values as large as 1.0 and as small as 0.000001
//and notice the difference in the output
//(c) 2009 debuguo
//(c) 2013 enthusiasticgeek for stack overflow
//Free to distribute and improve the code. Leave credits intact
#include <ev.h>
#include <stdio.h> // for puts
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t lock;
double timeout = 0.00001;
ev_timer timeout_watcher;
int timeout_count = 0;
ev_async async_watcher;
int async_count = 0;
struct ev_loop* loop2;
void* loop2thread(void* args)
{
printf("Inside loop 2"); // Here one could initiate another timeout watcher
ev_loop(loop2, 0); // similar to the main loop - call it say timeout_cb1
return NULL;
}
static void async_cb (EV_P_ ev_async *w, int revents)
{
//puts ("async ready");
pthread_mutex_lock(&lock); //Don't forget locking
++async_count;
printf("async = %d, timeout = %d \n", async_count, timeout_count);
pthread_mutex_unlock(&lock); //Don't forget unlocking
}
static void timeout_cb (EV_P_ ev_timer *w, int revents) // Timer callback function
{
//puts ("timeout");
if (ev_async_pending(&async_watcher)==false) { //the event has not yet been processed (or even noted) by the event loop? (i.e. Is it serviced? If yes then proceed to)
ev_async_send(loop2, &async_watcher); //Sends/signals/activates the given ev_async watcher, that is, feeds an EV_ASYNC event on the watcher into the event loop.
}
pthread_mutex_lock(&lock); //Don't forget locking
++timeout_count;
pthread_mutex_unlock(&lock); //Don't forget unlocking
w->repeat = timeout;
ev_timer_again(loop, &timeout_watcher); //Start the timer again.
}
int main (int argc, char** argv)
{
if (argc < 2) {
puts("Timeout value missing.\n./demo <timeout>");
return -1;
}
timeout = atof(argv[1]);
struct ev_loop *loop = EV_DEFAULT; //or ev_default_loop (0);
//Initialize pthread
pthread_mutex_init(&lock, NULL);
pthread_t thread;
// This loop sits in the pthread
loop2 = ev_loop_new(0);
//This block is specifically used pre-empting thread (i.e. temporary interruption and suspension of a task, without asking for its cooperation, with the intention to resume that task later.)
//This takes into account thread safety
ev_async_init(&async_watcher, async_cb);
ev_async_start(loop2, &async_watcher);
pthread_create(&thread, NULL, loop2thread, NULL);
ev_timer_init (&timeout_watcher, timeout_cb, timeout, 0.); // Non repeating timer. The timer starts repeating in the timeout callback function
ev_timer_start (loop, &timeout_watcher);
// now wait for events to arrive
ev_loop(loop, 0);
//Wait on threads for execution
pthread_join(thread, NULL);
pthread_mutex_destroy(&lock);
return 0;
}
Using libev within different threads at the same time is fine as long as each of them runs its own loop[1].
The c++ wrapper in libev (ev++.h) always uses the default loop instead of letting you specify which one you want to use. You should use the C header instead (ev.h) which allows you to specify which loop to use (e.g. ev_io_start takes a pointer to an ev_loop but the ev::io::start doesn't).
You can signal another thread's ev_loop safely through ev_async.
[1]http://doc.dvgu.ru/devel/ev.html#threads_and_coroutines
I'm using gSoap to write a webservice. It's running as a console application. In all gSoap examples I see, that requests are dispatched in infinite loop like for(;;;) even in multi-threaded version.
But how can I make my webservice to terminate gracefully when, say, user presses space on the console?
Preferably:
stop accepting new connections;
Serve existing ones;
Exit from application
The only solution I came up so far is using timeouts
soap->recv_timeout = 20;
soap->send_timeout = 20;
soap->connect_timeout = 5;
soap->accept_timeout = 5;
Then all blocking functions return periodically. But this is not ideal for me, because I want to be able to terminate the app quickly even if there is an ongoing transmission, but at the same time, don't want to compromise reliability on a slow/flaky connection (it's an embedded device connected via GPRS).
The section 7.2.4 How to Create a Multi-Threaded Stand-Alone Service in the documentation has example code for writing an accept loop. You need to write your own accept loop and add signal handling so it responds to Ctrl-C.
stop accepting new connections:
Leave the loop so you stop calling accept.
Serve existing ones:
The threads need to inform you when they are finished, so you can exit when the number of active clients is zero. (boost::thead_group has a join_all which does exactly that.)
Exit from application:
What you need to do is register signal handler so when you terminate your application using Ctrl + C, it calls you registered function where you can gracefully terminates.
e.g
class gsoap_test {
public:
void start() {
running_ = true;
while(running_) {
//gsoap threads
}
//stop and cleanup
}
void stop() {
running_ = false;
}
private:
bool running_;
};
//global variable
gsoap_test gsoap;
void sighandler(int sig)
{
std::cout<< "Signal caught..." << std::endl;
//Stop gracefully here
gsoap.stop();
exit(0);
}
int main(int argc, char** argv) {
//register signal
signal(SIGABRT, &sighandler);
signal(SIGTERM, &sighandler);
signal(SIGINT, &sighandler);
gsoap.start();
return EXIT_SUCCESS;
}