|
7 | 7 | // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
8 | 8 | //
|
9 | 9 |
|
| 10 | +import Dispatch |
10 | 11 |
|
11 | 12 | /* Class for managing set of indexes. The set of valid indexes are 0 .. NSNotFound - 1; trying to use indexes outside this range is an error. NSIndexSet uses NSNotFound as a return value in cases where the queried index doesn't exist in the set; for instance, when you ask firstIndex and there are no indexes; or when you ask for indexGreaterThanIndex: on the last index, and so on.
|
12 | 13 |
|
@@ -388,36 +389,60 @@ open class NSIndexSet : NSObject, NSCopying, NSMutableCopying, NSSecureCoding {
|
388 | 389 | let reverse = opts.contains(.reverse)
|
389 | 390 | let passRanges = paramType == NSRange.self
|
390 | 391 | let findIndex = returnType == Bool.self
|
391 |
| - var stop = false |
| 392 | + var sharedStop = false |
| 393 | + let lock = NSLock() |
392 | 394 | let ranges = _ranges[startRangeIndex...endRangeIndex]
|
393 |
| - let rangeSequence = (reverse ? AnySequence(ranges.reversed()) : AnySequence(ranges)) |
394 |
| - outer: for curRange in rangeSequence { |
395 |
| - let intersection = NSIntersectionRange(curRange, range) |
396 |
| - if passRanges { |
397 |
| - if intersection.length > 0 { |
398 |
| - let _ = block(intersection as! P, &stop) |
399 |
| - } |
400 |
| - if stop { |
401 |
| - break outer |
402 |
| - } |
403 |
| - } else if intersection.length > 0 { |
404 |
| - let maxIndex = NSMaxRange(intersection) - 1 |
405 |
| - let indexes = reverse ? stride(from: maxIndex, through: intersection.location, by: -1) : stride(from: intersection.location, through: maxIndex, by: 1) |
406 |
| - for idx in indexes { |
407 |
| - if findIndex { |
408 |
| - let found : Bool = block(idx as! P, &stop) as! Bool |
409 |
| - if found { |
410 |
| - result = idx |
411 |
| - stop = true |
412 |
| - } |
413 |
| - } else { |
414 |
| - let _ = block(idx as! P, &stop) |
| 395 | + let rangeSequence = (reverse ? AnyCollection(ranges.reversed()) : AnyCollection(ranges)) |
| 396 | + let iteration = withoutActuallyEscaping(block) { (closure: @escaping (P, UnsafeMutablePointer<ObjCBool>) -> R) -> (Int) -> Void in |
| 397 | + return { (rangeIdx) in |
| 398 | + lock.lock() |
| 399 | + var stop = sharedStop |
| 400 | + lock.unlock() |
| 401 | + if stop { return } |
| 402 | + |
| 403 | + let idx = rangeSequence.index(rangeSequence.startIndex, offsetBy: IntMax(rangeIdx)) |
| 404 | + let curRange = rangeSequence[idx] |
| 405 | + let intersection = NSIntersectionRange(curRange, range) |
| 406 | + if passRanges { |
| 407 | + if intersection.length > 0 { |
| 408 | + let _ = closure(intersection as! P, &stop) |
415 | 409 | }
|
416 | 410 | if stop {
|
417 |
| - break outer |
| 411 | + lock.lock() |
| 412 | + sharedStop = stop |
| 413 | + lock.unlock() |
| 414 | + return |
| 415 | + } |
| 416 | + } else if intersection.length > 0 { |
| 417 | + let maxIndex = NSMaxRange(intersection) - 1 |
| 418 | + let indexes = reverse ? stride(from: maxIndex, through: intersection.location, by: -1) : stride(from: intersection.location, through: maxIndex, by: 1) |
| 419 | + for idx in indexes { |
| 420 | + if findIndex { |
| 421 | + let found : Bool = closure(idx as! P, &stop) as! Bool |
| 422 | + if found { |
| 423 | + result = idx |
| 424 | + stop = true |
| 425 | + } |
| 426 | + } else { |
| 427 | + let _ = closure(idx as! P, &stop) |
| 428 | + } |
| 429 | + if stop { |
| 430 | + lock.lock() |
| 431 | + sharedStop = stop |
| 432 | + lock.unlock() |
| 433 | + return |
| 434 | + } |
418 | 435 | }
|
419 | 436 | }
|
420 |
| - } // else, continue |
| 437 | + } |
| 438 | + } |
| 439 | + |
| 440 | + if opts.contains(.concurrent) { |
| 441 | + DispatchQueue.concurrentPerform(iterations: Int(rangeSequence.count), execute: iteration) |
| 442 | + } else { |
| 443 | + for idx in 0..<Int(rangeSequence.count) { |
| 444 | + iteration(idx) |
| 445 | + } |
421 | 446 | }
|
422 | 447 |
|
423 | 448 | return result
|
|
0 commit comments