mirror of
https://github.com/s3fs-fuse/s3fs-fuse.git
synced 2024-05-29 07:00:49 +00:00
96f1c012db
This can find missing locks at compile-time.
151 lines
4.1 KiB
C++
151 lines
4.1 KiB
C++
/*
|
|
* s3fs - FUSE-based file system backed by Amazon S3
|
|
*
|
|
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#ifndef S3FS_MUTEX_H_
|
|
#define S3FS_MUTEX_H_
|
|
|
|
#include <mutex>
|
|
|
|
// Taken from: https://clang.llvm.org/docs/ThreadSafetyAnalysis.html
|
|
|
|
#if defined(__clang__)
|
|
#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
|
|
#else
|
|
#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
|
|
#endif
|
|
|
|
// These wrappers are necessary with GNU libstdc++. clang libc++ should have these already.
|
|
#define CAPABILITY(x) \
|
|
THREAD_ANNOTATION_ATTRIBUTE__(capability(x))
|
|
|
|
#define SCOPED_CAPABILITY \
|
|
THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
|
|
|
|
#define GUARDED_BY(x) \
|
|
THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
|
|
|
|
#define PT_GUARDED_BY(x) \
|
|
THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
|
|
|
|
#define ACQUIRED_BEFORE(...) \
|
|
THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
|
|
|
|
#define ACQUIRED_AFTER(...) \
|
|
THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
|
|
|
|
#define REQUIRES(...) \
|
|
THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__))
|
|
|
|
#define ACQUIRE(...) \
|
|
THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__))
|
|
|
|
#define RELEASE(...) \
|
|
THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__))
|
|
|
|
#define RELEASE_GENERIC(...) \
|
|
THREAD_ANNOTATION_ATTRIBUTE__(release_generic_capability(__VA_ARGS__))
|
|
|
|
#define TRY_ACQUIRE(...) \
|
|
THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__))
|
|
|
|
|
|
// Defines an annotated interface for mutexes.
|
|
// These methods can be implemented to use any internal mutex implementation.
|
|
class CAPABILITY("mutex") Mutex {
|
|
public:
|
|
// Acquire/lock this mutex exclusively. Only one thread can have exclusive
|
|
// access at any one time. Write operations to guarded data require an
|
|
// exclusive lock.
|
|
void Lock() ACQUIRE() {
|
|
lock.lock();
|
|
}
|
|
|
|
// Release/unlock an exclusive mutex.
|
|
void Unlock() RELEASE();
|
|
|
|
// Generic unlock, can unlock exclusive and shared mutexes.
|
|
void GenericUnlock() RELEASE_GENERIC() {
|
|
lock.unlock();
|
|
}
|
|
|
|
// Try to acquire the mutex. Returns true on success, and false on failure.
|
|
bool TryLock() TRY_ACQUIRE(true) {
|
|
return lock.try_lock();
|
|
}
|
|
|
|
Mutex() {}
|
|
Mutex(const Mutex&) = delete;
|
|
Mutex(Mutex&&) = delete;
|
|
Mutex& operator=(const Mutex&) = delete;
|
|
Mutex& operator=(Mutex&&) = delete;
|
|
|
|
private:
|
|
std::mutex lock;
|
|
};
|
|
|
|
// MutexLocker is an RAII class that acquires a mutex in its constructor, and
|
|
// releases it in its destructor.
|
|
class SCOPED_CAPABILITY MutexLocker {
|
|
private:
|
|
Mutex* mut;
|
|
bool locked;
|
|
|
|
public:
|
|
// Acquire mu, implicitly acquire *this and associate it with mu.
|
|
explicit MutexLocker(Mutex *mu) ACQUIRE(mu) : mut(mu), locked(true) {
|
|
mu->Lock();
|
|
}
|
|
|
|
// Release *this and all associated mutexes, if they are still held.
|
|
// There is no warning if the scope was already unlocked before.
|
|
~MutexLocker() RELEASE() {
|
|
if (locked)
|
|
mut->GenericUnlock();
|
|
}
|
|
|
|
// Acquire all associated mutexes exclusively.
|
|
void Lock() ACQUIRE() {
|
|
mut->Lock();
|
|
locked = true;
|
|
}
|
|
|
|
// Try to acquire all associated mutexes exclusively.
|
|
bool TryLock() TRY_ACQUIRE(true) {
|
|
return locked = mut->TryLock();
|
|
}
|
|
|
|
// Release all associated mutexes. Warn on double unlock.
|
|
void Unlock() RELEASE() {
|
|
mut->Unlock();
|
|
locked = false;
|
|
}
|
|
};
|
|
|
|
#endif // S3FS_MUTEX_H_
|
|
|
|
/*
|
|
* Local variables:
|
|
* tab-width: 4
|
|
* c-basic-offset: 4
|
|
* End:
|
|
* vim600: expandtab sw=4 ts=4 fdm=marker
|
|
* vim<600: expandtab sw=4 ts=4
|
|
*/
|