I started learning promise and future in C++11, But here I am stuck:
#include<iostream>
#include<future>
using namespace std;
void func(future<int> &ref)
{
cout << ref.get();
}
int main()
{
promise<int> prom;
future<int> fut = prom.get_future();
async(launch::deferred, func, ref(fut));
prom.set_value(100);
cout << "Exiting" << endl;
}
My understanding is, when we have async with launch::deferred it does not start a new thread.
So unless ref.get() executes func function won't return which will not happen since promise is set after that.
But my code exits successfully. Where is my understanding wrong?
IDE: VS2013
A deferred async call simply stores the invokable object and parameters.
Nothing much happens until you call .get() on the returned future.
You discard that returned future, so your call to async was basically a noop.
Nothing else prevents main from finishing, so...
Related
OS windows. I would like to create a back-buffer before paint. I want to use boost::asio::thread_pool to increase speed. I need to stop back-buffer creating, if my "input data"(tasks) is updated.
I wrote Test_CreateAndCancel function to simplify test.
class Task
{
public:
virtual void operator()
{
std::cout << "Task started " << std::endl;
DoSomeWork();
std::cout << "Task in progress" << std::endl;
for (int i = 0; i < 15; ++i)
boost::this_thread::sleep_for(boost::chrono::milliseconds(1000));
std::cout << "Task ended" << std::endl;
}
};
using TaskPtr = std::shared_ptr<Task>;
void Test_CreateAndCancel(std::vector<TaskPtr> &tasks)
{
//start back-buffer creating
boost::asio::thread_pool _thread_pool(4);
for (auto task : tasks)
{
boost::asio::post(thread_pool, [task] {
task->operator()();
});
}
// simulate cancel
thread_pool.stop(); // wait untill all threads are finished?
}
vector tasks has 4 items.
Result is: 4 "Task started" "Task in progress" "Task ended"
I am thinking to add custom IsCanceled() checkes in task::operator().
Is there are any other ways to make my tasks cancelable?
How can I implement cancel logic?
I will be grateful for any advices
Thanks
The easiest approach is to add a (probably atomic) variable "please_stop" to your Task and
query it inside the operator() regularly
set it from the outside (another task)
The basic problem is that you cannot cancel an operation that is running in a different task. You can only "ask it politely" to stop working.
boost::thread has an interrupt mechanism (see the link, #sehe posted above). This basically does not do anything different than what I suggested, except it's baked into boost::thread. There are certain "interruption points" that will query the "please stop" state and throw an exception, if it is set.
You have to catch the exception though, otherwise the thread itself will stop and you want only the operation to stop.
So you could do something like this:
class Task {
virtual void operator()()
{
try {
do_something();
boost::this_thread::sleep(boost::chrono::seconds(10000);
}
catch (boost::thread_interrupted&) { //
handle_please_stop_request();
}
}
};
// and later
task_thread.interrupt();
The problem with this approach is that you have to know the thread and you probably want to interrupt not the thread but the operation. Which is why the atomic approach has its charms.
BTW, your example has several problems. The task operation (operator()()) never stops at all. You are creating a task pool for every vector of tasks. I assume these are just artifacts of your example and your real world code is different.
One thing though. I haven't looked into asio::thread_pool yet, but I am missing the boost::asio::work object. Search stackoverflow on how to use the work object.
I am a novice trying to use google protobuf for work project. I want to find out difference between protobuf messages and hence trying to use the MessageDifferencer APIs. I get the SEGV while running the code below. Commenting the line "reporter->ReportModified(*Obj1, *Obj2, field_path);" results in no segv
Any help in usage of differencer appreciated!
google::protobuf::util::MessageDifferencer diff;
diff.set_report_matches(false);
diff.set_report_moves(false);
std::string reportDiff;
google::protobuf::io::StringOutputStream* opstream = new google::protobuf::io::StringOutputStream(&reportDiff);
google::protobuf::util::MessageDifferencer::StreamReporter* reporter = new google::protobuf::util::MessageDifferencer::StreamReporter(opstream);
diff.ReportDifferencesTo(reporter);
std::vector<google::protobuf::util::MessageDifferencer::SpecificField> field_path;
try
{
reporter->ReportModified(*Obj1, *Obj2, field_path);
}
catch (const std::exception& e)
{
std::cout << e.what() <<"\n";
}
cout << __func__ << " Report added " << field_path.size();
//Cleanup objects
delete Obj1;
delete Obj2;
delete reporter;
Thanks,
Maddy
You shouldn't be calling the ReportModified method directly, the MessageDifferencer class calls it when it finds a difference.
MessageDifferencer::Compare is the correct method to call, according to the docs. Assuming all else is correct, I believe changing your code inside the try-loop to call that should work.
Moving your code to a function, you could have something like
std::string CompareMessages(
const google::protobuf::Message& m1,
const google::protobuf::Message& m2) {
using google::protobuf::util::MessageDifferencer;
MessageDifferencer diff;
diff.set_report_matches(false);
diff.set_report_moves(false);
std::string reportDiff;
{
google::protobuf::io::StringOutputStream opstream(&reportDiff);
MessageDifferencer::StreamReporter reporter(&opstream);
diff.ReportDifferencesTo(&reporter);
diff.Compare(m1, m2);
}
return std::move(reportDiff);
}
I have been working on implementing a half duplex serial driver by learning from a basic serial terminal example using boost::asio::basic_serial_port:
http://lists.boost.org/boost-users/att-41140/minicom.cpp
I need to read asynchronously but still detect when the handler is finished in the main thread so I pass async_read_some a callback with several additional reference parameters in a lambda function using boost:bind. The handler never gets invoked but if I replace the async_read_some function with the read_some function it returns data without an issue.
I believe I'm satisfying all of the necessary requirements for this function to invoke the handler because they are the same for the asio::read some function which returns:
The buffer stays in scope
One or more bytes is received by the serial device
The io service is running
The port is open and running at the correct baud rate
Does anyone know if I'm missing another assumption unique to the asynchronous read or if I'm not setting up the io_service correctly?
Here is an example of how I'm using the code with async_read_some (http://www.boost.org/doc/libs/1_56_0/doc/html/boost_asio/reference/basic_serial_port/async_read_some.html):
void readCallback(const boost::system::error_code& error, size_t bytes_transfered, bool & finished_reading, boost::system::error_code& error_report, size_t & bytes_read)
{
std::cout << "READ CALLBACK\n";
std::cout.flush();
error_report = error;
bytes_read = bytes_transfered;
finished_reading = true;
return;
}
int main()
{
int baud_rate = 115200;
std::string port_name = "/dev/ttyUSB0";
boost::asio::io_service io_service_;
boost::asio::serial_port serial_port_(io_service_,port_name);
serial_port_.set_option(boost::asio::serial_port_base::baud_rate(baud_rate));
boost::thread service_thread_;
service_thread = boost::thread(boost::bind(&boost::asio::io_service::run, &io_service_));
std::cout << "Starting byte read\n";
boost::system::error_code ec;
bool finished_reading = false;
size_t bytes_read;
int max_response_size = 8;
uint8_t read_buffer[max_response_size];
serial_port_.async_read_some(boost::asio::buffer(read_buffer, max_response_size),
boost::bind(readCallback,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred,
finished_reading, ec, bytes_read));
std::cout << "Waiting for read to finish\n";
while (!finished_reading)
{
boost::this_thread::sleep(boost::posix_time::milliseconds(1));
}
std::cout << "Finished byte read: " << bytes_read << "\n";
for (int i = 0; i < bytes_read; ++i)
{
printf("0x%x ",read_buffer[i]);
}
}
The result is that the callback does not print out anything and the while !finished loop never finishes.
Here is how I use the blocking read_some function (boost.org/doc/libs/1_56_0/doc/html/boost_asio/reference/basic_serial_port/read_some.html):
int main()
{
int baud_rate = 115200;
std::string port_name = "/dev/ttyUSB0";
boost::asio::io_service io_service_;
boost::asio::serial_port serial_port_(io_service_,port_name);
serial_port_.set_option(boost::asio::serial_port_base::baud_rate(baud_rate));
boost::thread service_thread_;
service_thread = boost::thread(boost::bind(&boost::asio::io_service::run, &io_service_));
std::cout << "Starting byte read\n";
boost::system::error_code ec;
int max_response_size = 8;
uint8_t read_buffer[max_response_size];
int bytes_read = serial_port_.read_some(boost::asio::buffer(read_buffer, max_response_size),ec);
std::cout << "Finished byte read: " << bytes_read << "\n";
for (int i = 0; i < bytes_read; ++i)
{
printf("0x%x ",read_buffer[i]);
}
}
This version prints from 1 up to 8 characters that I send, blocking until at least one is sent.
The code does not guarantee that the io_service is running. io_service::run() will return when either:
All work has finished and there are no more handlers to be dispatched
The io_service has been stopped.
In this case, it is possible for the service_thread_ to be created and invoke io_service::run() before the serial_port::async_read_some() operation is initiated, adding work to the io_service. Thus, the service_thread_ could immediately return from io_service::run(). To resolve this, either:
Invoke io_service::run() after the asynchronous operation has been initiated.
Create a io_service::work object before starting the service_thread_. A work object prevents the io_service from running out of work.
This answer may provide some more insight into the behavior of io_service::run().
A few other things to note and to expand upon Igor's answer:
If a thread is not progressing in a meaningful way while waiting for an asynchronous operation to complete (i.e. spinning in a loop sleeping), then it may be worth examining if mixing synchronous behavior with asynchronous operations is the correct solution.
boost::bind() copies its arguments by value. To pass an argument by reference, wrap it with boost::ref() or boost::cref():
boost::bind(..., boost::ref(finished_reading), boost::ref(ec),
boost::ref(bytes_read));
Synchronization needs to be added to guarantee memory visibility of finished_reading in the main thread. For asynchronous operations, Boost.Asio will guarantee the appropriate memory barriers to ensure correct memory visibility (see this answer for more details). In this case, a memory barrier is required within the main thread to guarantee the main thread observes changes to finished_reading by other threads. Consider using either a Boost.Thread synchronization mechanism like boost::mutex, or Boost.Atomic's atomic objects or thread and signal fences.
Note that boost::bind copies its arguments. If you want to pass an argument by reference, wrap it with boost::ref (or std::ref):
boost::bind(readCallback, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, boost::ref(finished_reading), ec, bytes_read));
(However, strictly speaking, there's a race condition on the bool variable you pass to another thread. A better solution would be to use std::atomic_bool.)
I'm using a wrapper class to represent a network connection. My implementation contains a method, called async_connect(), which resolves a host/service and connects to a related endpoint (if possible). Something like this:
void tcp::connection::async_connect(std::string const& host, std::string const& service,
protocol_type tcp = protocol_type::v4())
{
std::cout << "thread [" << boost::this_thread::get_id() << "] tcp::connection::async_connect()" << std::endl;
resolver(m_io_service).async_resolve(resolver::query(tcp, host, service),
boost::bind(&connection::resolve_handler, this, _1, _2));
}
What I want to do know, is establishing the connection from the handler, invoked by the completion of the async_resolve method.
I'm not sure wheter the main thread or the a worker thread is used to invoke the handler. Thus, should I call socket::connect() (this would be the most sensible way if that code would be executed from a worker thread) or start an asynchronous operation again (socket::async_connect() - which should be used when executed by main thread).
void tcp::connection::resolve_handler(boost::system::error_code const& resolve_error,
tcp::resolver::iterator endpoint_iterator)
{
std::cout << "thread [" << boost::this_thread::get_id() << "] tcp::connection::resolve_handler()" << std::endl;
if (!resolve_error)
{
boost::system::error_code ec;
m_socket.connect(*endpoint_iterator, ec);
}
}
I've observed - from console output - that my resolve_handler is called from a worker thread. So, is it okay to call socket::connect() here?
IMO it is good to stick to a single programming model when using asio.
You are free to use asio's synchronous (blocking) calls, where you call a number of methods (resolve, connect, etc) and each one blocks until the result or error is available.
However If you're using the asynchronous programming model, your main or calling thread is typically blocked on io_service::run and the specified handlers are called from a different thread ( as is the case in what you described). When using this programming model you would typically call the next async method from the handler (worker thread), so instead of calling socket::connect, you would call socket::async_connect. It looks to me like you are trying to mix the two different models. I'm not sure what the implications are of mixing the two models (with your calling thread blocked on io_service::run) and you calling a synchronous method from the handler.
I am attempting to use boost::asio to read and write from a device on a serial port. Both boost::asio:read() and boost::asio::serial_port::read_some() block when there is nothing to read. Instead I would like to detect this condition and write a command to the port to kick-start the device.
How can I either detect that no data is available?
If necessary I can do everything asynchronously, I would just rather avoid the extra complexity if I can.
You have a couple of options, actually. You can either use the serial port's built-in async_read_some function, or you can use the stand-alone function boost::asio::async_read (or async_read_some).
You'll still run into the situation where you are effectively "blocked", since neither of these will call the callback unless (1) data has been read or (2) an error occurs. To get around this, you'll want to use a deadline_timer object to set a timeout. If the timeout fires first, no data was available. Otherwise, you will have read data.
The added complexity isn't really all that bad. You'll end up with two callbacks with similar behavior. If either the "read" or the "timeout" callback fires with an error, you know it's the race loser. If either one fires without an error, then you know it's the race winner (and you should cancel the other call). In the place where you would have had your blocking call to read_some, you will now have a call to io_svc.run(). Your function will still block as before when it calls run, but this time you control the duration.
Here's an example:
void foo()
{
io_service io_svc;
serial_port ser_port(io_svc, "your string here");
deadline_timer timeout(io_svc);
unsigned char my_buffer[1];
bool data_available = false;
ser_port.async_read_some(boost::asio::buffer(my_buffer),
boost::bind(&read_callback, boost::ref(data_available), boost::ref(timeout),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
timeout.expires_from_now(boost::posix_time::milliseconds(<<your_timeout_here>>));
timeout.async_wait(boost::bind(&wait_callback, boost::ref(ser_port),
boost::asio::placeholders::error));
io_svc.run(); // will block until async callbacks are finished
if (!data_available)
{
kick_start_the_device();
}
}
void read_callback(bool& data_available, deadline_timer& timeout, const boost::system::error_code& error, std::size_t bytes_transferred)
{
if (error || !bytes_transferred)
{
// No data was read!
data_available = false;
return;
}
timeout.cancel(); // will cause wait_callback to fire with an error
data_available = true;
}
void wait_callback(serial_port& ser_port, const boost::system::error_code& error)
{
if (error)
{
// Data was read and this timeout was canceled
return;
}
ser_port.cancel(); // will cause read_callback to fire with an error
}
That should get you started with only a few tweaks here and there to suit your specific needs. I hope this helps!
Another note: No extra threads were necessary to handle callbacks. Everything is handled within the call to run(). Not sure if you were already aware of this...
Its actually a lot simpler than the answers here have implied, and you can do it synchronously:
Suppose your blocking read was something like this:
size_t len = socket.receive_from(boost::asio::buffer(recv_buf), sender_endpoint);
Then you replace it with
socket.non_blocking(true);
size_t len = 0;
error = boost::asio::error::would_block;
while (error == boost::asio::error::would_block)
//do other things here like go and make coffee
len = socket.receive_from(boost::asio::buffer(recv_buf), sender_endpoint, 0, error);
std::cout.write(recv_buf.data(), len);
You use the alternative overloaded form of receive_from which almost all the send/receive methods have. They unfortunately take a flags argument but 0 seems to work fine.
You have to use the free-function asio::async_read.