forked from flutter/engine
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add fml::WeakPtr and update users in Shell. (flutter#4296)
- Loading branch information
1 parent
ac16530
commit 19e690e
Showing
26 changed files
with
532 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
// Copyright 2016 The Fuchsia Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
// This file provides weak pointers and weak pointer factories that work like | ||
// Chromium's |base::WeakPtr<T>| and |base::WeakPtrFactory<T>|. | ||
|
||
#ifndef FLUTTER_FML_MEMORY_WEAK_PTR_H_ | ||
#define FLUTTER_FML_MEMORY_WEAK_PTR_H_ | ||
|
||
#include <utility> | ||
|
||
#include "flutter/fml/memory/weak_ptr_internal.h" | ||
#include "lib/fxl/logging.h" | ||
#include "lib/fxl/memory/ref_counted.h" | ||
|
||
namespace fml { | ||
|
||
// Forward declaration, so |WeakPtr<T>| can friend it. | ||
template <typename T> | ||
class WeakPtrFactory; | ||
|
||
// Class for "weak pointers" that can be invalidated. Valid weak pointers can | ||
// only originate from a |WeakPtrFactory| (see below), though weak pointers are | ||
// copyable and movable. | ||
// | ||
// Weak pointers are not in general thread-safe. They may only be *used* on a | ||
// single thread, namely the same thread as the "originating" |WeakPtrFactory| | ||
// (which can invalidate the weak pointers that it generates). | ||
// | ||
// However, weak pointers may be passed to other threads, reset on other | ||
// threads, or destroyed on other threads. They may also be reassigned on other | ||
// threads (in which case they should then only be used on the thread | ||
// corresponding to the new "originating" |WeakPtrFactory|). | ||
template <typename T> | ||
class WeakPtr { | ||
public: | ||
WeakPtr() : ptr_(nullptr) {} | ||
|
||
// Copy constructor. | ||
WeakPtr(const WeakPtr<T>& r) = default; | ||
|
||
template <typename U> | ||
WeakPtr(const WeakPtr<U>& r) : ptr_(r.ptr_), flag_(r.flag_) {} | ||
|
||
// Move constructor. | ||
WeakPtr(WeakPtr<T>&& r) = default; | ||
|
||
template <typename U> | ||
WeakPtr(WeakPtr<U>&& r) : ptr_(r.ptr_), flag_(std::move(r.flag_)) {} | ||
|
||
~WeakPtr() = default; | ||
|
||
// The following methods are thread-friendly, in the sense that they may be | ||
// called subject to additional synchronization. | ||
|
||
// Copy assignment. | ||
WeakPtr<T>& operator=(const WeakPtr<T>& r) = default; | ||
|
||
// Move assignment. | ||
WeakPtr<T>& operator=(WeakPtr<T>&& r) = default; | ||
|
||
void reset() { flag_ = nullptr; } | ||
|
||
// The following methods should only be called on the same thread as the | ||
// "originating" |WeakPtrFactory|. | ||
|
||
explicit operator bool() const { return flag_ && flag_->is_valid(); } | ||
|
||
T* get() const { return *this ? ptr_ : nullptr; } | ||
|
||
T& operator*() const { | ||
FXL_DCHECK(*this); | ||
return *get(); | ||
} | ||
|
||
T* operator->() const { | ||
FXL_DCHECK(*this); | ||
return get(); | ||
} | ||
|
||
private: | ||
template <typename U> | ||
friend class WeakPtr; | ||
|
||
friend class WeakPtrFactory<T>; | ||
|
||
explicit WeakPtr(T* ptr, fxl::RefPtr<fml::internal::WeakPtrFlag>&& flag) | ||
: ptr_(ptr), flag_(std::move(flag)) {} | ||
|
||
T* ptr_; | ||
fxl::RefPtr<fml::internal::WeakPtrFlag> flag_; | ||
|
||
// Copy/move construction/assignment supported. | ||
}; | ||
|
||
// Class that produces (valid) |WeakPtr<T>|s. Typically, this is used as a | ||
// member variable of |T| (preferably the last one -- see below), and |T|'s | ||
// methods control how weak pointers to it are vended. This class is not | ||
// thread-safe, and should only be created, destroyed and used on a single | ||
// thread. | ||
// | ||
// Example: | ||
// | ||
// class Controller { | ||
// public: | ||
// Controller() : ..., weak_factory_(this) {} | ||
// ... | ||
// | ||
// void SpawnWorker() { Worker::StartNew(weak_factory_.GetWeakPtr()); } | ||
// void WorkComplete(const Result& result) { ... } | ||
// | ||
// private: | ||
// ... | ||
// | ||
// // Member variables should appear before the |WeakPtrFactory|, to ensure | ||
// // that any |WeakPtr|s to |Controller| are invalidated before its member | ||
// // variables' destructors are executed. | ||
// WeakPtrFactory<Controller> weak_factory_; | ||
// }; | ||
// | ||
// class Worker { | ||
// public: | ||
// static void StartNew(const WeakPtr<Controller>& controller) { | ||
// Worker* worker = new Worker(controller); | ||
// // Kick off asynchronous processing.... | ||
// } | ||
// | ||
// private: | ||
// Worker(const WeakPtr<Controller>& controller) : controller_(controller) {} | ||
// | ||
// void DidCompleteAsynchronousProcessing(const Result& result) { | ||
// if (controller_) | ||
// controller_->WorkComplete(result); | ||
// } | ||
// | ||
// WeakPtr<Controller> controller_; | ||
// }; | ||
template <typename T> | ||
class WeakPtrFactory { | ||
public: | ||
explicit WeakPtrFactory(T* ptr) : ptr_(ptr) { FXL_DCHECK(ptr_); } | ||
~WeakPtrFactory() { InvalidateWeakPtrs(); } | ||
|
||
// Gets a new weak pointer, which will be valid until either | ||
// |InvalidateWeakPtrs()| is called or this object is destroyed. | ||
WeakPtr<T> GetWeakPtr() { | ||
if (!flag_) | ||
flag_ = fxl::MakeRefCounted<fml::internal::WeakPtrFlag>(); | ||
return WeakPtr<T>(ptr_, flag_.Clone()); | ||
} | ||
|
||
// Call this method to invalidate all existing weak pointers. (Note that | ||
// additional weak pointers can be produced even after this is called.) | ||
void InvalidateWeakPtrs() { | ||
if (!flag_) | ||
return; | ||
flag_->Invalidate(); | ||
flag_ = nullptr; | ||
} | ||
|
||
// Call this method to determine if any weak pointers exist. (Note that a | ||
// "false" result is definitive, but a "true" result may not be if weak | ||
// pointers are held/reset/destroyed/reassigned on other threads.) | ||
bool HasWeakPtrs() const { return flag_ && !flag_->HasOneRef(); } | ||
|
||
private: | ||
// Note: See weak_ptr_internal.h for an explanation of why we store the | ||
// pointer here, instead of in the "flag". | ||
T* const ptr_; | ||
fxl::RefPtr<fml::internal::WeakPtrFlag> flag_; | ||
|
||
FXL_DISALLOW_COPY_AND_ASSIGN(WeakPtrFactory); | ||
}; | ||
|
||
} // namespace fml | ||
|
||
#endif // FLUTTER_FML_MEMORY_WEAK_PTR_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// Copyright 2016 The Fuchsia Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "flutter/fml/memory/weak_ptr_internal.h" | ||
|
||
#include "lib/fxl/logging.h" | ||
|
||
namespace fml { | ||
namespace internal { | ||
|
||
WeakPtrFlag::WeakPtrFlag() : is_valid_(true) {} | ||
|
||
WeakPtrFlag::~WeakPtrFlag() { | ||
// Should be invalidated before destruction. | ||
FXL_DCHECK(!is_valid_); | ||
} | ||
|
||
void WeakPtrFlag::Invalidate() { | ||
// Invalidation should happen exactly once. | ||
FXL_DCHECK(is_valid_); | ||
is_valid_ = false; | ||
} | ||
|
||
} // namespace internal | ||
} // namespace fml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// Copyright 2016 The Fuchsia 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_MEMORY_WEAK_PTR_INTERNAL_H_ | ||
#define FLUTTER_FML_MEMORY_WEAK_PTR_INTERNAL_H_ | ||
|
||
#include "lib/fxl/macros.h" | ||
#include "lib/fxl/memory/ref_counted.h" | ||
|
||
namespace fml { | ||
namespace internal { | ||
|
||
// |WeakPtr<T>|s have a reference to a |WeakPtrFlag| to determine whether they | ||
// are valid (non-null) or not. We do not store a |T*| in this object since | ||
// there may also be |WeakPtr<U>|s to the same object, where |U| is a superclass | ||
// of |T|. | ||
// | ||
// This class in not thread-safe, though references may be released on any | ||
// thread (allowing weak pointers to be destroyed/reset/reassigned on any | ||
// thread). | ||
class FXL_EXPORT WeakPtrFlag : public fxl::RefCountedThreadSafe<WeakPtrFlag> { | ||
public: | ||
WeakPtrFlag(); | ||
|
||
~WeakPtrFlag(); | ||
|
||
bool is_valid() const { return is_valid_; } | ||
|
||
void Invalidate(); | ||
|
||
private: | ||
bool is_valid_; | ||
|
||
FXL_DISALLOW_COPY_AND_ASSIGN(WeakPtrFlag); | ||
}; | ||
|
||
} // namespace internal | ||
} // namespace fml | ||
|
||
#endif // FLUTTER_FML_MEMORY_WEAK_PTR_INTERNAL_H_ |
Oops, something went wrong.