2 * Copyright 2014 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 #include <type_traits>
22 #include <folly/Optional.h>
26 //////////////////////////////////////////////////////////////////////
29 * Lazy -- for delayed initialization of a value. The value's
30 * initialization will be computed on demand at its first use, but
31 * will not be recomputed if its value is requested again. The value
32 * may still be mutated after its initialization if the lazy is not
35 * The value is created using folly::lazy, usually with a lambda, and
36 * its value is requested using operator().
38 * Note that the value is not safe for concurrent accesses by multiple
39 * threads, even if you declare it const. See note below.
45 * auto const val = folly::lazy([&]{
46 * return something_expensive(blah());
53 * useMaybeAgain(val());
55 * // Unneeded in this branch.
62 * - operator() is used to request the value instead of an implicit
63 * conversion because the slight syntactic overhead in common
64 * seems worth the increased clarity.
66 * - Lazy values do not model CopyConstructible because it is
67 * unclear what semantics would be desirable. Either copies
68 * should share the cached value (adding overhead to cases that
69 * don't need to support copies), or they could recompute the
70 * value unnecessarily. Sharing with mutable lazies would also
71 * leave them with non-value semantics despite looking
74 * - Not thread safe for const accesses. Many use cases for lazy
75 * values are local variables on the stack, where multiple
76 * threads shouldn't even be able to reach the value. It still
77 * is useful to indicate/check that the value doesn't change with
78 * const, particularly when it is captured by a large family of
79 * lambdas. Adding internal synchronization seems like it would
80 * pessimize the most common use case in favor of less likely use
85 //////////////////////////////////////////////////////////////////////
91 typedef typename std::result_of<Func()>::type result_type;
93 explicit Lazy(Func&& f) : func_(std::move(f)) {}
94 explicit Lazy(Func& f) : func_(f) {}
97 : value_(std::move(o.value_))
98 , func_(std::move(o.func_))
101 Lazy(const Lazy&) = delete;
102 Lazy& operator=(const Lazy&) = delete;
103 Lazy& operator=(Lazy&&) = delete;
105 const result_type& operator()() const {
106 return const_cast<Lazy&>(*this)();
109 result_type& operator()() {
110 if (!value_) value_ = func_();
115 Optional<result_type> value_;
121 //////////////////////////////////////////////////////////////////////
124 detail::Lazy<typename std::remove_reference<Func>::type>
126 return detail::Lazy<typename std::remove_reference<Func>::type>(
127 std::forward<Func>(fun)
131 //////////////////////////////////////////////////////////////////////