In the C++ coroutines TS (2017), there is an example of an awaitable object.
template <class Rep, class Period>
auto operator co_await(std::chrono::duration<Rep, Period> d) {
struct awaiter {
std::chrono::system_clock::duration duration;
...
awaiter(std::chrono::system_clock::duration d) : duration(d){}
bool await_ready() const { return duration.count() <= 0; }
void await_resume() {}
void await_suspend(std::experimental::coroutine_handle<> h){...}
};
return awaiter{d};
}
using namespace std::chrono;
my_future<int> h();
my_future<void> g() {
std::cout << "just about go to sleep...\n";
co_await 10ms;
std::cout << "resumed\n";
co_await h();
}
Like a typical StackOverflow Question, it will not compile. After cursing quietly for a while, I decided to turn it into a [MCVE] -- for learning. The code below compiles and runs on VC++17 with /await enabled. I think it probably does approximately what the TS authors intended. Alas, it employs a detached thread. It is not easy to see how that thread could be harvested via join or future::get or signal_all_at_thread_exit() or ...
For example, join cannot be added to a destructor for awaiter. In the spawned thread, h.resume() causes the awaiter object to be moved into the spawned thread and its (default) constructor called there. So the destructor is called in a different thread than the constructor.
The question, aside from "Is this what the TS intended?", is "Can this be improved, in a reasonably economical way, to tend to the dangling thread?" (And if so how?)
#include <experimental/coroutine>
#include <future>
#include <thread>
namespace xtd = std::experimental;
template <class Rep, class Period>
auto operator co_await(std::chrono::duration<Rep, Period> dur) {
struct awaiter {
using clock = std::chrono::high_resolution_clock;
clock::time_point resume_time;
awaiter(clock::duration dur) : resume_time(clock::now()+dur) {}
bool await_ready() { return resume_time <= clock::now(); }
void await_suspend(xtd::coroutine_handle<> h) {
std::thread([=]() {
std::this_thread::sleep_until(resume_time);
h.resume(); // destructs the obj, which has been std::move()'d
}).detach(); // Detach scares me.
}
void await_resume() {}
};
return awaiter{ dur };
}
using namespace std::chrono;
std::future<int> g() {
co_await 4000ms;
co_return 86;
}
template<typename R>
bool is_ready(std::future<R> const& f)
{ return f.wait_for(std::chrono::seconds(0)) == std::future_status::ready; }
int main() {
using std::cout;
auto gg = g();
cout << "Doing stuff in main, while coroutine is suspended...\n";
std::this_thread::sleep_for(1000ms);
if (!is_ready(gg)) {
cout << "La lala, lala, lala...\n";
std::this_thread::sleep_for(1500ms);
}
cout << "Whew! Done. Getting co_return now...\n";
auto ret = gg.get();
cout << "coroutine resumed and co_returned " << ret << '\n';
system("pause");
return ret;
}
Can this be improved, in a reasonably economical way, to tend to the dangling thread?
You can use "thread pool" implementation, instead of on-demand detached thread.
Here is toy example:
https://gist.github.com/yohhoy/a5ec6d4aeeb4c60d3e4f3adfd1df9ebf
Related
I'm trying to write a function that measures the time of execution of other functions.
It should have the same return type as the measured function.
The problem is that i'm getting a compiler error Variable has incomplete type 'void' when the return type is void.
Is there a workaround to solve this problem?
Help would be greatly appreciated, thanks!
#include <iostream>
#include <chrono>
template<class Func, typename... Parameters>
auto getTime(Func const &func, Parameters &&... args) {
auto begin = std::chrono::system_clock::now();
auto ret = func(std::forward<Parameters>(args)...);
auto end = std::chrono::system_clock::now();
std::cout << "The execution took " << std::chrono::duration<float>(end - begin).count() << " seconds.";
return ret;
}
int a() { return 0; }
void b() {}
int main()
{
getTime(a);
getTime(b);
return 0;
}
It's possible to solve this problem using specialization and an elaborate song-and-dance routine. But there's also a much simpler approach that takes advantage of return <void expression>; being allowed.
The trick is to fit it into this framework, by taking advantage of construction/destruction semantics.
#include <iostream>
#include <chrono>
struct measure_time {
std::chrono::time_point<std::chrono::system_clock> begin=
std::chrono::system_clock::now();
~measure_time()
{
auto end = std::chrono::system_clock::now();
std::cout << "The execution took "
<< std::chrono::duration<float>(end - begin).count()
<< " seconds.\n";
}
};
template<class Func, typename... Parameters>
auto getTime(Func const &func, Parameters &&... args) {
measure_time measure_it;
return func(std::forward<Parameters>(args)...);
}
int a() { return 0; }
void b() {}
int main()
{
getTime(a);
getTime(b);
return 0;
}
I call h.destroy() in final_suspend to destroy the coroutine automatically when it finishes execution and then I resume awaiting coroutine (that awaits the task to complete). I found a question about this technique and an answer explaining why it should work.
As far as I can see, this technique really works, but not with MSVC 2022 that calls task destructor twice, see the code below:
#include <coroutine>
#include <optional>
#include <iostream>
#include <thread>
#include <chrono>
#include <queue>
#include <vector>
// simple timers
// stored timer tasks
struct timer_task
{
std::chrono::steady_clock::time_point target_time;
std::coroutine_handle<> handle;
};
// comparator
struct timer_task_before_cmp
{
bool operator()(const timer_task& left, const timer_task& right) const
{
return left.target_time > right.target_time;
}
};
std::priority_queue<timer_task, std::vector<timer_task>, timer_task_before_cmp> timers;
inline void submit_timer_task(std::coroutine_handle<> handle, std::chrono::nanoseconds timeout)
{
timers.push(timer_task{ std::chrono::steady_clock::now() + timeout, handle });
}
//template <bool owning>
struct UpdatePromise;
//template <bool owning>
struct UpdateTask
{
// declare promise type
using promise_type = UpdatePromise;
UpdateTask(std::coroutine_handle<promise_type> handle) :
handle(handle)
{
std::cout << "UpdateTask constructor." << std::endl;
}
UpdateTask(const UpdateTask&) = delete;
UpdateTask(UpdateTask&& other) : handle(other.handle)
{
std::cout << "UpdateTask move constructor." << std::endl;
}
UpdateTask& operator = (const UpdateTask&) = delete;
UpdateTask& operator = (const UpdateTask&& other)
{
handle = other.handle;
std::cout << "UpdateTask move assignment." << std::endl;
return *this;
}
~UpdateTask()
{
std::cout << "UpdateTask destructor." << std::endl;
}
std::coroutine_handle<promise_type> handle;
};
struct UpdatePromise
{
std::coroutine_handle<> awaiting_coroutine;
UpdateTask get_return_object();
std::suspend_never initial_suspend()
{
return {};
}
void unhandled_exception()
{
std::terminate();
}
auto final_suspend() noexcept
{
// if there is a coroutine that is awaiting on this coroutine resume it
struct transfer_awaitable
{
std::coroutine_handle<> awaiting_coroutine;
// always stop at final suspend
bool await_ready() noexcept
{
return false;
}
std::coroutine_handle<> await_suspend(std::coroutine_handle<UpdatePromise> h) noexcept
{
// resume awaiting coroutine or if there is no coroutine to resume return special coroutine that do
// nothing
std::coroutine_handle<> val = awaiting_coroutine ? awaiting_coroutine : std::noop_coroutine();
h.destroy();
return val;
}
void await_resume() noexcept {}
};
return transfer_awaitable{ awaiting_coroutine };
}
void return_void() {}
// use `co_await std::chrono::seconds{n}` to wait specified amount of time
auto await_transform(std::chrono::milliseconds d)
{
struct timer_awaitable
{
std::chrono::milliseconds m_d;
// always suspend
bool await_ready()
{
return m_d <= std::chrono::milliseconds(0);
}
// h is a handler for current coroutine which is suspended
void await_suspend(std::coroutine_handle<> h)
{
// submit suspended coroutine to be resumed after timeout
submit_timer_task(h, m_d);
}
void await_resume() {}
};
return timer_awaitable{ d };
}
// also we can await other UpdateTask<T>
auto await_transform(UpdateTask& update_task)
{
if (!update_task.handle)
{
throw std::runtime_error("coroutine without promise awaited");
}
if (update_task.handle.promise().awaiting_coroutine)
{
throw std::runtime_error("coroutine already awaited");
}
struct task_awaitable
{
std::coroutine_handle<UpdatePromise> handle;
// check if this UpdateTask already has value computed
bool await_ready()
{
return handle.done();
}
// h - is a handle to coroutine that calls co_await
// store coroutine handle to be resumed after computing UpdateTask value
void await_suspend(std::coroutine_handle<> h)
{
handle.promise().awaiting_coroutine = h;
}
// when ready return value to a consumer
auto await_resume()
{
}
};
return task_awaitable{ update_task.handle };
}
};
inline UpdateTask UpdatePromise::get_return_object()
{
return { std::coroutine_handle<UpdatePromise>::from_promise(*this) };
}
// timer loop
void loop()
{
while (!timers.empty())
{
auto& timer = timers.top();
// if it is time to run a coroutine
if (timer.target_time < std::chrono::steady_clock::now())
{
auto handle = timer.handle;
timers.pop();
handle.resume();
}
else
{
std::this_thread::sleep_until(timer.target_time);
}
}
}
// example
using namespace std::chrono_literals;
UpdateTask TestTimerAwait()
{
using namespace std::chrono_literals;
std::cout << "testTimerAwait started." << std::endl;
co_await 1s;
std::cout << "testTimerAwait finished." << std::endl;
}
UpdateTask TestNestedTimerAwait()
{
using namespace std::chrono_literals;
std::cout << "testNestedTimerAwait started." << std::endl;
auto task = TestTimerAwait();
co_await 2s;
//co_await task;
std::cout << "testNestedTimerAwait finished." << std::endl;
}
// main can't be a coroutine and usually need some sort of looper (io_service or timer loop in this example)
int main()
{
auto task = TestNestedTimerAwait();
// execute deferred coroutines
loop();
}
the output with MSVC 2022 is:
UpdateTask constructor.
testNestedTimerAwait started.
UpdateTask constructor.
testTimerAwait started.
testTimerAwait finished.
testNestedTimerAwait finished.
UpdateTask destructor.
UpdateTask destructor.
UpdateTask destructor.
but the output with GCC 11.1.0 is:
UpdateTask constructor.
testNestedTimerAwait started.
UpdateTask constructor.
testTimerAwait started.
testTimerAwait finished.
testNestedTimerAwait finished.
UpdateTask destructor.
UpdateTask destructor.
as you can see there is one extra destructor call with MSVC 2022, so the behaviour of the code generated with MSVC 2022 is undefined and it can potentially format your hard drive.
MSVC 2022 version: Microsoft (R) C/C++ Optimizing Compiler Version 19.30.30709 for x86
EDIT9:
Figured out what happens. The destructor of UpdateTask is called twice with MSVC 2022, see updated code.
EDIT10:
From docs: The coroutine is suspended (its coroutine state is populated with local variables and current suspension point).
awaiter.await_suspend(handle) is called, where handle is the coroutine handle representing the current coroutine. Inside that function, the suspended coroutine state is observable via that handle, and it's this function's responsibility to schedule it to resume on some executor, or to be destroyed (returning false counts as scheduling)
Looks like it was a compiler bug, that is probably fixed in Microsoft (R) C/C++ Optimizing Compiler Version 19.31.31106.2 for x86, at least now the output is:
UpdateTask constructor.
testNestedTimerAwait started.
UpdateTask constructor.
testTimerAwait started.
testTimerAwait finished.
testNestedTimerAwait finished.
UpdateTask destructor.
UpdateTask destructor.
I'd like to wrap the result of a std::bind() or a lambda in a helper function that tracks the execution time of calls to the function. I'd like a generalized solution that will work with any number of parameters (and class methods) and is c++11 compatible.
My intent is to take the wrapped function and pass it to a boost::signals2::signal so the resulting function object needs to be identical in signature to the original function.
I'm basically looking for some magical class or function Wrapper that works like this:
std::function<void(int)> f = [](int x) {
std::cerr << x << std::endl;
};
boost::signals2::signal<void(int)> x_signal;
x_signal.connect(Wrapper<void(int)>(f));
x_signal(42);
that would time how long it took to print 42.
Thanks!
If it's about performance, I strongly suggest not to doubly wrap functions.
You can do without those:
template <typename Caption, typename F>
auto timed(Caption const& task, F&& f) {
return [f=std::forward<F>(f), task](auto&&... args) {
using namespace std::chrono;
struct measure {
high_resolution_clock::time_point start;
Caption const& task;
~measure() { std::cout << " -- (" << task << " completed in " << duration_cast<microseconds>(high_resolution_clock::now() - start).count() << "µs)\n"; }
} timing { high_resolution_clock::now(), task };
return f(std::forward<decltype(args)>(args)...);
};
}
See live demo:
Live On Coliru
#include <chrono>
#include <iostream>
template <typename Caption, typename F>
auto timed(Caption const& task, F&& f) {
return [f=std::forward<F>(f), task](auto&&... args) {
using namespace std::chrono;
struct measure {
high_resolution_clock::time_point start;
Caption const& task;
~measure() { std::cout << " -- (" << task << " completed in " << duration_cast<microseconds>(high_resolution_clock::now() - start).count() << "µs)\n"; }
} timing { high_resolution_clock::now(), task };
return f(std::forward<decltype(args)>(args)...);
};
}
#include <thread>
int main() {
using namespace std;
auto f = timed("IO", [] { cout << "hello world\n"; return 42; });
auto g = timed("Sleep", [](int i) { this_thread::sleep_for(chrono::seconds(i)); });
g(1);
f();
g(2);
std::function<int()> f_wrapped = f;
return f_wrapped();
}
Prints (e.g.):
-- (Sleep completed in 1000188µs)
hello world
-- (IO completed in 2µs)
-- (Sleep completed in 2000126µs)
hello world
-- (IO completed in 1µs)
exitcode: 42
UPDATE: c++11 version
Live On Coliru
#include <chrono>
#include <iostream>
namespace detail {
template <typename F>
struct timed_impl {
std::string _caption;
F _f;
timed_impl(std::string const& task, F f)
: _caption(task), _f(std::move(f)) { }
template <typename... Args>
auto operator()(Args&&... args) const -> decltype(_f(std::forward<Args>(args)...))
{
using namespace std::chrono;
struct measure {
high_resolution_clock::time_point start;
std::string const& task;
~measure() { std::cout << " -- (" << task << " completed in " << duration_cast<microseconds>(high_resolution_clock::now() - start).count() << "µs)\n"; }
} timing { high_resolution_clock::now(), _caption };
return _f(std::forward<decltype(args)>(args)...);
}
};
}
template <typename F>
detail::timed_impl<F> timed(std::string const& task, F&& f) {
return { task, std::forward<F>(f) };
}
#include <thread>
int main() {
using namespace std;
auto f = timed("IO", [] { cout << "hello world\n"; return 42; });
auto g = timed("Sleep", [](int i) { this_thread::sleep_for(chrono::seconds(i)); });
g(1);
f();
g(2);
std::function<int()> f_wrapped = f;
return f_wrapped();
}
I believe what you want to do can be solved with variadic templates.
http://www.cplusplus.com/articles/EhvU7k9E/
You can basically "forward" the argument list from your outer std::function to the inner.
EDIT:
Below, I added a minimal working example using the variadic template concept. In main(...), a lambda function is wrapped into another std::function object, using the specified parameters for the inner lambda function. This is done by passing the function to measure as a parameter to the templated function measureTimeWrapper. It returns a function with the same signature as the function passed in (given that you properly define that lambda's parameter list in the template argument of measureTimeWrapper).
The function who's running time is measured just sits here and waits for a number of milliseconds defined by its parameter. Other than that, it is not at all concerned with time measuring. That is done by the wrapper function.
Note that the return value of the inner function is lost this way; you might want to change the way values are returned (maybe as a struct, containing the measured time and the real return value) if you want to keep it.
Remember to compile your code with -std=c++11 at least.
#include <iostream>
#include <cstdlib>
#include <functional>
#include <chrono>
#include <thread>
template<typename T, typename... Args>
std::function<double(Args...)> measureTimeWrapper(std::function<T> fncFunctionToMeasure) {
return [fncFunctionToMeasure](Args... args) -> double {
auto tsStart = std::chrono::steady_clock::now();
fncFunctionToMeasure(args...);
auto tsEnd = std::chrono::steady_clock::now();
std::chrono::duration<double> durTimeTaken = tsEnd - tsStart;
return durTimeTaken.count();
};
}
int main(int argc, char** argv) {
std::function<double(int)> fncMeasured = measureTimeWrapper<void(int), int>([](int nParameter) {
std::cout << "Process function running" << std::endl;
std::chrono::milliseconds tsTime(nParameter); // Milliseconds
std::this_thread::sleep_for(tsTime);
});
std::cout << "Time taken: " << fncMeasured(500) << " sec" << std::endl;
return EXIT_SUCCESS;
}
#include <iostream>
#include <functional>
template<typename Signature>
std::function<Signature> Wrapper(std::function<Signature> func)
{
return [func](auto... args)
{
std::cout << "function tracked" << std::endl;
return func(args...);
};
}
int lol(const std::string& str)
{
std::cout << str << std::endl;
return 42;
}
int main(void)
{
auto wrapped = Wrapper<int(const std::string&)>(lol);
std::cout << wrapped("Hello") << std::endl;
}
Replace the "function tracked"part with whatever tracking logic you want (timing, cache, etc.)
This requires c++14 though
In C++11, this:
const std::vector<int>& f() {
static const std::vector<int> x { 1, 2, 3 };
return x;
}
is thread-safe. However, is there an extra penalty for calling this function after the first time (i.e. when it is initialized) due to this extra thread-safe guarantee? I am wondering if the function will be slower than one using a global variable, because it has to acquire a mutex to check whether it's being initialized by another thread every time it is called, or something.
"The best intution to be ever had is 'I should measure this.'" So let's find out:
#include <atomic>
#include <chrono>
#include <cstdint>
#include <iostream>
#include <numeric>
#include <vector>
namespace {
class timer {
using hrc = std::chrono::high_resolution_clock;
hrc::time_point start;
static hrc::time_point now() {
// Prevent memory operations from reordering across the
// time measurement. This is likely overkill, needs more
// research to determine the correct fencing.
std::atomic_thread_fence(std::memory_order_seq_cst);
auto t = hrc::now();
std::atomic_thread_fence(std::memory_order_seq_cst);
return t;
}
public:
timer() : start(now()) {}
hrc::duration elapsed() const {
return now() - start;
}
template <typename Duration>
typename Duration::rep elapsed() const {
return std::chrono::duration_cast<Duration>(elapsed()).count();
}
template <typename Rep, typename Period>
Rep elapsed() const {
return elapsed<std::chrono::duration<Rep,Period>>();
}
};
const std::vector<int>& f() {
static const auto x = std::vector<int>{ 1, 2, 3 };
return x;
}
static const auto y = std::vector<int>{ 1, 2, 3 };
const std::vector<int>& g() {
return y;
}
const unsigned long long n_iterations = 500000000;
template <typename F>
void test_one(const char* name, F f) {
f(); // First call outside the timer.
using value_type = typename std::decay<decltype(f()[0])>::type;
std::cout << name << ": " << std::flush;
auto t = timer{};
auto sum = uint64_t{};
for (auto i = n_iterations; i > 0; --i) {
const auto& vec = f();
sum += std::accumulate(begin(vec), end(vec), value_type{});
}
const auto elapsed = t.elapsed<std::chrono::milliseconds>();
std::cout << elapsed << " ms (" << sum << ")\n";
}
} // anonymous namespace
int main() {
test_one("local static", f);
test_one("global static", g);
}
Running at Coliru, the local version does 5e8 iterations in 4618 ms, the global version in 4392 ms. So yes, the local version is slower by approximately 0.452 nanoseconds per iteration. Although there's a measurable difference, it's too small to impact observed performance in most situations.
EDIT: Interesting counterpoint, switching from clang++ to g++ changes the result ordering. The g++-compiled binary runs in 4418 ms (global) vs. 4181 ms (local) so local is faster by 474 picoseconds per iteration. It does nonetheless reaffirm the conclusion that the variance between the two methods is small.
EDIT 2: Examining the generated assembly, I decided to convert from function pointers to function objects for better inlining. Timing with indirect calls through function pointers isn't really characteristic of the code in the OP. So I used this program:
#include <atomic>
#include <chrono>
#include <cstdint>
#include <iostream>
#include <numeric>
#include <vector>
namespace {
class timer {
using hrc = std::chrono::high_resolution_clock;
hrc::time_point start;
static hrc::time_point now() {
// Prevent memory operations from reordering across the
// time measurement. This is likely overkill.
std::atomic_thread_fence(std::memory_order_seq_cst);
auto t = hrc::now();
std::atomic_thread_fence(std::memory_order_seq_cst);
return t;
}
public:
timer() : start(now()) {}
hrc::duration elapsed() const {
return now() - start;
}
template <typename Duration>
typename Duration::rep elapsed() const {
return std::chrono::duration_cast<Duration>(elapsed()).count();
}
template <typename Rep, typename Period>
Rep elapsed() const {
return elapsed<std::chrono::duration<Rep,Period>>();
}
};
class f {
public:
const std::vector<int>& operator()() {
static const auto x = std::vector<int>{ 1, 2, 3 };
return x;
}
};
class g {
static const std::vector<int> x;
public:
const std::vector<int>& operator()() {
return x;
}
};
const std::vector<int> g::x{ 1, 2, 3 };
const unsigned long long n_iterations = 500000000;
template <typename F>
void test_one(const char* name, F f) {
f(); // First call outside the timer.
using value_type = typename std::decay<decltype(f()[0])>::type;
std::cout << name << ": " << std::flush;
auto t = timer{};
auto sum = uint64_t{};
for (auto i = n_iterations; i > 0; --i) {
const auto& vec = f();
sum += std::accumulate(begin(vec), end(vec), value_type{});
}
const auto elapsed = t.elapsed<std::chrono::milliseconds>();
std::cout << elapsed << " ms (" << sum << ")\n";
}
} // anonymous namespace
int main() {
test_one("local static", f());
test_one("global static", g());
}
Not surprisingly, runtimes were faster under both g++ (3803ms local, 2323ms global) and clang (4183ms local, 3253ms global). The results affirm our intuition that the global technique should be faster than the local, with deltas of 2.96 nanoseconds (g++) and 1.86 nanoseconds (clang) per iteration.
Yes, there will be a cost to check whether the object has been initialised. This would typically test an atomic Boolean variable, rather than lock a mutex.
I have a function foo that returns a future. foo will register a callback which will be called after foo returns.
future<int> foo() {
promise<int> p;
future<int> ret(p.get_future());
thread(bind([] (promise<int> &&p) {
this_thread::sleep_for(chrono::seconds(3));
p.set_value(10);
}, move(p))).detach();
return move(ret);
}
int main()
{
auto f = foo();
cout << f.get() << endl;
return 0;
}
But it seems like that std::bind forwards the rvalue reference as a lvalue reference so that can not be successfully compiled. Is there any way to fix it?
I have to write an ugly class to move the promise object:
template<typename T>
class promise_forward {
promise<T> promise_;
public:
promise_forward(promise<T> &&p) :
promise_(move(p)) {}
promise_forward(promise_forward<T> &&other) :
promise_(move(other.promise_)) {}
operator promise<T> () {
return move(promise_);
}
};
future<int> foo() {
promise<int> p;
future<int> ret(p.get_future());
thread(bind([] (promise<int> &&p) {
this_thread::sleep_for(chrono::seconds(3));
p.set_value(10);
}, promise_forward<int>(move(p)))).detach();
return ret;
}
int main()
{
auto f = foo();
cout << f.get() << endl;
return 0;
}
You, basically, doesn't need std::bind here (well , I believe so =)).
Here is a quick draft of a simplest async task launcher. It almost same as yours, but, just a little more generic: it can accept any function objects and it is less intrusive: function objects doesn't know nothing about promises or threading at all.
There are may be mistakes (I'm quite sure they are). And, of course, it is far far away, from std::async implementation (which, generally, more than just thread launcher, but, ideally, have a huge thread management back-end).
#include <thread>
#include <future>
#include <iostream>
#include <chrono>
template< class Function, class... Args>
std::future<typename std::result_of<Function(Args...)>::type> my_async(Function && f, Args && ... args)
{
typedef typename std::result_of<Function(Args...)>::type ret_type;
std::promise<ret_type> p;
auto fut = p.get_future();
// lambda in separate variable, just to improve readability
auto l = [](Function && f, Args && ... args, std::promise<ret_type> && p)
{
p.set_value(f(args...));
};
std::thread th(l, std::move(f), std::move(args...), std::move(p));
th.detach();
return std::move(fut);
}
int wannaRunAsync(int i)
{
return i;
};
int main()
{
auto fut = my_async(&wannaRunAsync, 42);
auto fut2 = my_async([](int i) -> int { return i; }, 42);
std::cout << fut.get() << std::endl;
std::cout << fut2.get() << std::endl;
std::cin.get();
return 0;
}
I was able to compile and run it with
g++-4.8 and
clang++ but with msvc 2012 and 2013 preview it doesn't even compiles (probably, due to errors).
I've not tested this code at all, so be careful =) Hope it helps.