In short you want to synchronize on 1 asynchronous action in the midst of many asynchronous ones.
I'd suggest using the non-async_
* version of the call. You claim that read_some
doesn't work for you:
I tried read_some but it blocks other clients from connecting – Chocolate Donut 1 hour ago
I must say I'm a bit surprised here, but your code isn't self contained so I can't review/try to reproduce.
Here's a "hack" using deadline_timer
that you could use to as a "signal". In all fairness this means that now you do deadline_timer::wait()
synchronously, and there's no real reason to think that is fundamentally different from doing the read_some
synchronously.
However, my sample is self contained, you and I can test that/how it
it works. It might inspire you to get why it works, how you can amend your own code.
#include <boost/asio.hpp>
#include <boost/optional.hpp>
#include <iostream>
#include <thread>
namespace ba = boost::asio;
using ba::ip::tcp;
struct X : std::enable_shared_from_this<X> {
X(unsigned short port) {
socket_.connect({{}, port});
std::cout << "connected\n";
}
~X() {
work_.reset();
if (io_thread_.joinable())
io_thread_.join();
}
int tcp_menu_id_receive()
{
auto self(shared_from_this());
int menuid = 0;
std::vector<char> buf(4);
ba::deadline_timer sig(svc_);
sig.expires_at(boost::posix_time::max_date_time);
socket_.async_read_some(boost::asio::buffer(buf), [&, self](boost::system::error_code ec, std::size_t length)
{
std::cout << "Callback: " << ec.message() << "\n";
if (!ec) {
std::string ReceivedData(buf.data(), length);
menuid = std::stoi(ReceivedData);
sig.expires_at(boost::posix_time::min_date_time);
}
sig.cancel(); // just abort
});
// synchronous wait
boost::system::error_code ec;
sig.wait(ec); // ignoring error code
// optionally check result
if (sig.expires_at() == boost::posix_time::max_date_time)
std::cout << "Receive error\n";
return menuid;
}
private:
ba::io_service svc_;
boost::optional<ba::io_service::work> work_{svc_};
std::thread io_thread_ { [this] {
std::cout << "start io_thread_\n";
svc_.run();
std::cout << "exit io_thread_\n";
} };
tcp::socket socket_{svc_};
};
int main() {
auto x = std::make_shared<X>(6767);
std::cout << "DEBUG: menuid: " << x->tcp_menu_id_receive() << "\n";
}
I tested it on my machine using a test server:
echo 2345 | netcat -l -p 6767
And the output was:
connected
start io_thread_
Callback: Success
DEBUG: menuid: 2345
exit io_thread_