【问题标题】:Using boost asio stream_handle with sequential like file based devices将 boost asio stream_handle 与基于文件的设备一起使用
【发布时间】:2015-06-19 19:59:03
【问题描述】:

我正在考虑使用 asio 在使用 CreateFile(...overlapped...) 创建的 Windows“设备句柄”上执行“重叠”(完成端口)样式 IO

虽然我有一个非常特殊的设计,但由于我的应用程序的具体情况,我必须维护一个不同的线程池来执行数​​据的实际处理(工作池)和一个池(一个非常小的,可能只是一个线程) 由处理池触发的实际 IO 完成。

基本上,一开始我想向我的设备触发一些从 IO 池启动的 IO 请求。当这些完成时,我通知调度组件 POSTS 完成数据包内容到工作池中的不同线程。这些完成通知很快返回,因为实际处理将发生在工作池中 -> 并且在处理发生后从特定工作池线程启动新的“读取”,这应该触发 io 池上的完成。

是否可以使用 windows::stream_handle 进行这种分离?一般来说,asio API 似乎将读取完成与与流对象关联的相同 io_service 相关联。

编辑 现在已经很长时间了,因为我已经实施了这种方法。 我已更新我的回复以反映我的选择。

【问题讨论】:

    标签: c++ windows boost-asio


    【解决方案1】:
    1. 我使用 Windows 特定功能创建“设备”句柄:

      HANDLE file_handle = CreateFile(... FILE_FLAG_OVERLAPPED ...);

    2. 我可以将句柄与我的 ioService 关联/注册,以便对设备的所有重叠请求都由 ioService 线程之一处理。

      error_code ec; 自动 &io_service_impl = use_service(ioservice); io_service_impl.register_handle(file_handle, ec);

    3. 然后我可以使用重叠的 asio 从与 ioService.run() 不同的线程启动异步 IO,使其在 io 服务线程中触发完成:

          void IoPool::InitiateNewRead()
          {
      
          service.post([this]() {auto handler = InterceptorReadHandler::Create(bufferPool, data, service);
                      handler->SetContext(context);
      
                      return device.Read(std::move(handler));
                  });
              }
          }
      
    4. 设备读取实现参考:

      bool Device::Read(std::shared_ptr<InterceptorReadHandler> handler) {
      auto handlerWrapper = [handler](const boost::system::error_code &ec, std::size_t len) {
          handler->Completion(ec, len);
      };
      win::overlapped_ptr overlapped(handler->GetService(), handlerWrapper);
      
      
      unsigned long bytesRead = 0;
      auto& packet = handler->GetBuffer();
      auto ok = ::ReadFile(handle,
                           packet.data,
                           static_cast<DWORD> (packet.length),
                           &bytesRead,
                           overlapped.get()) ? true : false;
      
      auto lastError = ::GetLastError();
      if (!ok && lastError != ERROR_IO_PENDING) {
          boost::system::error_code errCode(lastError, boost::system::get_system_category());
          overlapped.complete(errCode, 0);
          return false;
      } else {
          overlapped.release();
      }
      
      return true;
      

      }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-01
      • 1970-01-01
      • 2018-08-28
      • 1970-01-01
      • 2021-05-06
      • 2011-02-19
      • 2013-03-02
      相关资源
      最近更新 更多