C++元编程——模拟javascript异步执行

本文介绍了JavaScript中的期约调用机制以及C++11的chain类实现的异步操作,对比了两者在处理并行任务中的特点,提及了Boostsignals2模块的观察者模式。作者指出各自的优缺点,特别是关于链式构造的代价问题。
摘要由CSDN通过智能技术生成

javascript有一个期约调用,就是利用内部的一种协程机制实现的类似并行的操作。以下是用ChatGPT搞出来的一块演示代码:

// 异步任务
function asyncTask() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const randomNumber = Math.floor(Math.random() * 10);
      if (randomNumber < 5) {
        resolve(randomNumber);
      } else {
        reject("Error: Random number is greater than or equal to 5");
      }
    }, 1000);
  });
}
// 调用异步任务
asyncTask()
  .then((result) => {
    console.log("Resolved:", result);
  })
  .catch((error) => {
    console.error("Rejected:", error);
  });

可以看到,这个里面用了asyncTask创建了一个期约,然后调用期约执行程序。在期约执行的期间主线程会继续执行。

下面有C++11搞了个类似的通过then串联逻辑链的:

template<typename f_t, typename...fs_t>
class chain
{
private:
	f_t cur_f;
	chain<fs_t...> next;
public:
	chain(f_t f, fs_t...fs) :cur_f(f), next(fs...)
	{
	}
	chain(f_t f, chain<fs_t...> pre):cur_f(f), next(pre)
	{

	}

	template<typename next_f_t>
	auto then(next_f_t next_f)
	{
		return chain<next_f_t, f_t, fs_t...>(next_f, *this);
	}
	template<typename...args_t>
	auto run(args_t...args)
	{
		return cur_f(next.run(args...));
	}
	template<typename...args_t>
	void start(args_t...args)
	{
		std::thread([&]() {run(args...); }).detach();		// 使用一种并行机制运行
	}
};

template<typename f_t>
class chain<f_t>
{
private:
	f_t cur_f;
public:
	chain(f_t f):cur_f(f)
	{}
	template<typename next_f_t>
	auto then(next_f_t next_f)
	{
		return chain<next_f_t, f_t>(next_f, cur_f);
	}
	template<typename...args_t>
	auto run(args_t...args)
	{
		return cur_f(args...);
	}
	template<typename...args_t>
	void start(args_t...args)
	{
		std::thread([&]() {run(args...); }).detach();		// 使用一种并行机制运行
	}
};

template<typename f_t>
chain<f_t> chain_call(f_t f)
{
	return chain<f_t>(f);
}

#include <iostream>
#include <future>
#include <chrono>

int main(int argc, char** argv)
{
	chain_call([](int i) {return i + 1; })
		.then([](int i) { return i * i; })	
		.then([](int i) {return i * (i + 1); })	
		.then([](int i) {std::cout << i << std::endl; })
		.start(1);
	std::this_thread::sleep_for(std::chrono::seconds(3));
	std::cout << "main out" << std::endl;
	return 0;
}

这个程序的原理就是通过chain_call的一元构造函数构造出来一个chain_call<f_t>的对象,然后调用then自动创建出chain_call<f_t,f_t1...>。实际最后调用start的是一个chain_call<f_t,f_t1...>的对象。

在boost中有一个叫signals2的模块,这个模块是设计用于观察者模式的,可以动态地注册槽函数(slot),最后形成一个调用链。signals2的调用链槽函数形式必须是统一的,这样信号对象在调用的时候可以把传入参数作为下面各个槽的参数,槽函数之间是没有直接关系的。而本博客实现的调用链上一个调用的返回结果作为下一个调用的参数,可以形成一个调用链,这样模块化更好一些。但是缺点也很明显,在构造的时候要构造chain_call<f_t>,chain_call<f_t,f_t1>...所有类型的对象,构造的代价比较大。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

腾昵猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

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

抵扣说明:

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

余额充值