File: async.h

package info (click to toggle)
concurrentqueue 1.0.4%2Bds-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,656 kB
  • sloc: cpp: 37,309; makefile: 99; ansic: 67; python: 46; sh: 11
file content (118 lines) | stat: -rw-r--r-- 3,347 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// Copyright (C) 2016  Davis E. King (davis@dlib.net)
// License: Boost Software License   See LICENSE.txt for the full license.
#ifndef DLIB_AsYNC_Hh_
#define DLIB_AsYNC_Hh_ 

// C++11 things don't work in old versions of visual studio 
#if !defined( _MSC_VER) ||  _MSC_VER >= 1900

#include "async_abstract.h"
#include "thread_pool_extension.h"
#include <future>
#include <functional>

namespace dlib
{

// ----------------------------------------------------------------------------------------

    namespace impl
    {
        template <typename T> struct selector {};

        template <typename T, typename U, typename V>
        void call_prom_set_value(
            T& prom,
            U& fun,
            selector<V> 
        )
        {
            prom.set_value(fun());
        }

        template <typename T, typename U>
        void call_prom_set_value(
            T& prom,
            U& fun,
            selector<void>
        )
        {
            fun();
            prom.set_value();
        }

        template <typename> struct result_of;

#if (__cplusplus >= 201703L ||                          \
     (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)) && \
    __cpp_lib_is_invocable >= 201703L
        template <typename F, typename... Args>
        struct result_of<F(Args...)> : std::invoke_result<F, Args...> {};
#else
        template <typename F, typename... Args>
        struct result_of<F(Args...)>
                : std::result_of<F&&(Args&&...)> {};
#endif
    }

// ----------------------------------------------------------------------------------------

    thread_pool& default_thread_pool();

// ----------------------------------------------------------------------------------------

    template < 
        typename Function, 
        typename ...Args
        >
    std::future<typename impl::result_of<Function(Args...)>::type> async(
        thread_pool& tp, 
        Function&& f, 
        Args&&... args 
    )
    {
        auto prom = std::make_shared<std::promise<typename impl::result_of<Function(Args...)>::type>>();
        std::future<typename impl::result_of<Function(Args...)>::type> ret = prom->get_future();
        using bind_t = decltype(std::bind(std::forward<Function>(f), std::forward<Args>(args)...));
        auto fun = std::make_shared<bind_t>(std::bind(std::forward<Function>(f), std::forward<Args>(args)...));
        tp.add_task_by_value([fun, prom]()
        { 
            try
            {
                impl::call_prom_set_value(*prom, *fun, impl::selector<typename impl::result_of<Function(Args...)>::type>());
            }
            catch(...)
            {
                prom->set_exception(std::current_exception());
            }
        });
        return ret;
    }

// ----------------------------------------------------------------------------------------

    template < 
        typename Function, 
        typename ...Args
        >
    std::future<typename impl::result_of<Function(Args...)>::type> async(
        Function&& f, 
        Args&&... args 
    )
    {
        return async(default_thread_pool(), std::forward<Function>(f), std::forward<Args>(args)...);
    }

}

// ----------------------------------------------------------------------------------------

#ifdef NO_MAKEFILE
#include "async.cpp"
#endif

#endif
#endif // DLIB_AsYNC_Hh_