Skip to content
This repository was archived by the owner on Aug 29, 2022. It is now read-only.

Commit 83cf62e

Browse files
authored
Merge pull request #229 from bignerdranch/zwaldowski/skinny-deferred
Skinny Deferred
2 parents 9373157 + 572ebbb commit 83cf62e

File tree

12 files changed

+485
-232
lines changed

12 files changed

+485
-232
lines changed

Deferred.xcodeproj/project.pbxproj

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,14 @@
172172
DB34FC942096DCE1005D5B82 /* FilledDeferredTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB34FC932096DCE1005D5B82 /* FilledDeferredTests.swift */; };
173173
DB34FC952096DCE1005D5B82 /* FilledDeferredTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB34FC932096DCE1005D5B82 /* FilledDeferredTests.swift */; };
174174
DB34FC962096DCE1005D5B82 /* FilledDeferredTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB34FC932096DCE1005D5B82 /* FilledDeferredTests.swift */; };
175+
DB3E3C4620964B2A001F648A /* DeferredVariant.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB3E3C4520964B2A001F648A /* DeferredVariant.swift */; };
176+
DB3E3C4720964B2A001F648A /* DeferredVariant.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB3E3C4520964B2A001F648A /* DeferredVariant.swift */; };
177+
DB3E3C4820964B2A001F648A /* DeferredVariant.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB3E3C4520964B2A001F648A /* DeferredVariant.swift */; };
178+
DB3E3C4920964B2A001F648A /* DeferredVariant.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB3E3C4520964B2A001F648A /* DeferredVariant.swift */; };
179+
DB647573209652DC00F67EA1 /* DeferredQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB647572209652DC00F67EA1 /* DeferredQueue.swift */; };
180+
DB647574209652DC00F67EA1 /* DeferredQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB647572209652DC00F67EA1 /* DeferredQueue.swift */; };
181+
DB647575209652DC00F67EA1 /* DeferredQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB647572209652DC00F67EA1 /* DeferredQueue.swift */; };
182+
DB647576209652DC00F67EA1 /* DeferredQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB647572209652DC00F67EA1 /* DeferredQueue.swift */; };
175183
DB8A071C2060D38C00639AB3 /* PerformanceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8A071B2060D38C00639AB3 /* PerformanceTests.swift */; };
176184
DB8A071D2060D38C00639AB3 /* PerformanceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8A071B2060D38C00639AB3 /* PerformanceTests.swift */; };
177185
DB8A071E2060D38C00639AB3 /* PerformanceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8A071B2060D38C00639AB3 /* PerformanceTests.swift */; };
@@ -232,6 +240,7 @@
232240
DB34FC8F2096D335005D5B82 /* ObjectDeferredTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObjectDeferredTests.swift; sourceTree = "<group>"; };
233241
DB34FC932096DCE1005D5B82 /* FilledDeferredTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilledDeferredTests.swift; sourceTree = "<group>"; };
234242
DB39B2D01DDE194C00DDE4C0 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
243+
DB3E3C4520964B2A001F648A /* DeferredVariant.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeferredVariant.swift; sourceTree = "<group>"; };
235244
DB4002691DDC21B300382BAE /* SwiftBugTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftBugTests.swift; sourceTree = "<group>"; };
236245
DB524C8C1D851E5B00DDF16D /* Base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Base.xcconfig; sourceTree = "<group>"; };
237246
DB524C8D1D851E5B00DDF16D /* Framework.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Framework.xcconfig; sourceTree = "<group>"; };
@@ -280,6 +289,7 @@
280289
DB55F1FC1D96968E00FC1439 /* TaskTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TaskTests.swift; sourceTree = "<group>"; };
281290
DB55F1FD1D96968E00FC1439 /* TaskWorkItemTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TaskWorkItemTests.swift; sourceTree = "<group>"; };
282291
DB55F20B1D969A1B00FC1439 /* FutureTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FutureTests.swift; sourceTree = "<group>"; };
292+
DB647572209652DC00F67EA1 /* DeferredQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeferredQueue.swift; sourceTree = "<group>"; };
283293
DB8A071B2060D38C00639AB3 /* PerformanceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PerformanceTests.swift; sourceTree = "<group>"; };
284294
DBA01AFD2071E5D300083CD0 /* FutureUpon.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FutureUpon.swift; sourceTree = "<group>"; };
285295
DBA01B022071E68F00083CD0 /* FutureMap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FutureMap.swift; sourceTree = "<group>"; };
@@ -400,6 +410,8 @@
400410
children = (
401411
DBABD0BA203F2E3E00C50896 /* Atomics.swift */,
402412
DB524C931D85200C00DDF16D /* Deferred.swift */,
413+
DB647572209652DC00F67EA1 /* DeferredQueue.swift */,
414+
DB3E3C4520964B2A001F648A /* DeferredVariant.swift */,
403415
DB524C941D85200C00DDF16D /* Executor.swift */,
404416
DB524C951D85200C00DDF16D /* ExistentialFuture.swift */,
405417
DB524C9A1D85200C00DDF16D /* Future.swift */,
@@ -800,6 +812,7 @@
800812
DB126D291E5368A700054E95 /* EitherRecovery.swift in Sources */,
801813
DB126CFF1E5368A100054E95 /* Future.swift in Sources */,
802814
DB126D3E1E5368AD00054E95 /* TaskWorkItem.swift in Sources */,
815+
DB3E3C4620964B2A001F648A /* DeferredVariant.swift in Sources */,
803816
DB126D031E5368A100054E95 /* FutureIgnore.swift in Sources */,
804817
DB126D041E5368A100054E95 /* Locking.swift in Sources */,
805818
DB126D361E5368AD00054E95 /* ResultPromise.swift in Sources */,
@@ -810,6 +823,7 @@
810823
DB126D391E5368AD00054E95 /* TaskGroup.swift in Sources */,
811824
DB126CFC1E5368A100054E95 /* Deferred.swift in Sources */,
812825
DB126D051E5368A100054E95 /* Promise.swift in Sources */,
826+
DB647573209652DC00F67EA1 /* DeferredQueue.swift in Sources */,
813827
DBA01B042071E69100083CD0 /* FutureMap.swift in Sources */,
814828
DB126D001E5368A100054E95 /* FutureCollections.swift in Sources */,
815829
DB126D011E5368A100054E95 /* FutureComposition.swift in Sources */,
@@ -863,6 +877,7 @@
863877
DB126D0A1E5368A100054E95 /* Future.swift in Sources */,
864878
DB126D491E5368AD00054E95 /* TaskWorkItem.swift in Sources */,
865879
DB126D0E1E5368A100054E95 /* FutureIgnore.swift in Sources */,
880+
DB3E3C4720964B2A001F648A /* DeferredVariant.swift in Sources */,
866881
DB126D0F1E5368A100054E95 /* Locking.swift in Sources */,
867882
DB126D411E5368AD00054E95 /* ResultPromise.swift in Sources */,
868883
DB126D461E5368AD00054E95 /* TaskMap.swift in Sources */,
@@ -873,6 +888,7 @@
873888
DB126D071E5368A100054E95 /* Deferred.swift in Sources */,
874889
DBABD0BC203F2E3E00C50896 /* Atomics.swift in Sources */,
875890
DB126D101E5368A100054E95 /* Promise.swift in Sources */,
891+
DB647574209652DC00F67EA1 /* DeferredQueue.swift in Sources */,
876892
DBA01B052071E69100083CD0 /* FutureMap.swift in Sources */,
877893
DB126D0B1E5368A100054E95 /* FutureCollections.swift in Sources */,
878894
DB126D0C1E5368A100054E95 /* FutureComposition.swift in Sources */,
@@ -926,6 +942,7 @@
926942
DB126D151E5368A200054E95 /* Future.swift in Sources */,
927943
DB126D541E5368AE00054E95 /* TaskWorkItem.swift in Sources */,
928944
DB126D191E5368A200054E95 /* FutureIgnore.swift in Sources */,
945+
DB3E3C4820964B2A001F648A /* DeferredVariant.swift in Sources */,
929946
DB126D1A1E5368A200054E95 /* Locking.swift in Sources */,
930947
DB126D4C1E5368AE00054E95 /* ResultPromise.swift in Sources */,
931948
DB126D511E5368AE00054E95 /* TaskMap.swift in Sources */,
@@ -936,6 +953,7 @@
936953
DB126D121E5368A200054E95 /* Deferred.swift in Sources */,
937954
DBABD0BD203F2E3E00C50896 /* Atomics.swift in Sources */,
938955
DB126D1B1E5368A200054E95 /* Promise.swift in Sources */,
956+
DB647575209652DC00F67EA1 /* DeferredQueue.swift in Sources */,
939957
DBA01B062071E69100083CD0 /* FutureMap.swift in Sources */,
940958
DB126D161E5368A200054E95 /* FutureCollections.swift in Sources */,
941959
DB126D171E5368A200054E95 /* FutureComposition.swift in Sources */,
@@ -989,6 +1007,7 @@
9891007
DB126D201E5368A200054E95 /* Future.swift in Sources */,
9901008
DB126D5F1E5368AE00054E95 /* TaskWorkItem.swift in Sources */,
9911009
DB126D241E5368A200054E95 /* FutureIgnore.swift in Sources */,
1010+
DB3E3C4920964B2A001F648A /* DeferredVariant.swift in Sources */,
9921011
DB126D251E5368A200054E95 /* Locking.swift in Sources */,
9931012
DB126D571E5368AE00054E95 /* ResultPromise.swift in Sources */,
9941013
DB126D5C1E5368AE00054E95 /* TaskMap.swift in Sources */,
@@ -999,6 +1018,7 @@
9991018
DB126D1D1E5368A200054E95 /* Deferred.swift in Sources */,
10001019
DBABD0BE203F2E3E00C50896 /* Atomics.swift in Sources */,
10011020
DB126D261E5368A200054E95 /* Promise.swift in Sources */,
1021+
DB647576209652DC00F67EA1 /* DeferredQueue.swift in Sources */,
10021022
DBA01B072071E69100083CD0 /* FutureMap.swift in Sources */,
10031023
DB126D211E5368A200054E95 /* FutureCollections.swift in Sources */,
10041024
DB126D221E5368A200054E95 /* FutureComposition.swift in Sources */,

Sources/Atomics/include/Atomics.h

Lines changed: 80 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,21 @@
2424
#ifndef __BNR_DEFERRED_ATOMIC_SHIMS__
2525
#define __BNR_DEFERRED_ATOMIC_SHIMS__
2626

27+
#if !__has_include(<stdatomic.h>) || !__has_extension(c_atomic)
28+
#error Required compiler features are not available
29+
#endif
30+
2731
#include <stdatomic.h>
2832
#if defined(__APPLE__)
2933
#include <os/lock.h>
3034
#endif
3135
#include <pthread.h>
3236
#include <dispatch/dispatch.h>
3337

34-
#if defined(__has_attribute) && __has_attribute(always_inline)
3538
#define BNR_ATOMIC_INLINE static inline __attribute__((always_inline))
36-
#else
37-
#define BNR_ATOMIC_INLINE static inline
38-
#endif
39+
#define BNR_ATOMIC_OVERLOAD __attribute__((overloadable))
40+
#define BNR_ATOMIC_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
41+
#define BNR_ATOMIC_LIKELY(expression) __builtin_expect(!!(expression), 1)
3942

4043
#if !defined(SWIFT_ENUM)
4144
#define SWIFT_ENUM(_type, _name) enum _name _name##_t; enum _name
@@ -106,7 +109,8 @@ bool bnr_native_lock_trylock(bnr_native_lock_t address) {
106109
return pthread_mutex_trylock(&address->impl.legacy) == 0;
107110
}
108111

109-
BNR_ATOMIC_INLINE void bnr_native_lock_unlock(bnr_native_lock_t address) {
112+
BNR_ATOMIC_INLINE
113+
void bnr_native_lock_unlock(bnr_native_lock_t address) {
110114
#if defined(__APPLE__)
111115
if (&os_unfair_lock_unlock != NULL) {
112116
return os_unfair_lock_unlock(&address->impl.modern);
@@ -116,80 +120,103 @@ BNR_ATOMIC_INLINE void bnr_native_lock_unlock(bnr_native_lock_t address) {
116120
pthread_mutex_unlock(&address->impl.legacy);
117121
}
118122

119-
typedef volatile struct bnr_atomic_ptr_s {
120-
_Atomic(const void *_Nullable) value;
121-
} bnr_atomic_ptr, *_Nonnull bnr_atomic_ptr_t;
123+
typedef const void *_Nullable volatile *_Nonnull bnr_atomic_ptr_t;
122124

123-
BNR_ATOMIC_INLINE
124-
const void *_Nullable bnr_atomic_ptr_load(bnr_atomic_ptr_t target, bnr_atomic_memory_order_t order) {
125-
return atomic_load_explicit(&target->value, order);
125+
BNR_ATOMIC_INLINE BNR_ATOMIC_OVERLOAD
126+
void bnr_atomic_init(bnr_atomic_ptr_t target, const void *_Nullable initial) {
127+
atomic_init((const void *_Atomic *)target, initial);
126128
}
127129

128-
BNR_ATOMIC_INLINE
129-
const void *_Nullable bnr_atomic_ptr_exchange(bnr_atomic_ptr_t target, const void *_Nullable desired, bnr_atomic_memory_order_t order) {
130-
return atomic_exchange_explicit(&target->value, desired, order);
130+
BNR_ATOMIC_INLINE BNR_ATOMIC_WARN_UNUSED_RESULT BNR_ATOMIC_OVERLOAD
131+
const void *_Nullable bnr_atomic_load(bnr_atomic_ptr_t target, bnr_atomic_memory_order_t order) {
132+
return atomic_load_explicit((const void *_Atomic *)target, order);
131133
}
132134

133-
BNR_ATOMIC_INLINE
134-
bool bnr_atomic_ptr_compare_and_swap(bnr_atomic_ptr_t target, const void *_Nullable expected, const void *_Nullable desired, bnr_atomic_memory_order_t order) {
135-
return atomic_compare_exchange_strong_explicit(&target->value, &expected, desired, order, memory_order_relaxed);
135+
BNR_ATOMIC_INLINE BNR_ATOMIC_WARN_UNUSED_RESULT
136+
const void *_Nullable bnr_atomic_exchange(bnr_atomic_ptr_t target, const void *_Nullable desired, bnr_atomic_memory_order_t order) {
137+
return atomic_exchange_explicit((const void *_Atomic *)target, desired, order);
136138
}
137139

138-
typedef volatile struct bnr_atomic_flag_s {
139-
_Atomic(_Bool) value;
140-
} bnr_atomic_flag, *_Nonnull bnr_atomic_flag_t;
140+
BNR_ATOMIC_INLINE BNR_ATOMIC_WARN_UNUSED_RESULT
141+
bool bnr_atomic_compare_and_swap(bnr_atomic_ptr_t target, const void *_Nullable expected, const void *_Nullable desired, bnr_atomic_memory_order_t order) {
142+
return atomic_compare_exchange_strong_explicit((const void *_Atomic *)target, &expected, desired, order, memory_order_relaxed);
143+
}
141144

142-
BNR_ATOMIC_INLINE
143-
bool bnr_atomic_flag_load(bnr_atomic_flag_t target, bnr_atomic_memory_order_t order) {
144-
return atomic_load_explicit(&target->value, order);
145+
BNR_ATOMIC_INLINE BNR_ATOMIC_WARN_UNUSED_RESULT
146+
const void *_Nonnull bnr_atomic_load_and_wait(bnr_atomic_ptr_t target) {
147+
const void *result = NULL;
148+
for (;;) {
149+
if (BNR_ATOMIC_LIKELY(result = bnr_atomic_load(target, bnr_atomic_memory_order_acquire))) break;
150+
#if defined(__x86_64__) || defined(__i386__)
151+
__asm__("pause");
152+
#elif defined(__arm__) || defined(__arm64__)
153+
__asm__("yield");
154+
#else
155+
__asm__("");
156+
#endif
157+
}
158+
return result;
145159
}
146160

147-
BNR_ATOMIC_INLINE
148-
bool bnr_atomic_flag_test_and_set(bnr_atomic_flag_t target, bnr_atomic_memory_order_t order) {
149-
return atomic_exchange_explicit(&target->value, true, order);
161+
typedef volatile bool *_Nonnull bnr_atomic_flag_t;
162+
163+
BNR_ATOMIC_INLINE BNR_ATOMIC_OVERLOAD
164+
void bnr_atomic_init(bnr_atomic_flag_t target, bool initial) {
165+
atomic_init((atomic_bool *)target, initial);
150166
}
151167

152-
typedef volatile struct bnr_atomic_bitmask_s {
153-
_Atomic(uint8_t) value;
154-
} bnr_atomic_bitmask, *_Nonnull bnr_atomic_bitmask_t;
168+
BNR_ATOMIC_INLINE BNR_ATOMIC_WARN_UNUSED_RESULT BNR_ATOMIC_OVERLOAD
169+
bool bnr_atomic_load(bnr_atomic_flag_t target, bnr_atomic_memory_order_t order) {
170+
return atomic_load_explicit((atomic_bool *)target, order);
171+
}
155172

156-
BNR_ATOMIC_INLINE
157-
void bnr_atomic_bitmask_init(bnr_atomic_bitmask_t target, uint8_t mask) {
158-
atomic_init(&target->value, mask);
173+
BNR_ATOMIC_INLINE BNR_ATOMIC_OVERLOAD
174+
void bnr_atomic_store(bnr_atomic_flag_t target, bool desired, bnr_atomic_memory_order_t order) {
175+
atomic_store_explicit((atomic_bool *)target, desired, order);
159176
}
160177

161-
BNR_ATOMIC_INLINE
162-
uint8_t bnr_atomic_bitmask_add(bnr_atomic_bitmask_t target, uint8_t mask, bnr_atomic_memory_order_t order) {
163-
return atomic_fetch_or_explicit(&target->value, mask, order);
178+
typedef volatile uint8_t *_Nonnull bnr_atomic_bitmask_t;
179+
180+
BNR_ATOMIC_INLINE BNR_ATOMIC_OVERLOAD
181+
void bnr_atomic_init(bnr_atomic_bitmask_t target, uint8_t mask) {
182+
atomic_init((uint8_t _Atomic *)target, mask);
164183
}
165184

166-
BNR_ATOMIC_INLINE
167-
uint8_t bnr_atomic_bitmask_remove(bnr_atomic_bitmask_t target, uint8_t mask, bnr_atomic_memory_order_t order) {
168-
return atomic_fetch_and_explicit(&target->value, ~mask, order);
185+
BNR_ATOMIC_INLINE BNR_ATOMIC_WARN_UNUSED_RESULT BNR_ATOMIC_OVERLOAD
186+
uint8_t bnr_atomic_load(bnr_atomic_bitmask_t target, bnr_atomic_memory_order_t order) {
187+
return atomic_load_explicit((uint8_t _Atomic *)target, order);
169188
}
170189

171-
BNR_ATOMIC_INLINE
172-
bool bnr_atomic_bitmask_test(bnr_atomic_bitmask_t target, uint8_t mask, bnr_atomic_memory_order_t order) {
173-
return (atomic_load_explicit(&target->value, order) & mask) != 0;
190+
BNR_ATOMIC_INLINE BNR_ATOMIC_OVERLOAD
191+
uint8_t bnr_atomic_fetch_or(bnr_atomic_bitmask_t target, uint8_t mask, bnr_atomic_memory_order_t order) {
192+
return atomic_fetch_or_explicit((uint8_t _Atomic *)target, mask, order);
174193
}
175194

176-
typedef volatile struct bnr_atomic_counter_s {
177-
_Atomic(long) value;
178-
} bnr_atomic_counter, *_Nonnull bnr_atomic_counter_t;
195+
BNR_ATOMIC_INLINE BNR_ATOMIC_OVERLOAD
196+
uint8_t bnr_atomic_fetch_and(bnr_atomic_bitmask_t target, uint8_t mask, bnr_atomic_memory_order_t order) {
197+
return atomic_fetch_and_explicit((uint8_t _Atomic *)target, mask, order);
198+
}
179199

180-
BNR_ATOMIC_INLINE
181-
long bnr_atomic_counter_load(bnr_atomic_counter_t target) {
182-
return atomic_load(&target->value);
200+
typedef volatile long *_Nonnull bnr_atomic_counter_t;
201+
202+
BNR_ATOMIC_INLINE BNR_ATOMIC_OVERLOAD
203+
void bnr_atomic_init(bnr_atomic_counter_t target) {
204+
atomic_init((atomic_long *)target, 0);
183205
}
184206

185-
BNR_ATOMIC_INLINE
186-
long bnr_atomic_counter_increment(bnr_atomic_counter_t target) {
187-
return atomic_fetch_add(&target->value, 1) + 1;
207+
BNR_ATOMIC_INLINE BNR_ATOMIC_WARN_UNUSED_RESULT BNR_ATOMIC_OVERLOAD
208+
long bnr_atomic_load(bnr_atomic_counter_t target) {
209+
return atomic_load((atomic_long *)target);
188210
}
189211

190-
BNR_ATOMIC_INLINE
191-
long bnr_atomic_counter_decrement(bnr_atomic_counter_t target) {
192-
return atomic_fetch_sub(&target->value, 1) - 1;
212+
BNR_ATOMIC_INLINE BNR_ATOMIC_OVERLOAD
213+
long bnr_atomic_fetch_add(bnr_atomic_counter_t target, long offset) {
214+
return atomic_fetch_add((atomic_long *)target, offset);
215+
}
216+
217+
BNR_ATOMIC_INLINE BNR_ATOMIC_OVERLOAD
218+
long bnr_atomic_fetch_subtract(bnr_atomic_counter_t target, long offset) {
219+
return atomic_fetch_sub((atomic_long *)target, offset);
193220
}
194221

195222
#undef SWIFT_ENUM

0 commit comments

Comments
 (0)