// Copyright (c) 2015 Amanieu d'Antras // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #ifndef ASYNCXX_H_ # error "Do not include this header directly, include instead." #endif namespace async { namespace detail { // Pseudo-void type: it takes up no space but can be moved and copied struct fake_void {}; template struct void_to_fake_void { typedef T type; }; template<> struct void_to_fake_void { typedef fake_void type; }; template T fake_void_to_void(T&& x) { return std::forward(x); } inline void fake_void_to_void(fake_void) {} // Check if type is a task type, used to detect task unwraping template struct is_task: public std::false_type {}; template struct is_task>: public std::true_type {}; template struct is_task>: public std::true_type {}; template struct is_task>: public std::true_type {}; template struct is_task>: public std::true_type {}; // Extract the result type of a task if T is a task, otherwise just return T template struct remove_task { typedef T type; }; template struct remove_task> { typedef T type; }; template struct remove_task> { typedef T type; }; template struct remove_task> { typedef T type; }; template struct remove_task> { typedef T type; }; // Check if a type is callable with the given arguments typedef char one[1]; typedef char two[2]; template()(std::declval()...))> two& is_callable_helper(int); template one& is_callable_helper(...); template struct is_callable; template struct is_callable: public std::integral_constant(0)) - 1> {}; // Wrapper to run a function object with an optional parameter: // - void returns are turned into fake_void // - fake_void parameter will invoke the function with no arguments template()())>::value>::type> decltype(std::declval()()) invoke_fake_void(Func&& f) { return std::forward(f)(); } template()())>::value>::type> fake_void invoke_fake_void(Func&& f) { std::forward(f)(); return fake_void(); } template typename void_to_fake_void()(std::declval()))>::type invoke_fake_void(Func&& f, Param&& p) { return detail::invoke_fake_void([&f, &p] {return std::forward(f)(std::forward(p));}); } template typename void_to_fake_void()())>::type invoke_fake_void(Func&& f, fake_void) { return detail::invoke_fake_void(std::forward(f)); } // Various properties of a continuation function template()())> fake_void is_value_cont_helper(const Parent&, int, int); template()(std::declval().get()))> std::true_type is_value_cont_helper(const Parent&, int, int); template()())> std::true_type is_value_cont_helper(const task&, int, int); template()())> std::true_type is_value_cont_helper(const shared_task&, int, int); template()(std::declval()))> std::false_type is_value_cont_helper(const Parent&, int, ...); template void is_value_cont_helper(const Parent&, ...); template struct continuation_traits { typedef typename std::decay::type decay_func; typedef decltype(detail::is_value_cont_helper(std::declval(), 0, 0)) is_value_cont; static_assert(!std::is_void::value, "Parameter type for continuation function is invalid for parent task type"); typedef typename std::conditional::value, fake_void, typename std::conditional::value, typename void_to_fake_void().get())>::type, Parent>::type>::type param_type; typedef decltype(detail::fake_void_to_void(detail::invoke_fake_void(std::declval(), std::declval()))) result_type; typedef task::type> task_type; }; } // namespace detail } // namespace async