如何实现不阻止其用户的引擎类

Posted

技术标签:

【中文标题】如何实现不阻止其用户的引擎类【英文标题】:How to implement engine class which doesn't block its user 【发布时间】:2016-01-21 10:49:41 【问题描述】:

我有类,我们称之为“引擎”,它包含类似事件循环的东西,其逻辑可以用以下伪代码解释:

for(;;) 
  int interruptId;
  waitForInterrupt(); // blocking wait
  switch(interruptId) 
    case REQUEST_DATA:
    doSomeStuff();

    ...
  

事件循环用于中断处理(来自硬件设备的驱动程序)。 引擎将由客户使用。客户端应该能够启动/停止引擎。 但启动引擎不应暂停客户端。

我的意图:引擎启动时会启动一个新线程,在该线程中执行事件循环 for(;;)。

问题是一种解决方案吗,您能否提出适用于这种情况的现有设计模式,关于实现的任何建议以及我应该考虑的可能的瓶颈。

注意!!!更新:引擎类作为动态库提供给客户端

【问题讨论】:

如果您的客户端已经有一个事件循环,如果您想避免额外的线程,您可以将引擎事件循环合并到其中。 Engine 类作为单独的动态库提供给客户端,所以我无法合并它们的循环 "merge" 可能是一个不好的词选择——“call from”怎么样——即。对于每个客户端事件循环迭代,您还检查引擎是否有未决事件(如果有,则处理引擎事件 - 如果没有,您只需执行下一个客户端循环迭代)。 这不起作用,因为引擎循环包含阻塞调用,因此客户端也将被阻塞,直到驱动程序的下一个中断,这不是我想要的一种行为 如果引擎库不提供任何可以让您将两个事件循环合并为一个的功能,您就不得不拥有两个线程(每个事件循环一个线程)。跨度> 【参考方案1】:
#include <thread>
#include <functional>
#include <vector>
#include <iostream>
#include <memory>
#include <cassert>

struct MsgFromAgent 
  std::string str;
;

struct MsgToAgent 
  std::string str;
;

struct IClient 
  virtual void onMsgFromBC(MsgFromAgent& msg) = 0;
  virtual void onTimeout() = 0;
  virtual ~IClient() ;
;

struct Engine 
  Engine(IClient& client) : isRunning(false), client(client)  
  ~Engine() 
    // we expect that if client started the engine
    // client must stop it before Engine will be destructed
    assert(!isRunning && "Running engine should be stoped by the client");

    // in any way, handle exceptional situation if it arises
    if(isRunning) 
      isRunning = false;
      th.join();
    
  
  void start() 
    isRunning = true;
    th = std::thread(std::bind(&Engine::eventLoop, this));
  
  bool write(const MsgToAgent& msg) 
    // some code
  
  void stop() 
    isRunning = false;
    th.join();
  
  void eventLoop() 
    while(isRunning) 
      // blocking calls, that return control when certain interrupts from hardware arrives

      // if interrupt haven't arraived within certain time limit:
      try 
        client.onTimeout();
       catch(...) 

      

      // interrupt about incomming msg:
      MsgFromAgent dummyMsg;
      try 
        client.onMsgFromBC(dummyMsg);
      
      catch (...) 

      
    
  
  bool isRunning;
  std::thread th;
  IClient& client;
;

struct Client : public IClient 
  Client() : e(*this)  

  ;
  ~Client() 
  
  void onMsgFromBC(MsgFromAgent& msg) 
    std::cout << "On message\n";
  
  void onTimeout() 
    std::cout << "On timeout\n";
  
  Engine e;
;

int main() 
  Client c;
  return 0;

【讨论】:

以上是关于如何实现不阻止其用户的引擎类的主要内容,如果未能解决你的问题,请参考以下文章

循环阻止异步请求被发送。为什么以及如何解决?

如何阻止某人更改 gcloud 配置文件?

如何阻止 Rails 4 引擎中的部分内容?

如何不向不想接收推送的用户发送FCM?

thinkphp 5.0如何实现自定义404(异常处理)页面

如何阻止 ProGuard 从类中剥离 Serializable 接口