Chinmay Garde b111a13d25 Allow embedders to post Dart objects on send ports from the native side. (flutter/engine#14477)
This is a non-breaking addition to the stable Flutter Embedder API and exposes a
subset of the functionality provided by Dart_PostCObject API in a stable and
tested manner to custom embedder implementations.

Send port acquisition can currently be done as described in the unit-test but
there may be opportunities to extend this API in the future to access ports more
easily or create ports from the native side.

The following capabilities of the the Dart_PostCObject API are explicitly NOT
exposed:
* Object arrays: This allows callers to create complex object graphs but only
  using the primitives specified in the native API. I could find no current use
  case for this and would have made the implementation a lot more complex. This
  is something we can add in the future if necessary however.
* Capabilities and ports: Again no use cases and I honestly I didn’t understand
  how to use capabilities. If needed, these can be added at a later point by
  appending to the union.

Fixes https://github.com/flutter/flutter/issues/46624
Fixes b/145982720
2019-12-13 17:28:21 -08:00

65 lines
2.0 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 {
public:
ScopedCleanupClosure() = default;
ScopedCleanupClosure(const fml::closure& closure) : closure_(closure) {}
~ScopedCleanupClosure() {
if (closure_) {
closure_();
}
}
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;
}
private:
fml::closure closure_;
FML_DISALLOW_COPY_AND_ASSIGN(ScopedCleanupClosure);
};
} // namespace fml
#endif // FLUTTER_FML_CLOSURE_H_