@@ -63,6 +63,7 @@ final class Pool<T: Sendable>: Sendable {
6363 private let itemsSemaphore : DispatchSemaphore // limits the number of elements
6464 private let itemsGroup : DispatchGroup // knows when no element is used
6565 private let barrierQueue : DispatchQueue
66+ private let barrierActor : DispatchQueueActor
6667 private let semaphoreWaitingQueue : DispatchQueue // Inspired by https://khanlou.com/2016/04/the-GCD-handbook/
6768 private let semaphoreWaitingActor : DispatchQueueActor
6869
@@ -84,6 +85,7 @@ final class Pool<T: Sendable>: Sendable {
8485 self . itemsSemaphore = DispatchSemaphore ( value: maximumCount)
8586 self . itemsGroup = DispatchGroup ( )
8687 self . barrierQueue = DispatchQueue ( label: " GRDB.Pool.barrier " , qos: qos, attributes: [ . concurrent] )
88+ self . barrierActor = DispatchQueueActor ( queue: barrierQueue, flags: [ . barrier] )
8789 self . semaphoreWaitingQueue = DispatchQueue ( label: " GRDB.Pool.wait " , qos: qos)
8890 self . semaphoreWaitingActor = DispatchQueueActor ( queue: semaphoreWaitingQueue)
8991 }
@@ -203,6 +205,15 @@ final class Pool<T: Sendable>: Sendable {
203205 }
204206 }
205207
208+ func barrier< R: Sendable > (
209+ execute barrier: sending ( ) throws -> sending R
210+ ) async rethrows -> sending R {
211+ try await barrierActor. execute {
212+ itemsGroup. wait ( )
213+ return try barrier ( )
214+ }
215+ }
216+
206217 /// Asynchronously runs the `barrier` function when no element is used, and
207218 /// before any other element is dequeued.
208219 func asyncBarrier( execute barrier: @escaping @Sendable ( ) -> Void ) {
0 commit comments