2017-11-13 21 views
1

asio의 설명서를 읽으면서 완료 핸들러가 io_service의 io.run() 메서드를 호출 한 스레드 중 하나에 의해 호출된다는 것은 분명합니다. 그러나 나에게 명확하지 않은 것은 읽기/쓰기 비동기 메소드가 발생하는 스레드입니다. 내가 메서드라고 부르는 스레드입니까, 아니면 io.run() 메서드를 호출 한 스레드 중 하나입니까? 또는 마지막으로 라이브러리가 장면 뒤에서 또 다른 스레드를 만들고 작업을 수행합니까?스레드 비동기 작업 수행

+0

이인가 그러나, async_write(socket1, ...)를 호출 한 후, socket2io_service가 실행되지 않은 경우에도 데이터가 변수가 있거나 다른 목적이 있습니까? – Yakk

+0

중요한 응용 프로그램을 개발 중이므로 응용 프로그램이 실행중인 스레드에 시간을 낭비 할 여유가 없습니다. 나는 람다가 io_service를 써서 run() 메서드를 호출 한 스레드 중 하나에서 작업을 작성하도록 게시 할 수 있음을 알고있다. 그러나 라이브러리 자체가 쓰기 작업을 수행하기 위해 다른 스레드를 만드는 경우 io_service에 게시 할 필요가 없습니다. –

+0

[플랫폼 별 구현 참고 사항] (http://www.boost.org/doc/libs/1_65_1/doc/html/boost_asio/overview/implementation.html) 문서는 모든 내부 스레드의 생성과 용도에 대해 설명합니다. 내부 쓰레드는 쓰기 조작을 서비스하지 않습니다. –

답변

0

예를 들어 일부 데이터를 원격 파트너 비동기로 보내려합니다.

boost::asio::async_write(_socket, boost::asio::buffer(msg.data(), msg.size()), 
    std::bind(&Socket::WriteHandlerInternal, this->shared_from_this(), std::placeholders::_1, std::placeholders::_2)); 
//Where 'this' is the class Socket 

그 전에 아마도 ioService.run()이라는 스레드를 만들었을 것입니다. async_write 함수는 소켓을 만드는 데 사용한 것과 동일한 ioService을 사용합니다. 의 큐에 쓰기 작업을 실행하고 에서 이미 제시 한대로 ioService이 실행되는 스레드에서 처리기 - 을 실행합니다.

+0

그게 내가 의심했던 것이다. 그러나, 나는 이것을 boost 문서에서 명시 적으로 보지 않았기 때문에 어떤 가정도하고 싶지 않았다. –

0

시작하는 async_* 기능 내에서 입출력 작업이 시도됩니다. 작업의 완료 조건이 충족되거나 오류가 발생하면 작업이 완료되고 완료 핸들러가 io_service에 게시됩니다. 그렇지 않으면 작업이 완료되지 않으며 io_service의 기능 poll(), poll_one(), run() 또는 run_one()을 실행하는 응용 프로그램 스레드가 기본 I/O 작업을 수행하는 io_service에 대기열에 포함됩니다. 두 경우 모두 완료 핸들러는 io_service을 처리하는 스레드에 의해 호출됩니다.

는 무관하게 비동기 동작을 즉시 아닌지 완료 여부 핸들러가이 함수 내에서 호출되지 않는다 :

async_write() 문서는 비동기 작업이 즉시 완료 될 수 있다는 것을 지적한다. 핸들러 호출은 boost::asio::io_service::post()을 사용하는 것과 동일한 방식으로 수행됩니다.

이 문제는 또한 Requirements on Asynchronous Operations 문서에 기록됩니다 :

  • 바운드를 구축 : 비동기 작업이 완료되면

    , 운영을위한 핸들러가 호출되는 경우와 같은 처리기에 대한 완료 처리기 bch

  • 지연된 호출에 대한 처리기를 예약하기 위해 ios.post(bch)을 호출하려면 ...

이는 비동기 작업이 즉시 완료 되더라도 시작 함수 내에서 직접 핸들러를 호출하면 안된다는 것을 의미합니다. 여기


는 완전한 예를 demonstrating이 동작입니다. 그 안에 socket1socket2이 연결되어 있습니다. 처음에는 socket2에 데이터가 없습니다.당신이 스레드 로컬 상태 알고 싶어 차단 일부 작업의 경우, 또는 때문에 알고 싶어하기 때문에

#include <boost/asio.hpp> 

constexpr auto noop = [](auto&& ...){}; 

int main() 
{ 
    using boost::asio::ip::tcp; 
    boost::asio::io_service io_service; 

    // Create all I/O objects. 
    tcp::acceptor acceptor{io_service, {{}, 0}}; 
    tcp::socket socket1{io_service}; 
    tcp::socket socket2{io_service}; 

    // Connect sockets. 
    acceptor.async_accept(socket1, noop); 
    socket2.async_connect(acceptor.local_endpoint(), noop); 
    io_service.run(); 
    io_service.reset(); 

    // Verify socket2 has no data. 
    assert(0 == socket2.available()); 

    // Initiate an asynchronous write. However, do not run 
    // the `io_service`. 
    std::string data{"example"}; 
    async_write(socket1, boost::asio::buffer(data), noop); 

    // Verify socket2 has data. 
    assert(0 < socket2.available()); 
}