I am trying to use the boost process (0.5) library.
In asych_io.cpp example, the read handler is not getting called even once.
even after io_service.run() is called.
I am using Linux.
#include <boost/process.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/asio.hpp>
#include <boost/array.hpp>
#include <string>
using namespace boost::process;
using namespace boost::process::initializers;
using namespace boost::iostreams;
boost::process::pipe create_async_pipe()
{
return create_pipe();
}
int main()
{
boost::process::pipe p = create_async_pipe();
file_descriptor_sink sink(p.sink, close_handle);
child c = execute(
run_exe(search_path("nasm")),
set_cmd_line("nasm -v"),
bind_stdout(sink)
);
file_descriptor_source source(p.source, close_handle);
typedef boost::asio::posix::stream_descriptor pipe_end;
boost::asio::io_service io_service;
pipe_end pend(io_service,p.source);
boost::array<char, 4096> buffer;
boost::asio::async_read(pend, boost::asio::buffer(buffer),
[&](const boost::system::error_code&, std::size_t bytes_transferred){
std::cout << std::string(buffer.data(), bytes_transferred) << std::flush;
});
io_service.run();
}
After I replaced
boost::asio::async_read(pend...
with
pend.async_read_some(...
It worked for me.
Related
Let us say, that we use packaged_task for implementing async work in a program.
#include <map>
#include <iostream>
#include <vector>
#include <algorithm>
#include <sstream>
#include <iterator>
#include <future>
#include <thread>
#include <chrono>
int main()
{
std::packaged_task<int()> packagedTaskOne([]()
{
using namespace std::chrono_literals;
std::this_thread::sleep_for(4s);
return 4;
});
std::future<int> futureResultOne = packagedTaskOne.get_future();
std::thread tOne(std::move(packagedTaskOne));
futureResultOne.wait();
tOne.join();
std::cout << "done\n";
return 0;
}
I can barely imagine how to implement waiting cursor in C#, because I can use something like while(!Task.Run(async () => await _service.GetValue()).IsCompleted) and output some dots that show loading. I want the same with packaged_task but I do not understand how to fuse it with while loop because I do not get what a condition I should for checking is this thread completed. How to make the same loop in C++ with packaged_task?
If you don't want to use futureResultOne.get(); to avoid blocking, the following is a way to check if your task has finished or not in the main (you can use an independent one of course) thread.
#include <iostream>
#include <future>
#include <thread>
#include <chrono>
#include <condition_variable>
using namespace std::chrono_literals;
std::condition_variable cv;
bool theThreadHasFinished;
std::mutex mut;
int main()
{
std::packaged_task<int()> packagedTaskOne([]{
std::this_thread::sleep_for(4s);
return 4;
});
std::future<int> futureResultOne = packagedTaskOne.get_future();
std::thread tOne([&]{packagedTaskOne();
std::lock_guard lg{mut};
theThreadHasFinished = true;
cv.notify_all();});
tOne.detach();
std::unique_lock<std::mutex> lock{ mut };
cv.wait(lock, [ ](){ return theThreadHasFinished; });
std::cout << "done\n";
return 0;
}
You can use a while loop ad wait_for but this consumes your resources
I'm trying to build a chat room using by Boost Libraries. But when I'm trying to use asio::io_context, the compiler says:
io_context is not an member of asio.
I built Boost 4 times and I thought maybe the problem was due to an installation failure on my part, but it doesn't seem to be.
#include <ctime>
#include <iostream>
#include <string>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
std::string make_daytime_string()
{
using namespace std; // For time_t, time and ctime;
time_t now = time(0);
return ctime(&now);
}
class tcp_connection
: public boost::enable_shared_from_this<tcp_connection>
{
public:
typedef boost::shared_ptr<tcp_connection> pointer;
static pointer create(boost::asio::io_context& io_context)
{
return pointer(new tcp_connection(io_context));
}
tcp::socket& socket()
{
return socket_;
}
void start()
{
message_ = make_daytime_string();
boost::asio::async_write(socket_, boost::asio::buffer(message_),
boost::bind(&tcp_connection::handle_write, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
private:
tcp_connection(boost::asio::io_context& io_context)
: socket_(io_context)
{
}
void handle_write(const boost::system::error_code& /*error*/,
size_t /*bytes_transferred*/)
{
}
tcp::socket socket_;
std::string message_;
};
class tcp_server
{
public:
tcp_server(boost::asio::io_context& io_context) //error
: acceptor_(io_context, tcp::endpoint(tcp::v4(), 13)) //error
{
start_accept();
}
Things changed in Boost 1.66:
The release notes show the renamed/changed interfaces:
Boost.Asio now provides the interfaces and functionality specified by the "C++ Extensions for Networking" Technical Specification. In addition to access via the usual Boost.Asio header files, this functionality may be accessed through special headers that correspond to the header files defined in the TS. These are listed in the table below:
I am trying to write a simple client to publish a UDP message to a server. My buffer is not being sent as a udp. When I try and send the message to netcat it does not appear.
#include <iostream>
#include <boost/array.hpp>
#include <boost/asio.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/thread.hpp>
int main(int argc, char *argv[])
{
boost::asio::io_service io_service;
boost::asio::ip::udp::endpoint endpoint_(boost::asio::ip::address::from_string("0.0.0.0"), 2399);
boost::asio::ip::udp::socket socket(io_service, endpoint_);
boost::asio::socket_base::broadcast option(true);
socket.set_option(option);
char* data = "hello";
socket.send_to(boost::asio::buffer(data, strlen(data)), endpoint_);
getchar();
return 0;
}
Binding the socket to an endpoint is a server function. You could notice this by the fact you may receive a "Bind error/Address already in use" error if something listens on that port already.
Instead use socket.open:
Live On Coliru
#include <iostream>
#include <boost/asio.hpp>
int main()
{
using namespace boost::asio;
using ip::udp;
io_service io_service;
udp::socket socket(io_service);
socket.open(udp::v4());
socket.set_option(socket_base::broadcast(true));
const char* data = "hello";
udp::endpoint endpoint_(ip::address::from_string("0.0.0.0"), 2399);
socket.send_to(boost::asio::buffer(data, strlen(data)), endpoint_);
}
I am going to write an adapter class. In this class there is an xmlrpc-c server (abyss server). I want to start the server by creating a new thread, and the thread's function is the member function XMLThreadFun().
When I try to use the code below there is an error at the line of the adapter's constructor implementation:
/usr/include/boost/bind/bind.hpp:69:37: error: ‘void (Adapter::*)()’ is not a class, struct, or union type
Can anyone tell me how to solve this error, or how to achieve my goal? I really appreciate it.
Below is my code snippet:
#ifdef _MSC_VER
#pragma warning( disable : 4503 4355 4786 )
#else
#include "config.h"
#endif
#include "quickfix/FileStore.h"
#include "quickfix/SocketInitiator.h"
#include "quickfix/SessionSettings.h"
#include "Application.h"
#include <string>
#include <iostream>
#include <fstream>
#include "quickfix/SessionID.h"
#include "quickfix/Session.h"
#include "getopt-repl.h"
#include <cassert>
#include <xmlrpc-c/base.hpp>
#include <xmlrpc-c/registry.hpp>
#include <xmlrpc-c/server_abyss.hpp>
#include <boost/thread.hpp>
#include <boost/date_time.hpp>
using namespace std;
class theClient : public xmlrpc_c::method {
public:
theClient() {}
theClient(FIX::SocketInitiator* initiator) {
set<FIX::SessionID> s(initiator->getSessions());
set<FIX::SessionID>::iterator myIterator;
for (myIterator = s.begin(); myIterator != s.end(); myIterator++) {
string str(myIterator->getSenderCompID());
clientname = str;
}
}
void execute(xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retvalP) {
*retvalP = xmlrpc_c::value_string(clientname);
}
private:
string clientname;
};
class Adapter {
private:
xmlrpc_c::registry myRegistry;
xmlrpc_c::methodPtr XMLRPCMethodP;
xmlrpc_c::serverAbyss webServer;
boost::thread webServerThread;
public:
void initWebServer(string rpcHost, string rpcPort);
void XMLThreadFun();
Adapter(string rpcHost, string rpcPort);
};
Adapter::Adapter(string rpcHost, string rpcPort) : myRegistry(), XMLRPCMethodP(new theClient), webServer(myRegistry, 8181, "/tmp/xmlrpc_log"), webServerThread(boost::bind(&Adapter::XMLThreadFun, this, &webServer))
{
initWebServer(rpcHost, rpcPort);
}
void Adapter::XMLThreadFun() {
webServer->run();
}
void Adapter::initWebServer(string rpcHost, string rpcPort) {
webServerThread.join();
}
You will need to use boost::bind to call a member function as a thread.
Something like
class MyClass {
public:
void Start();
void DoStuff( int limit );
};
MyClass foo;
boost::thread thread1( boost::bind( &MyClass::Start, &foo ) );
boost::thread thread2( boost::bind( &MyClass::DoStuff, &foo, 30 ) );
// threads do stuff here
thread1.join();
thread2.join();
Specifically here, it looks like you would change
webServerThread( boost::bind( &Adapter::XMLThreadFun, this, &webServer)
to
webServerThread( boost::bind( &Adapter::XMLThreadFun, this )
No need to use boost::bind
boost::thread thread2( boost::bind( &MyClass::DoStuff, &foo, 30 ) );
is equivalent to:
boost::thread thread2( &MyClass::DoStuff, &foo, 30 );
I expected the code below to print Hello, world! every 5 seconds, but what happens is that the program pauses for 5 seconds and then prints the message over and over with no subsequent pauses. What am I missing?
#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost::asio;
using namespace std;
io_service io;
void print(const boost::system::error_code& /*e*/)
{
cout << "Hello, world!\n";
deadline_timer t(io, boost::posix_time::seconds(5));
t.async_wait(print);
}
int main()
{
deadline_timer t(io, boost::posix_time::seconds(5));
t.async_wait(print);
io.run();
return 0;
}
edit to add working code below. thanks guys.
#include <iostream>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost::asio;
using namespace std;
class Deadline {
public:
Deadline(deadline_timer &timer) : t(timer) {
wait();
}
void timeout(const boost::system::error_code &e) {
if (e)
return;
cout << "tick" << endl;
wait();
}
void cancel() {
t.cancel();
}
private:
void wait() {
t.expires_from_now(boost::posix_time::seconds(5));
t.async_wait(boost::bind(&Deadline::timeout, this, boost::asio::placeholders::error));
}
deadline_timer &t;
};
class CancelDeadline {
public:
CancelDeadline(Deadline &d) :dl(d) { }
void operator()() {
string cancel;
cin >> cancel;
dl.cancel();
return;
}
private:
Deadline &dl;
};
int main()
{
io_service io;
deadline_timer t(io);
Deadline d(t);
CancelDeadline cd(d);
boost::thread thr1(cd);
io.run();
return 0;
}
You're creating the deadline_timer as a local variable and then immediately exiting the function. This causes the timer to destruct and cancel itself, and calls your function with an error code which you ignore, causing the infinite loop.
Using a single timer object, stored in a member or global variable, should fix this.
#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost::asio;
using namespace std;
io_service io;
deadline_timer t(io, boost::posix_time::seconds(5));
void print(const boost::system::error_code& /*e*/)
{
cout << "Hello, world!\n";
t.expires_from_now(boost::posix_time::seconds(5));
t.async_wait(print);
}
int main()
{
//deadline_timer t(io, boost::posix_time::seconds(5));
t.async_wait(print);
io.run();
return 0;
}
If you look at the error code, you're getting operation cancelled errors.