folly copyright 2015 -> copyright 2016
[folly.git] / folly / experimental / fibers / ForEach-inl.h
1 /*
2  * Copyright 2016 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include <folly/experimental/fibers/FiberManager.h>
17
18 namespace folly { namespace fibers {
19
20 namespace {
21
22 template <class F, class G>
23 typename std::enable_if<
24   !std::is_same<typename std::result_of<F()>::type, void>::value, void>::type
25 inline callFuncs(F&& f, G&& g, size_t id) {
26   g(id, f());
27 }
28
29 template <class F, class G>
30 typename std::enable_if<
31   std::is_same<typename std::result_of<F()>::type, void>::value, void>::type
32 inline callFuncs(F&& f, G&& g, size_t id) {
33   f();
34   g(id);
35 }
36
37 }  // anonymous namespace
38
39 template <class InputIterator, class F>
40 inline void forEach(InputIterator first, InputIterator last, F&& f) {
41   if (first == last) {
42     return;
43   }
44
45   typedef typename std::iterator_traits<InputIterator>::value_type FuncType;
46
47   size_t tasksTodo = 1;
48   std::exception_ptr e;
49   Baton baton;
50
51 #ifdef __clang__
52 #pragma clang diagnostic push // ignore generalized lambda capture warning
53 #pragma clang diagnostic ignored "-Wc++1y-extensions"
54 #endif
55   auto taskFunc =
56     [&tasksTodo, &e, &f, &baton] (size_t id, FuncType&& func) {
57     return [id, &tasksTodo, &e, &f, &baton,
58             func_ = std::forward<FuncType>(func)]() mutable {
59         try {
60           callFuncs(std::forward<FuncType>(func_), f, id);
61         } catch (...) {
62           e = std::current_exception();
63         }
64         if (--tasksTodo == 0) {
65           baton.post();
66         }
67       };
68     };
69 #ifdef __clang__
70 #pragma clang diagnostic pop
71 #endif
72
73   auto firstTask = first;
74   ++first;
75
76   for (size_t i = 1; first != last; ++i, ++first, ++tasksTodo) {
77     addTask(taskFunc(i, std::move(*first)));
78   }
79
80   taskFunc(0, std::move(*firstTask))();
81   baton.wait();
82
83   if (e != std::exception_ptr()) {
84     std::rethrow_exception(e);
85   }
86 }
87
88 }}  // folly::fibers