diff options
author | Justin Lebar <jlebar@google.com> | 2018-08-06 14:41:01 -0700 |
---|---|---|
committer | TensorFlower Gardener <gardener@tensorflow.org> | 2018-08-06 14:45:30 -0700 |
commit | e8def0cec8cf2399e333dbe804f29ae26e8997c9 (patch) | |
tree | 1d43d93dca7aef6940b5dfb4a7e73d88db87b9f9 /tensorflow/core/platform | |
parent | 2c6ae175591a687aae4d3ab69b5719d0b656ea13 (diff) |
Add missing annotation to mutex_lock's move constructor.
Because ~mutex_lock() is marked as an UNLOCK_FUNCTION, we have to mark
the move constructor as locking ml.mu_. Otherwise if you try to move a
mutex_lock, clang sees the destructor call and thinks that the mutex has
been unlocked for good.
Same for tf_shared_lock.
Also make tf_shared_lock's move constructor non-explicit. This is just
a performance optimization; tf_shared_lock was already copyable.
PiperOrigin-RevId: 207610922
Diffstat (limited to 'tensorflow/core/platform')
-rw-r--r-- | tensorflow/core/platform/default/mutex.h | 8 | ||||
-rw-r--r-- | tensorflow/core/platform/mutex_test.cc | 39 |
2 files changed, 45 insertions, 2 deletions
diff --git a/tensorflow/core/platform/default/mutex.h b/tensorflow/core/platform/default/mutex.h index 89e57d58a0..48d90779e1 100644 --- a/tensorflow/core/platform/default/mutex.h +++ b/tensorflow/core/platform/default/mutex.h @@ -77,7 +77,10 @@ class SCOPED_LOCKABLE mutex_lock { // Manually nulls out the source to prevent double-free. // (std::move does not null the source pointer by default.) - mutex_lock(mutex_lock&& ml) noexcept : mu_(ml.mu_) { ml.mu_ = nullptr; } + mutex_lock(mutex_lock&& ml) noexcept EXCLUSIVE_LOCK_FUNCTION(ml.mu_) + : mu_(ml.mu_) { + ml.mu_ = nullptr; + } ~mutex_lock() UNLOCK_FUNCTION() { if (mu_ != nullptr) { mu_->unlock(); @@ -113,7 +116,8 @@ class SCOPED_LOCKABLE tf_shared_lock { // Manually nulls out the source to prevent double-free. // (std::move does not null the source pointer by default.) - explicit tf_shared_lock(tf_shared_lock&& ml) noexcept : mu_(ml.mu_) { + tf_shared_lock(tf_shared_lock&& ml) noexcept SHARED_LOCK_FUNCTION(ml.mu_) + : mu_(ml.mu_) { ml.mu_ = nullptr; } ~tf_shared_lock() UNLOCK_FUNCTION() { diff --git a/tensorflow/core/platform/mutex_test.cc b/tensorflow/core/platform/mutex_test.cc new file mode 100644 index 0000000000..7ba57775dd --- /dev/null +++ b/tensorflow/core/platform/mutex_test.cc @@ -0,0 +1,39 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/core/platform/mutex.h" +#include "tensorflow/core/platform/test.h" + +namespace tensorflow { +namespace { + +// Check that mutex_lock and shared_mutex_lock are movable and that their +// thread-safety annotations are correct enough that we don't get an error when +// we use a moved-from lock. (For instance, we might incorrectly get an error +// at the end of Test() when we destruct the mutex_lock, if the compiler isn't +// aware that the mutex is in fact locked at this point.) +struct MovableMutexLockTest { + mutex_lock GetLock() { return mutex_lock{mu}; } + void Test() { mutex_lock lock = GetLock(); } + mutex mu; +}; +struct SharedMutexLockTest { + tf_shared_lock GetLock() { return tf_shared_lock{mu}; } + void Test() { tf_shared_lock lock = GetLock(); } + mutex mu; +}; + +} // namespace +} // namespace tensorflow |