C++并发编程之线程异步 std::future知识点总结

1、std::future介绍

类模板 std::future 提供访问异步操作结果的机制:(通过 std::async 、 std::packaged_task 或 std::promise 创建的)异步操作能提供一个 std::future 对象给该异步操作的创建者。然后,异步操作的创建者能用各种方法查询、等待或从 std::future 提取值。若异步操作仍未提供值,则这些方法可能阻塞。异步操作准备好发送结果给创建者时,它能通过修改链接到创建者的 std::future 的共享状态(例如 std::promise::set_value )进行。

注意, std::future 所引用的共享状态不与另一异步返回对象共享(与 std::shared_future 相反)。
—摘抄自https://www.apiref.com/cpp-zh/cpp/thread/future.html

这是官方的定义,那我们就看下具体std::future是怎么回事和怎么使用的吧。

std::future头文件如下:

 #include <future>

std::future作用是希望线程返回一个结果,用于异步的操作。
下面,首先看下std::__basic_future 的定义:

 /// Common implementation for future and shared_future.
  template<typename _Res>
    class __basic_future : public __future_base
    {
    protected:
      typedef shared_ptr<_State_base>		__state_type;
      typedef __future_base::_Result<_Res>&	__result_type;

    private:
      __state_type 		_M_state;

    public:
      // Disable copying.
      __basic_future(const __basic_future&) = delete;
      __basic_future& operator=(const __basic_future&) = delete;

      bool
      valid() const noexcept { return static_cast<bool>(_M_state); }

      void
      wait() const
      {
        _State_base::_S_check(_M_state);
        _M_state->wait();
      }

      template<typename _Rep, typename _Period>
        future_status
        wait_for(const chrono::duration<_Rep, _Period>& __rel) const
        {
          _State_base::_S_check(_M_state);
          return _M_state->wait_for(__rel);
        }

      template<typename _Clock, typename _Duration>
        future_status
        wait_until(const chrono::time_point<_Clock, _Duration>& __abs) const
        {
          _State_base::_S_check(_M_state);
          return _M_state->wait_until(__abs);
        }

    protected:
      /// Wait for the state to be ready and rethrow any stored exception
      __result_type
      _M_get_result() const
      {
        _State_base::_S_check(_M_state);
        _Result_base& __res = _M_state->wait();
        if (!(__res._M_error == 0))
          rethrow_exception(__res._M_error);
        return static_cast<__result_type>(__res);
      }

      void _M_swap(__basic_future& __that) noexcept
      {
        _M_state.swap(__that._M_state);
      }

      // Construction of a future by promise::get_future()
      explicit
      __basic_future(const __state_type& __state) : _M_state(__state)
      {
        _State_base::_S_check(_M_state);
        _M_state->_M_set_retrieved_flag();
      }

      // Copy construction from a shared_future
      explicit
      __basic_future(const shared_future<_Res>&) noexcept;

      // Move construction from a shared_future
      explicit
      __basic_future(shared_future<_Res>&&) noexcept;

      // Move construction from a future
      explicit
      __basic_future(future<_Res>&&) noexcept;

      constexpr __basic_future() noexcept : _M_state() { }

      struct _Reset
      {
        explicit _Reset(__basic_future& __fut) noexcept : _M_fut(__fut) { }
        ~_Reset() { _M_fut._M_state.reset(); }
        __basic_future& _M_fut;
      };
    };

之后就是我们可以看到,std::future是继承std::__basic_future的,具体的定义如下:

 /// Primary template for future.
  template<typename _Res>
    class future : public __basic_future<_Res>
    {
      friend class promise<_Res>;
      template<typename> friend class packaged_task;
      template<typename _Fn, typename... _Args>
        friend future<typename result_of<_Fn(_Args...)>::type>
        async(launch, _Fn&&, _Args&&...);

      typedef __basic_future<_Res> _Base_type;
      typedef typename _Base_type::__state_type __state_type;

      explicit
      future(const __state_type& __state) : _Base_type(__state) { }

    public:
      constexpr future() noexcept : _Base_type() { }

      /// Move constructor
      future(future&& __uf) noexcept : _Base_type(std::move(__uf)) { }

      // Disable copying
      future(const future&) = delete;
      future& operator=(const future&) = delete;

      future& operator=(future&& __fut) noexcept
      {
        future(std::move(__fut))._M_swap(*this);
        return *this;
      }

      /// Retrieving the value
      _Res
      get()
      {
        typename _Base_type::_Reset __reset(*this);
        return std::move(this->_M_get_result()._M_value());
      }

      shared_future<_Res> share();
    };

  /// Partial specialization for future<R&>
  template<typename _Res>
    class future<_Res&> : public __basic_future<_Res&>
    {
      friend class promise<_Res&>;
      template<typename> friend class packaged_task;
      template<typename _Fn, typename... _Args>
        friend future<typename result_of<_Fn(_Args...)>::type>
        async(launch, _Fn&&, _Args&&...);

      typedef __basic_future<_Res&> _Base_type;
      typedef typename _Base_type::__state_type __state_type;

      explicit
      future(const __state_type& __state) : _Base_type(__state) { }

    public:
      constexpr future() noexcept : _Base_type() { }

      /// Move constructor
      future(future&& __uf) noexcept : _Base_type(std::move(__uf)) { }

      // Disable copying
      future(const future&) = delete;
      future& operator=(const future&) = delete;

      future& operator=(future&& __fut) noexcept
      {
        future(std::move(__fut))._M_swap(*this);
        return *this;
      }
      /// Retrieving the value
      _Res&
      get()
      {
        typename _Base_type::_Reset __reset(*this);
        return this->_M_get_result()._M_get();
      }
      shared_future<_Res&> share();
    };
  /// Explicit specialization for future<void>
  template<>
    class future<void> : public __basic_future<void>
    {
      friend class promise<void>;
      template<typename> friend class packaged_task;
      template<typename _Fn, typename... _Args>
        friend future<typename result_of<_Fn(_Args...)>::type>
        async(launch, _Fn&&, _Args&&...);
      typedef __basic_future<void> _Base_type;
      typedef typename _Base_type::__state_type __state_type;
      explicit
      future(const __state_type& __state) : _Base_type(__state) { }
    public:
      constexpr future() noexcept : _Base_type() { }
      /// Move constructor
      future(future&& __uf) noexcept : _Base_type(std::move(__uf)) { }
      // Disable copying
      future(const future&) = delete;
      future& operator=(const future&) = delete;

      future& operator=(future&& __fut) noexcept
      {
        future(std::move(__fut))._M_swap(*this);
        return *this;
      }
      /// Retrieving the value
      void
      get()
      {
        typename _Base_type::_Reset __reset(*this);
        this->_M_get_result();
      }
      shared_future<void> share();
    };

在C11中,std::future有两种类型的模板。
1、唯一期望值unique futures, std::future<> std::future的实例只能关联一个事件。
2、共享期望值shared futures, std::shared_future<> std::shared_future可以关联多个事件。

异步执行的三种状态如下:

  /// Status code for futures
  enum class future_status
  {
    ready,//异步操作已经完成
    timeout,//异步操作超时
    deferred//异步操作还没有开始
  };

这是基本的std::future的定义,下面我们需要看下std::async的定义。
std::async用于启动一个异步执行策略

/// async
  template<typename _Fn, typename... _Args>
    future<typename result_of<_Fn(_Args...)>::type>
    async(launch __policy, _Fn&& __fn, _Args&&... __args)
    {
      typedef typename result_of<_Fn(_Args...)>::type result_type;
      std::shared_ptr<__future_base::_State_base> __state;
      if ((__policy & (launch::async|launch::deferred)) == launch::async)
	{
	  __state = __future_base::_S_make_async_state(std::__bind_simple(
              std::forward<_Fn>(__fn), std::forward<_Args>(__args)...));
	}
      else
	{
	  __state = __future_base::_S_make_deferred_state(std::__bind_simple(
              std::forward<_Fn>(__fn), std::forward<_Args>(__args)...));
	}
      return future<result_type>(__state);
    }

  /// async, potential overload
  template<typename _Fn, typename... _Args>
    inline future<typename result_of<_Fn(_Args...)>::type>
    async(_Fn&& __fn, _Args&&... __args)
    {
      return async(launch::async|launch::deferred, std::forward<_Fn>(__fn),
		   std::forward<_Args>(__args)...);
    }
  /// Launch code for futures
  enum class launch
  {
    async = 1, //保证异步行为,即传递函数在单独的线程中执行。
    deferred = 2 //当其他线程调用get()/waite()访问共享状态时,调用非异步的行为。
  };

2、std::future重要成员函数介绍

operator= 移动future对象

share 将*this转移共享状态给shared_future并返回它

get获取返回结果
状态
valid() 检查future是否拥有共享状态
wait() 等待执行结果变成可以获得
wait_for() 等待结果,如果在超过指定时间间隔后仍然无法得到结果,则立即返回

3、std::future用法示例

/*************************************************************************
	> File Name: thread_future.cpp
	> Author: 小和尚敲木鱼
	> Mail:  
	> Created Time: Tue 21 Sep 2021 02:13:25 AM PDT
 ************************************************************************/

#include <iostream>
#include <thread>
#include <string>
#include <vector>
#include <mutex>
#include <future>
#include <chrono>

using namespace std;
/*****************************文件说明***********************************
************************************************************************/
class Base
{
public:
	int baseThread1(int param)
	{
		int value = 5;
		std::cout <<__func__ <<"Reiver param" << param << std::endl;
		std::cout << __func__ <<"Current Thread ID = "<< std::this_thread::get_id() << std::endl;
		std::chrono::milliseconds  sleep_time(500);
		std::this_thread::sleep_for(sleep_time);
		std::cout << "Current Thread ID ="<< std::this_thread::get_id() << std::endl;
		std::cout << "Return = " << (value + param) << std::endl;
		return (value + param);
	}
	int baseThread2()
	{
		int value = 5;
		std::cout <<__func__ <<"Reiver param"<< std::endl;
		std::cout << __func__ <<"Current Thread ID = "<< std::this_thread::get_id() << std::endl;
		std::chrono::milliseconds  sleep_time(500);
		std::this_thread::sleep_for(sleep_time);
		std::cout << "Current Thread ID ="<< std::this_thread::get_id() << std::endl;
		std::cout << "Return = " << value<< std::endl;
		return (value);
	}
};

int main(int agc,char * agv[])
{
	int temp = 20;
	Base base_test;
	std::cout << "Main Thread ID = " << std::this_thread::get_id() << std::endl;
	std::future<int> result = std::async(std::launch::async, &Base::baseThread1, &base_test, temp); 

	std::cout << "Continue...." << std::endl;
	result.wait();
	//阻塞在这里,知道result能够获得并得到最后的结果。
	//当共享状态值是不可以用时,调用wait接口可以一直阻塞,直到共享状态变为"就绪"时,就变为可以用了。
	std::cout << "Final result = " << result.get() << std::endl;
	return 0;
}
//OUT
//Main Thread ID = 140522049050432
//Continue....
//baseThread1Reiver param20
//baseThread1Current Thread ID = 140522031671040
//Current Thread ID =140522031671040
//Return = 25 
//Final result = 25

std::futere查询状态

//查询future的状态
std::future_status status;
do {
    status = future.wait_for(std::chrono::seconds(1));
    switch(status)
    {
	    case std::future_status::deferred:
	    	std::cout << "std::future_status::deferred" <<std::endl;
	    break;
	    case std::future_status::timeout:
	    	std::cout << "std::future_status::timeout" <<std::endl;
	    break;
	    case std::future_status::ready:
	    	std::cout << "std::future_status::ready" <<std::endl;
	    break;
	    default:
	    	std::cout << "none status" << std::endl;
	    break;
    }
} while (status != std::future_status::ready);

4、总结

一般来说std::future都是配合std::async、std::packaged_task和std::promise一起使用。返回其异步执行的结果。使用起来也是非常的银杏。
Todo:
后续补充std::future::wait_for的示例。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
C++11 标准提供了一些并发编程的指南,帮助程序员处理并发编程中的常见问题。这些指南可以帮助开发者实现高效、可靠的多线程应用。 首先,C++11 引入了 std::thread 类,它是一种线程的表示方式,可以方便地创建和管理线程。通过 std::thread,我们可以启动一个新线程并指定要执行的函数或函数对象。此外,std::thread 还提供了一系列的成员函数,如 join() 和 detach(),用于等待线程结束或分离线程。 其次,C++11 还引入了 std::mutex 和 std::lock_guard 类,用于解决多线程下的竞争条件问题。std::mutex 是一种互斥量,可以通过调用 lock() 和 unlock() 来控制对共享资源的访问。std::lock_guard 是一种锁保护类型,它的构造函数会自动在当前作用域上锁,析构函数会自动解锁,确保锁的正确使用。 此外,C++11 提供了 std::condition_variable 类,用于实现多线程间的条件变量通信。std::condition_variable 允许线程等待某个条件的发生,并在条件满足时由其他线程进行通知。 还有一个重要的概念是原子操作,C++11 提供了 std::atomic 类模板来实现无锁编程。通过 std::atomic,我们可以对共享变量进行原子操作,避免了需要锁保护的临界区域。 最后,C++11 还引入了 std::future 类模板和 std::promise 类模板,用于实现异步计算和线程间的数据传递。std::future 可以保存一个异步操作(如函数调用)的结果,而 std::promise 则可以在某个时间点设置这个结果。 综上所述,C++11 并发指南中的一些关键特性包括 std::thread、std::mutex、std::lock_guard、std::condition_variable、std::atomic、std::futurestd::promise。它们为我们提供了一些基本工具和机制,帮助我们更加方便地编写多线程应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

给大佬递杯卡布奇诺

你们的鼓励就是我传作的动力!

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

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

打赏作者

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

抵扣说明:

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

余额充值