/home/users/khuck/src/hpx-lsu/hpx/util/detail/basic_function.hpp

Line% of fetchesSource
1  
//  Copyright (c) 2011 Thomas Heller
2  
//  Copyright (c) 2013 Hartmut Kaiser
3  
//  Copyright (c) 2014 Agustin Berge
4  
//
5  
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
6  
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7  
8  
#ifndef HPX_UTIL_DETAIL_BASIC_FUNCTION_HPP
9  
#define HPX_UTIL_DETAIL_BASIC_FUNCTION_HPP
10  
11  
#include <hpx/config.hpp>
12  
#include <hpx/runtime/serialization/serialization_fwd.hpp>
13  
#include <hpx/traits/get_function_address.hpp>
14  
#include <hpx/traits/is_callable.hpp>
15  
#include <hpx/util/detail/empty_function.hpp>
16  
#include <hpx/util/detail/vtable/serializable_function_vtable.hpp>
17  
#include <hpx/util/detail/vtable/serializable_vtable.hpp>
18  
#include <hpx/util/detail/vtable/vtable.hpp>
19  
20  
#include <cstddef>
21  
#include <cstring>
22  
#include <string>
23  
#include <type_traits>
24  
#include <typeinfo>
25  
#include <utility>
26  
27  
namespace hpx { namespace util { namespace detail
28  
{
29  
    ///////////////////////////////////////////////////////////////////////////
30  
    template <typename F>
31  
    static bool is_empty_function(F const&, std::false_type) HPX_NOEXCEPT
32  
    {
33  
        return false;
34  
    }
35  
36  
    template <typename F>
37  
    static bool is_empty_function(F const& f, std::true_type) HPX_NOEXCEPT
38  
    {
39  
        return f == nullptr;
40  
    }
41  
42  
    template <typename F>
43  
    static bool is_empty_function(F const& f) HPX_NOEXCEPT
44  
    {
45  
        std::integral_constant<bool,
46  
            std::is_pointer<F>::value
47  
         || std::is_member_pointer<F>::value
48  
        > is_pointer;
49  
        return is_empty_function(f, is_pointer);
50  
    }
51  
52  
    ///////////////////////////////////////////////////////////////////////////
53  
    template <typename VTable, typename Sig>
54  
    class function_base;
55  
56  
    template <typename VTable, typename R, typename ...Ts>
57  
    class function_base<VTable, R(Ts...)>
58  
    {
59  
        HPX_MOVABLE_ONLY(function_base);
60  
61  
        // make sure the empty table instance is initialized in time, even
62  
        // during early startup
63  
        static VTable const* get_empty_table()
64  
        {
65  
            static VTable const empty_table =
66  
                detail::construct_vtable<detail::empty_function<R(Ts...)> >();
67  
            return &empty_table;
68  
        }
69  
70  
    public:
71  
        function_base() HPX_NOEXCEPT
72  
          : vptr(get_empty_table())
73  
        {
74  
            std::memset(object, 0, vtable::function_storage_size);
75  
            vtable::default_construct<empty_function<R(Ts...)> >(object);
76  
        }
77  
78  
        function_base(function_base&& other) HPX_NOEXCEPT
79  
          : vptr(other.vptr)
80  
        {
81  
            // move-construct
82  
            std::memcpy(object, other.object, vtable::function_storage_size);
83  
            other.vptr = get_empty_table();
84  
            vtable::default_construct<empty_function<R(Ts...)> >(other.object);
85  
        }
86  
87  
        ~function_base()
88  
        {
89  
            vptr->delete_(object);
90  
        }
91  
92  
        function_base& operator=(function_base&& other) HPX_NOEXCEPT
93  
        {
94  
            if (this != &other)
95  
            {
96  
                swap(other);
97  
                other.reset();
98  
            }
99  
            return *this;
100  
        }
101  
102  
        void assign(std::nullptr_t) HPX_NOEXCEPT
103  
        {
104  
            reset();
105  
        }
106  
107  
        template <typename F>
108  
        void assign(F&& f)
109  
        {
110  
            if (!is_empty_function(f))
111  
            {
112  
                typedef typename std::decay<F>::type target_type;
113  
114  
                VTable const* f_vptr = get_vtable<target_type>();
115  
                if (vptr == f_vptr)
116  
                {
117  
                    vtable::reconstruct<target_type>(object, std::forward<F>(f));
118  
                } else {
119  
                    reset();
120  
                    vtable::_delete<empty_function<R(Ts...)> >(object);
121  
122  
                    vptr = f_vptr;
123  
                    vtable::construct<target_type>(object, std::forward<F>(f));
124  
                }
125  
            } else {
126  
                reset();
127  
            }
128  
        }
129  
130  
        void reset() HPX_NOEXCEPT
131  
        {
132  
            if (!vptr->empty)
133  
            {
134  
                vptr->delete_(object);
135  
136  
                vptr = get_empty_table();
137  
                vtable::default_construct<empty_function<R(Ts...)> >(object);
138  
            }
139  
        }
140  
141  
        void swap(function_base& f) HPX_NOEXCEPT
142  
        {
143  
            std::swap(vptr, f.vptr);
144  
            std::swap(object, f.object); // swap
145  
        }
146  
147  
        bool empty() const HPX_NOEXCEPT
148  
        {
149  
            return vptr->empty;
150  
        }
151  
152  
        explicit operator bool() const HPX_NOEXCEPT
153  
        {
154  
            return !empty();
155  
        }
156  
157  
        std::type_info const& target_type() const HPX_NOEXCEPT
158  
        {
159  
            return empty() ? typeid(void) : vptr->get_type();
160  
        }
161  
162  
        template <typename T>
163  
        T* target() HPX_NOEXCEPT
164  
        {
165  
            typedef typename std::remove_cv<T>::type target_type;
166  
167  
            static_assert(
168  
                traits::is_callable<target_type&(Ts...), R>::value
169  
              , "T shall be Callable with the function signature");
170  
171  
            VTable const* f_vptr = get_vtable<target_type>();
172  
            if (vptr != f_vptr || empty())
173  
                return nullptr;
174  
175  
            return &vtable::get<target_type>(object);
176  
        }
177  
178  
        template <typename T>
179  
        T const* target() const HPX_NOEXCEPT
180  
        {
181  
            typedef typename std::remove_cv<T>::type target_type;
182  
183  
            static_assert(
184  
                traits::is_callable<target_type&(Ts...), R>::value
185  
              , "T shall be Callable with the function signature");
186  
187  
            VTable const* f_vptr = get_vtable<target_type>();
188  
            if (vptr != f_vptr || empty())
189  
                return nullptr;
190  
191  
            return &vtable::get<target_type>(object);
192  
        }
193  
194  
        HPX_FORCEINLINE R operator()(Ts... vs) const
195  
        {
196  
            return vptr->invoke(object, std::forward<Ts>(vs)...);
197  
        }
198  
199  
        std::size_t get_function_address() const
200  
        {
201  
            return vptr->get_function_address(object);
202  
        }
203  
204  
    private:
205  
        template <typename T>
206  
        static VTable const* get_vtable() HPX_NOEXCEPT
207  
        {
208  
            return detail::get_vtable<VTable, T>();
209  
        }
210  
211  
    protected:
212  
        VTable const *vptr;
213  
        mutable void* object[(vtable::function_storage_size / sizeof(void*))];
214  
    };
215  
216  
    template <typename Sig, typename VTable>
217  
    static bool is_empty_function(function_base<VTable, Sig> const& f) HPX_NOEXCEPT
218  
    {
219  
        return f.empty();
220  
    }
221  
222  
    ///////////////////////////////////////////////////////////////////////////
223  
    template <typename VTable, typename Sig, bool Serializable>
224  
    class basic_function;
225  
226  
    template <typename VTable, typename R, typename ...Ts>
227  
    class basic_function<VTable, R(Ts...), true>
228  
      : public function_base<
229  
            serializable_function_vtable<VTable>
230  
          , R(Ts...)
231  
        >
232  
    {
233  
        HPX_MOVABLE_ONLY(basic_function);
234  
235  
        typedef serializable_function_vtable<VTable> vtable;
236  
        typedef function_base<vtable, R(Ts...)> base_type;
237  
238  
    public:
239  
        typedef R result_type;
240  
241  
        basic_function() HPX_NOEXCEPT
242  
          : base_type()
243  
        {}
244  
245  
        basic_function(basic_function&& other) HPX_NOEXCEPT
246  
          : base_type(static_cast<base_type&&>(other))
247  
        {}
248  
249  
        basic_function& operator=(basic_function&& other) HPX_NOEXCEPT
250  
        {
251  
            base_type::operator=(static_cast<base_type&&>(other));
252  
            return *this;
253  
        }
254  
255  
    private:
256  
        friend class hpx::serialization::access;
257  
258  
        void load(serialization::input_archive& ar, const unsigned version)
259  
        {
260  
            this->reset();
261  
262  
            bool is_empty = false;
263  
            ar >> is_empty;
264  
            if (!is_empty)
265  
            {
266  
                std::string name;
267  
                ar >> name;
268  
269  
                this->vptr = detail::get_vtable<vtable>(name);
270  
                this->vptr->load_object(this->object, ar, version);
271  
            }
272  
        }
273  
274  
        void save(serialization::output_archive& ar, const unsigned version) const
275  
        {
276  
            bool is_empty = this->empty();
277  
            ar << is_empty;
278  
            if (!is_empty)
279  
            {
280  
                std::string function_name = this->vptr->name;
281  
                ar << function_name;
282  
283  
                this->vptr->save_object(this->object, ar, version);
284  
            }
285  
        }
286  
287  
        HPX_SERIALIZATION_SPLIT_MEMBER()
288  
    };
289  
290  
    template <typename VTable, typename R, typename ...Ts>
291  
    class basic_function<VTable, R(Ts...), false>
292  
      : public function_base<VTable, R(Ts...)>
293  
    {
294  
        HPX_MOVABLE_ONLY(basic_function);
295  
296  
        typedef function_base<VTable, R(Ts...)> base_type;
297  
298  
    public:
299  
        typedef R result_type;
300  
301  
        basic_function() HPX_NOEXCEPT
302  
          : base_type()
303  
        {}
304  
305  
        basic_function(basic_function&& other) HPX_NOEXCEPT
306  
          : base_type(static_cast<base_type&&>(other))
307  
        {}
308  
309  
        basic_function& operator=(basic_function&& other) HPX_NOEXCEPT
310  
        {
311  
            base_type::operator=(static_cast<base_type&&>(other));
312  
            return *this;
313  
        }
314  
    };
315  
316  
    template <typename Sig, typename VTable, bool Serializable>
317  
    static bool is_empty_function(
318  
        basic_function<VTable, Sig, Serializable> const& f) HPX_NOEXCEPT
319  
    {
320  
        return f.empty();
321  
    }
322  
}}}
323  
324  
#endif
325  

Copyright (c) 2006-2012 Rogue Wave Software, Inc. All Rights Reserved.
Patents pending.