proxygen
Lazy.h
Go to the documentation of this file.
1 /*
2  * Copyright 2013-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 
17 #pragma once
18 
19 #include <type_traits>
20 #include <utility>
21 
22 #include <folly/Optional.h>
24 
25 namespace folly {
26 
28 
29 /*
30  * Lazy -- for delayed initialization of a value. The value's
31  * initialization will be computed on demand at its first use, but
32  * will not be recomputed if its value is requested again. The value
33  * may still be mutated after its initialization if the lazy is not
34  * declared const.
35  *
36  * The value is created using folly::lazy, usually with a lambda, and
37  * its value is requested using operator().
38  *
39  * Note that the value is not safe for concurrent accesses by multiple
40  * threads, even if you declare it const. See note below.
41  *
42  *
43  * Example Usage:
44  *
45  * void foo() {
46  * auto const val = folly::lazy([&]{
47  * return something_expensive(blah());
48  * });
49  *
50  * if (condition1) {
51  * use(val());
52  * }
53  * if (condition2) {
54  * useMaybeAgain(val());
55  * } else {
56  * // Unneeded in this branch.
57  * }
58  * }
59  *
60  *
61  * Rationale:
62  *
63  * - operator() is used to request the value instead of an implicit
64  * conversion because the slight syntactic overhead in common
65  * seems worth the increased clarity.
66  *
67  * - Lazy values do not model CopyConstructible because it is
68  * unclear what semantics would be desirable. Either copies
69  * should share the cached value (adding overhead to cases that
70  * don't need to support copies), or they could recompute the
71  * value unnecessarily. Sharing with mutable lazies would also
72  * leave them with non-value semantics despite looking
73  * value-like.
74  *
75  * - Not thread safe for const accesses. Many use cases for lazy
76  * values are local variables on the stack, where multiple
77  * threads shouldn't even be able to reach the value. It still
78  * is useful to indicate/check that the value doesn't change with
79  * const, particularly when it is captured by a large family of
80  * lambdas. Adding internal synchronization seems like it would
81  * pessimize the most common use case in favor of less likely use
82  * cases.
83  *
84  */
85 
87 
88 namespace detail {
89 
90 template <class Func>
91 struct Lazy {
93 
94  static_assert(
96  "Func should not be a const-qualified type");
97  static_assert(
99  "Func should not be a reference type");
100 
101  explicit Lazy(Func&& f) : func_(std::move(f)) {}
102  explicit Lazy(const Func& f) : func_(f) {}
103 
104  Lazy(Lazy&& o) : value_(std::move(o.value_)), func_(std::move(o.func_)) {}
105 
106  Lazy(const Lazy&) = delete;
107  Lazy& operator=(const Lazy&) = delete;
108  Lazy& operator=(Lazy&&) = delete;
109 
110  const result_type& operator()() const {
112 
113  return *value_;
114  }
115 
116  result_type& operator()() {
118 
119  return *value_;
120  }
121 
122  private:
123  void ensure_initialized() const {
124  if (!value_) {
125  value_ = func_();
126  }
127  }
128 
130  mutable Func func_;
131 };
132 
133 } // namespace detail
134 
136 
137 template <class Func>
138 auto lazy(Func&& fun) {
139  return detail::Lazy<remove_cvref_t<Func>>(std::forward<Func>(fun));
140 }
141 
143 
144 } // namespace folly
result_type & operator()()
Definition: Lazy.h:116
auto lazy(Func &&fun)
Definition: Lazy.h:138
invoke_result_t< Func > result_type
Definition: Lazy.h:92
auto f
typename invoke_result< F, Args... >::type invoke_result_t
Definition: Invoke.h:142
Optional< result_type > value_
Definition: Lazy.h:129
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
STL namespace.
Lazy(const Func &f)
Definition: Lazy.h:102
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
Lazy & operator=(const Lazy &)=delete
void ensure_initialized() const
Definition: Lazy.h:123
Lazy(Func &&f)
Definition: Lazy.h:101
static const char *const value
Definition: Conv.cpp:50
const result_type & operator()() const
Definition: Lazy.h:110
void fun()
Lazy(Lazy &&o)
Definition: Lazy.h:104