| Index: base/ios/weak_nsobject.h
|
| diff --git a/base/ios/weak_nsobject.h b/base/ios/weak_nsobject.h
|
| index 46aecb5e0b641fb3d004e23b71a5111f02295bfe..a1984bb91824dbc886570d43363b1d9162a3b939 100644
|
| --- a/base/ios/weak_nsobject.h
|
| +++ b/base/ios/weak_nsobject.h
|
| @@ -36,17 +36,28 @@
|
| // NSObject, this relationship is maintained via the ObjectiveC associated
|
| // object API, indirectly via an ObjectiveC CRBWeakNSProtocolSentinel class.
|
| //
|
| -// The implementation assumes that the tracked object will be released on the
|
| -// same thread that the WeakNSObject is created on.
|
| -//
|
| +// Threading restrictions:
|
| +// - Several WeakNSObject pointing to the same underlying object must all be
|
| +// created and dereferenced on the same thread;
|
| +// - thread safety is enforced by the implementation, except in two cases:
|
| +// (1) it is allowed to copy a WeakNSObject on a different thread. However,
|
| +// that copy must return to the original thread before being dereferenced,
|
| +// (2) it is allowed to destroy a WeakNSObject on any thread;
|
| +// - the implementation assumes that the tracked object will be released on the
|
| +// same thread that the WeakNSObject is created on.
|
| namespace base {
|
|
|
| // WeakContainer keeps a weak pointer to an object and clears it when it
|
| // receives nullify() from the object's sentinel.
|
| class WeakContainer : public base::RefCountedThreadSafe<WeakContainer> {
|
| public:
|
| - WeakContainer(id object) : object_(object) {}
|
| - id object() { return object_; }
|
| + explicit WeakContainer(id object) : object_(object) {}
|
| +
|
| + id object() {
|
| + DCHECK(checker_.CalledOnValidThread());
|
| + return object_;
|
| + }
|
| +
|
| void nullify() {
|
| DCHECK(checker_.CalledOnValidThread());
|
| object_ = nil;
|
| @@ -74,53 +85,63 @@ namespace base {
|
|
|
| // Base class for all WeakNSObject derivatives.
|
| template <typename NST>
|
| -class WeakNSProtocol : public base::NonThreadSafe {
|
| +class WeakNSProtocol {
|
| public:
|
| explicit WeakNSProtocol(NST object = nil) {
|
| container_ = [CRBWeakNSProtocolSentinel containerForObject:object];
|
| }
|
|
|
| WeakNSProtocol(const WeakNSProtocol<NST>& that) {
|
| + // A WeakNSProtocol object can be copied on one thread and used on
|
| + // another.
|
| + checker_.DetachFromThread();
|
| container_ = that.container_;
|
| }
|
|
|
| ~WeakNSProtocol() {
|
| - // A WeakNSProtocol object can be allocated on one thread and released on
|
| + // A WeakNSProtocol object can be used on one thread and released on
|
| // another. This is not the case for the contained object.
|
| - DetachFromThread();
|
| + checker_.DetachFromThread();
|
| }
|
|
|
| void reset(NST object = nil) {
|
| - DCHECK(CalledOnValidThread());
|
| + DCHECK(checker_.CalledOnValidThread());
|
| container_ = [CRBWeakNSProtocolSentinel containerForObject:object];
|
| }
|
|
|
| NST get() const {
|
| - DCHECK(CalledOnValidThread());
|
| + DCHECK(checker_.CalledOnValidThread());
|
| if (!container_.get())
|
| return nil;
|
| return container_->object();
|
| }
|
|
|
| WeakNSProtocol& operator=(const WeakNSProtocol<NST>& that) {
|
| - DCHECK(CalledOnValidThread());
|
| + DCHECK(checker_.CalledOnValidThread());
|
| container_ = that.container_;
|
| return *this;
|
| }
|
|
|
| bool operator==(NST that) const {
|
| - DCHECK(CalledOnValidThread());
|
| + DCHECK(checker_.CalledOnValidThread());
|
| return get() == that;
|
| }
|
|
|
| - bool operator!=(NST that) const { return get() != that; }
|
| + bool operator!=(NST that) const {
|
| + DCHECK(checker_.CalledOnValidThread());
|
| + return get() != that;
|
| + }
|
|
|
| - operator NST() const { return get(); }
|
| + operator NST() const {
|
| + DCHECK(checker_.CalledOnValidThread());
|
| + return get();
|
| + }
|
|
|
| private:
|
| // Refecounted reference to the container tracking the ObjectiveC object this
|
| // class encapsulates.
|
| scoped_refptr<base::WeakContainer> container_;
|
| + base::ThreadChecker checker_;
|
| };
|
|
|
| // Free functions
|
|
|