77 lines
2.2 KiB
C++
77 lines
2.2 KiB
C++
// Copyright 2013 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef FLUTTER_FML_CLOSURE_H_
|
|
#define FLUTTER_FML_CLOSURE_H_
|
|
|
|
#include <functional>
|
|
|
|
#include "flutter/fml/macros.h"
|
|
|
|
namespace fml {
|
|
|
|
using closure = std::function<void()>;
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// @brief Wraps a closure that is invoked in the destructor unless
|
|
/// released by the caller.
|
|
///
|
|
/// This is especially useful in dealing with APIs that return a
|
|
/// resource by accepting ownership of a sub-resource and a closure
|
|
/// that releases that resource. When such APIs are chained, each
|
|
/// link in the chain must check that the next member in the chain
|
|
/// has accepted the resource. If not, it must invoke the closure
|
|
/// eagerly. Not doing this results in a resource leak in the
|
|
/// erroneous case. Using this wrapper, the closure can be released
|
|
/// once the next call in the chain has successfully accepted
|
|
/// ownership of the resource. If not, the closure gets invoked
|
|
/// automatically at the end of the scope. This covers the cases
|
|
/// where there are early returns as well.
|
|
///
|
|
class ScopedCleanupClosure final {
|
|
public:
|
|
ScopedCleanupClosure() = default;
|
|
|
|
ScopedCleanupClosure(ScopedCleanupClosure&& other) {
|
|
closure_ = other.Release();
|
|
}
|
|
|
|
ScopedCleanupClosure& operator=(ScopedCleanupClosure&& other) {
|
|
closure_ = other.Release();
|
|
return *this;
|
|
}
|
|
|
|
explicit ScopedCleanupClosure(const fml::closure& closure)
|
|
: closure_(closure) {}
|
|
|
|
~ScopedCleanupClosure() { Reset(); }
|
|
|
|
fml::closure SetClosure(const fml::closure& closure) {
|
|
auto old_closure = closure_;
|
|
closure_ = closure;
|
|
return old_closure;
|
|
}
|
|
|
|
fml::closure Release() {
|
|
fml::closure closure = closure_;
|
|
closure_ = nullptr;
|
|
return closure;
|
|
}
|
|
|
|
void Reset() {
|
|
if (closure_) {
|
|
closure_();
|
|
closure_ = nullptr;
|
|
}
|
|
}
|
|
|
|
private:
|
|
fml::closure closure_;
|
|
|
|
FML_DISALLOW_COPY_AND_ASSIGN(ScopedCleanupClosure);
|
|
};
|
|
|
|
} // namespace fml
|
|
|
|
#endif // FLUTTER_FML_CLOSURE_H_
|