Skip to content

Commit 6a5f0fe

Browse files
committed
Use atomic data access for a cocurrent pointer read/write
1 parent 748b6fb commit 6a5f0fe

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
@@ -393,24 +393,27 @@ final class SyntaxDataArena: @unchecked Sendable {
393393
// The storage of the buffer address is allocated next to the SyntaxData.
394394
let baseAddressRef = parent.advanced(by: 1)
395395
.unsafeRawPointer
396-
.assumingMemoryBound(to: UnsafePointer<SyntaxDataReference?>?.self)
396+
.assumingMemoryBound(to: AtomicPointer.self)
397397

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

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

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

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

415418
return SyntaxDataReferenceBuffer(buffer)
416419
}
@@ -460,7 +463,7 @@ final class SyntaxDataArena: @unchecked Sendable {
460463
return min(totalSize, 4096)
461464
}
462465

463-
/// Allocate and initialize `SyntaxData` with the trailing uninitialized buffer for the references to the children.
466+
/// Allocate and initialize `SyntaxData` with the trailing pointer storage for the references to the children.
464467
private static func createDataImpl(
465468
allocator: BumpPtrAllocator,
466469
raw: RawSyntax,
@@ -474,7 +477,7 @@ final class SyntaxDataArena: @unchecked Sendable {
474477
var totalSize = MemoryLayout<SyntaxData>.stride
475478
if childCount != 0 {
476479
// Tail allocate the storage for the pointer to the lazily allocated layout data.
477-
totalSize &+= MemoryLayout<UnsafePointer<SyntaxDataReference?>?>.size
480+
totalSize &+= MemoryLayout<AtomicPointer>.size
478481
}
479482
let alignment = MemoryLayout<SyntaxData>.alignment
480483
let allocated = allocator.allocate(byteCount: totalSize, alignment: alignment).baseAddress!
@@ -492,10 +495,10 @@ final class SyntaxDataArena: @unchecked Sendable {
492495

493496
if childCount != 0 {
494497
// Initlaize the tail allocated storage with 'nil'.
495-
allocated
498+
let layoutBufferBaseAddressRef = allocated
496499
.advanced(by: MemoryLayout<SyntaxData>.stride)
497-
.bindMemory(to: UnsafePointer<SyntaxDataReference?>?.self, capacity: 1)
498-
.initialize(to: nil)
500+
.bindMemory(to: AtomicPointer.self, capacity: 1)
501+
swiftsyntax_atomic_pointer_set(layoutBufferBaseAddressRef, nil)
499502
}
500503

501504
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)