Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: 6043dcb673
Fetching contributors…

Cannot retrieve contributors at this time

file 99 lines (85 sloc) 2.278 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
// Copyright (c) 2010-2011, Rasmus Andersson. All rights reserved.
// Use of this source code is governed by a MIT-style license that can be
// found in the LICENSE file.

#ifndef H_SPIN_LOCK_H_
#define H_SPIN_LOCK_H_

#import <libkern/OSAtomic.h>

#ifdef __cplusplus

class HSpinLock {
  volatile OSSpinLock lock_;

 public:
  HSpinLock() : lock_(0) { }
  inline void lock() { OSSpinLockLock(&lock_); }
  inline bool tryLock() { return OSSpinLockTry(&lock_); }
  inline void unlock() { OSSpinLockUnlock(&lock_); }

  class Scope {
   private:
    HSpinLock &sl_;
    Scope(Scope const &);
    Scope & operator=( Scope const & );
   public:
    explicit Scope(HSpinLock & sl) : sl_(sl) { sl.lock(); }
    ~Scope() { sl_.unlock(); }
  };
};

/**
* Critical section helper.
*
* Example:
*
* HSpinLock sl;
* // do something non-critical here
* HSpinLockSync(sl) {
* // the lock has been aquired
* // do critical stuff
* }
* // the lock has been released
*
*/
#define HSpinLockSync(sl) \
for (_HSpinLockScopeLocker __hslsl(sl); __hslsl.lockOnce() ; )
// push _HSpinLockUnlocker(sl)
// __hslsl.lockOnce() {
// used_ => false
// sl.lock()
// used_ = true
// } => true
// exec ...
// __hslsl.lockOnce() {
// used_ => true
// } => false
// break
// pop ~_HSpinLockScopeLocker {
// sl.unlock();
// }


/**
* Like HSpinLockSync, but w/o a scope helper. It's a light-weight construct
* which does not handle premature breaks, like return statements.
*/
#define HSpinLockSync2(sl) \
for (int8_t __hsl_x = 2 ; \
(--__hsl_x && __hsl_lock2(sl)) || __hsl_unlock2(sl) ; )
// __hsl_x = 2
// __hsl_x -= 1 => 1
// __hsl_lock2(sl)
// exec ...
// __hsl_x -= 1 => 0
// __hsl_unlock2(sl)
// break


// Helpers for the critical section macros

class _HSpinLockScopeLocker {
 public:
  bool used_;
  HSpinLock &sl_;
  explicit _HSpinLockScopeLocker(HSpinLock & sl) : sl_(sl), used_(false) { }
  ~_HSpinLockScopeLocker() { sl_.unlock(); }
  inline bool lockOnce() {
    if (used_) return false;
    sl_.lock();
    return (used_ = true);
  }
};

static inline bool __hsl_lock2(HSpinLock & sl) { sl.lock(); return true; }
static inline bool __hsl_unlock2(HSpinLock & sl) { sl.unlock(); return false; }

#endif // __cplusplus
#endif // H_SPIN_LOCK_H_
Something went wrong with that request. Please try again.