proxygen
AddTasks-inl.h
Go to the documentation of this file.
1 /*
2  * Copyright 2014-present 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 <memory>
17 #include <vector>
18 
19 namespace folly {
20 namespace fibers {
21 
22 template <typename T>
24  : context_(std::move(other.context_)), id_(other.id_), fm_(other.fm_) {}
25 
26 template <typename T>
27 inline bool TaskIterator<T>::hasCompleted() const {
28  return context_->tasksConsumed < context_->results.size();
29 }
30 
31 template <typename T>
32 inline bool TaskIterator<T>::hasPending() const {
33  return !context_.unique();
34 }
35 
36 template <typename T>
37 inline bool TaskIterator<T>::hasNext() const {
38  return hasPending() || hasCompleted();
39 }
40 
41 template <typename T>
43  assert(hasCompleted() || hasPending());
44  reserve(1);
45 
46  size_t i = context_->tasksConsumed++;
47  id_ = context_->results[i].first;
48  return std::move(context_->results[i].second);
49 }
50 
51 template <typename T>
53  return std::move(awaitNextResult().value());
54 }
55 
56 template <>
58  awaitNextResult().value();
59 }
60 
61 template <typename T>
62 inline void TaskIterator<T>::reserve(size_t n) {
63  size_t tasksReady = context_->results.size() - context_->tasksConsumed;
64 
65  // we don't need to do anything if there are already n or more tasks complete
66  // or if we have no tasks left to execute.
67  if (!hasPending() || tasksReady >= n) {
68  return;
69  }
70 
71  n -= tasksReady;
72  size_t tasksLeft = context_->totalTasks - context_->results.size();
73  n = std::min(n, tasksLeft);
74 
75  await([this, n](Promise<void> promise) {
76  context_->tasksToFulfillPromise = n;
77  context_->promise.assign(std::move(promise));
78  });
79 }
80 
81 template <typename T>
82 inline size_t TaskIterator<T>::getTaskID() const {
83  assert(id_ != static_cast<size_t>(-1));
84  return id_;
85 }
86 
87 template <typename T>
88 template <typename F>
89 void TaskIterator<T>::addTask(F&& func) {
90  static_assert(
91  std::is_convertible<invoke_result_t<F>, T>::value,
92  "TaskIterator<T>: T must be convertible from func()'s return type");
93 
94  auto taskId = context_->totalTasks++;
95 
96  fm_.addTask(
97  [taskId, context = context_, func = std::forward<F>(func)]() mutable {
98  context->results.emplace_back(
99  taskId, folly::makeTryWith(std::move(func)));
100 
101  // Check for awaiting iterator.
102  if (context->promise.hasValue()) {
103  if (--context->tasksToFulfillPromise == 0) {
104  context->promise->setValue();
105  context->promise.clear();
106  }
107  }
108  });
109 }
110 
111 template <class InputIterator>
114 addTasks(InputIterator first, InputIterator last) {
115  typedef invoke_result_t<
116  typename std::iterator_traits<InputIterator>::value_type>
117  ResultType;
118  typedef TaskIterator<ResultType> IteratorType;
119 
120  IteratorType iterator;
121 
122  for (; first != last; ++first) {
123  iterator.addTask(std::move(*first));
124  }
125 
126  iterator.context_->results.reserve(iterator.context_->totalTasks);
127 
128  return std::move(iterator);
129 }
130 } // namespace fibers
131 } // namespace folly
folly::Try< T > awaitNextResult()
Definition: AddTasks-inl.h:42
typename invoke_result< F, Args... >::type invoke_result_t
Definition: Invoke.h:142
context
Definition: CMakeCache.txt:563
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
STL namespace.
folly::std T
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
requires E e noexcept(noexcept(s.error(std::move(e))))
LogLevel min
Definition: LogLevel.cpp:30
size_t getTaskID() const
Definition: AddTasks-inl.h:82
TaskIterator< invoke_result_t< typename std::iterator_traits< InputIterator >::value_type > > addTasks(InputIterator first, InputIterator last)
Definition: AddTasks-inl.h:114
std::enable_if< std::is_integral< Src >::value &&IsSomeString< Tgt >::value &&sizeof(Src)< 4 >::typetoAppend(Src value, Tgt *result){typedef typename std::conditional< std::is_signed< Src >::value, int64_t, uint64_t >::type Intermediate;toAppend< Tgt >static_cast< Intermediate >value), result);}template< class Src >typename std::enable_if< std::is_integral< Src >::value &&sizeof(Src)< 4 &&!std::is_same< Src, char >::value, size_t >::typeestimateSpaceNeeded(Src value){typedef typename std::conditional< std::is_signed< Src >::value, int64_t, uint64_t >::type Intermediate;return estimateSpaceNeeded(static_cast< Intermediate >value));}template< class Tgt, class Src >typename std::enable_if< std::is_enum< Src >::value &&IsSomeString< Tgt >::value >::typetoAppend(Src value, Tgt *result){toAppend(static_cast< typename std::underlying_type< Src >::type >value), result);}template< class Src >typename std::enable_if< std::is_enum< Src >::value, size_t >::typeestimateSpaceNeeded(Src value){return estimateSpaceNeeded(static_cast< typename std::underlying_type< Src >::type >value));}namespace detail{constexpr int kConvMaxDecimalInShortestLow=-6;constexpr int kConvMaxDecimalInShortestHigh=21;}template< class Tgt, class Src >typename std::enable_if< std::is_floating_point< Src >::value &&IsSomeString< Tgt >::value >::typetoAppend(Src value, Tgt *result, double_conversion::DoubleToStringConverter::DtoaMode mode, unsigned int numDigits){using namespace double_conversion;DoubleToStringConverter conv(DoubleToStringConverter::NO_FLAGS,"Infinity","NaN", 'E', detail::kConvMaxDecimalInShortestLow, detail::kConvMaxDecimalInShortestHigh, 6, 1);char buffer[256];StringBuilder builder(buffer, sizeof(buffer));switch(mode){case DoubleToStringConverter::SHORTEST:conv.ToShortest(value,&builder);break;case DoubleToStringConverter::SHORTEST_SINGLE:conv.ToShortestSingle(static_cast< float >value),&builder);break;case DoubleToStringConverter::FIXED:conv.ToFixed(value, int(numDigits),&builder);break;default:CHECK(mode==DoubleToStringConverter::PRECISION);conv.ToPrecision(value, int(numDigits),&builder);break;}const size_t length=size_t(builder.position());builder.Finalize();result->append(buffer, length);}template< class Tgt, class Src >typename std::enable_if< std::is_floating_point< Src >::value &&IsSomeString< Tgt >::value >::typetoAppend(Src value, Tgt *result){toAppend(value, result, double_conversion::DoubleToStringConverter::SHORTEST, 0);}template< class Src >typename std::enable_if< std::is_floating_point< Src >::value, size_t >::typeestimateSpaceNeeded(Src value){constexpr int kMaxMantissaSpace=double_conversion::DoubleToStringConverter::kBase10MaximalLength+1;constexpr int kMaxExponentSpace=2+3;static const int kMaxPositiveSpace=std::max({kMaxMantissaSpace+kMaxExponentSpace, kMaxMantissaSpace-detail::kConvMaxDecimalInShortestLow, detail::kConvMaxDecimalInShortestHigh,});return size_t(kMaxPositiveSpace+(value< 0?1:0));}template< class Src >struct HasLengthEstimator:std::false_type{};template< class Src >constexpr typename std::enable_if< !std::is_fundamental< Src >::value &&!IsSomeString< Src >::value &&!std::is_convertible< Src, const char * >::value &&!std::is_convertible< Src, StringPiece >::value &&!std::is_enum< Src >::value &&!HasLengthEstimator< Src >::value, size_t >::typeestimateSpaceNeeded(const Src &){return sizeof(Src)+1;}namespace detail{template< class Tgt >typename std::enable_if< IsSomeString< Tgt >::value, size_t >::typeestimateSpaceToReserve(size_t sofar, Tgt *){return sofar;}template< class T, class...Ts >size_t estimateSpaceToReserve(size_t sofar, const T &v, const Ts &...vs){return estimateSpaceToReserve(sofar+estimateSpaceNeeded(v), vs...);}template< class...Ts >void reserveInTarget(const Ts &...vs){getLastElement(vs...) -> reserve(estimateSpaceToReserve(0, vs...))
Definition: Conv.h:792
Definition: Try.h:51
std::enable_if< !std::is_same< invoke_result_t< F >, void >::value, Try< invoke_result_t< F > > >::type makeTryWith(F &&f)
Definition: Try-inl.h:223
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
constexpr detail::First first
Definition: Base-inl.h:2553
FirstArgOf< F >::type::value_type await(F &&func)