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
12namespace fml {
13
14using 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///
32class 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