$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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