Skip to content

Commit 74beef9

Browse files
committed
Use atomic data access for a cocurrent pointer read/write
1 parent 2551980 commit 74beef9

File tree

4 files changed

+26
-11
lines changed

4 files changed

+26
-11
lines changed

Sources/SwiftSyntax/Syntax.swift

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -392,24 +392,27 @@ final class SyntaxDataArena: @unchecked Sendable {
392392
// The storage of the buffer address is allocated next to the SyntaxData.
393393
let baseAddressRef = parent.advanced(by: 1)
394394
.unsafeRawPointer
395-
.assumingMemoryBound(to: UnsafePointer<SyntaxDataReference?>?.self)
395+
.assumingMemoryBound(to: AtomicPointer.self)
396396

397397
// If the buffer is already populated, return it.
398-
if let baseAddress = baseAddressRef.pointee {
398+
if let baseAddress = swiftsyntax_atomic_pointer_get(baseAddressRef)?.assumingMemoryBound(to: SyntaxDataReference?.self) {
399399
return SyntaxDataReferenceBuffer(UnsafeBufferPointer(start: baseAddress, count: childCount))
400400
}
401401

402402
mutex.lock()
403403
defer { mutex.unlock() }
404404

405405
// Recheck, maybe some other thread has populated the buffer during acquiring the lock.
406-
if let baseAddress = baseAddressRef.pointee {
406+
if let baseAddress = swiftsyntax_atomic_pointer_get(baseAddressRef)?.assumingMemoryBound(to: SyntaxDataReference?.self) {
407407
return SyntaxDataReferenceBuffer(UnsafeBufferPointer(start: baseAddress, count: childCount))
408408
}
409409

410410
let buffer = createLayoutDataImpl(parent)
411411
// Remeber the base address of the created buffer.
412-
UnsafeMutablePointer(mutating: baseAddressRef).pointee = buffer.baseAddress
412+
swiftsyntax_atomic_pointer_set(
413+
UnsafeMutablePointer(mutating: baseAddressRef),
414+
UnsafeRawPointer(buffer.baseAddress)
415+
)
413416

414417
return SyntaxDataReferenceBuffer(buffer)
415418
}
@@ -459,7 +462,7 @@ final class SyntaxDataArena: @unchecked Sendable {
459462
return min(totalSize, 4096)
460463
}
461464

462-
/// Allocate and initialize `SyntaxData` with the trailing uninitialized buffer for the references to the children.
465+
/// Allocate and initialize `SyntaxData` with the trailing pointer storage for the references to the children.
463466
private static func createDataImpl(
464467
allocator: BumpPtrAllocator,
465468
raw: RawSyntax,
@@ -473,7 +476,7 @@ final class SyntaxDataArena: @unchecked Sendable {
473476
var totalSize = MemoryLayout<SyntaxData>.stride
474477
if childCount != 0 {
475478
// Tail allocate the storage for the pointer to the lazily allocated layout data.
476-
totalSize &+= MemoryLayout<UnsafePointer<SyntaxDataReference?>?>.size
479+
totalSize &+= MemoryLayout<AtomicPointer>.size
477480
}
478481
let alignment = MemoryLayout<SyntaxData>.alignment
479482
let allocated = allocator.allocate(byteCount: totalSize, alignment: alignment).baseAddress!
@@ -491,10 +494,10 @@ final class SyntaxDataArena: @unchecked Sendable {
491494

492495
if childCount != 0 {
493496
// Initlaize the tail allocated storage with nil.
494-
allocated
497+
let layoutBufferBaseAddressRef = allocated
495498
.advanced(by: MemoryLayout<SyntaxData>.stride)
496-
.bindMemory(to: UnsafePointer<SyntaxDataReference?>?.self, capacity: 1)
497-
.initialize(to: nil)
499+
.bindMemory(to: AtomicPointer.self, capacity: 1)
500+
swiftsyntax_atomic_pointer_set(layoutBufferBaseAddressRef, nil)
498501
}
499502

500503
return SyntaxDataReference(UnsafePointer(dataRef))

Sources/_SwiftSyntaxCShims/include/AtomicBool.h renamed to Sources/_SwiftSyntaxCShims/include/Atomics.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,16 @@ static inline void swiftsyntax_atomic_bool_destroy(AtomicBool *_Nonnull atomic)
3838
free(atomic);
3939
}
4040

41+
typedef struct {
42+
_Atomic(const void *_Nullable) value;
43+
} AtomicPointer;
44+
45+
static inline const void *_Nullable swiftsyntax_atomic_pointer_get(const AtomicPointer *_Nonnull atomic) {
46+
return atomic->value;
47+
}
48+
49+
static inline void swiftsyntax_atomic_pointer_set(AtomicPointer *_Nonnull atomic, const void *_Nullable newValue) {
50+
atomic->value = newValue;
51+
}
52+
4153
#endif // SWIFTSYNTAX_ATOMICBOOL_H

Sources/_SwiftSyntaxCShims/include/SwiftSyntaxCShims.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "_includes.h"
14-
#include "AtomicBool.h"
14+
#include "Atomics.h"
1515
#include "PlatformMutex.h"
1616
#include "swiftsyntax_errno.h"
1717
#include "swiftsyntax_stdio.h"

Sources/_SwiftSyntaxCShims/include/module.modulemap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module _SwiftSyntaxCShims {
22
header "_includes.h"
3-
header "AtomicBool.h"
3+
header "Atomics.h"
44
header "PlatformMutex.h"
55
header "swiftsyntax_errno.h"
66
header "swiftsyntax_stdio.h"

0 commit comments

Comments
 (0)