Index: base/callback_internal.cc |
diff --git a/base/callback_internal.cc b/base/callback_internal.cc |
index f360388273dac06d9dfe4eda1a9cc737c19ee7f9..1b223172d42e4810c5fd37aae2699c9c374ec9f9 100644 |
--- a/base/callback_internal.cc |
+++ b/base/callback_internal.cc |
@@ -9,28 +9,62 @@ |
namespace base { |
namespace internal { |
-CallbackBase::CallbackBase(const CallbackBase& c) = default; |
-CallbackBase& CallbackBase::operator=(const CallbackBase& c) = default; |
+void BindStateBase::AddRef() { |
+ AtomicRefCountInc(&ref_count_); |
+} |
+ |
+void BindStateBase::Release() { |
+ if (!AtomicRefCountDec(&ref_count_)) |
+ destructor_(this); |
+} |
void CallbackBase::Reset() { |
- polymorphic_invoke_ = NULL; |
- // NULL the bind_state_ last, since it may be holding the last ref to whatever |
- // object owns us, and we may be deleted after that. |
- bind_state_ = NULL; |
+ polymorphic_invoke_ = nullptr; |
+ // null the bind_state_ first, since it may be holding the last ref to |
+ // whatever object owns us, and we may be deleted after that. |
+ if (bind_state_) { |
+ BindStateBase* to_release = bind_state_; |
+ bind_state_ = nullptr; |
+ to_release->Release(); |
+ } |
} |
bool CallbackBase::Equals(const CallbackBase& other) const { |
- return bind_state_.get() == other.bind_state_.get() && |
+ return bind_state_ == other.bind_state_ && |
polymorphic_invoke_ == other.polymorphic_invoke_; |
} |
+CallbackBase::CallbackBase() |
+ : bind_state_(nullptr), polymorphic_invoke_(nullptr) { |
+} |
+ |
CallbackBase::CallbackBase(BindStateBase* bind_state) |
- : bind_state_(bind_state), |
- polymorphic_invoke_(NULL) { |
- DCHECK(!bind_state_.get() || bind_state_->HasOneRef()); |
+ : bind_state_(bind_state) { |
+ bind_state_->AddRef(); |
+ DCHECK_EQ(1, bind_state_->ref_count_); |
+} |
+ |
+CallbackBase::CallbackBase(const CallbackBase& c) |
+ : bind_state_(c.bind_state_), polymorphic_invoke_(c.polymorphic_invoke_) { |
+ if (bind_state_) |
+ bind_state_->AddRef(); |
+} |
+ |
+CallbackBase& CallbackBase::operator=(const CallbackBase& c) { |
+ // Increment first to handle self-assignment correctly. |
+ if (c.bind_state_) |
+ c.bind_state_->AddRef(); |
+ if (bind_state_) |
+ bind_state_->Release(); |
+ |
+ bind_state_ = c.bind_state_; |
+ polymorphic_invoke_ = c.polymorphic_invoke_; |
+ return *this; |
} |
CallbackBase::~CallbackBase() { |
+ if (bind_state_) |
+ bind_state_->Release(); |
} |
} // namespace internal |