1 /* Copyright (c) 2015-2016. The SimGrid Team.
2 * All rights reserved. */
4 /* This program is free software; you can redistribute it and/or modify it
5 * under the terms of the license (GNU LGPL) which comes with this package. */
7 #ifndef XBT_FUNCTIONAL_HPP
8 #define XBT_FUNCTIONAL_HPP
18 #include <xbt/sysdep.h>
19 #include <xbt/utility.hpp>
27 char** argv_ = nullptr;
33 void assign(int argc, const char*const* argv)
36 char** new_argv = xbt_new(char*,argc + 1);
37 for (int i = 0; i < argc; i++)
38 new_argv[i] = xbt_strdup(argv[i]);
39 new_argv[argc] = nullptr;
41 this->argv_ = new_argv;
43 args(int argc, const char*const* argv)
45 this->assign(argc, argv);
48 char** to_argv() const
50 const int argc = argc_;
51 char** argv = xbt_new(char*, argc + 1);
52 for (int i=0; i< argc; i++)
53 argv[i] = xbt_strdup(argv_[i]);
61 for (int i = 0; i < this->argc_; i++)
62 std::free(this->argv_[i]);
63 std::free(this->argv_);
65 this->argv_ = nullptr;
70 args(args const& that)
72 this->assign(that.argc(), that.argv());
74 args& operator=(args const& that)
76 this->assign(that.argc(), that.argv());
81 args(args&& that) : argc_(that.argc_), argv_(that.argv_)
86 args& operator=(args&& that)
88 this->argc_ = that.argc_;
89 this->argv_ = that.argv_;
95 int argc() const { return argc_; }
96 char** argv() { return argv_; }
97 const char*const* argv() const { return argv_; }
98 char* operator[](std::size_t i) { return argv_[i]; }
101 template<class F> inline
102 std::function<void()> wrapMain(F code, std::shared_ptr<simgrid::xbt::args> args)
105 code(args->argc(), args->argv());
109 template<class F> inline
110 std::function<void()> wrapMain(F code, simgrid::xbt::args args)
112 return wrapMain(std::move(code),
113 std::unique_ptr<simgrid::xbt::args>(new simgrid::xbt::args(std::move(args))));
116 template<class F> inline
117 std::function<void()> wrapMain(F code, int argc, const char*const* argv)
119 return wrapMain(std::move(code), args(argc, argv));
123 template <class F, class Tuple, std::size_t... I>
124 constexpr auto apply(F&& f, Tuple&& t, simgrid::xbt::index_sequence<I...>)
125 -> decltype(std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...))
127 return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...);
131 /** Call a functional object with the values in the given tuple (from C++17)
134 * int foo(int a, bool b);
136 * auto args = std::make_tuple(1, false);
137 * int res = apply(foo, args);
140 template <class F, class Tuple>
141 constexpr auto apply(F&& f, Tuple&& t)
142 -> decltype(simgrid::xbt::bits::apply(
144 std::forward<Tuple>(t),
145 simgrid::xbt::make_index_sequence<
146 std::tuple_size<typename std::decay<Tuple>::type>::value
149 return simgrid::xbt::bits::apply(
151 std::forward<Tuple>(t),
152 simgrid::xbt::make_index_sequence<
153 std::tuple_size<typename std::decay<Tuple>::type>::value
157 template<class T> class Task;
159 /** Type-erased run-once task
161 * * Like std::function but callable only once.
162 * However, it works with move-only types.
164 * * Like std::packaged_task<> but without the shared state.
166 template<class R, class... Args>
167 class Task<R(Args...)> {
169 // Type-erasure for the code:
173 virtual R operator()(Args...) = 0;
176 class Impl : public Base {
178 Impl(F&& code) : code_(std::move(code)) {}
179 Impl(F const& code) : code_(code) {}
181 R operator()(Args... args) override
183 return code_(std::forward<Args>(args)...);
188 std::unique_ptr<Base> code_;
191 Task(std::nullptr_t) {}
195 code_(new Impl<F>(std::forward<F>(code))) {}
197 operator bool() const { return code_ != nullptr; }
198 bool operator!() const { return code_ == nullptr; }
200 template<class... OtherArgs>
201 R operator()(OtherArgs&&... args)
203 std::unique_ptr<Base> code = std::move(code_);
204 return (*code)(std::forward<OtherArgs>(args)...);
208 template<class F, class... Args>
212 std::tuple<Args...> args_;
213 typedef decltype(simgrid::xbt::apply(std::move(code_), std::move(args_))) result_type;
215 TaskImpl(F code, std::tuple<Args...> args) :
216 code_(std::move(code)),
217 args_(std::move(args))
219 result_type operator()()
221 return simgrid::xbt::apply(std::move(code_), std::move(args_));
225 template<class F, class... Args>
226 auto makeTask(F code, Args... args)
227 -> Task< decltype(code(std::move(args)...))() >
229 TaskImpl<F, Args...> task(std::move(code), std::make_tuple(std::move(args)...));
230 return std::move(task);