SObjectizer:简化C++并发编程的强大工具

SObjectizer:简化C++并发编程的强大工具

项目介绍

SObjectizer是一款跨平台的开源C++“actor框架”,旨在显著简化C++中并发和多线程应用程序的开发。它不仅支持Actor模型,还支持发布-订阅模型和类似CSP的通道。SObjectizer允许将并发应用程序创建为一组通过异步消息相互交互的代理对象,处理消息分发并为消息处理提供工作上下文。

项目技术分析

SObjectizer的核心技术包括:

  1. Actor模型:通过代理对象(agents)实现并发编程,代理对象之间通过异步消息进行通信。
  2. 发布-订阅模型:支持多生产者/多消费者消息盒,消息发送给该消息盒后,所有订阅者都会收到该消息。
  3. CSP-like通道:提供类似CSP(Communicating Sequential Processes)的通道,简化并发任务之间的通信。
  4. 多种调度器:提供多种现成的调度器,允许用户根据需求调整消息分发和工作上下文。

项目及技术应用场景

SObjectizer适用于以下场景:

  1. 多线程代理服务器:通过代理对象实现并发处理请求,提高服务器性能。
  2. 自动控制系统:利用发布-订阅模型实现传感器数据的分发和处理。
  3. 消息队列代理(MQ-broker):支持高效的消息传递和处理,适用于分布式系统中的消息队列。
  4. 数据库服务器:通过并发处理提高数据库服务器的响应速度和吞吐量。

项目特点

  1. 成熟稳定:SObjectizer基于1995-2000年的思想,自2002年以来一直在开发,SObjectizer-5自2010年以来持续演进,广泛应用于生产环境。
  2. 跨平台:支持Windows、Linux、FreeBSD、macOS和Android等多个操作系统。
  3. 易用性:提供易于理解的API,并附带大量示例和详细的项目Wiki文档。
  4. 免费开源:采用BSD-3-CLAUSE许可证,可免费用于开发商业软件。
  5. 不同于TBB、taskflow或HPX:SObjectizer专注于并发计算,而非并行计算,适用于简化多任务并发处理。

代码示例

HelloWorld示例

#include <so_5/all.hpp>

class hello_actor final : public so_5::agent_t {
public:
   using so_5::agent_t::agent_t;

   void so_evt_start() override {
      std::cout << "Hello, World!" << std::endl;
      // 结束示例工作
      so_deregister_agent_coop_normally();
   }
};

int main() {
   // 启动SObjectizer
   so_5::launch([](so_5::environment_t & env) {
         // 在新合作中添加hello_actor实例
         env.register_agent_as_coop( env.make_agent<hello_actor>() );
      });

   return 0;
}

Ping-Pong示例

#include <so_5/all.hpp>

struct ping {
   int counter_;
};

struct pong {
   int counter_;
};

class pinger final : public so_5::agent_t {
   so_5::mbox_t ponger_;

   void on_pong(mhood_t<pong> cmd) {
      if(cmd->counter_ > 0)
         so_5::send<ping>(ponger_, cmd->counter_ - 1);
      else
         so_deregister_agent_coop_normally();
   }

public:
   pinger(context_t ctx) : so_5::agent_t{std::move(ctx)} {}

   void set_ponger(const so_5::mbox_t mbox) { ponger_ = mbox; }

   void so_define_agent() override {
      so_subscribe_self().event( &pinger::on_pong );
   }

   void so_evt_start() override {
      so_5::send<ping>(ponger_, 1000);
   }
};

class ponger final : public so_5::agent_t {
   const so_5::mbox_t pinger_;
   int pings_received_{};

public:
   ponger(context_t ctx, so_5::mbox_t pinger)
      :  so_5::agent_t{std::move(ctx)}
      ,  pinger_{std::move(pinger)}
   {}

   void so_define_agent() override {
      so_subscribe_self().event(
         [this](mhood_t<ping> cmd) {
            ++pings_received_;
            so_5::send<pong>(pinger_, cmd->counter_);
         });
   }

   void so_evt_finish() override {
      std::cout << "pings received: " << pings_received_ << std::endl;
   }
};

int main() {
   so_5::launch([](so_5::environment_t & env) {
         env.introduce_coop([](so_5::coop_t & coop) {
               auto pinger_actor = coop.make_agent<pinger>();
               auto ponger_actor = coop.make_agent<ponger>(
                     pinger_actor->so_direct_mbox());

               pinger_actor->set_ponger(ponger_actor->so_direct_mbox());
            });
      });

   return 0;
}

Pub/Sub示例

#include <so_5/all.hpp>

using namespace std::literals;

struct acquired_value {
   std::chrono::steady_clock::time_point acquired_at_;
   int value_;
};

class producer final : public so_5::agent_t {
   const so_5::mbox_t board_;
   so_5::timer_id_t timer_;
   int counter_{};

   struct acquisition_time final : public so_5::signal_t {};

   void on_timer(mhood_t<acquisition_time>) {
      // 向所有消费者发布下一个值
      so_5::send<acquired_value>(
            board_, std::chrono::steady_clock::now(), ++counter_);
   }

public:
   producer(context_t ctx, so_5::mbox_t board)
      :  so_5::agent_t{std::move(ctx)}
      ,  board_{std::move(board)}
   {}

   void so_define_agent() override {
      so_subscribe_self().event(&producer::on_timer);
   }

   void so_evt_start() override {
      // 代理将定期接收acquisition_time信号,无初始延迟,周期为750ms
      timer_ = so_5::send_periodic<acquisition_time>(*this, 0ms, 750ms);
   }
};

class consumer final : public so_5::agent_t {
   const so_5::mbox_t board_;
   const std::string name_;

   void on_value(mhood_t<acquired_value> cmd) {
      std::cout << name_ << ": " << cmd->value_ << std::endl;
   }

public:
   consumer(context_t ctx, so_5::mbox_t board, std::string name)
      :  so_5::agent_t{std::move(ctx)}
      ,  board_{std::move(board)}
      ,  name_{std::move(name)}
   {}

   void so_define_agent() override {
      so_subscribe(board_).event(&consumer::on_value);
   }
};

int main() {
   so_5::launch([](so_5::environment_t & env) {
         auto board = env.create_mbox();
         env.introduce_coop([board](so_5::coop_t & coop) {
               coop.make_agent<producer>(board);
               coop.make_agent<consumer>(board, "first"s);
               coop.make_agent<consumer>(board, "second"s);
            });

         std::this_thread::sleep_for(std::chrono::seconds(4));
         env.stop();
      });

   return 0;
}

总结

SObjectizer凭借其成熟稳定的技术、跨平台支持、易用性和免费开源的特点,成为C++并发编程的理想选择。无论是开发多线程代理服务器、自动控制系统,还是消息队列代理和数据库服务器,SObjectizer都能提供强大的支持。立即尝试SObjectizer,体验其简化并发编程的强大功能!

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值