dispatch いちいち書くの面倒だったら…自分で改良すればいいじゃない！

まあ皆さんも多分思ってるじゃないでしょうか、バックグラウンドスレッドに切り替えたり逆にメインスレッドを呼び出したりすることがよくありますが、`dispatch` 系、もしくはは GCD 系の文法ってなんでいちいちそんなに書くの面倒でしょう、と。

まあ GCD 系の命令は純粋な C 言語の物なので、名前空間はもちろん、クラスなんざも当然ないし、ただの関数だから引数ラベルなんかもあるわけない。そのせいで関数名は全て `dispatch_` なんちゃらになるから、今の Xcode 7.3 より古い Xcode なら補完効かせるのもすごいしんどかったです。7.3 からは途中入力も効くようになったからだいぶ助かりましたが。

それでも `dispatch` 系の関数を利用するのに、いちいち `dispatch` 系の変数を作らなきゃいけなかったりと利用するのに一手間かかるものです…

**そうだ！GCD struct を作ろう**

というわけで、作ってみた結果がこれです：

```swift:GCD.swift
import Foundation

struct GCD {
	
	enum Thread {
		
		case Main
		case Static(queue: dispatch_queue_t)
		case Dynamic(name: String, attribute: QueueAttribute)
		
		var queue: dispatch_queue_t {
			switch self {
			case .Main:
				return dispatch_get_main_queue()
				
			case .Static(queue: let queue):
				return queue
				
			case .Dynamic(name: let name, attribute: let attribute):
				return dispatch_queue_create(name, attribute.queueAttribute)
			}
		}
		
		enum QueueAttribute {
			case Serial
			case Concurrent
			
			var queueAttribute: dispatch_queue_attr_t {
				switch self {
				case .Serial:
					return DISPATCH_QUEUE_SERIAL
					
				case .Concurrent:
					return DISPATCH_QUEUE_CONCURRENT
				}
			}
		}
		
	}
	
	private init() {
		
	}

}

extension GCD { // MARK: Semaphores
	
	enum DispatchTime {
		case Forever
		case TimeAfter(delta: NSTimeInterval)
		
		var dispatchTimeType: dispatch_time_t {
			switch self {
			case .Forever:
				return DISPATCH_TIME_FOREVER
				
			case .TimeAfter(delta: let delta):
				let nanoseconds = Int64(delta * NSTimeInterval(NSEC_PER_SEC))
				let time = dispatch_time(DISPATCH_TIME_NOW, nanoseconds)
				return time
			}
		}
	}
	
	static func createSemaphore(value: Int) -> dispatch_semaphore_t {
		return dispatch_semaphore_create(value)
	}
	
	static func fireSemaphore(semaphore: dispatch_semaphore_t) {
		dispatch_semaphore_signal(semaphore)
	}
	
	static func waitForSemaphore(semaphore: dispatch_semaphore_t, until deadLine: DispatchTime = .Forever) {
		dispatch_semaphore_wait(semaphore, deadLine.dispatchTimeType)
	}
	
}

extension GCD { // MARK: Queues
	
	static func runSynchronizedQueue(at thread: Thread = .Main, with action: (() -> Void)) {
		
		dispatch_sync(thread.queue) {
			action()
		}
		
	}
	
	static func runAsynchronizedQueue(at thread: Thread = .Main, waitUntilStartForMax waitTime: NSTimeInterval? = nil, with action: (() -> Void)) {
		
		if let waitTime = waitTime {
			let semaphore = GCD.createSemaphore(thread.queue.hash)
			dispatch_async(thread.queue, {
				GCD.fireSemaphore(semaphore)
				action()
			})
			GCD.waitForSemaphore(semaphore, until: waitTime == 0 || waitTime == .infinity ? .Forever : .TimeAfter(delta: waitTime))
			
		} else {
			dispatch_async(thread.queue) {
				action()
			}
		}
		
	}
	
}
```

とりあえず一番よく使う `dispatch_(a)sync` の関数と `dispatch_semaphore` 系の関数を `GCD` という `struct` の静的メソッドに変身させました。これで結構使いやすくなります。例えば非同期でメインスレッドで `view.setNeedsDisplay()` を実行させたい、そしてメインスレッドが実際動くまで最大 1 秒待機させておきたい場合、今までですと

```swift
let semaphore = dispatch_semaphore_create(0)
dispatch_async(dispatch_get_main_queue()) {
	dispatch_semaphore_signal(semaphore)
	view.setNeedsDisplay()
}
dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, Int64(NSEC_PER_SEC)))
```

という面倒なコードを書かなければいけなかった（この中に本当に重要なのはただの `view.setNeedsDisplay()` の 1 行だけだというのに…）が、自前で `dispatch` 系の `struct` を使うと

```
GCD.runAsynchronizedQueue(waitUntilStartForMax: 1) { 
	view.setNeedsDisplay()
}
```

のようにたったの3行で解決できちゃいます、しかも `dispatch` 用に何か新しい変数をいちいち自分で作る必要がなくなり、名前空間も効けば `enum` の活用でコードも短くなる上読みやすさも向上されます。まあ皆さんも自分のコードスタイルに合わせて `dispatch` をもっと使いやすいように何かしらの `struct` なり `class` なりを作ってみればマルチスレッドの制御がもっと書きやすくなると思いますよ！

宣伝：実は今プライベートで Swift の勉強や練習も兼ねて iOS 用の ADV エンジンを作ろうとしており、[プロジェクトは GitHub 上で公開しています](https://github.com/el-hoshino/Canola)。完成にはまだほど遠いし master ブランチはまだ何もありませんし develop ブランチは今頑張って毎日更新しようとしているところですが出来てるのはまだ背景と立ち絵の表示だけですが。ちなみに最大の目標は読みやすいスクリプト文法を作ることです。というわけでおそらく ADV スクリプト文法としては初めてなんじゃないかな？という試みはスクリプト命令に変数ラベルを導入してみました。やはり Objective-C の最大の功績は変数ラベルですよ。はい。というわけで、実はこのプロジェクトがこの `GCD struct` を初めて使ってみたプロジェクトです。