Skip to content

Instantly share code, notes, and snippets.

@theuni
Created June 23, 2015 20:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save theuni/f5d6d3db9434ca546422 to your computer and use it in GitHub Desktop.
Save theuni/f5d6d3db9434ca546422 to your computer and use it in GitHub Desktop.
clang locking test
#include <vector>
#include <mutex>
#if defined(__clang__) && (!defined(SWIG))
#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
#else
#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
#endif
#define EXCLUSIVE_LOCKS_REQUIRED(...) THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))
#define LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(lockable)
#define SCOPED_LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
#define EXCLUSIVE_LOCK_FUNCTION(...) THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__))
#define UNLOCK_FUNCTION(...) THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__))
#define EXCLUSIVE_TRYLOCK_FUNCTION(...) THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__))
#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
// Defines an annotated interface for mutexes.
// These methods can be implemented to use any internal mutex implementation.
template <typename BaseMutex>
class LOCKABLE MutexInt {
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() EXCLUSIVE_LOCK_FUNCTION() { mutex.lock(); }
// Release/unlock an exclusive mutex.
void unlock() UNLOCK_FUNCTION() { mutex.unlock(); }
// Try to acquire the mutex. Returns true on success, and false on failure.
bool try_lock() EXCLUSIVE_TRYLOCK_FUNCTION(true) { return mutex.try_lock(); }
// For negative capabilities.
const MutexInt& operator!() const { return *this; }
BaseMutex mutex;
typedef BaseMutex type;
};
// MutexLocker is an RAII class that acquires a mutex in its constructor, and
// releases it in its destructor.
template <typename M>
class SCOPED_LOCKABLE QuickLockInt {
private:
std::lock_guard<M> mylock;
public:
QuickLockInt(M &mu) EXCLUSIVE_LOCK_FUNCTION(mu) : mylock(mu) {
}
~QuickLockInt() UNLOCK_FUNCTION() {
}
};
template <typename M>
class SCOPED_LOCKABLE LockInt {
private:
std::unique_lock<M> mylock;
public:
typedef M type;
LockInt(M &mu) EXCLUSIVE_LOCK_FUNCTION(mu) : mylock(mu) {}
void lock() EXCLUSIVE_LOCK_FUNCTION() { mylock.lock(); }
void unlock() UNLOCK_FUNCTION() { mylock.unlock(); }
bool try_lock() EXCLUSIVE_TRYLOCK_FUNCTION(true) { return mylock.try_lock(); }
bool owns_lock() const { return mylock.owns_lock(); }
~LockInt() UNLOCK_FUNCTION() {
}
};
typedef MutexInt<std::mutex> Mutex;
typedef MutexInt<std::recursive_mutex> RecursiveMutex;
typedef LockInt<Mutex> UniqueLock;
typedef QuickLockInt<Mutex> QuickUniqueLock;
typedef LockInt<RecursiveMutex> RecursiveLock;
typedef QuickLockInt<RecursiveMutex> QuickRecursiveLock;
#define LOCK(x) RecursiveLock lock(x)
#define ULOCK(x) UniqueLock lock(x)
#define QUICKLOCK(x) QuickRecursiveLock lock(x)
#define QUICKULOCK(x) QuickUniqueLock lock(x)
#define ENTER_CRITICAL_SECTION(cs) \
{ \
(cs).lock(); \
}
#define LEAVE_CRITICAL_SECTION(cs) \
{ \
(cs).unlock(); \
}
static RecursiveMutex cs_main;
static int myint = 0;
static std::vector<int*> GUARDED_BY(cs_main) vec(1,&myint);
int* func2()
{
LOCK(cs_main);
return vec[0];
}
void func1() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
func2();
vec.clear();
}
int main()
{
int* unguarded = func2();
*unguarded = 3;
LOCK(cs_main);
func1();
unguarded = func2();
return *unguarded;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment