ParallelWorker.swift 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. //
  2. // ParallelWorker.swift
  3. // Nextcloud
  4. //
  5. // Created by Henrik Storch on 18.02.22.
  6. // Copyright © 2022 Henrik Storch. All rights reserved.
  7. //
  8. // Author Henrik Storch <henrik.storch@nextcloud.com>
  9. //
  10. // This program is free software: you can redistribute it and/or modify
  11. // it under the terms of the GNU General Public License as published by
  12. // the Free Software Foundation, either version 3 of the License, or
  13. // (at your option) any later version.
  14. //
  15. // This program is distributed in the hope that it will be useful,
  16. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. // GNU General Public License for more details.
  19. //
  20. // You should have received a copy of the GNU General Public License
  21. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. //
  23. import Foundation
  24. import UIKit
  25. /// Object to execute multiple tasks in parallel like uploading or downloading.
  26. /// - Can display a progress indicator with status message
  27. /// - Can be canceled by user
  28. class ParallelWorker {
  29. let completionGroup = DispatchGroup()
  30. let queue = DispatchQueue(label: "ParallelWorker")
  31. let semaphore: DispatchSemaphore
  32. let titleKey: String
  33. var hud = NCHud()
  34. var totalTasks: Int?
  35. var completedTasks = 0
  36. var isCancelled = false
  37. /// Creates a ParallelWorker
  38. /// - Parameters:
  39. /// - n: Amount of tasks to be executed in parallel
  40. /// - titleKey: Localized String key, used for the status. Default: *Please Wait...*
  41. /// - totalTasks: Number of total tasks, if known
  42. /// - hudView: The parent view or current view which should present the progress indicator. If `nil`, no progress indicator will be shown.
  43. init(n: Int, titleKey: String?, totalTasks: Int?, controller: NCMainTabBarController?) {
  44. semaphore = DispatchSemaphore(value: n)
  45. self.totalTasks = totalTasks
  46. self.titleKey = titleKey ?? "_wait_"
  47. hud.initHudRing(view: controller?.view,
  48. text: NSLocalizedString(self.titleKey, comment: ""),
  49. tapToCancelDetailText: true) {
  50. self.isCancelled = true
  51. NCNetworking.shared.cancelUploadTasks()
  52. NCNetworking.shared.cancelDownloadTasks()
  53. }
  54. }
  55. /// Execute
  56. /// - Parameter task: The task to execute. Needs to call `completion()` when done so the next task can be executed.
  57. func execute(task: @escaping (_ completion: @escaping () -> Void) -> Void) {
  58. completionGroup.enter()
  59. queue.async {
  60. self.semaphore.wait()
  61. guard !self.isCancelled else { return self.completionGroup.leave() }
  62. task {
  63. self.completedTasks += 1
  64. self.hud.setText(text: "\(NSLocalizedString(self.titleKey, comment: ""))")
  65. self.semaphore.signal()
  66. self.completionGroup.leave()
  67. }
  68. }
  69. }
  70. /// Indicates that all tasks have been scheduled. Some tasks might still be in progress.
  71. /// - Parameter completion: Will be called after all tasks have finished
  72. func completeWork(completion: (() -> Void)? = nil) {
  73. completionGroup.notify(queue: .main) {
  74. guard !self.isCancelled else { return }
  75. self.hud.dismiss()
  76. completion?()
  77. }
  78. }
  79. }