Chromium Code Reviews| Index: mojo/public/cpp/bindings/strong_binding.h |
| diff --git a/mojo/public/cpp/bindings/strong_binding.h b/mojo/public/cpp/bindings/strong_binding.h |
| index 99d10956c6f040e2835ff9f705f713f38486a641..f2efeb293da39ca1f739429e8644718cda50bb88 100644 |
| --- a/mojo/public/cpp/bindings/strong_binding.h |
| +++ b/mojo/public/cpp/bindings/strong_binding.h |
| @@ -31,6 +31,33 @@ class StrongBinding; |
| template <typename Interface> |
| using StrongBindingPtr = base::WeakPtr<StrongBinding<Interface>>; |
| +// Interface implementations must inherit this in order to support being |
| +// strongly bound to a message pipe. |
| +template <typename Interface> |
| +class SupportsStrongBinding : public Interface { |
| + public: |
| + virtual ~SupportsStrongBinding() { |
| + if (binding_) { |
| + // Dissociate |this| from the binding before closing it. |
| + ignore_result(binding_->Release().release()); |
| + |
| + // Deletes |*binding_|. |
| + binding_->Close(); |
| + } |
| + } |
| + |
| + private: |
| + friend class StrongBinding<Interface>; |
| + |
| + void set_binding(const StrongBindingPtr<Interface>& binding) { |
| + binding_ = binding; |
| + } |
| + |
| + StrongBindingPtr<Interface> binding_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(SupportsStrongBinding); |
| +}; |
| + |
| // This connects an interface implementation strongly to a pipe. When a |
| // connection error is detected the implementation is deleted. |
| // |
| @@ -46,12 +73,19 @@ class StrongBinding { |
| // Create a new StrongBinding instance. The instance owns itself, cleaning up |
| // only in the event of a pipe connection error. Returns a WeakPtr to the new |
| // StrongBinding instance. |
| + // |
| + // Note that it's also safe for |impl| to delete itself at any time. |
| + template <typename Impl> |
| static StrongBindingPtr<Interface> Create( |
|
dcheng
2016/11/21 10:42:12
Would this still need to return a weak pointer to
|
| - std::unique_ptr<Interface> impl, |
| + std::unique_ptr<Impl> impl, |
| InterfaceRequest<Interface> request) { |
| + SupportsStrongBinding<Interface>* raw_impl = impl.get(); |
| StrongBinding* binding = |
| new StrongBinding(std::move(impl), std::move(request)); |
| - return binding->weak_factory_.GetWeakPtr(); |
| + StrongBindingPtr<Interface> weak_binding = |
| + binding->weak_factory_.GetWeakPtr(); |
| + raw_impl->set_binding(weak_binding); |
| + return weak_binding; |
| } |
| // Note: The error handler must not delete the interface implementation. |
| @@ -74,6 +108,10 @@ class StrongBinding { |
| // Forces the binding to close. This destroys the StrongBinding instance. |
| void Close() { delete this; } |
| + std::unique_ptr<Interface> Release() WARN_UNUSED_RESULT { |
| + return std::move(impl_); |
| + } |
| + |
| Interface* impl() { return impl_.get(); } |
| // Exposed for testing, should not generally be used. |
| @@ -95,7 +133,12 @@ class StrongBinding { |
| base::Bind(&StrongBinding::OnConnectionError, base::Unretained(this))); |
| } |
| - ~StrongBinding() {} |
| + ~StrongBinding() { |
| + // Ensure any WeakPtrs are invalidated *before* |impl_| is destroyed, |
| + // otherwise the |impl_|'s destructor will attempt to reenter this object to |
| + // Close it. |
| + weak_factory_.InvalidateWeakPtrs(); |
| + } |
| void OnConnectionError(uint32_t custom_reason, |
| const std::string& description) { |
| @@ -115,6 +158,7 @@ class StrongBinding { |
| DISALLOW_COPY_AND_ASSIGN(StrongBinding); |
| }; |
| +// Convenient helper wrapping StrongBinding::Create. See above. |
| template <typename Interface, typename Impl> |
| StrongBindingPtr<Interface> MakeStrongBinding( |
| std::unique_ptr<Impl> impl, |