@@ -207,41 +207,63 @@ inline FutureBase::FutureBase(const FutureBase& rhs)
207207 : api_(NULL ) // NOLINT
208208{ // NOLINT
209209 *this = rhs;
210- detail::RegisterForCleanup (api_, this );
211210}
212211
213212inline FutureBase& FutureBase::operator =(const FutureBase& rhs) {
214213 Release ();
215- api_ = rhs.api_ ;
216- handle_ = rhs.handle_ ;
217- if (api_ != NULL ) { // NOLINT
218- api_->ReferenceFuture (handle_);
214+
215+ detail::FutureApiInterface* new_api;
216+ FutureHandle new_handle;
217+ {
218+ std::lock_guard<std::mutex> lock (rhs.mutex_ );
219+ new_api = rhs.api_ ;
220+ new_handle = rhs.handle_ ;
219221 }
220- detail::RegisterForCleanup (api_, this );
222+
223+ {
224+ std::lock_guard<std::mutex> lock (mutex_);
225+ api_ = new_api;
226+ handle_ = new_handle;
227+
228+ if (api_ != NULL ) { // NOLINT
229+ api_->ReferenceFuture (handle_);
230+ }
231+ detail::RegisterForCleanup (api_, this );
232+ }
233+
221234 return *this ;
222235}
223236
224237#if defined(FIREBASE_USE_MOVE_OPERATORS)
225238inline FutureBase::FutureBase (FutureBase&& rhs) noexcept
226239 : api_(NULL ) // NOLINT
227240{
228- detail::UnregisterForCleanup (rhs.api_ , &rhs);
229241 *this = std::move (rhs);
230- detail::RegisterForCleanup (api_, this );
231242}
232243
233244inline FutureBase& FutureBase::operator =(FutureBase&& rhs) noexcept {
234245 Release ();
235- detail::UnregisterForCleanup (rhs.api_ , &rhs);
236- api_ = rhs.api_ ;
237- handle_ = rhs.handle_ ;
238- rhs.api_ = NULL ; // NOLINT
246+
247+ detail::FutureApiInterface* new_api;
248+ FutureHandle new_handle;
249+ {
250+ std::lock_guard<std::mutex> lock (rhs.mutex_ );
251+ detail::UnregisterForCleanup (rhs.api_ , &rhs);
252+ new_api = rhs.api_ ;
253+ new_handle = rhs.handle_ ;
254+ rhs.api_ = NULL ; // NOLINT
255+ }
256+
257+ std::lock_guard<std::mutex> lock (mutex_);
258+ api_ = new_api;
259+ handle_ = new_handle;
239260 detail::RegisterForCleanup (api_, this );
240261 return *this ;
241262}
242263#endif // defined(FIREBASE_USE_MOVE_OPERATORS)
243264
244265inline void FutureBase::Release () {
266+ std::lock_guard<std::mutex> lock (mutex_);
245267 if (api_ != NULL ) { // NOLINT
246268 detail::UnregisterForCleanup (api_, this );
247269 api_->ReleaseFuture (handle_);
@@ -250,25 +272,30 @@ inline void FutureBase::Release() {
250272}
251273
252274inline FutureStatus FutureBase::status () const {
275+ std::lock_guard<std::mutex> lock (mutex_);
253276 return api_ == NULL ? // NOLINT
254277 kFutureStatusInvalid
255278 : api_->GetFutureStatus (handle_);
256279}
257280
258281inline int FutureBase::error () const {
282+ std::lock_guard<std::mutex> lock (mutex_);
259283 return api_ == NULL ? -1 : api_->GetFutureError (handle_); // NOLINT
260284}
261285
262286inline const char * FutureBase::error_message () const {
287+ std::lock_guard<std::mutex> lock (mutex_);
263288 return api_ == NULL ? NULL : api_->GetFutureErrorMessage (handle_); // NOLINT
264289}
265290
266291inline const void * FutureBase::result_void () const {
292+ std::lock_guard<std::mutex> lock (mutex_);
267293 return api_ == NULL ? NULL : api_->GetFutureResult (handle_); // NOLINT
268294}
269295
270296inline void FutureBase::OnCompletion (CompletionCallback callback,
271297 void * user_data) const {
298+ std::lock_guard<std::mutex> lock (mutex_);
272299 if (api_ != NULL ) { // NOLINT
273300 api_->AddCompletionCallback (handle_, callback, user_data, nullptr ,
274301 /* clear_existing_callbacks=*/ true );
@@ -278,6 +305,7 @@ inline void FutureBase::OnCompletion(CompletionCallback callback,
278305#if defined(INTERNAL_EXPERIMENTAL)
279306inline FutureBase::CompletionCallbackHandle FutureBase::AddOnCompletion (
280307 CompletionCallback callback, void * user_data) const {
308+ std::lock_guard<std::mutex> lock (mutex_);
281309 if (api_ != NULL ) { // NOLINT
282310 return api_->AddCompletionCallback (handle_, callback, user_data, nullptr ,
283311 /* clear_existing_callbacks=*/ false );
@@ -287,6 +315,7 @@ inline FutureBase::CompletionCallbackHandle FutureBase::AddOnCompletion(
287315
288316inline void FutureBase::RemoveOnCompletion (
289317 CompletionCallbackHandle completion_handle) const {
318+ std::lock_guard<std::mutex> lock (mutex_);
290319 if (api_ != NULL ) { // NOLINT
291320 api_->RemoveCompletionCallback (handle_, completion_handle);
292321 }
@@ -296,6 +325,7 @@ inline void FutureBase::RemoveOnCompletion(
296325#if defined(FIREBASE_USE_STD_FUNCTION)
297326inline void FutureBase::OnCompletion (
298327 std::function<void (const FutureBase&)> callback) const {
328+ std::lock_guard<std::mutex> lock (mutex_);
299329 if (api_ != NULL ) { // NOLINT
300330 api_->AddCompletionCallbackLambda (handle_, callback,
301331 /* clear_existing_callbacks=*/ true );
@@ -305,6 +335,7 @@ inline void FutureBase::OnCompletion(
305335#if defined(INTERNAL_EXPERIMENTAL)
306336inline FutureBase::CompletionCallbackHandle FutureBase::AddOnCompletion (
307337 std::function<void (const FutureBase&)> callback) const {
338+ std::lock_guard<std::mutex> lock (mutex_);
308339 if (api_ != NULL ) { // NOLINT
309340 return api_->AddCompletionCallbackLambda (
310341 handle_, callback,
0 commit comments