/src/abseil-cpp/absl/cleanup/cleanup.h
Line  | Count  | Source  | 
1  |  | // Copyright 2021 The Abseil Authors.  | 
2  |  | //  | 
3  |  | // Licensed under the Apache License, Version 2.0 (the "License");  | 
4  |  | // you may not use this file except in compliance with the License.  | 
5  |  | // You may obtain a copy of the License at  | 
6  |  | //  | 
7  |  | //      https://www.apache.org/licenses/LICENSE-2.0  | 
8  |  | //  | 
9  |  | // Unless required by applicable law or agreed to in writing, software  | 
10  |  | // distributed under the License is distributed on an "AS IS" BASIS,  | 
11  |  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  | 
12  |  | // See the License for the specific language governing permissions and  | 
13  |  | // limitations under the License.  | 
14  |  | //  | 
15  |  | // -----------------------------------------------------------------------------  | 
16  |  | // File: cleanup.h  | 
17  |  | // -----------------------------------------------------------------------------  | 
18  |  | //  | 
19  |  | // `absl::Cleanup` implements the scope guard idiom, invoking the contained  | 
20  |  | // callback's `operator()() &&` on scope exit.  | 
21  |  | //  | 
22  |  | // Example:  | 
23  |  | //  | 
24  |  | // ```  | 
25  |  | //   absl::Status CopyGoodData(const char* source_path, const char* sink_path) { | 
26  |  | //     FILE* source_file = fopen(source_path, "r");  | 
27  |  | //     if (source_file == nullptr) { | 
28  |  | //       return absl::NotFoundError("No source file");  // No cleanups execute | 
29  |  | //     }  | 
30  |  | //  | 
31  |  | //     // C++17 style cleanup using class template argument deduction  | 
32  |  | //     absl::Cleanup source_closer = [source_file] { fclose(source_file); }; | 
33  |  | //  | 
34  |  | //     FILE* sink_file = fopen(sink_path, "w");  | 
35  |  | //     if (sink_file == nullptr) { | 
36  |  | //       return absl::NotFoundError("No sink file");  // First cleanup executes | 
37  |  | //     }  | 
38  |  | //  | 
39  |  | //     // C++11 style cleanup using the factory function  | 
40  |  | //     auto sink_closer = absl::MakeCleanup([sink_file] { fclose(sink_file); }); | 
41  |  | //  | 
42  |  | //     Data data;  | 
43  |  | //     while (ReadData(source_file, &data)) { | 
44  |  | //       if (!data.IsGood()) { | 
45  |  | //         absl::Status result = absl::FailedPreconditionError("Read bad data"); | 
46  |  | //         return result;  // Both cleanups execute  | 
47  |  | //       }  | 
48  |  | //       SaveData(sink_file, &data);  | 
49  |  | //     }  | 
50  |  | //  | 
51  |  | //     return absl::OkStatus();  // Both cleanups execute  | 
52  |  | //   }  | 
53  |  | // ```  | 
54  |  | //  | 
55  |  | // Methods:  | 
56  |  | //  | 
57  |  | // `std::move(cleanup).Cancel()` will prevent the callback from executing.  | 
58  |  | //  | 
59  |  | // `std::move(cleanup).Invoke()` will execute the callback early, before  | 
60  |  | // destruction, and prevent the callback from executing in the destructor.  | 
61  |  | //  | 
62  |  | // Usage:  | 
63  |  | //  | 
64  |  | // `absl::Cleanup` is not an interface type. It is only intended to be used  | 
65  |  | // within the body of a function. It is not a value type and instead models a  | 
66  |  | // control flow construct. Check out `defer` in Golang for something similar.  | 
67  |  |  | 
68  |  | #ifndef ABSL_CLEANUP_CLEANUP_H_  | 
69  |  | #define ABSL_CLEANUP_CLEANUP_H_  | 
70  |  |  | 
71  |  | #include <utility>  | 
72  |  |  | 
73  |  | #include "absl/base/config.h"  | 
74  |  | #include "absl/base/macros.h"  | 
75  |  | #include "absl/cleanup/internal/cleanup.h"  | 
76  |  |  | 
77  |  | namespace absl { | 
78  |  | ABSL_NAMESPACE_BEGIN  | 
79  |  |  | 
80  |  | template <typename Arg, typename Callback = void()>  | 
81  |  | class [[nodiscard]] Cleanup final { | 
82  |  |   static_assert(cleanup_internal::WasDeduced<Arg>(),  | 
83  |  |                 "Explicit template parameters are not supported.");  | 
84  |  |  | 
85  |  |   static_assert(cleanup_internal::ReturnsVoid<Callback>(),  | 
86  |  |                 "Callbacks that return values are not supported.");  | 
87  |  |  | 
88  |  |  public:  | 
89  | 4.12M  |   Cleanup(Callback callback) : storage_(std::move(callback)) {}  // NOLINTlog_sink_set.cc:absl::Cleanup<absl::cleanup_internal::Tag, absl::log_internal::(anonymous namespace)::GlobalLogSinkSet::LogToSinks(absl::LogEntry const&, absl::Span<absl::LogSink*>, bool)::{lambda()#1}>::Cleanup({lambda()#1})Line  | Count  | Source  |  89  | 4.12M  |   Cleanup(Callback callback) : storage_(std::move(callback)) {}  // NOLINT |  
 Unexecuted instantiation: log_sink_set.cc:absl::Cleanup<absl::cleanup_internal::Tag, absl::log_internal::(anonymous namespace)::GlobalLogSinkSet::FlushLogSinks()::{lambda()#1}>::Cleanup({lambda()#1}) | 
90  |  |  | 
91  |  |   Cleanup(Cleanup&& other) = default;  | 
92  |  |  | 
93  |  |   void Cancel() && { | 
94  |  |     ABSL_HARDENING_ASSERT(storage_.IsCallbackEngaged());  | 
95  |  |     storage_.DestroyCallback();  | 
96  |  |   }  | 
97  |  |  | 
98  |  |   void Invoke() && { | 
99  |  |     ABSL_HARDENING_ASSERT(storage_.IsCallbackEngaged());  | 
100  |  |     storage_.InvokeCallback();  | 
101  |  |     storage_.DestroyCallback();  | 
102  |  |   }  | 
103  |  |  | 
104  | 4.12M  |   ~Cleanup() { | 
105  | 4.12M  |     if (storage_.IsCallbackEngaged()) { | 
106  | 4.12M  |       storage_.InvokeCallback();  | 
107  | 4.12M  |       storage_.DestroyCallback();  | 
108  | 4.12M  |     }  | 
109  | 4.12M  |   } log_sink_set.cc:absl::Cleanup<absl::cleanup_internal::Tag, absl::log_internal::(anonymous namespace)::GlobalLogSinkSet::LogToSinks(absl::LogEntry const&, absl::Span<absl::LogSink*>, bool)::{lambda()#1}>::~Cleanup()Line  | Count  | Source  |  104  | 4.12M  |   ~Cleanup() { |  105  | 4.12M  |     if (storage_.IsCallbackEngaged()) { |  106  | 4.12M  |       storage_.InvokeCallback();  |  107  | 4.12M  |       storage_.DestroyCallback();  |  108  | 4.12M  |     }  |  109  | 4.12M  |   }  |  
 Unexecuted instantiation: log_sink_set.cc:absl::Cleanup<absl::cleanup_internal::Tag, absl::log_internal::(anonymous namespace)::GlobalLogSinkSet::FlushLogSinks()::{lambda()#1}>::~Cleanup() | 
110  |  |  | 
111  |  |  private:  | 
112  |  |   cleanup_internal::Storage<Callback> storage_;  | 
113  |  | };  | 
114  |  |  | 
115  |  | // `absl::Cleanup c = /* callback */;`  | 
116  |  | //  | 
117  |  | // C++17 type deduction API for creating an instance of `absl::Cleanup`  | 
118  |  | template <typename Callback>  | 
119  |  | Cleanup(Callback callback) -> Cleanup<cleanup_internal::Tag, Callback>;  | 
120  |  |  | 
121  |  | // `auto c = absl::MakeCleanup(/* callback */);`  | 
122  |  | //  | 
123  |  | // C++11 type deduction API for creating an instance of `absl::Cleanup`  | 
124  |  | template <typename... Args, typename Callback>  | 
125  | 4.12M  | absl::Cleanup<cleanup_internal::Tag, Callback> MakeCleanup(Callback callback) { | 
126  | 4.12M  |   static_assert(cleanup_internal::WasDeduced<cleanup_internal::Tag, Args...>(),  | 
127  | 4.12M  |                 "Explicit template parameters are not supported.");  | 
128  |  |  | 
129  | 4.12M  |   static_assert(cleanup_internal::ReturnsVoid<Callback>(),  | 
130  | 4.12M  |                 "Callbacks that return values are not supported.");  | 
131  |  |  | 
132  | 4.12M  |   return {std::move(callback)}; | 
133  | 4.12M  | } log_sink_set.cc:absl::Cleanup<absl::cleanup_internal::Tag, absl::log_internal::(anonymous namespace)::GlobalLogSinkSet::LogToSinks(absl::LogEntry const&, absl::Span<absl::LogSink*>, bool)::{lambda()#1}> absl::MakeCleanup<, absl::log_internal::(anonymous namespace)::GlobalLogSinkSet::LogToSinks(absl::LogEntry const&, absl::Span<absl::LogSink*>, bool)::{lambda()#1}>(absl::cleanup_internal::Tag)Line  | Count  | Source  |  125  | 4.12M  | absl::Cleanup<cleanup_internal::Tag, Callback> MakeCleanup(Callback callback) { |  126  | 4.12M  |   static_assert(cleanup_internal::WasDeduced<cleanup_internal::Tag, Args...>(),  |  127  | 4.12M  |                 "Explicit template parameters are not supported.");  |  128  |  |  |  129  | 4.12M  |   static_assert(cleanup_internal::ReturnsVoid<Callback>(),  |  130  | 4.12M  |                 "Callbacks that return values are not supported.");  |  131  |  |  |  132  | 4.12M  |   return {std::move(callback)}; |  133  | 4.12M  | }  |  
 Unexecuted instantiation: log_sink_set.cc:absl::Cleanup<absl::cleanup_internal::Tag, absl::log_internal::(anonymous namespace)::GlobalLogSinkSet::FlushLogSinks()::{lambda()#1}> absl::MakeCleanup<, absl::log_internal::(anonymous namespace)::GlobalLogSinkSet::FlushLogSinks()::{lambda()#1}>(absl::cleanup_internal::Tag) | 
134  |  |  | 
135  |  | ABSL_NAMESPACE_END  | 
136  |  | }  // namespace absl  | 
137  |  |  | 
138  |  | #endif  // ABSL_CLEANUP_CLEANUP_H_  |