conditional_variable::wait unexpected behavior? - c++11

I picked up the code from the conditional_variable::wait reference. The reference states that :
wait causes the current thread to block until the condition variable
is notified or a spurious wakeup occurs, optionally looping until some
predicate is satisfied.
The link also states that the wait is equivalent to :
while (!pred()) {
wait(lock); }
If that is the case, is there a reason why the following code does not work as the original code?
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
std::condition_variable cv;
std::mutex cv_m; // This mutex is used for three purposes:
// 1) to synchronize accesses to i
// 2) to synchronize accesses to std::cerr
// 3) for the condition variable cv
int i = 0;
void waits()
{
std::unique_lock<std::mutex> lk(cv_m);
std::cerr << "Waiting... \n";
cv.wait(lk, [] {std::cout << "Check Done!" << std::endl; return i == 1; });
std::cerr << "...finished waiting. i == 1\n";
}
void signals()
{
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::lock_guard<std::mutex> lk(cv_m);
std::cerr << "Notifying...\n";
}
cv.notify_all();
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::lock_guard<std::mutex> lk(cv_m);
i = 1;
std::cerr << "Notifying again...\n";
}
//cv.notify_all();
}
int main()
{
std::thread t1(waits), t2(waits), t3(waits), t4(signals);
t1.join();
t2.join();
t3.join();
t4.join();
}

Related

What does "boost::wrapexcept<boost::system::system_error> : body limit exceeded" mean?

I'm trying to download this link using an C++ apllication. But the it encountered exception:
terminate called after throwing an instance of 'boost::wrapexcept'
what(): body limit exceeded
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
I found out the problem is in http::write.
What on earth is going wrong? Does that mean I was just trying to download the whole file into the memory? If yes, can I continue using ssl::stream anymore? Or there's any alternative?
#ifndef __kernel_entry
#define __kernel_entry
#endif
#include <boost/asio.hpp>
#include <windows.h>
#include <boost/asio/ssl.hpp>
#include <boost/beast.hpp>
#include <boost/beast/http.hpp>
#include <boost/process.hpp>
#include <boost/process/async.hpp>
#include <iomanip>
#include <iostream>
void handle_batch(std::vector<size_t> params) {
std::mutex s_mx;
if (!params.empty()) {
// emulate some work, because I'm lazy
auto sum = std::accumulate(begin(params), end(params), 0ull);
// then wait some 100..200ms
{
using namespace std::chrono_literals;
std::mt19937 prng(std::random_device{}());
std::this_thread::sleep_for(
std::uniform_real_distribution<>(100,200)(prng)*1ms);
}
// simple thread id (thread::id displays ugly)
auto tid = std::hash<std::thread::id>{}(std::this_thread::get_id()) % 100;
// report results to stdout
std::lock_guard lk(s_mx); // make sure the output doesn't intermix
std::cout
<< "Thread #" << std::setw(2) << std::setfill('0') << tid
<< " Batch n:" << params.size()
<< "\tRange [" << params.front() << ".." << params.back() << "]"
<< "\tSum:" << sum
<< std::endl;
}
}
namespace net = boost::asio;
namespace ssl = net::ssl;
namespace beast = boost::beast;
namespace http = beast::http;
namespace process = boost::process;
using boost::system::error_code;
using boost::system::system_error;
using net::ip::tcp;
using stream = ssl::stream<tcp::socket>;
auto ssl_context() {
ssl::context ctx{ssl::context::sslv23};
return ctx;
}
void connect_https(stream& s, std::string const& host, tcp::resolver::iterator eps) {
net::connect(s.lowest_layer(), eps);
s.lowest_layer().set_option(tcp::no_delay(true));//dealt here
if (!SSL_set_tlsext_host_name(s.native_handle(), host.c_str())) {
throw system_error{ { (int)::ERR_get_error(), net::error::get_ssl_category() } };
}
s.handshake(stream::handshake_type::client);
}
auto get_request(std::string const& host, std::string const& path) {
using namespace http;
using std::cerr;
request<string_body> req;
req.version(11);cerr<<"__ver";
req.method(verb::get);cerr<<"__met";
req.target("https://" + host + path);cerr<<"__tar";
//req.set(field::user_agent, "test");
req.set(field::host, host);cerr<<"__set";
std::cerr << req << std::endl;
Sleep(1000);
return req;
}
int main() {
net::io_context io; // main thread does all io
net::thread_pool pool(6); // worker threads
// outside for lifetime
http::response_parser<http::buffer_body> response_reader;
beast::flat_buffer lookahead; // for the response_reader
std::array<char,512> buf{0}; // for download content
auto ctx = ssl_context();
ssl::stream<tcp::socket> s(io, ctx);
{ // synchronously write request
std::string host = "www.sfml-dev.org";
try{
connect_https(s, host, tcp::resolver{io}.resolve(host, "https"));
}catch(std::exception& e){std::cerr<<e.what()<<std::endl;}
http::write(s, get_request(host, "/files/SFML-2.5.1-windows-gcc-7.3.0-mingw-32-bit.zip"));
http::read_header(s, lookahead, response_reader);
std::cerr << "Headers: " << response_reader.get().base() << std::endl;
}//https://www.sfml-dev.org/files/SFML-2.5.1-windows-gcc-7.3.0-mingw-32-bit.zip
// now, asynchoronusly read contents
process::async_pipe pipe_to_zcat(io);
std::function<void(error_code, size_t)> receive_zip;
receive_zip = [&s, &response_reader, &pipe_to_zcat, &buf, &lookahead, &receive_zip](error_code ec, size_t /*ignore_this*/) {
auto& res = response_reader.get();
auto& body = res.body();
if (body.data) {
auto n = sizeof(buf) - body.size;
net::write(pipe_to_zcat, net::buffer(buf, n));
}
bool done = ec && !(ec == http::error::need_buffer);
done += response_reader.is_done();
if (done) {
std::cerr << "receive_zip: " << ec.message() << std::endl;
pipe_to_zcat.close();
} else {
body.data = buf.data();
body.size = buf.size();
http::async_read(s, lookahead, response_reader, receive_zip);
}
};
// kick off receive loop
receive_zip(error_code{}, 0);
process::async_pipe zcat_output(io);
process::child zcat(
process::search_path("zcat"),
process::std_in < pipe_to_zcat,
process::std_out > zcat_output,
process::on_exit([](int exitcode, std::error_code ec) {
std::cerr << "Child process exited with " << exitcode << " (" << ec.message() << ")\n";
}), io);
std::function<void(error_code, size_t)> receive_primes;
net::streambuf sb;
receive_primes = [&zcat_output, &sb, &receive_primes, &pool](error_code ec, size_t /*transferred*/) {
{
std::istream is(&sb);
size_t n = std::count(net::buffers_begin(sb.data()), net::buffers_end(sb.data()), '\n');
std::vector<size_t> batch(n);
std::copy_n(std::istream_iterator<size_t>(is), n, batch.begin());
is.ignore(1, '\n'); // we know a newline is pending, eat it to keep invariant
post(pool, std::bind(handle_batch, std::move(batch)));
}
if (ec) {
std::cerr << "receive_primes: " << ec.message() << std::endl;
zcat_output.close();
} else {
net::async_read_until(zcat_output, sb, "\n", receive_primes);
}
};
// kick off handler loop as well:
receive_primes(error_code{}, 0);
io.run();
pool.join();
}

boost socket example stuck in while loop

I am trying to learn boost asio socket. there is one interesting example in boost web page which set a deadline time to monitor the timeout and change async io to sync io fashion. but when I remove the deadline timer the program stuck in while loop in write_line, I don't understand why the connection can be setup but the socket write is stuck. it seems that the writing never finished ,the handler never called so the "ec" never changed. Thank you in advance!!
#include <boost/asio/connect.hpp>
#include <boost/asio/deadline_timer.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/read_until.hpp>
#include <boost/asio/streambuf.hpp>
#include <boost/system/system_error.hpp>
#include <boost/asio/write.hpp>
#include <cstdlib>
#include <iostream>
#include <string>
#include <boost/bind.hpp>
using boost::asio::deadline_timer;
using boost::asio::ip::tcp;
class client
{
public:
client()
: socket_(io_service_),
deadline_(io_service_)
{
deadline_.expires_from_now(boost::posix_time::seconds(10));
check_deadline(); // without this line which means without the this timer
//async_wait, the code stuck in write_line io_service_.run_one() loop .
}
void connect_handler(const boost::system::error_code& error,boost::system::error_code *er)
{
std::cerr<<"connect handler"<<std::endl;
*er = error;
std::cerr<<error<<std::endl;
}
void connect(const std::string& host, const std::string& service)
{
tcp::resolver::query query(host, service);
tcp::resolver::iterator iter = tcp::resolver(io_service_).resolve(query);
std::cerr<<"connect start"<<std::endl;
boost::system::error_code ec = boost::asio::error::would_block;
boost::asio::async_connect(socket_, iter, bind(&client::connect_handler,this,_1,&ec));
do
{io_service_.run_one();
}while (ec == boost::asio::error::would_block);
std::cerr<<"connect done"<<std::endl; // always works fine!
if (ec || !socket_.is_open())
throw boost::system::system_error(
ec ? ec : boost::asio::error::operation_aborted);
}
void write_handler(const boost::system::error_code& error, std::size_t size,boost::system::error_code* er )
{
std::cerr<<"write handler "<<std::endl;
*er=error;
std::cerr<<error<<std::endl;
}
void write_line(const std::string& line)
{
std::cerr<<"write start"<<std::endl;
std::string data = line + "\n";
boost::system::error_code ec = boost::asio::error::would_block;
boost::asio::async_write(socket_, boost::asio::buffer(data), bind(&client::write_handler,this,_1,_2,&ec));
do
{
io_service_.run_one(); //stuck here without "check_deadline();" in constructor.
}while (ec == boost::asio::error::would_block);
std::cerr<<"write done";
if (ec)
throw boost::system::system_error(ec);
}
private:
void check_deadline()
{
if (deadline_.expires_at() <= deadline_timer::traits_type::now())
{
boost::system::error_code ignored_ec;
socket_.close(ignored_ec);
deadline_.expires_at(boost::posix_time::pos_infin);
throw boost::system::system_error(ignored_ec);
}
deadline_.async_wait(std::bind(&client::check_deadline, this));
}
boost::asio::io_service io_service_;
tcp::socket socket_;
deadline_timer deadline_;
};
int main()
{
try
{
client c,d;
c.connect("216.58.194.164", "80");// google IP.
c.write_line("test");
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
Without comment out line "check_deadline();" in constructor the output is :
connect start
connect handler
system:0
connect done
write start
write handler
system:0
write done
when the line "check_deadline();" comment out in constructor, the output is :
connect start
connect handler
system:0
connect done
write start
and stuck there forever.
The whole point of that particular example is to have timeouts on blocking operations. This is why they use the async_* flavour of functions.
If you don't need that, don't use the async_* flavour at all:
#include <boost/asio.hpp>
#include <iostream>
#include <string>
using boost::asio::ip::tcp;
class client {
public:
client() : socket_(io_service_) { }
void connect(const std::string &host, const std::string &service) {
tcp::resolver::query query(host, service);
socket_.close();
boost::asio::connect(socket_, tcp::resolver(io_service_).resolve(query));
}
std::string read_line() {
boost::system::error_code ec;
boost::asio::read_until(socket_, input_buffer_, '\n', ec);
if (ec == boost::asio::error::eof)
socket_.close();
else if (ec)
throw boost::system::system_error(ec);
std::string line;
std::getline(std::istream(&input_buffer_), line);
return line;
}
void write_line(const std::string &line) {
std::string data = line + "\n";
boost::asio::write(socket_, boost::asio::buffer(data));
}
private:
boost::asio::io_service io_service_;
tcp::socket socket_;
boost::asio::streambuf input_buffer_;
};
int main(int argc, char *argv[]) {
try {
if (argc != 4) {
std::cerr << "Usage: blocking_tcp <host> <port> <message>\n";
return 1;
}
client c;
c.connect(argv[1], argv[2]);
boost::posix_time::ptime time_sent = boost::posix_time::microsec_clock::universal_time();
c.write_line(argv[3]);
for (;;) {
std::string line = c.read_line();
std::cout << "Received '" << line << "'\n";
if (line == argv[3])
break;
}
boost::posix_time::ptime time_received = boost::posix_time::microsec_clock::universal_time();
std::cout << "Round trip time: ";
std::cout << (time_received - time_sent).total_microseconds();
std::cout << " microseconds\n";
} catch (std::exception &e) {
std::cerr << "Exception: " << e.what() << "\n";
}
}
That's a lot simpler. In fact, it's too simple in case the packets arriving contain more than 1 line at a time.
Instead of "fixing" the sample by re-complicating it, it can be ENORMOUSLY simpler:
#include <boost/asio.hpp>
#include <iostream>
#include <string>
using boost::asio::ip::tcp;
int main(int argc, char *argv[]) {
try {
if (argc != 4) {
std::cerr << "Usage: blocking_tcp <host> <port> <message>\n";
return 1;
}
tcp::iostream c(argv[1], argv[2]);
boost::posix_time::ptime time_sent = boost::posix_time::microsec_clock::universal_time();
c << argv[3] << "\n";
std::string line;
while (getline(c, line)) {
std::cout << "Received '" << line << "'\n";
if (line == argv[3])
break;
}
boost::posix_time::ptime time_received = boost::posix_time::microsec_clock::universal_time();
std::cout << "Round trip time: ";
std::cout << (time_received - time_sent).total_microseconds();
std::cout << " microseconds\n";
} catch (std::exception &e) {
std::cerr << "Exception: " << e.what() << "\n";
}
}

How to get error object? when use member function in deadline_timer

I use boost::asio::deadline_timer using a member function as a handler (callback function).
If I cancel a timer, how to get error object in print() member function?
class printer
{
public:
printer(boost::asio::io_service& io)
: timer_(io, boost::posix_time::seconds(1)),
count_(0)
{
timer_.async_wait(boost::bind(&printer::print, this));
}
~printer()
{
std::cout << "Final count is " << count_ << "\n";
}
void print()
{
if (count_ < 5)
{
std::cout << count_ << "\n";
++count_;
timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(1));
timer_.async_wait(boost::bind(&printer::print, this));
}
}
private:
boost::asio::deadline_timer timer_;
int count_;
};
int main()
{
boost::asio::io_service io;
printer p(io);
io.run();
return 0;
}
I try to set error object using bind in async_wait(), but it's compile error
timer_.async_wait(boost::bind(&printer::print, this, boost::asio::placeholders::error));
As long as your method signature matches, it should be no problem:
void print(boost::system::error_code const ec)
// and
boost::bind(&printer::print, this, boost::asio::placeholders::error)
See it Live On Coliru:
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <iostream>
class printer
{
public:
printer(boost::asio::io_service& io)
: timer_(io, boost::posix_time::seconds(1)),
count_(0)
{
timer_.async_wait(boost::bind(&printer::print, this, boost::asio::placeholders::error));
}
~printer()
{
std::cout << "Final count is " << count_ << "\n";
}
void print(boost::system::error_code const ec)
{
if (ec)
std::cout << "Error: " << ec.message() << "\n";
if (count_ < 5)
{
std::cout << count_ << "\n";
++count_;
timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(1));
timer_.async_wait(boost::bind(&printer::print, this, boost::asio::placeholders::error));
}
}
private:
boost::asio::deadline_timer timer_;
int count_;
};
int main()
{
boost::asio::io_service io;
printer p(io);
io.run();
}

zero mq asynchronous server side is getting core dump

This is first post in the forum and need help.
I have implemented the ZeroMQ server part much same as documented here
https://github.com/egalli64/thisthread/blob/master/zmq/d2r.cpp.
Below is my code
#include <string>
#include <boost/thread.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/random.hpp>
#include "zmq2.h"
#include <pthread.h>
#include <unistd.h>
#include <cassert>
#include <string>
#include <iostream>
#include <zmq.hpp>
boost::mutex mio;
void *worker(void *arg)
{
std::cout << "in worker" << std::endl;
zmq::context_t *context = (zmq::context_t *) arg;
zmq::Socket skWorker(*context, ZMQ_DEALER);
std::cout << "in worker2" << std::endl;
skWorker.connect("inproc://backend");
std::cout<< "Worker started" << std::endl;
while(true)
{
std::cout << "in while" << std::endl;
zmq::Frames frames = skWorker.blockingRecv(2, false);
if(frames.size() == 1)
{
std::cout << "in if" << std::endl;
break;
}
// send a few replies
for(int i =0; i < 10; ++i)
{
boost::this_thread::sleep(boost::posix_time::millisec(100 * 10));
std::cout << "worker reply" << std::endl;
skWorker.send(frames);
}
}
std::cout << "terminating worker" << std::endl;
return (NULL);
}
void dumpId(const char* tag, const std::string& msg)
{
boost::lock_guard<boost::mutex> lock(mio);
std::string id = boost::lexical_cast<std::string>(boost::this_thread::get_id());
std::cout << id << ' ' << tag << ' ' << msg << std::endl;
}
int main()
{
zmq::context_t context(1);
zmq::Socket client(context, ZMQ_ROUTER);
client.bind("tcp://*:5555");
zmq::Socket workers(context, ZMQ_DEALER);
workers.bind("inproc://workers");
for (int thread_nbr = 0; thread_nbr != 2; thread_nbr++)
{
pthread_t threads;
pthread_create(&threads, NULL, worker, (void *) &context);
}
std::cout << " server started" << std::endl;
zmq_pollitem_t items [] =
{
{ client, 0, ZMQ_POLLIN, 0 },
{ workers, 0, ZMQ_POLLIN, 0 }
};
while(true)
{
if(zmq_poll(items, 2, 3000 * 1000) < 1) // 3 secs
break;
if(items[0].revents & ZMQ_POLLIN)
{
zmq::Frames frames = client.blockingRecv(2);
dumpId("Received on frontend", frames[0]);
workers.send(frames);
items[0].revents = 0; // cleanup
}
if(items[1].revents & ZMQ_POLLIN)
{
zmq::Frames frames = workers.blockingRecv(2);
dumpId("Received on backend", frames[0]);
client.send(frames);
items[1].revents = 0; // cleanup
}
}
std::cout <<"Nothing happened for a while" << std::endl;
// send a terminator to each worker
for(int i = 0; i < 2; ++i)
workers.send("");
std::cout << "Server shutdown" << std::endl;
}
After running the its getting core dumped.
Below is the output
in workerin worker server started
in worker2
in worker2
terminate called after throwing an instance of 'zmq::error_t'
terminate called recursively
Aborted (core dumped)
Could some one let me know where I m doing wrong.......
Thanks in advance....

Mac OS X : boost interprocess semaphore timed_wait : Abnormal CPU consumption

After porting a code segment from Windows to Mac OS X, I found it to consume a whole CPU core while running; the responsible call for the CPU consumption is boost::interprocess::interprocess_semaphore::timed_wait.
Here follows the code portion which reproduces this behaviour.
#include <boost/interprocess/sync/interprocess_semaphore.hpp>
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/thread/thread_time.hpp>
#include <iostream>
static bool gStopRequested(false);
struct ShmObj
{
boost::interprocess::interprocess_semaphore mSemaphore;
ShmObj() : mSemaphore(0) {};
~ShmObj() {};
};
int main(char* argc, const char** argv)
{
boost::interprocess::shared_memory_object* lShmObj = NULL;
std::string lShmObjName("My_Boost_Interprocess_Test");
boost::interprocess::mapped_region* lRegion;
ShmObj* lObj;
//Create shared segment
try
{
lShmObj = new boost::interprocess::shared_memory_object(boost::interprocess::create_only, lShmObjName.c_str(), boost::interprocess::read_write);
}
catch (boost::interprocess::interprocess_exception &ex)
{
if (ex.get_error_code() != boost::interprocess::already_exists_error)
{
std::cerr << "Some error" << std::endl;
exit(1);
}
else
{
std::cerr << "Already exists, just taking it back." << std::endl;
try
{
lShmObj = new boost::interprocess::shared_memory_object(boost::interprocess::open_only, lShmObjName.c_str(), boost::interprocess::read_write);
}
catch (boost::interprocess::interprocess_exception &ex2)
{
std::cerr << "D'oh !" << std::endl;
exit(1);
}
}
}
if (!lShmObj)
{
exit(1);
}
lShmObj->truncate(sizeof(ShmObj));
lRegion = new boost::interprocess::mapped_region(*lShmObj, boost::interprocess::read_write);
lObj = new (lRegion->get_address()) ShmObj;
// The loop
while (!gStopRequested)
{
boost::system_time lDeadlineAbsoluteTime = boost::get_system_time() + boost::posix_time::milliseconds(500);
if (lObj->mSemaphore.timed_wait(lDeadlineAbsoluteTime))
{
std::cout << "acquired !" << std::endl;
}
else
{
std::cout << "tick" << std::endl;
}
}
}
Then, I read that unnamed semaphores were not available under Mac OS X, so I thought it could be because unnamed semaphores were not efficiently emulated... I then tried the following, unsucessfully:
#include <boost/interprocess/sync/named_semaphore.hpp>
#include <boost/thread/thread_time.hpp>
#include <iostream>
static bool gStopRequested(false);
int main(char* argc, const char** argv)
{
boost::interprocess::named_semaphore::remove("My_Boost_Interprocess_Test");
boost::interprocess::named_semaphore lMySemaphore(boost::interprocess::open_or_create, "My_Boost_Interprocess_Test", 1);
// The loop
while (!gStopRequested)
{
boost::system_time lDeadlineAbsoluteTime = boost::get_system_time() + boost::posix_time::milliseconds(500);
if (lMySemaphore.timed_wait(lDeadlineAbsoluteTime))
{
std::cout << "acquired !" << std::endl;
}
else
{
std::cout << "tick" << std::endl;
}
}
}
I was actually expecting a better behaviour of boost::interprocess on Mac OS X because of the available Posix primitives, but it is actually not. Any idea for a resolution? Thanks a lot.
I successfully Used Mach semaphores instead of the ones of boost::interprocess... see http://pkaudio.blogspot.com/2010/05/mac-os-x-no-timed-semaphore-waits.html

Resources