Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r52781 - sandbox/boost0x/boost/function
From: sebastian.redl_at_[hidden]
Date: 2009-05-05 19:06:55


Author: cornedbee
Date: 2009-05-05 19:06:54 EDT (Tue, 05 May 2009)
New Revision: 52781
URL: http://svn.boost.org/trac/boost/changeset/52781

Log:
Complete variadic function
Text files modified:
   sandbox/boost0x/boost/function/function_variadic.hpp | 259 ++++++++++++++++++++++++++++++++++++++-
   1 files changed, 251 insertions(+), 8 deletions(-)

Modified: sandbox/boost0x/boost/function/function_variadic.hpp
==============================================================================
--- sandbox/boost0x/boost/function/function_variadic.hpp (original)
+++ sandbox/boost0x/boost/function/function_variadic.hpp 2009-05-05 19:06:54 EDT (Tue, 05 May 2009)
@@ -8,7 +8,12 @@
 
 // For more information, see http://www.boost.org
 
+#ifndef BOOST_FUNCTION_FUNCTION_VARIADIC_HPP
+#define BOOST_FUNCTION_FUNCTION_VARIADIC_HPP
+
 #include <boost/function/detail/prologue.hpp>
+#include <boost/function/function_variadic_invoker.hpp>
+#include <boost/function/function_variadic_vtable.hpp>
 
 namespace boost
 {
@@ -37,11 +42,30 @@
     class function<R (Args...)> : public function_base,
         public detail::function::which_std_function<R, Args...>::type
     {
- typedef function_base base_type;
         typedef function<R (Args...)> self_type;
         struct clear_type {};
 
+ typedef boost::detail::function::basic_vtable<R, Args...>
+ vtable_type;
+
+ vtable_type* get_vtable() const {
+ return reinterpret_cast<vtable_type*>(
+ reinterpret_cast<std::size_t>(vtable) & ~(std::size_t)0x01);
+ }
+
     public:
+ typedef R result_type;
+
+ BOOST_STATIC_CONSTANT(int, args = sizeof...(Args));
+ BOOST_STATIC_CONSTANT(int, arity = sizeof...(Args));
+
+ // add signature for boost::lambda
+ template<typename Args>
+ struct sig
+ {
+ typedef result_type type;
+ };
+ // Note: argN_type typedefs are gone
 
         function() : base_type() {}
 
@@ -52,8 +76,9 @@
                               (is_integral<Functor>::value)>::value),
                            int>::type = 0
                ) :
- base_type(f)
+ function_base()
         {
+ this->assign_to(f);
         }
         template<typename Functor, typename Allocator>
         function(Functor f, Allocator a
@@ -62,19 +87,33 @@
                               (is_integral<Functor>::value)>::value),
                            int>::type = 0
                ) :
- base_type(f,a)
+ function_base()
         {
+ this->assign_to_a(f, a);
         }
 
- function(clear_type*) : base_type() {}
+ function(clear_type*) : function_base() {}
 
         function(const self_type& f)
- : base_type(static_cast<const base_type&>(f))
- {}
+ : function_base()
+ {
+ this->assign_to_own(f);
+ }
+
+ ~function() { clear(); }
 
         self_type& operator=(const self_type& f)
         {
- self_type(f).swap(*this);
+ if (&f == this)
+ return *this;
+
+ this->clear();
+ try {
+ this->assign_to_own(f);
+ } catch (...) {
+ vtable = 0;
+ throw;
+ }
             return *this;
         }
 
@@ -85,7 +124,30 @@
                           self_type&>::type
         operator=(Functor f)
         {
- self_type(f).swap(*this);
+ this->clear();
+ try {
+ this->assign_to(f);
+ } catch (...) {
+ vtable = 0;
+ throw;
+ }
+ return *this;
+ }
+
+ template<typename Functor>
+ typename enable_if_c<
+ (boost::type_traits::ice_not<
+ (is_integral<Functor>::value)>::value),
+ self_type&>::type
+ operator=(Functor f, Allocator a)
+ {
+ this->clear();
+ try {
+ this->assign_to_a(f, a);
+ } catch (...) {
+ vtable = 0;
+ throw;
+ }
             return *this;
         }
 
@@ -94,5 +156,186 @@
             this->clear();
             return *this;
         }
+
+
+ void swap(self_type& other)
+ {
+ if (&other == this)
+ return;
+
+ self_type tmp;
+ tmp.move_assign(*this);
+ this->move_assign(other);
+ other.move_assign(tmp);
+ }
+
+ // Clear out a target, if there is one
+ 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(); }
+
+ result_type operator()(Args... args) const;
+
+ private:
+ void assign_to_own(const self_type& 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<typename Functor>
+ void assign_to(Functor f)
+ {
+ using detail::function::vtable_base;
+
+ typedef typename
+ detail::function::get_function_tag<Functor>::type tag;
+ typedef detail::function::get_invoker<tag> get_invoker;
+ typedef typename
+ get_invoker::template apply<Functor, R, Args...>
+ handler_type;
+
+ typedef typename handler_type::invoker_type invoker_type;
+ typedef typename handler_type::manager_type manager_type;
+
+ // Note: it is extremely important that this initialization use
+ // static initialization. Otherwise, we will have a race
+ // condition here in multi-threaded code. See
+ // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
+ static vtable_type stored_vtable =
+ { { &manager_type::manage }, &invoker_type::invoke };
+
+ if (stored_vtable.assign_to(f, functor)) {
+ std::size_t value = reinterpret_cast<std::size_t>(
+ &stored_vtable.base);
+ if (boost::has_trivial_copy_constructor<Functor>::value &&
+ boost::has_trivial_destructor<Functor>::value &&
+ detail::function::
+ function_allows_small_object_optimization<Functor>::
+ value)
+ value |= (std::size_t)0x01;
+ vtable = reinterpret_cast<detail::function::vtable_base *>(
+ value);
+ } else
+ vtable = 0;
+ }
+
+ template<typename Functor, typename Allocator>
+ void assign_to_a(Functor f, Allocator a)
+ {
+ using detail::function::vtable_base;
+
+ typedef typename
+ detail::function::get_function_tag<Functor>::type tag;
+ typedef detail::function::get_invoker<tag> get_invoker;
+ typedef typename get_invoker::
+ template apply_a<Functor, Allocator, R, Args...>
+ handler_type;
+
+ typedef typename handler_type::invoker_type invoker_type;
+ typedef typename handler_type::manager_type manager_type;
+
+ // Note: it is extremely important that this initialization use
+ // static initialization. Otherwise, we will have a race
+ // condition here in multi-threaded code. See
+ // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
+ static 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<std::size_t>(
+ &stored_vtable.base);
+ if (boost::has_trivial_copy_constructor<Functor>::value &&
+ boost::has_trivial_destructor<Functor>::value &&
+ detail::function::
+ function_allows_small_object_optimization<Functor>::
+ value)
+ value |= (std::size_t)0x01;
+ vtable = reinterpret_cast<detail::function::vtable_base *>(
+ value);
+ } else
+ vtable = 0;
+ }
+
+ // Moves the value from the specified argument to *this. If the
+ // argument has its function object allocated on the heap,
+ // move_assign will pass its buffer to *this, and set the
+ // argument's buffer pointer to NULL.
+ void move_assign(BOOST_FUNCTION_FUNCTION& f)
+ {
+ if (&f == this)
+ return;
+
+#if !defined(BOOST_NO_EXCEPTIONS)
+ try {
+#endif
+ 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();
+ }
+#if !defined(BOOST_NO_EXCEPTIONS)
+ } catch (...) {
+ vtable = 0;
+ throw;
+ }
+#endif
+ }
     };
+
+ template<typename Signature>
+ inline void swap(function<Signature>& f1, function<Signature>& f2)
+ {
+ f1.swap(f2);
+ }
+
+ template<typename R, typename... Args>
+ inline R
+ function<R, Args...>::operator()(Args ...args) const
+ {
+ if (this->empty())
+ boost::throw_exception(bad_function_call());
+
+ return get_vtable()->invoker(this->functor, args...);
+ }
+
+ // Poison comparisons between boost::function objects of the same type.
+ template<typename Signature>
+ void operator==(const function<Signature>&, const function<Signature>&);
+ template<typename Signature>
+ void operator!=(const function<Signature>&, const function<Signature>&);
 }
+
+#endif


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk