Fix a race in Observable context destruction
[folly.git] / folly / experimental / observer / Observer-inl.h
1 /*
2  * Copyright 2017 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 #pragma once
17
18 #include <folly/experimental/observer/detail/ObserverManager.h>
19
20 namespace folly {
21 namespace observer {
22
23 template <typename T>
24 Snapshot<T> Observer<T>::getSnapshot() const {
25   auto data = core_->getData();
26   return Snapshot<T>(
27       *core_,
28       std::static_pointer_cast<const T>(std::move(data.data)),
29       data.version);
30 }
31
32 template <typename T>
33 Observer<T>::Observer(observer_detail::Core::Ptr core)
34     : core_(std::move(core)) {}
35
36 template <typename F>
37 Observer<observer_detail::ResultOfUnwrapSharedPtr<F>> makeObserver(
38     F&& creator) {
39   auto core = observer_detail::Core::
40       create([creator = std::forward<F>(creator)]() mutable {
41         return std::static_pointer_cast<const void>(creator());
42       });
43
44   observer_detail::ObserverManager::initCore(core);
45
46   return Observer<observer_detail::ResultOfUnwrapSharedPtr<F>>(core);
47 }
48
49 template <typename F>
50 Observer<observer_detail::ResultOf<F>> makeObserver(F&& creator) {
51   return makeObserver([creator = std::forward<F>(creator)]() mutable {
52     return std::make_shared<observer_detail::ResultOf<F>>(creator());
53   });
54 }
55
56 template <typename T>
57 TLObserver<T>::TLObserver(Observer<T> observer)
58     : observer_(observer),
59       snapshot_([&] { return new Snapshot<T>(observer_.getSnapshot()); }) {}
60
61 template <typename T>
62 TLObserver<T>::TLObserver(const TLObserver<T>& other)
63     : TLObserver(other.observer_) {}
64
65 template <typename T>
66 const Snapshot<T>& TLObserver<T>::getSnapshotRef() const {
67   auto& snapshot = *snapshot_;
68   if (observer_.needRefresh(snapshot) ||
69       observer_detail::ObserverManager::inManagerThread()) {
70     snapshot = observer_.getSnapshot();
71   }
72
73   return snapshot;
74 }
75 }
76 }