Skip to content

Instantly share code, notes, and snippets.

@hecomi
Last active December 10, 2015 11:28
Show Gist options
  • Save hecomi/4427622 to your computer and use it in GitHub Desktop.
Save hecomi/4427622 to your computer and use it in GitHub Desktop.
Boost.Thread + Boost.Asio で thread 中で io_service.run() すると落ちる…;;
//
// ViewController.m
// AsioTest
//
// Created by hecomi on 2012/12/31.
// Copyright (c) 2012年 hecomi. All rights reserved.
//
#import "ViewController.h"
#include <dispatch/dispatch.h>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
using namespace std;
namespace asio = boost::asio;
using boost::asio::ip::tcp;
class Client {
typedef boost::function<void(const string&, const string&)> callback;
callback callback_;
string host_;
string html_;
asio::io_service& io_service_;
tcp::socket socket_;
tcp::resolver resolver_;
asio::streambuf buf_;
public:
Client(asio::io_service& io_service)
: io_service_(io_service),
socket_(io_service),
resolver_(io_service)
{}
void get(const string& host, callback callback)
{
std::cout << "get\n";
host_ = host;
callback_ = callback;
html_ = "";
tcp::resolver::query query(host, "http");
resolver_.async_resolve(
query,
boost::bind(
&Client::on_resolve,
this,
asio::placeholders::error,
asio::placeholders::iterator));
boost::thread t(boost::bind(&asio::io_service::run, &io_service_));
t.join();
}
private:
void on_resolve(const boost::system::error_code& error,
tcp::resolver::iterator endpoint_iterator)
{
std::cout << "on_resolve\n";
if (has_error(error)) return;
async_connect(
socket_,
endpoint_iterator,
boost::bind(&Client::on_connect, this, asio::placeholders::error));
}
void on_connect(const boost::system::error_code& error)
{
std::cout << "on_connect\n";
if (has_error(error)) return;
buf_.consume(buf_.size());
ostream s(&buf_);
s << "GET / HTTP/1.0\r\n";
s << "Host: " << host_ << "\r\n";
s << "\r\n";
async_write(
socket_,
buf_,
boost::bind(&Client::on_write, this, asio::placeholders::error));
}
void on_write(const boost::system::error_code& error)
{
std::cout << "on_write\n";
if (has_error(error)) return;
buf_.consume(buf_.size());
async_read(
socket_,
buf_,
asio::transfer_at_least(1),
boost::bind(&Client::on_receive, this, asio::placeholders::error));
}
void on_receive(const boost::system::error_code& error)
{
std::cout << "on_receive\n";
if (error.message().find("End of file") != std::string::npos) {
callback_("", html_);
return;
}
if (has_error(error)) return;
const string data(asio::buffer_cast<const char*>(buf_.data()), buf_.size());
buf_.consume(buf_.size());
html_ += data;
async_read(
socket_,
buf_,
asio::transfer_at_least(1),
boost::bind(&Client::on_receive, this, asio::placeholders::error));
}
bool has_error(const boost::system::error_code& error)
{
std::cout << "has_error\n";
if (error) {
std::cerr << error.message() << std::endl;
callback_(error.message(), html_);
return true;
}
return false;
}
};
@interface ViewController ()
@end
@implementation ViewController
- (void)setText:(NSString *)str
{
_textView.text = str;
}
- (void)viewDidLoad
{
asio::io_service io_service;
Client client(io_service);
const string url = "www.boost.org";
client.get(url, [&](const string& error, const string& html) {
std::cout << "callback\n";
if (!error.empty()) {
std::cerr << error << std::endl;
return;
}
NSString* str = [[NSString alloc] initWithCString:html.c_str() encoding:NSUTF8StringEncoding];
[self performSelectorOnMainThread:@selector(setText:) withObject:str waitUntilDone:NO];
});
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment