• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

STEllAR-GROUP / hpx / #882

31 Aug 2023 07:44PM UTC coverage: 41.798% (-44.7%) from 86.546%
#882

push

19442 of 46514 relevant lines covered (41.8%)

126375.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.67
/libs/core/functional/include/hpx/functional/detail/basic_function.hpp
1
//  Copyright (c) 2011 Thomas Heller
2
//  Copyright (c) 2013-2025 Hartmut Kaiser
3
//  Copyright (c) 2014-2019 Agustin Berge
4
//  Copyright (c) 2017 Google
5
//
6
//  SPDX-License-Identifier: BSL-1.0
7
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
8
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9

10
#pragma once
11

12
#include <hpx/config.hpp>
13
#include <hpx/assert.hpp>
14
#include <hpx/functional/detail/empty_function.hpp>
15
#include <hpx/functional/detail/vtable/function_vtable.hpp>
16
#include <hpx/functional/detail/vtable/vtable.hpp>
17
#include <hpx/functional/traits/get_function_address.hpp>
18
#include <hpx/functional/traits/get_function_annotation.hpp>
19
#include <hpx/modules/tag_invoke.hpp>
20

21
#include <cstddef>
22
#include <cstring>
23
#include <functional>
24
#include <memory>
25
#include <new>
26
#include <string>
27
#include <type_traits>
28
#include <utility>
29

30
namespace hpx::util::detail {
31

32
    inline constexpr std::size_t function_storage_size = 3 * sizeof(void*);
33

34
    ///////////////////////////////////////////////////////////////////////////
35
    class HPX_CORE_EXPORT function_base
36
    {
37
        using vtable = function_base_vtable;
38

39
    public:
40
        explicit constexpr function_base(
41
            function_base_vtable const* empty_vptr) noexcept
376,837✔
42
          : vptr(empty_vptr)
376,837✔
43
          , object(nullptr)
373,527✔
44
          , storage_init()
45
        {
46
        }
47

48
        function_base(function_base const& other, vtable const* empty_vtable);
49
        function_base(function_base&& other, vtable const* empty_vptr) noexcept;
50

51
        ~function_base();
52

53
        void op_assign(function_base const& other, vtable const* empty_vtable);
54
        void op_assign(
55
            function_base&& other, vtable const* empty_vtable) noexcept;
56

57
        void destroy() const noexcept;
58
        void reset(vtable const* empty_vptr) noexcept;
59
        void swap(function_base& f) noexcept;
60

61
        [[nodiscard]] constexpr bool empty() const noexcept
62
        {
55,113,306✔
63
            return object == nullptr;
64
        }
65

66
        explicit constexpr operator bool() const noexcept
67
        {
68
            return !empty();
69
        }
70

71
        [[nodiscard]] std::size_t get_function_address() const;
72
        [[nodiscard]] char const* get_function_annotation() const;
73
        [[nodiscard]] util::itt::string_handle get_function_annotation_itt()
74
            const;
75

76
    protected:
77
        vtable const* vptr;
78
        void* object;
79
        union
80
        {
81
            char storage_init;
82
            mutable unsigned char storage[function_storage_size];
83
        };
84
    };
85

86
    ///////////////////////////////////////////////////////////////////////////
87
    template <typename F>
88
    [[nodiscard]] constexpr bool is_empty_function(F* fp) noexcept
89
    {
90
        return fp == nullptr;
91
    }
92

93
    template <typename T, typename C>
94
    [[nodiscard]] constexpr bool is_empty_function(T C::* mp) noexcept
95
    {
96
        return mp == nullptr;
97
    }
98

99
    [[nodiscard]] constexpr bool is_empty_function_impl(
100
        function_base const* f) noexcept
101
    {
102
        return f->empty();
103
    }
104

105
    [[nodiscard]] constexpr bool is_empty_function_impl(...) noexcept
106
    {
107
        return false;
108
    }
109

110
    template <typename F>
111
    [[nodiscard]] constexpr bool is_empty_function(F const& f) noexcept
112
    {
113
        return detail::is_empty_function_impl(&f);
114
    }
115

116
    template <typename Sig>
117
    [[nodiscard]] constexpr bool is_empty_function(
118
        std::function<Sig> const& f) noexcept
119
    {
120
        return !f;
121
    }
122

123
    ///////////////////////////////////////////////////////////////////////////
124
    template <typename Sig, bool Copyable, bool Serializable>
125
    class basic_function;
126

127
    template <bool Copyable, typename R, typename... Ts>
128
    class basic_function<R(Ts...), Copyable, /*Serializable*/ false>
129
      : public function_base
130
    {
131
        using base_type = function_base;
132
        using vtable = function_vtable<R(Ts...), Copyable>;
254,619✔
133

255,405✔
134
    public:
135
        constexpr basic_function() noexcept
136
          : base_type(get_empty_vtable())
137
        {
259,064✔
138
        }
258,699✔
139

140
        basic_function(basic_function const& other)
141
          : base_type(other, get_empty_vtable())
142
        {
143
        }
144

288✔
145
        basic_function(basic_function&& other) noexcept
146
          : base_type(HPX_MOVE(other), get_empty_vtable())
147
        {
148
        }
149

150
        basic_function& operator=(basic_function const& other)
103,063✔
151
        {
152
            base_type::op_assign(other, get_empty_vtable());
153
            return *this;
154
        }
447,130✔
155

156
        basic_function& operator=(basic_function&& other) noexcept
157
        {
158
            base_type::op_assign(HPX_MOVE(other), get_empty_vtable());
159
            return *this;
160
        }
161

162
        ~basic_function() = default;
9,416✔
163

164
        constexpr void assign(std::nullptr_t) noexcept
165
        {
166
            base_type::reset(get_empty_vtable());
167
        }
168

11,413✔
169
        template <typename F>
170
        void assign(F&& f)
171
        {
172
            using T = std::decay_t<F>;
9,330✔
173
            static_assert(!Copyable || std::is_constructible_v<T, T const&>,
174
                "F shall be CopyConstructible");
175

176
            if (!detail::is_empty_function(f))
177
            {
×
178
                constexpr vtable const* f_vptr = get_vtable<T>();
179
                void* buffer;
180
                if (vptr == f_vptr)
181
                {
182
                    HPX_ASSERT(object != nullptr);
183

18,933✔
184
                    // reuse object storage
19,351✔
185
                    buffer = object;
186
                    std::destroy_at(
27,898✔
187
                        std::addressof(vtable::template get<T>(object)));
188
                }
18,932✔
189
                else
190
                {
191
                    destroy();
192
                    vptr = f_vptr;
×
193
                    buffer = vtable::template allocate<T>(
194
                        storage, function_storage_size);
9,416✔
195
                }
196
                // NOLINTNEXTLINE(bugprone-multi-level-implicit-pointer-conversion)
197
                object = ::new (buffer) T(HPX_FORWARD(F, f));
198
            }
45,405✔
199
            else
200
            {
201
                base_type::reset(get_empty_vtable());
202
            }
203
        }
204

205
        constexpr void reset() noexcept
206
        {
207
            base_type::reset(get_empty_vtable());
208
        }
209

210
        using base_type::empty;
211
        using base_type::swap;
212
        using base_type::operator bool;
213

214
        template <typename T>
215
        [[nodiscard]] T* target() noexcept
216
        {
217
            using TD = std::remove_cv_t<T>;
218
            static_assert(hpx::is_invocable_r_v<R, TD&, Ts...>,
219
                "T shall be Callable with the function signature");
220

221
            constexpr vtable const* f_vptr = get_vtable<TD>();
222
            if (vptr != f_vptr || empty())
223
                return nullptr;
224

225
            return &vtable::template get<TD>(object);
226
        }
227

228
        template <typename T>
229
        [[nodiscard]] T const* target() const noexcept
230
        {
231
            using TD = std::remove_cv_t<T>;
232
            static_assert(hpx::is_invocable_r_v<R, TD&, Ts...>,
233
                "T shall be Callable with the function signature");
234

235
            constexpr vtable const* f_vptr = get_vtable<TD>();
1,484,233✔
236
            if (vptr != f_vptr || empty())
1,484,233✔
237
                return nullptr;
238

239
            return &vtable::template get<TD>(object);
240
        }
241

242
        HPX_FORCEINLINE R operator()(Ts... vs) const
243
        {
244
            vtable const* f_vptr = static_cast<vtable const*>(base_type::vptr);
245
            return f_vptr->invoke(object, HPX_FORWARD(Ts, vs)...);
246
        }
247

248
        using base_type::get_function_address;
249
        using base_type::get_function_annotation;
250
        using base_type::get_function_annotation_itt;
251

252
    private:
253
        [[nodiscard]] static constexpr vtable const* get_empty_vtable() noexcept
254
        {
255
            return detail::get_empty_function_vtable<R(Ts...)>();
256
        }
257

258
        template <typename T>
259
        [[nodiscard]] static constexpr vtable const* get_vtable() noexcept
260
        {
261
            return detail::get_vtable<vtable, T>();
262
        }
263

264
    protected:
265
        using base_type::object;
266
        using base_type::storage;
267
        using base_type::vptr;
268
    };
269
}    // namespace hpx::util::detail
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc