Swift3でCountdownLatchを作る、あるいはSemaphoreのtimeoutをSwift3で書く
テストの都合でラッチが欲しかったので、GCDのSemaphoreのラッパークラスを書こうと思ったんですね。
それで、 https://github.com/zhuhaow/CountdownLatch を参考にすれば割と簡単では! と思ったんですが、GCDの記法がSwift3で変わりすぎていて死ぬかと思った。のでメモ。
// 参考元: https://github.com/zhuhaow/CountdownLatch import Foundation class CountDownLatch { var count: Int private let dispatchQueue = DispatchQueue(label: "CountdownQueue") // 参考: https://qiita.com/codelynx/items/56ce2f91cd3f4f409aeb let semaphore = DispatchSemaphore(value: 0) let timeInSec : Int init?(count: Int, timeInSec: Int) { guard count > 0 else { return nil } self.count = count self.timeInSec = timeInSec } func countdown() { dispatchQueue.async { self.count -= 1 if self.count == 0 { self.semaphore.signal() } } } func await() -> Bool { // 参考: http://www.brilliantraven.com/code-snippets/grand-central-dispatch.html let result = semaphore.wait(timeout: DispatchTime.now() + DispatchTimeInterval.seconds(self.timeInSec)) if (result == .success) { return true } else { return false } } }
CouuntDownLatch
を使う側のコードは以下
func doTask() { let countDownLatch = CountDownLatch(count: 1, timeInSec: 30)! checkTimeoutBeforeCompletion(latch: countDownLatch) // なんか重い処理する countDownLatch.countdown() } func checkTimeoutBeforeCompletion(latch: CountDownLatch) { let queue = DispatchQueue(label: "background", attributes: .concurrent) queue.async { let processedOnTime = latch.await() if (processedOnTime) { NSLog("processed on time") } else { assertionFailure("遅いぞ!!!!") } } }
計数型セマフォについて
http://woshidan.hatenadiary.jp/entry/2017/08/27/005353 で使い方の勉強をした気がするんですが意味がよくわかってなかったので。
計数型セマフォは「チケットを配ってチケットをもらえたスレッドは処理を先へ進めることができる」みたいなもの。 ここから下はチケットを配ってもらえたスレッドにしか実行させない、みたいな箇所で
semaphore.await();
dispatch_semaphore_wait(semaphore, time);
のように、wait
っぽい関数を置く。 (少なくともObjCの場合は) wait
関数から抜ける時にセマフォのカウンタ(比喩でいうとチケットの枚数)がデクリメントする。
初期化時にセマフォが何枚のチケットを持っているか指定して、チケットを配られたスレッドたちが実行する処理の中でチケットを返したり(Semaphoreのカウンタをインクリメントする)する。
ObjCの場合、Semaphoreのカウンタをインクリメントする処理は以下。
dispatch_semaphore_signal(semaphore)
なので、全体の処理としてはこんな感じになる。
// セマフォの用意 dispatch_semaphore_t semaphore = dispatch_semaphore_create(1); // セマフォのところで待つ時間 dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 1ull * NSEC_PER_SEC); // ここからセマフォで用意したチケットの枚数ぶん以上のスレッドは実行してくれるなよ long result = dispatch_semaphore_wait(semaphore, time); // 上の行を通り過ぎるとセマフォのカウンタは1減っている if (result == 0) { // セマフォのカウンタが1以上だった or 待機時間中にセマフォのカウンタが1以上になったので // 処理が進められる // 排他制御したかった処理 // この処理の最後あたりでセマフォのカウンタを戻しておきましょう dispatch_semaphore_signal(semaphore) } else { // 指定時間待機したけどセマフォのカウンタが0のままだった }
現場からは以上です。
エキスパートObjective-Cプログラミング ?iOS/OS Xのメモリ管理とマルチスレッド?
- 作者: 坂本一樹
- 出版社/メーカー: インプレス
- 発売日: 2011/11/18
- メディア: 単行本(ソフトカバー)
- 購入: 8人 クリック: 343回
- この商品を含むブログ (25件) を見る
iOSのUIをコードで追加して配置する
5回ググって書く気が失せたのでBlogged.
// https://qiita.com/i_terasaka/items/2cf7d0f7146f32c3f2c1#%E5%8F%96%E5%BE%97%E6%96%B9%E6%B3%95 let button = UIButton(type: UIButtonType.system) button.frame = CGRect(x: 180, y: 50, width: 100, height: 40) button.setTitle("button", for: UIControlState.normal) button.accessibilityIdentifier = "button" // XCUITest用 button.addTarget(self, action: #selector(ViewController.someAction), for: UIControlEvents.touchUpInside) self.view.addSubview(button) // https://qiita.com/on0z/items/9768d2bccc29cc4e1851 var wkWebView : WKWebView! wkWebView = WKWebView(frame: CGRect(x: 100, y: 100, width: self.view.frame.size.width / 2, height: self.view.frame.size.height / 2)) self.view.addSubview(wkWebView) // 初期化メソッドに差はない var uiwebview : UIWebView! uiwebview = UIWebView(frame: CGRect(x: 100, y: 120 + self.view.frame.size.height / 4 , width: self.view.frame.size.width / 2, height: self.view.frame.size.height / 4)) self.view.addSubview(uiwebview)
参考
合わせて読みたい
iOSでBundleファイルを扱う
.bundle
拡張子のついたフォルダーを用意- その下にファイルを置く
.bundle
拡張子のついたファイルをXCode上で追加したいプロジェクトに追加- 下記のように
NSString
やNSData
,UIImage
などの関数でデータを読み込む
NSString* filePath = [NSString stringWithFormat:@"%@/%@", [[NSBundle mainBundle] pathForResource:@"test" ofType:@"bundle"], FILE_NAME]; NSString* content = [NSString stringWithContentsOfFile:filename encoding:NSUTF8StringEncoding error:nil]; NSLog(@"content: %@", content); NSData *contentData = [NSData dataWithContentsOfFile:filePath options:NSDataReadingMappedIfSafe error:nil]; [UIImage imageNamed:filePath];
参考
今日のAWS
terraform ちょっとだけ触りました
resource "aws_s3_bucket", "woshidan-terrafom-test" { # 追加する種類のリソース, リソース名 # s3の場合 bucket = "woshidan-terrafom-test" path = "/" acl = "private" # acl = "..." で設定しているのはAWS側によってあらかじめ定義された既定ACL # privateはデフォルト設定。所有者はすべての権限を持つが他のユーザにアクセス許可はない # http://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/acl-overview.html#canned-acl # 既定ACLに付け加えて記載するポリシー. JSON形式で書く policy = << POLICY { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "aws-portal:View*", "Resource": "*" } ] } POLICY }
AWS S3のACL
http://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/acl-overview.html
AWS S3 アクセスコントロールリスト(ACL)では、バケットとオブジェクトへのアクセスを管理ができる。各バケットとオブジェクトにはサブリソースとしてACLが付与されていて、ACLには
- 所有者
- 被付与者(AWSアカウントまたはグループ)
- 付与されたアクセス許可
の要素がある。
PolicyとPolicy Attachment
Policyのリソース( aws_iam_policy
)は別個に定義することができて、下記のようにさらにAttachmentリソースの定義でユーザーやグループと結びつけることで、管理画面でやるようにユーザーが所属するグループの食い合わせによってそのユーザーが持っている権限が定義される、というような管理の仕方ができそう。
resource "aws_iam_policy" "WoshidanTerraformTestFullAccess" { name = "WoshidanTerraformTestFullAccess" path = "/" description = "terraform hello world" policy = <<POLICY { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:List*", "Resource": "arn:aws:s3:::*" }, { "Effect": "Allow", "Action": [ "s3:GetObject*", "s3:DeleteObject*", "s3:PutObject*" ], "Resource": [ "arn:aws:s3:::woshidan-terrafom-test/*" ] } ] } POLICY }
resource "aws_iam_policy_attachment" "WoshidanTerraformTestFullAccess" { name = "WoshidanTerraformTestFullAccess" users = [...] roles = [] policy_arn = "${aws_iam_policy.WoshidanTerraformTestFullAccess.arn}" }
Cocos2d-x用の日本語対応フォントファイルをGlyph Designer2を使って書き出し
Glyph Designer 2 の入手
Glyph Designer - A Bitmap Font Generator for Mac · 71Squared
よりDLした後、ライセンス(月900円~)を購入してアクティベイトキーを入力。
日本語フォントの追加
【cocos2d/unity3d】簡単に日本語表示用のフォントが作れる「GlyphDesigner」の使い方 | albatrus.comを参考にしつつ、 Font Systems
のアプリケーションから利用したいフォントのフォルダを開いて、フォントファイル (.otf
)を Glyph Designer 2
から開くことができるパスへコピーします。
なお、今回利用させていただいたフォントはこちらのりぃ手書きNです。
そのフォントを Glyph Designer 2
のメニューの File > Load Font
で開きます。
すると以下のように利用可能なフォントとして追加されます。
設定ファイル上で日本語を利用できるようにする
このままでは設定ファイルは以下の文字しか対応していません。ゲーム上で利用した場合、日本語は利用できなくなっています。
それでは困るので、フォントの設定にひらがなとカタカナを利用可能な文字として追加することにします。
真ん中の目のアイコンを押すとプレビュー画面が開き、実際にフォントを利用した場合の様子を試すことができます。
設定ファイルのexport