@@ -35,28 +35,30 @@ public final class GCDReadWriteLock: ReadWriteLock {
35
35
}
36
36
}
37
37
38
- public class AtomicInt {
39
- private var mutex = pthread_mutex_t ( )
40
- private( set) var value : Int32 = 0
38
+ public final class SpinLock : ReadWriteLock {
39
+ private var lock : UnsafeMutablePointer < Int32 >
41
40
42
- init ( ) {
43
- pthread_mutex_init ( & mutex, nil )
41
+ public init ( ) {
42
+ lock = UnsafeMutablePointer . allocate ( capacity: 1 )
43
+ lock. pointee = OS_SPINLOCK_INIT
44
44
}
45
45
46
46
deinit {
47
- pthread_mutex_destroy ( & mutex )
47
+ lock . deallocate ( )
48
48
}
49
49
50
- func compareAndSwap( oldValue: Int32 , newValue: Int32 ) -> Bool {
51
- pthread_mutex_lock ( & mutex)
52
- defer {
53
- pthread_mutex_unlock ( & mutex)
54
- }
55
- if oldValue != value {
56
- return false
57
- }
58
- value = newValue
59
- return true
50
+ public func withReadLock< T> ( block: ( ) -> T ) -> T {
51
+ OSSpinLockLock ( lock)
52
+ let result = block ( )
53
+ OSSpinLockUnlock ( lock)
54
+ return result
55
+ }
56
+
57
+ public func withWriteLock< T> ( block: ( ) -> T ) -> T {
58
+ OSSpinLockLock ( lock)
59
+ let result = block ( )
60
+ OSSpinLockUnlock ( lock)
61
+ return result
60
62
}
61
63
}
62
64
@@ -69,24 +71,33 @@ public final class CASSpinLock: ReadWriteLock {
69
71
static let MASK_READER_BITS = ~ MASK_WRITER_BITS
70
72
}
71
73
72
- private let _state = AtomicInt ( )
74
+ private var _state : UnsafeMutablePointer < Int32 >
75
+
76
+ public init ( ) {
77
+ _state = UnsafeMutablePointer . allocate ( capacity: 1 )
78
+ _state. pointee = 0
79
+ }
80
+
81
+ deinit {
82
+ _state. deallocate ( )
83
+ }
73
84
74
85
public func withWriteLock< T> ( block: ( ) -> T ) -> T {
75
86
// spin until we acquire write lock
76
87
repeat {
77
- let state = _state. value
88
+ let state = _state. pointee
78
89
79
90
// if there are no readers and no one holds the write lock, try to grab the write lock immediately
80
91
if ( state == 0 || state == Masks . WRITER_WAITING_BIT) &&
81
- _state . compareAndSwap ( oldValue : state, newValue : Masks . WRITER_BIT) {
92
+ OSAtomicCompareAndSwap32Barrier ( state, Masks . WRITER_BIT, _state ) {
82
93
break
83
94
}
84
95
85
96
// If we get here, someone is reading or writing. Set the WRITER_WAITING_BIT if
86
97
// it isn't already to block any new readers, then wait a bit before
87
98
// trying again. Ignore CAS failure - we'll just try again next iteration
88
99
if state & Masks . WRITER_WAITING_BIT == 0 {
89
- _ = _state . compareAndSwap ( oldValue : state, newValue : state | Masks . WRITER_WAITING_BIT)
100
+ OSAtomicCompareAndSwap32Barrier ( state, state | Masks . WRITER_WAITING_BIT, _state )
90
101
}
91
102
} while true
92
103
@@ -95,11 +106,11 @@ public final class CASSpinLock: ReadWriteLock {
95
106
96
107
// unlock
97
108
repeat {
98
- let state = _state. value
109
+ let state = _state. pointee
99
110
100
111
// clear everything except (possibly) WRITER_WAITING_BIT, which will only be set
101
112
// if another writer is already here and waiting (which will keep out readers)
102
- if _state . compareAndSwap ( oldValue : state, newValue : state & Masks . WRITER_WAITING_BIT) {
113
+ if OSAtomicCompareAndSwap32Barrier ( state, state & Masks . WRITER_WAITING_BIT, _state ) {
103
114
break
104
115
}
105
116
} while true
@@ -110,11 +121,11 @@ public final class CASSpinLock: ReadWriteLock {
110
121
public func withReadLock< T> ( block: ( ) -> T ) -> T {
111
122
// spin until we acquire read lock
112
123
repeat {
113
- let state = _state. value
124
+ let state = _state. pointee
114
125
115
126
// if there is no writer and no writer waiting, try to increment reader count
116
127
if ( state & Masks . MASK_WRITER_BITS) == 0 &&
117
- _state . compareAndSwap ( oldValue : state, newValue : state + 1 ) {
128
+ OSAtomicCompareAndSwap32Barrier ( state, state + 1 , _state ) {
118
129
break
119
130
}
120
131
} while true
@@ -124,7 +135,7 @@ public final class CASSpinLock: ReadWriteLock {
124
135
125
136
// decrement reader count
126
137
repeat {
127
- let state = _state. value
138
+ let state = _state. pointee
128
139
129
140
// sanity check that we have a positive reader count before decrementing it
130
141
assert ( ( state & Masks . MASK_READER_BITS) > 0 , " unlocking read lock - invalid reader count " )
@@ -133,7 +144,7 @@ public final class CASSpinLock: ReadWriteLock {
133
144
let newState = ( ( state & Masks . MASK_READER_BITS) - 1 ) |
134
145
( state & Masks . WRITER_WAITING_BIT)
135
146
136
- if _state . compareAndSwap ( oldValue : state, newValue : newState) {
147
+ if OSAtomicCompareAndSwap32Barrier ( state, newState, _state ) {
137
148
break
138
149
}
139
150
} while true
0 commit comments