1 | // Copyright 2013 The Flutter Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | #ifndef FLUTTER_FML_CLOSURE_H_ |
6 | #define FLUTTER_FML_CLOSURE_H_ |
7 | |
8 | #include <functional> |
9 | |
10 | #include "flutter/fml/macros.h" |
11 | |
12 | namespace fml { |
13 | |
14 | using closure = std::function<void()>; |
15 | |
16 | //------------------------------------------------------------------------------ |
17 | /// @brief Wraps a closure that is invoked in the destructor unless |
18 | /// released by the caller. |
19 | /// |
20 | /// This is especially useful in dealing with APIs that return a |
21 | /// resource by accepting ownership of a sub-resource and a closure |
22 | /// that releases that resource. When such APIs are chained, each |
23 | /// link in the chain must check that the next member in the chain |
24 | /// has accepted the resource. If not, it must invoke the closure |
25 | /// eagerly. Not doing this results in a resource leak in the |
26 | /// erroneous case. Using this wrapper, the closure can be released |
27 | /// once the next call in the chain has successfully accepted |
28 | /// ownership of the resource. If not, the closure gets invoked |
29 | /// automatically at the end of the scope. This covers the cases |
30 | /// where there are early returns as well. |
31 | /// |
32 | class ScopedCleanupClosure { |
33 | public: |
34 | ScopedCleanupClosure() = default; |
35 | |
36 | ScopedCleanupClosure(const fml::closure& closure) : closure_(closure) {} |
37 | |
38 | ~ScopedCleanupClosure() { |
39 | if (closure_) { |
40 | closure_(); |
41 | } |
42 | } |
43 | |
44 | fml::closure SetClosure(const fml::closure& closure) { |
45 | auto old_closure = closure_; |
46 | closure_ = closure; |
47 | return old_closure; |
48 | } |
49 | |
50 | fml::closure Release() { |
51 | fml::closure closure = closure_; |
52 | closure_ = nullptr; |
53 | return closure; |
54 | } |
55 | |
56 | private: |
57 | fml::closure closure_; |
58 | |
59 | FML_DISALLOW_COPY_AND_ASSIGN(ScopedCleanupClosure); |
60 | }; |
61 | |
62 | } // namespace fml |
63 | |
64 | #endif // FLUTTER_FML_CLOSURE_H_ |
65 | |