GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing github.com — JavaScriptKit/Sources/JavaScriptEventLoop/JobQueue.swift at main · swiftwasm/JavaScriptKit Expand file tree/ Copy pathJobQueue.swiftMore file actions 139 lines (120 loc) · 5.01 KB / Copy pathJobQueue.swiftFile metadata and controls139 lines (120 loc) · 5.01 KB 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 // This file contains the job queue implementation which re-order jobs based on their priority. // Jobs form runs, one per priority in descending order, FIFO within a run. The first job of each // run points to its last job, so an insert steps over whole runs. import _Concurrency import _CJavaScriptEventLoop #if compiler(>=5.5) @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) struct QueueState: Sendable { fileprivate var headJob: UnownedJob? = nil fileprivate var isSpinning: Bool = false } @available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *) extension JavaScriptEventLoop { func insertJobQueue(job newJob: UnownedJob) { withUnsafeMutablePointer(to: &queueState.headJob) { headJobPtr in var position: UnsafeMutablePointer<UnownedJob?> = headJobPtr while let runHead = position.pointee, runHead.rawPriority >= newJob.rawPriority { let runTail = runHead.lastInRun().pointee! if runHead.rawPriority == newJob.rawPriority { newJob.nextInQueue().pointee = runTail.nextInQueue().pointee runTail.nextInQueue().pointee = newJob runHead.lastInRun().pointee = newJob return } position = runTail.nextInQueue() } newJob.nextInQueue().pointee = position.pointee newJob.lastInRun().pointee = newJob position.pointee = newJob } // TODO: use CAS when supporting multi-threaded environment if !queueState.isSpinning { self.queueState.isSpinning = true JavaScriptEventLoop.shared.queueMicrotask { self.runAllJobs() } } } func runAllJobs() { assert(queueState.isSpinning) // The clock is only read while `yieldInterval` is set. var start: DrainInstant? = yieldInterval == nil ? nil : drainClockNow() // A clock read costs more than a small job. Read it every `clockStride` jobs, and double // the stride (up to 256) while the drain is far from the interval. var clockStride = 1 var jobsUntilClockRead = 1 while let job = self.claimNextFromQueue() { #if compiler(>=5.9) job.runSynchronously(on: self.asUnownedSerialExecutor()) #else job._runSynchronously(on: self.asUnownedSerialExecutor()) #endif if let yieldInterval, queueState.headJob != nil { if let start { jobsUntilClockRead -= 1 if jobsUntilClockRead > 0 { continue } let elapsed = drainElapsed(since: start) if elapsed >= yieldInterval { // Keep `isSpinning` set so new jobs wait for the continuation. queueHostTask { self.runAllJobs() } return } if elapsed * 4 < yieldInterval { clockStride = min(clockStride * 2, 256) } jobsUntilClockRead = clockStride } else { start = drainClockNow() } } } queueState.isSpinning = false } func claimNextFromQueue() -> UnownedJob? { if let job = self.queueState.headJob { let nextJob = job.nextInQueue().pointee if let nextJob { let runTail = job.lastInRun().pointee! if !runTail.isSameJob(as: job) { nextJob.lastInRun().pointee = runTail } } self.queueState.headJob = nextJob return job } return nil } } @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) extension UnownedJob { private func asImpl() -> UnsafeMutablePointer<_CJavaScriptEventLoop.Job> { unsafeBitCast(self, to: UnsafeMutablePointer<_CJavaScriptEventLoop.Job>.self) } fileprivate var flags: JobFlags { JobFlags(bits: asImpl().pointee.Flags) } fileprivate var rawPriority: UInt32 { flags.priority } fileprivate func nextInQueue() -> UnsafeMutablePointer<UnownedJob?> { return withUnsafeMutablePointer(to: &asImpl().pointee.SchedulerPrivate.0) { rawNextJobPtr in let nextJobPtr = UnsafeMutableRawPointer(rawNextJobPtr).bindMemory(to: UnownedJob?.self, capacity: 1) return nextJobPtr } } /// The last job of the run. Valid only on the first job of a run. fileprivate func lastInRun() -> UnsafeMutablePointer<UnownedJob?> { return withUnsafeMutablePointer(to: &asImpl().pointee.SchedulerPrivate.1) { rawLastJobPtr in UnsafeMutableRawPointer(rawLastJobPtr).bindMemory(to: UnownedJob?.self, capacity: 1) } } fileprivate func isSameJob(as other: UnownedJob) -> Bool { asImpl() == other.asImpl() } } private struct JobFlags { var bits: UInt32 = 0 var priority: UInt32 { (bits & 0xFF00) >> 8 } } #endif |
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |