function 源码分析2--boost function的源码分析

首先我假定大家已熟悉function的接口,我不打算把boost的源码完全分析,只分析部分。我的boost版本是1_57_0。

我们要能够存储函数指针,成员函数指针,仿函数,函数指针直接存储函数指针原始值,成员函数指针存储为仿函数,仿函数直接new一个拷贝即可。function_buffer解决存储问题,定义为union为了节省内存,都老生常谈了。boost比我实现的缩水版本要多了很多类型,成员函数指针我一开始以为会存储在function_buffer中,事实上我多心了,function直接把成员函数封装为仿函数,再调用仿函数存储,但是调用成员函数的时候,是使用了bound_memfunc_ptr的。这里要说的是,缩水版的function并没有考虑小对象(所谓的小对象是指仿函数在内存中的size比function_buffer小)的内存优化问题,如果new一个新的对象,频繁new小对象并不是好的选择,这时候直接在function_buffer上定位new。

class X;
union function_buffer
{
	// 仿函数的指针
	mutable void* obj_ptr;

	// 指向std::type_info的指针
	struct type_t {
		// (get_functor_type_tag, check_functor_type_tag).
		const detail::sp_typeinfo* type;

		// Whether the type is const-qualified.
		bool const_qualified;
		// Whether the type is volatile-qualified.
		bool volatile_qualified;
	} type;

	// 函数指针
	mutable void(*func_ptr)();

	// 成员函数指针
	struct bound_memfunc_ptr_t {
		void (X::*memfunc_ptr)(int);
		void* obj_ptr;
	} bound_memfunc_ptr;

	// 仿函数引用类型
	struct obj_ref_t {
		mutable void* obj_ptr;
		bool is_const_qualified;
		bool is_volatile_qualified;
	} obj_ref;

	// 小对象内存优化时使用
	mutable char data;
};

接着看vtable_base类型,这个是操作function_buffer的,可以克隆、移动、销毁、检查类型、获取类型。

// The operation type to perform on the given functor/function pointer
enum functor_manager_operation_type {
	clone_functor_tag,
	move_functor_tag,
	destroy_functor_tag,
	check_functor_type_tag,
	get_functor_type_tag
};
/**
* Stores the "manager" portion of the vtable for a
* boost::function object.
*/
struct vtable_base
{
	void(*manager)(const function_buffer& in_buffer,
		function_buffer& out_buffer,
		functor_manager_operation_type op);
};

首先是仿函数引用类型,肯定是操作function_buffer的obj_ref

   template
      struct reference_manager
      {
        static inline void
        manage(const function_buffer& in_buffer, function_buffer& out_buffer, 
               functor_manager_operation_type op)
        {
          switch (op) {
          case clone_functor_tag: 
            out_buffer.obj_ref = in_buffer.obj_ref;
            return;

          case move_functor_tag:
            out_buffer.obj_ref = in_buffer.obj_ref;
            in_buffer.obj_ref.obj_ptr = 0;
            return;

          case destroy_functor_tag:
            out_buffer.obj_ref.obj_ptr = 0;
            return;

          case check_functor_type_tag:
            {
              const detail::sp_typeinfo& check_type 
                = *out_buffer.type.type;

              // Check whether we have the same type. We can add
              // cv-qualifiers, but we can't take them away.
              if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(F))
                  && (!in_buffer.obj_ref.is_const_qualified 
                      || out_buffer.type.const_qualified)
                  && (!in_buffer.obj_ref.is_volatile_qualified
                      || out_buffer.type.volatile_qualified))
                out_buffer.obj_ptr = in_buffer.obj_ref.obj_ptr;
              else
                out_buffer.obj_ptr = 0;
            }
            return;

          case get_functor_type_tag:
            out_buffer.type.type = &BOOST_SP_TYPEID(F);
            out_buffer.type.const_qualified = in_buffer.obj_ref.is_const_qualified;
            out_buffer.type.volatile_qualified = in_buffer.obj_ref.is_volatile_qualified;
            return;
          }
        }
      };
接着是函数指针,主要对func_ptr操作

     template
      struct functor_manager_common
      {
        typedef Functor functor_type;

        // Function pointers
        static inline void
        manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer, 
                functor_manager_operation_type op)
        {
          if (op == clone_functor_tag)
            out_buffer.func_ptr = in_buffer.func_ptr;
          else if (op == move_functor_tag) {
            out_buffer.func_ptr = in_buffer.func_ptr;
            in_buffer.func_ptr = 0;
          } else if (op == destroy_functor_tag)
            out_buffer.func_ptr = 0;
          else if (op == check_functor_type_tag) {
            const detail::sp_typeinfo& check_type 
              = *out_buffer.type.type;
            if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor)))
              out_buffer.obj_ptr = &in_buffer.func_ptr;
            else
              out_buffer.obj_ptr = 0;
          } else /* op == get_functor_type_tag */ {
            out_buffer.type.type = &BOOST_SP_TYPEID(Functor);
            out_buffer.type.const_qualified = false;
            out_buffer.type.volatile_qualified = false;
          }
        }
小对象的仿函数,由于使用定位new,所以需要手动调用析构函数。

       // Function objects that fit in the small-object buffer.
        static inline void
        manage_small(const function_buffer& in_buffer, function_buffer& out_buffer, 
                functor_manager_operation_type op)
        {
          if (op == clone_functor_tag || op == move_functor_tag) {
            const functor_type* in_functor = 
              reinterpret_cast(&in_buffer.data);
            new (reinterpret_cast(&out_buffer.data)) functor_type(*in_functor);

            if (op == move_functor_tag) {
              functor_type* f = reinterpret_cast(&in_buffer.data);
              (void)f; // suppress warning about the value of f not being used (MSVC)
              f->~Functor();
            }
          } else if (op == destroy_functor_tag) {
            // Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
             functor_type* f = reinterpret_cast(&out_buffer.data);
             (void)f; // suppress warning about the value of f not being used (MSVC)
             f->~Functor();
          } else if (op == check_functor_type_tag) {
            const detail::sp_typeinfo& check_type 
              = *out_buffer.type.type;
            if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor)))
              out_buffer.obj_ptr = &in_buffer.data;
            else
              out_buffer.obj_ptr = 0;
          } else /* op == get_functor_type_tag */ {
            out_buffer.type.type = &BOOST_SP_TYPEID(Functor);
            out_buffer.type.const_qualified = false;
            out_buffer.type.volatile_qualified = false;            
          }
        }
仿函数,需要从堆上分配内存的,

        static inline void
        manager(const function_buffer& in_buffer, function_buffer& out_buffer, 
                functor_manager_operation_type op, mpl::false_)
        {
          if (op == clone_functor_tag) {
            // Clone the functor
            // GCC 2.95.3 gets the CV qualifiers wrong here, so we
            // can't do the static_cast that we should do.
            // jewillco: Changing this to static_cast because GCC 2.95.3 is
            // obsolete.
            const functor_type* f =
              static_cast(in_buffer.obj_ptr);
            functor_type* new_f = new functor_type(*f);
            out_buffer.obj_ptr = new_f;
          } else if (op == move_functor_tag) {
            out_buffer.obj_ptr = in_buffer.obj_ptr;
            in_buffer.obj_ptr = 0;
          } else if (op == destroy_functor_tag) {
            /* Cast from the void pointer to the functor pointer type */
            functor_type* f =
              static_cast(out_buffer.obj_ptr);
            delete f;
            out_buffer.obj_ptr = 0;
          } else if (op == check_functor_type_tag) {
            const detail::sp_typeinfo& check_type
              = *out_buffer.type.type;
            if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor)))
              out_buffer.obj_ptr = in_buffer.obj_ptr;
            else
              out_buffer.obj_ptr = 0;
          } else /* op == get_functor_type_tag */ {
            out_buffer.type.type = &BOOST_SP_TYPEID(Functor);
            out_buffer.type.const_qualified = false;
            out_buffer.type.volatile_qualified = false;
          }
        }
可能比较奇怪的是多了个参数mpl::false_,这个参数是通过下面的函数来判断的。

      template
      struct function_allows_small_object_optimization
      {
        BOOST_STATIC_CONSTANT
          (bool, 
           value = ((sizeof(F) <= sizeof(function_buffer) &&
                     (alignment_of::value 
                      % alignment_of::value == 0))));
      };
并没有成员函数的manage版本,是因为成员函数会转化为仿函数。

然后是所有function的基类,主要是负责存储。这里比较奇怪的是使用vtable的最后一个bit是否是1来作为trivial的判断(就是小对象),如果是我自己编写,我会使用bool变量来标明,我一开始有疑问,当vtable_base指针的最后一个bit是1岂不是全部出错,调试发现该指针的内存地址的最后一个bit始终为0,这个可能与编译器的对齐方式有关,因为vtable_base的指针是一个函数的static变量。

class function_base
{
public:
	function_base() : vtable(0) { }
	//...
	detail::function::vtable_base* get_vtable() const {
		return reinterpret_cast(
			reinterpret_cast(vtable) & ~static_cast(0x01));
	}

	bool has_trivial_copy_and_destroy() const {
		return reinterpret_cast(vtable) & 0x01;
	}
public:
	vtable_base* vtable;
	mutable function_buffer functor;
};

接下来是get_function_tag,用来萃取函数类型,是函数指针,成员函数指针,或者仿函数。

struct function_ptr_tag {};
struct function_obj_tag {};
struct member_ptr_tag {};
struct function_obj_ref_tag {};

template
class get_function_tag
{
	typedef typename mpl::if_c<(is_pointer::value),
		function_ptr_tag,
		function_obj_tag>::type ptr_or_obj_tag;

	typedef typename mpl::if_c<(is_member_pointer::value),
		member_ptr_tag,
		ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;

	typedef typename mpl::if_c<(is_reference_wrapper::value),
		function_obj_ref_tag,
		ptr_or_obj_or_mem_tag>::type or_ref_tag;

public:
	typedef or_ref_tag type;
};

if_c是mpl函数(博客不对任何mpl展开分析),用伪代码表示如下,其他mpl函数如函数名,value值是true或者false,大家自行把各个情况放入上面验证,至于mpl可以自行搜索,c++reference上也给出了可能实现。

if_c::type = int
if_c::type = double

function_base至此所有的代码已经完毕,基本上是完成了对function_buffer的操作,主要是实现function的拷贝、移动、类型比较等。不管function是什么类型,这部分操作是共用的,定义一个基类的确很有必要。

接下来以一元function为例,分析代码。

basic_vtable1

template
struct basic_vtable1
{
	typedef R result_type;
	typedef result_type(*invoker_type)(function_buffer&,T0);
	template
	//将f存储入function_buffer
	bool assign_to(F f, function_buffer& functor) const
	{
		typedef typename get_function_tag::type tag;//萃取类型
		return assign_to(f, functor, tag());//根据不同的类型,调用不同的重载函数,Policies design
	}
	void clear(function_buffer& functor) const
	{
		if (base.manager)//调用destroy
			base.manager(functor, functor, destroy_functor_tag);
	}
private:
	template
	bool assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) const
	{
		// 函数指针,直接赋值
		this->clear(functor);
		if (f) {
			functor.func_ptr = reinterpret_cast(f);
			return true;
		}
		else {
			return false;
		}
	}

	template
	bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag) const
	{
		//成员函数指针,先使用mem_fn返回仿函数,再调用前面的接口来存储
		if (f) {
			this->assign_to(boost::mem_fn(f), functor);
			return true;
		}
		else {
			return false;
		}
	}
	template
	bool assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) const
	{
		if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
			//仿函数对象,根据仿函数对象的size,决定是否需要重新分配内存,如果仿函数内存不比function_buffer大,那么可以不用分配新的内存
			assign_functor(f, functor,mpl::bool_<(function_allows_small_object_optimization::value)>());
			return true;
		}
		else {
			return false;
		}
	}

	template
	void assign_functor(FunctionObj f, function_buffer& functor, mpl::true_) const
	{
		new (reinterpret_cast(&functor.data)) FunctionObj(f);//定位new
	}

	template
	void assign_functor(FunctionObj f, function_buffer& functor, mpl::false_) const
	{
		functor.obj_ptr = new FunctionObj(f);//copy
	}

	template
	bool assign_to(const reference_wrapper& f,
			function_buffer& functor, function_obj_ref_tag) const
	{
		//函数对象引用
		functor.obj_ref.obj_ptr = (void *)(f.get_pointer());
		functor.obj_ref.is_const_qualified = is_const::value;
		functor.obj_ref.is_volatile_qualified = is_volatile::value;
		return true;
	}
public:
	vtable_base base;
	invoker_type invoker;//调用的函数指针
};

有了basic_vtable1,仿函数的存储和调用都齐全了。当然还差invoke的具体:

template
struct function_invoker1
{
	static R invoke(function_buffer& function_ptr,T0 a0)
	{
		FunctionPtr f = reinterpret_cast(function_ptr.func_ptr);
		return f(a0);//函数指针直接转换类型后调用
	}
};

template
struct function_obj_invoker1
{
	static R invoke(function_buffer& function_obj_ptr,T0 a0)
	{
		FunctionObj* f;
		if (function_allows_small_object_optimization::value)
			f = reinterpret_cast(&function_obj_ptr.data);
		else
			f = reinterpret_cast(function_obj_ptr.obj_ptr);
		return (*f)(a0);//仿函数分两种情况,一种小对象转换data,否则转换obj_ptr
	}
};

template
struct function_ref_invoker1
{
	static R invoke(function_buffer& function_obj_ptr,T0 a0)
	{
		FunctionObj* f =reinterpret_cast(function_obj_ptr.obj_ptr);
		return (*f)(a0);//仿函数引用
	}
};
//成员函数的调用很奇葩,前面manage的时候是使用定位new,原本我以为这里应该再调用仿函数来调用
//这里直接将data转换为MemberPtr,这是假定成员函数的仿函数的第一个成员变量就是MemberPtr
template
struct function_mem_invoker1
{
	static R invoke(function_buffer& function_obj_ptr,T0 a0)
	{
		MemberPtr* f =reinterpret_cast(&function_obj_ptr.data);
		return boost::mem_fn(*f)(a0);
	}
};

mem_fn将返回仿函数mf1

template
_mfi::mf1 mem_fn(R(T::*f) (A1))
{
	return _mfi::mf1(f);
}
mf1肯定是个仿函数,如下,只有一个成员变量f_(成员函数指针类型)。

template class mf1
{
public:

	typedef R result_type;
	typedef T * first_argument_type;
	typedef A1 second_argument_type;
private:

	typedef R(T::*F) (A1);
	F f_;

	template R call(U & u, T const *, B1 & b1) const
	{
		return (u.*f_)(b1);
	}

	template R call(U & u, void const *, B1 & b1) const
	{
		return (get_pointer(u)->*f_)(b1);
	}

public:

	explicit mf1(F f) : f_(f) {}

	R operator()(T * p, A1 a1) const
	{
		return (p->*f_)(a1);//R(T*,A1)最终使用成员函数指针来调用
	}

	template R operator()(U & u, A1 a1) const
	{
		U const * p = 0;
		return call(u, p, a1);
	}

	template R operator()(U const & u, A1 a1) const
	{
		U const * p = 0;
		return call(u, p, a1);
	}

	R operator()(T & t, A1 a1) const
	{
		return (t.*f_)(a1);//R(T&,A1)
	}

	bool operator==(mf1 const & rhs) const
	{
		return f_ == rhs.f_;
	}

	bool operator!=(mf1 const & rhs) const
	{
		return f_ != rhs.f_;
	}
};

接下来是function1,代码太多,先分为几部分,最后上所有代码,先分析构造

function1() : function_base() { }

	template
	function1(Functor  f, typename enable_if_c<
		(boost::type_traits::ice_not<
		(is_integral::value)>::value),
		int>::type = 0
	) :
		function_base()
	{
		this->assign_to(f);
	}
	template
	function1(Functor  f, Allocator a
		, typename enable_if_c<
		(boost::type_traits::ice_not<
		(is_integral::value)>::value),
		int>::type = 0
	) :
		function_base()
	{
		this->assign_to_a(f, a);
	}


	function1(clear_type*) : function_base() { }

	function1(const function1& f) : function_base()
	{
		this->assign_to_own(f);
	}


	function1(function1&& f) : function_base()
	{
		this->move_assign(f);
	}
各种assign_to

	void assign_to_own(const function1& f)
	{
		if (!f.empty()) {
			this->vtable = f.vtable;
			if (this->has_trivial_copy_and_destroy())
				this->functor = f.functor;
			else
				get_vtable()->base.manager(f.functor, this->functor,
					boost::detail::function::clone_functor_tag);
		}
	}

	template
	void assign_to(Functor f)
	{
		using detail::function::vtable_base;

		typedef typename detail::function::get_function_tag::type tag;
		typedef detail::function::get_invoker1 get_invoker;
		typedef typename get_invoker::
			template apply
			handler_type;

		typedef typename handler_type::invoker_type invoker_type;
		typedef typename handler_type::manager_type manager_type;





		static const vtable_type stored_vtable =
		{ { &manager_type::manage }, &invoker_type::invoke };

		if (stored_vtable.assign_to(f, functor)) {
			std::size_t value = reinterpret_cast(&stored_vtable.base);

			if (boost::has_trivial_copy_constructor::value &&
				boost::has_trivial_destructor::value &&
				detail::function::function_allows_small_object_optimization::value)
				value |= static_cast(0x01);
			vtable = reinterpret_cast(value);
		}
		else
			vtable = 0;
	}

	template
	void assign_to_a(Functor f, Allocator a)
	{
		using detail::function::vtable_base;

		typedef typename detail::function::get_function_tag::type tag;
		typedef detail::function::get_invoker1 get_invoker;
		typedef typename get_invoker::
			template apply_a
			handler_type;

		typedef typename handler_type::invoker_type invoker_type;
		typedef typename handler_type::manager_type manager_type;





		static const vtable_type stored_vtable =
		{ { &manager_type::manage }, &invoker_type::invoke };

		if (stored_vtable.assign_to_a(f, functor, a)) {
			std::size_t value = reinterpret_cast(&stored_vtable.base);

			if (boost::has_trivial_copy_constructor::value &&
				boost::has_trivial_destructor::value &&
				detail::function::function_allows_small_object_optimization::value)
				value |= static_cast(0x01);
			vtable = reinterpret_cast(value);
		}
		else
			vtable = 0;
	}




	void move_assign(function1& f)
	{
		if (&f == this)
			return;

		{ try {
			if (!f.empty()) {
				this->vtable = f.vtable;
				if (this->has_trivial_copy_and_destroy())
					this->functor = f.functor;
				else
					get_vtable()->base.manager(f.functor, this->functor,
						boost::detail::function::move_functor_tag);
				f.vtable = 0;
			}
			else {
				clear();
			}
		}
		catch (...) {
			vtable = 0;
			throw;;
		}
		}
	}
operator=

	function1& operator=(clear_type*)
	{
		this->clear();
		return *this;
	}

	function1& operator=(const function1& f)
	{
		if (&f == this)
			return *this;

		this->clear();
		{ try {
			this->assign_to_own(f);
		}
		catch (...) {
			vtable = 0;
			throw;;
		}
		}
		return *this;
	}


	function1& operator=(function1&& f)
	{

		if (&f == this)
			return *this;

		this->clear();
		{ try {
			this->move_assign(f);
		}
		catch (...) {
			vtable = 0;
			throw;;
		}
		}
		return *this;
	}
所谓的safe bool 惯用法,在C++11下只需要explicit operator bool即可。

private:
	struct dummy {
		void nonnull() {}
	};

	typedef void (dummy::*safe_bool)();

public:
	operator safe_bool () const
	{
		return (this->empty()) ? 0 : &dummy::nonnull;
	}

	bool operator!() const
	{
		return this->empty();
	}

当然,还得重载operator()

	result_type operator()(T0 a0) const
	{
		if (this->empty())
			boost::throw_exception(bad_function_call());

		return get_vtable()->invoker
		(this->functor, a0);
	}

写到这,function1具备了function的所有特征,function再写就多余了,事实上funcation1多余,

template
	class function
	: public function1
{
	typedef function1 base_type;
	typedef function self_type;

	struct clear_type {};

public:

	function() : base_type() {}

	template
	function(Functor f

		, typename enable_if_c<
		(boost::type_traits::ice_not<
		(is_integral::value)>::value),
		int>::type = 0
	) :
		base_type(f)
	{
	}
	template
	function(Functor f, Allocator a

		, typename enable_if_c<
		(boost::type_traits::ice_not<
		(is_integral::value)>::value),
		int>::type = 0
	) :
		base_type(f, a)
	{
	}

	function(clear_type*) : base_type() {}

	function(const self_type& f) : base_type(static_cast(f)) {}

	function(const base_type& f) : base_type(static_cast(f)) {}



	function(self_type&& f) : base_type(static_cast(f)) {}
	function(base_type&& f) : base_type(static_cast(f)) {}

	self_type& operator=(const self_type& f)
	{
		self_type(f).swap(*this);
		return *this;
	}


	self_type& operator=(self_type&& f)
	{
		self_type(static_cast(f)).swap(*this);
		return *this;
	}

	template

	typename enable_if_c<
		(boost::type_traits::ice_not<
		(is_integral::value)>::value),
		self_type&>::type
		operator=(Functor f)
	{
		self_type(f).swap(*this);
		return *this;
	}


	self_type& operator=(clear_type*)
	{
		this->clear();
		return *this;
	}

	self_type& operator=(const base_type& f)
	{
		self_type(f).swap(*this);
		return *this;
	}


	self_type& operator=(base_type&& f)
	{
		self_type(static_cast(f)).swap(*this);
		return *this;
	}
};
上述代码基本就是重新写了构造函数和operator=。

文末,附上function1的所有源码

template
class function1 : public function_base, public std::unary_function
{
public:
	typedef R         result_type;
private:
	typedef boost::detail::function::basic_vtable1 vtable_type;

	vtable_type* get_vtable() const {
		return reinterpret_cast(
			reinterpret_cast(vtable) & ~static_cast(0x01));
	}

	struct clear_type {};
public:
	static const int args = 1;


	template
	struct sig
	{
		typedef result_type type;
	};


	typedef T0 argument_type;

	static const int arity = 1;
	typedef T0 arg1_type;

	typedef function1 self_type;

	function1() : function_base() { }



	template
	function1(Functor  f, typename enable_if_c<
		(boost::type_traits::ice_not<
		(is_integral::value)>::value),
		int>::type = 0
	) :
		function_base()
	{
		this->assign_to(f);
	}
	template
	function1(Functor  f, Allocator a
		, typename enable_if_c<
		(boost::type_traits::ice_not<
		(is_integral::value)>::value),
		int>::type = 0
	) :
		function_base()
	{
		this->assign_to_a(f, a);
	}


	function1(clear_type*) : function_base() { }

	function1(const function1& f) : function_base()
	{
		this->assign_to_own(f);
	}


	function1(function1&& f) : function_base()
	{
		this->move_assign(f);
	}

	~function1() { clear(); }

	result_type operator()(T0 a0) const
	{
		if (this->empty())
			boost::throw_exception(bad_function_call());

		return get_vtable()->invoker
		(this->functor, a0);
	}

	template

	typename enable_if_c<
		(boost::type_traits::ice_not<
		(is_integral::value)>::value),
		function1&>::type
		operator=(Functor  f)
	{
		this->clear();
		{ try {
			this->assign_to(f);
		}
		catch (...) {
			vtable = 0;
			throw;;
		}
		}
		return *this;
	}
	template
	void assign(Functor  f, Allocator a)
	{
		this->clear();
		{ try {
			this->assign_to_a(f, a);
		}
		catch (...) {
			vtable = 0;
			throw;;
		}
		}
	}


	function1& operator=(clear_type*)
	{
		this->clear();
		return *this;
	}

	function1& operator=(const function1& f)
	{
		if (&f == this)
			return *this;

		this->clear();
		{ try {
			this->assign_to_own(f);
		}
		catch (...) {
			vtable = 0;
			throw;;
		}
		}
		return *this;
	}


	function1& operator=(function1&& f)
	{

		if (&f == this)
			return *this;

		this->clear();
		{ try {
			this->move_assign(f);
		}
		catch (...) {
			vtable = 0;
			throw;;
		}
		}
		return *this;
	}

	void swap(function1& other)
	{
		if (&other == this)
			return;

		function1 tmp;
		tmp.move_assign(*this);
		this->move_assign(other);
		other.move_assign(tmp);
	}


	void clear()
	{
		if (vtable) {
			if (!this->has_trivial_copy_and_destroy())
				get_vtable()->clear(this->functor);
			vtable = 0;
		}
	}

private:
	struct dummy {
		void nonnull() {}
	};

	typedef void (dummy::*safe_bool)();

public:
	operator safe_bool () const
	{
		return (this->empty()) ? 0 : &dummy::nonnull;
	}

	bool operator!() const
	{
		return this->empty();
	}
private:
	void assign_to_own(const function1& f)
	{
		if (!f.empty()) {
			this->vtable = f.vtable;
			if (this->has_trivial_copy_and_destroy())
				this->functor = f.functor;
			else
				get_vtable()->base.manager(f.functor, this->functor,
					boost::detail::function::clone_functor_tag);
		}
	}

	template
	void assign_to(Functor f)
	{
		using detail::function::vtable_base;

		typedef typename detail::function::get_function_tag::type tag;
		typedef detail::function::get_invoker1 get_invoker;
		typedef typename get_invoker::
			template apply
			handler_type;

		typedef typename handler_type::invoker_type invoker_type;
		typedef typename handler_type::manager_type manager_type;





		static const vtable_type stored_vtable =
		{ { &manager_type::manage }, &invoker_type::invoke };

		if (stored_vtable.assign_to(f, functor)) {
			std::size_t value = reinterpret_cast(&stored_vtable.base);

			if (boost::has_trivial_copy_constructor::value &&
				boost::has_trivial_destructor::value &&
				detail::function::function_allows_small_object_optimization::value)
				value |= static_cast(0x01);
			vtable = reinterpret_cast(value);
		}
		else
			vtable = 0;
	}

	template
	void assign_to_a(Functor f, Allocator a)
	{
		using detail::function::vtable_base;

		typedef typename detail::function::get_function_tag::type tag;
		typedef detail::function::get_invoker1 get_invoker;
		typedef typename get_invoker::
			template apply_a
			handler_type;

		typedef typename handler_type::invoker_type invoker_type;
		typedef typename handler_type::manager_type manager_type;





		static const vtable_type stored_vtable =
		{ { &manager_type::manage }, &invoker_type::invoke };

		if (stored_vtable.assign_to_a(f, functor, a)) {
			std::size_t value = reinterpret_cast(&stored_vtable.base);

			if (boost::has_trivial_copy_constructor::value &&
				boost::has_trivial_destructor::value &&
				detail::function::function_allows_small_object_optimization::value)
				value |= static_cast(0x01);
			vtable = reinterpret_cast(value);
		}
		else
			vtable = 0;
	}




	void move_assign(function1& f)
	{
		if (&f == this)
			return;

		{ try {
			if (!f.empty()) {
				this->vtable = f.vtable;
				if (this->has_trivial_copy_and_destroy())
					this->functor = f.functor;
				else
					get_vtable()->base.manager(f.functor, this->functor,
						boost::detail::function::move_functor_tag);
				f.vtable = 0;
			}
			else {
				clear();
			}
		}
		catch (...) {
			vtable = 0;
			throw;;
		}
		}
	}
};















你可能感兴趣的:(function源码分析)