summaryrefslogtreecommitdiffstats
path: root/base/ios/weak_nsobject.h
diff options
context:
space:
mode:
Diffstat (limited to 'base/ios/weak_nsobject.h')
-rw-r--r--base/ios/weak_nsobject.h49
1 files changed, 35 insertions, 14 deletions
diff --git a/base/ios/weak_nsobject.h b/base/ios/weak_nsobject.h
index 46aecb5..a1984bb 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