@@ -31,10 +31,10 @@ extension Task where Success == Never, Failure == Never {
3131
3232 /// The type of continuation used in the implementation of
3333 /// sleep(nanoseconds:).
34- private typealias SleepContinuation = UnsafeContinuation < ( ) , Error >
34+ typealias SleepContinuation = UnsafeContinuation < ( ) , Error >
3535
3636 /// Describes the state of a sleep() operation.
37- private enum SleepState {
37+ enum SleepState {
3838 /// The sleep continuation has not yet begun.
3939 case notStarted
4040
@@ -106,7 +106,7 @@ extension Task where Success == Never, Failure == Never {
106106
107107 /// Called when the sleep(nanoseconds:) operation woke up without being
108108 /// canceled.
109- private static func onSleepWake(
109+ static func onSleepWake(
110110 _ wordPtr: UnsafeMutablePointer < Builtin . Word >
111111 ) {
112112 while true {
@@ -150,7 +150,7 @@ extension Task where Success == Never, Failure == Never {
150150
151151 /// Called when the sleep(nanoseconds:) operation has been canceled before
152152 /// the sleep completed.
153- private static func onSleepCancel(
153+ static func onSleepCancel(
154154 _ wordPtr: UnsafeMutablePointer < Builtin . Word >
155155 ) {
156156 while true {
@@ -294,133 +294,4 @@ extension Task where Success == Never, Failure == Never {
294294 throw error
295295 }
296296 }
297-
298- @available ( SwiftStdlib 5 . 7 , * )
299- internal static func _sleep(
300- until seconds: Int64 , _ nanoseconds: Int64 ,
301- tolerance: Duration ? ,
302- clock: _ClockID
303- ) async throws {
304- // Allocate storage for the storage word.
305- let wordPtr = UnsafeMutablePointer< Builtin . Word> . allocate( capacity: 1 )
306-
307- // Initialize the flag word to "not started", which means the continuation
308- // has neither been created nor completed.
309- Builtin . atomicstore_seqcst_Word (
310- wordPtr. _rawValue, SleepState . notStarted. word. _builtinWordValue)
311-
312- do {
313- // Install a cancellation handler to resume the continuation by
314- // throwing CancellationError.
315- try await withTaskCancellationHandler {
316- let _: ( ) = try await withUnsafeThrowingContinuation { continuation in
317- while true {
318- let state = SleepState ( loading: wordPtr)
319- switch state {
320- case . notStarted:
321- // The word that describes the active continuation state.
322- let continuationWord =
323- SleepState . activeContinuation ( continuation) . word
324-
325- // Try to swap in the continuation word.
326- let ( _, won) = Builtin . cmpxchg_seqcst_seqcst_Word (
327- wordPtr. _rawValue,
328- state. word. _builtinWordValue,
329- continuationWord. _builtinWordValue)
330- if !Bool( _builtinBooleanLiteral: won) {
331- // Keep trying!
332- continue
333- }
334-
335- // Create a task that resumes the continuation normally if it
336- // finishes first. Enqueue it directly with the delay, so it fires
337- // when we're done sleeping.
338- let sleepTaskFlags = taskCreateFlags (
339- priority: nil , isChildTask: false , copyTaskLocals: false ,
340- inheritContext: false , enqueueJob: false ,
341- addPendingGroupTaskUnconditionally: false )
342- let ( sleepTask, _) = Builtin . createAsyncTask ( sleepTaskFlags) {
343- onSleepWake ( wordPtr)
344- }
345- let toleranceSeconds : Int64
346- let toleranceNanoseconds : Int64
347- if let components = tolerance? . components {
348- toleranceSeconds = components. seconds
349- toleranceNanoseconds = components. attoseconds / 1_000_000_000
350- } else {
351- toleranceSeconds = 0
352- toleranceNanoseconds = - 1
353- }
354-
355- _enqueueJobGlobalWithDeadline (
356- seconds, nanoseconds,
357- toleranceSeconds, toleranceNanoseconds,
358- clock. rawValue, Builtin . convertTaskToJob ( sleepTask) )
359- return
360-
361- case . activeContinuation, . finished:
362- fatalError ( " Impossible to have multiple active continuations " )
363-
364- case . cancelled:
365- fatalError ( " Impossible to have cancelled before we began " )
366-
367- case . cancelledBeforeStarted:
368- // Finish the continuation normally. We'll throw later, after
369- // we clean up.
370- continuation. resume ( )
371- return
372- }
373- }
374- }
375- } onCancel: {
376- onSleepCancel ( wordPtr)
377- }
378-
379- // Determine whether we got cancelled before we even started.
380- let cancelledBeforeStarted : Bool
381- switch SleepState ( loading: wordPtr) {
382- case . notStarted, . activeContinuation, . cancelled:
383- fatalError ( " Invalid state for non-cancelled sleep task " )
384-
385- case . cancelledBeforeStarted:
386- cancelledBeforeStarted = true
387-
388- case . finished:
389- cancelledBeforeStarted = false
390- }
391-
392- // We got here without being cancelled, so deallocate the storage for
393- // the flag word and continuation.
394- wordPtr. deallocate ( )
395-
396- // If we got cancelled before we even started, through the cancellation
397- // error now.
398- if cancelledBeforeStarted {
399- throw _Concurrency. CancellationError ( )
400- }
401- } catch {
402- // The task was cancelled; propagate the error. The "on wake" task is
403- // responsible for deallocating the flag word and continuation, if it's
404- // still running.
405- throw error
406- }
407- }
408-
409- /// Suspends the current task until the given deadline within a tolerance.
410- ///
411- /// If the task is canceled before the time ends, this function throws
412- /// `CancellationError`.
413- ///
414- /// This function doesn't block the underlying thread.
415- ///
416- /// try await Task.sleep(until: .now + .seconds(3), clock: .continuous)
417- ///
418- @available ( SwiftStdlib 5 . 7 , * )
419- public static func sleep< C: Clock > (
420- until deadline: C . Instant ,
421- tolerance: C . Instant . Duration ? = nil ,
422- clock: C
423- ) async throws {
424- try await clock. sleep ( until: deadline, tolerance: tolerance)
425- }
426297}
0 commit comments