カテゴリー: programming

Swift3について色々まとめていくスレ

String を Data に変換する

色々実験したスクショ

スクリーンショット 2016-08-12 18.50.49

C++メモ

  • struct/classの違い➡︎デフォルトの可視性
  • 基本的にすべて値型
  • const は signature に含まれる
  • 抽象クラスを作るときは必ずデストラクタを作る

厨二病

virtual 継承とそうでないものの違い

superクラスのコンストラクタを取り込む

Swift1系脳で出来ないと思い込んでいたことができるようになっていた件

再帰的構造を持つ enum

Swift 1 系では、再帰的構造を持つ enum を定義することはできませんでした。たとえば、

というコードを書くと、Swiftの処理系は受け付けてくれません。しかしながら、Swift2はとても素晴らしい indirect という修飾子を導入することにより、再帰的構造を持つ enum を定義できるようになりました。

また、挙動的に面白いのが、再帰的構造を持つが即座に評価されないようになっている場合、たとえば以下のような遅延ストリームについては、indirect 修飾子がなくても動くのです。これは Swift 1 系のときに挙動を試してないので、どうだったかわかりませんが、Xcode ダウンロードするのめちゃめちゃ時間掛かるし重いのでだれか試して欲しい。

にゃ〜ん…って感じですね?

関数内に定義した関数の再帰呼び出し

まあコードみればわかると思うけど、以下のようなコードが Swift 1 系では動かなかった(記憶がある…)。間違っていたらごめんなさい。でも関数内に定義した関数なんて、再帰呼び出しにくらいしか使わなくないですか?と半ギレした記憶があるので多分ほんとに動かなかったと思う。Swift2でやっと動くようになりました。

Swift 最高!!!!!!(大嘘)

AWS SDK for Node.jsを用いたSQSの操作

AWS Lambda を使ってお手軽に SQS を操作するために、普段はあまり使わないが Node.js 経由で試してみることにした。本当はJavaのほうが慣れているし、好きなのですがいかんせん Lambda にいちいち jar をアップロードするのは非常に厳しい気持ちになるので、まあたまには…。

自分のためのメモ書きなので、各位はドキュメントを見るべきだと思います
http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/SQS.html

SQS へのメッセージの送信

SQS メッセージの受信

SQS 受信メッセージの削除

Node.js 書くのかったるい…

PHPの private なメソッドを無理やりテストする方法

Java の package プライベートとかほんと素晴らしい仕組みだと思うのですが、他言語はなかなかないですね…。最近だと Swift2 でようやく @testable import などという形で、モジュールプライベート的なメソッドをテストできるようになっていますが、まだまだ Java に比べると柔軟ではない感じはあります。そもそも、Swift1系はアクセス修飾子の設計普通にミスってるんじゃないかと思いますが、まあ言語を作っている方々は自分よりもはるかに知識がある方々だと思うので、いろいろあったのかな…という感想。自分はコードを読み書きするときにアクセス修飾子を基準にどこから読み進めるかとか、このメソッドは重要だなとかを判断するので、やっぱりこのあたりの機能が柔軟な言語のほうが好き。

本題。PHPの private メソッドを無理やりテストする方法。まあリフレクションしかないですよね。ということで、以下のような具合(自分のための備忘録)。

にゃ〜ん…って感じだ。

AWS Lambda を用いた Amazon SNS のエンドポイント整理

 Amazon SNS の Application に紐付いているエンドポイントには Enabled という Attribute がついています。文字どおり、有効なエンドポイントかどうかを表すものです。Amazon SNS は賢いので APNSGCM からのフィードバックを受けて、プッシュトークンが無効になった場合に自動的に false にしてくれます。しかし、基本的には Enabledfalse になったエンドポイントは不要です。したがって、これらを自動的に削除するような仕組みがあったほうがよさそうです。そこで、この記事では AWS Lambda を用いて、それを実現する方法について説明します。

AWS Lambda で動かすスクリプト

 コード自体は非常に簡単で以下のような形です。AWS Lambda Function を素早く立ち上げるとしたら本来は pythonnode.js のほうが良いかと思いますが、今回の作りたいものに関してはそれほど即時性を求められるようなものではないと思うので、好きな言語(もちろん Lambda でうごくもの)で問題ないと思います。

 json4s とか typesafe config とか scala logging とか使ってます。よい塩梅に jar に固めて、 Lambda Function を作って、アップロードしてください。これで AWS Lambda 側の準備は完了です。

Amazon SNS 側の連携設定

Amazon SNS側の作業は次の2点になります。

  1. 先ほど作った AWS Lambda Function の実行をフックさせるためトピックを作成し、購読(Subscribe)させる
  2. エンドポイントの整理をしたい対象の Application の持つエンドポイントの状態変化をフックして、トピックに通知を送るように設定する

それぞれについて見ていきましょう。

トピックおよび、サブスクリプションの作成

 トピックの作成は通常どおり普通にやってあげれば大丈夫です。とりあえず適当に「endpoint-updated-topic」とでも名前をつけておきましょう。続いて作成したトピックを先ほど作成した Lambda Function に購読させましょう。以下のような形で Protocol で AWS Lambda を選択すれば Endpoint のプルダウンリストに先ほど作成した Lambda Function の ARN がでてくるでしょう。

スクリーンショット 2016-05-26 0.41.37

Application のイベント設定

 最後に Amazon SNS の Application に紐づくエンドポイントの Attributes が変化したイベントをトピックに通知させるように設定します。 Application 一覧の画面で設定対象のアイテムを選択し Actions から configure events を選択してください。

スクリーンショット 2016-05-26 0.46.00

 そして、次に表示されるダイアログの Endpoint Updated の項目に、先ほどつくったトピックの ARN を入力すれば、すべての作業は完了です。

スクリーンショット 2016-05-26 0.48.25

動作確認テスト

 設定が終わったら適当に Application へ Endpoint を追加してみて、Edit Endpoint Attributes から Enable を false にしてみてください。きっと自動的にエンドポイントが削除されるはずです。

スクリーンショット 2016-05-26 0.50.55

 Application エンドポイントの Attribute 変更以外にも、作成イベント、削除イベントなどをフックすることができるので、やり方次第では様々な連携を AWS Lambda を用いて行うことができると思います。

Immutable パターン

結城先生のデザパタ本マルチスレッド編 第2章のまとめ

問題

複数のスレッドがインスタンスを共有しているが、インスタンスの状態は変化しない。
このときに、何も考えず Single Threaded Execution パターンを使うとスループットが落ちてしまいます。

解決方法

インスタンスが状態変化しないのであれば Single Threaded Execution パターンを使う必要はありません。
その場合は意図しない状態変化を防ぐためにフィールドが変化しないようにする Immutable パターンを用います。
不変性を保つのは大変なので、気をつけて実装する必要があります。またドキュメントにクラスが不変であることを明示する方が良いでしょう。

関連するパターン

  • 状態を変更するスレッドが参照するスレッドの数よりも少ないときは、Read-Write Lock パターンが使えます

コード例はあまりにもつまらないので割愛

適用可能性

  • インスタンスの生成後、状態が変化しない時
  • インスタンスが共有され、頻繁にアクセスされるとき

余談

mutable なクラスと immutable なクラス

Java 標準ライブラリには mutable なクラスと immutable なクラスが対になっているものがある。

  • java.lang.String
  • java.lang.StringBuffer

不変性を守るために

  • フィールドの保持している mutable なインスタンスをそのまま返すようなことをすると不変性が破られる可能性がある
  • コンストラクタに引数として渡したインスタンスをそのままフィールドに代入した場合、不変性が破られる可能性がある

Single Threaded Executionパターン

結城先生のデザパタ本マルチスレッド編 第1章のまとめ

問題

複数のスレッドがインスタンスを共有している状態で、
それぞれのスレッドがインスタンスの状態を勝手に変更すると、インスタンスの安全性が失われます。

解決方法

そこで、そのままではインスタンスが不定な状態に陥ってしまう範囲を定めます。
これをクリティカルセクションと呼びます。
このクリティカルセクションを synchronized を用いて1つのスレッドだけが実行できるようにガードします。
このようなパターンを Single Threaded Execution パターンと呼びます。

関連するパターン

  • インスタンスの状態が変化しないときには Immutable パターンを使うことにより、スループットを向上させることができる
  • インスタンスの状態を参照するスレッドと変更するスレッドが分かれている場合は Read-Write Lock パターンを使うことにより、スループットを向上させることができる

以下のようなカウンターがあったとします

これを次のように複数のスレッドから呼び出すとおかしなことが起こります

実行すると同じ値がログ出力されたり、
300回 increment が呼び出されているはずなのに、最後のログ出力が 300 になっていなかったりするはずです。
increment はインスタンス内部の状態を変化させるメソッドであり、複数のスレッドから呼び出すと予期せぬ挙動をとります。
この部分をクリティカルセクションとして保護してあげれば良いでしょう。単に synchronized をつければよいだけです。

パフォーマンスのために、一般にクリティカルセクションは小さく保つほうが良いでしょう。

適用可能性

  • 複数のスレッドからクラスへのアクセスが行われるとき
    • シングルスレッドで実行するプログラムにはこのような対応は必要ない。
  • クラスが状態変化する可能性を持っているとき
  • 安全性を保つ必要があるとき

余談

long と double はアトミックに扱われない

Javaのprimitive型の参照や代入は基本的にアトミックです。
しかし、longdouble に関してはアトミックではありません。

例えば、同じ long フィールドに対して、異なる2つのスレッドから同時に 5678, 1234 という形で代入をおこなったとします。
するとこのフィールドがどのような値をとるか保証されません。この場合は synchronized を使うか volatile キーワードを使うという手があります。

まとめると

  • 基本型・参照型の参照・代入はアトミック
  • long, double に関しては例外
  • long, double をスレッド間で共有する場合は synchronizedvolatile を使う

計数セマフォ

synchronized を使うと、ある領域を1つのスレッドのみが実行できるように制限できますが、
n個のスレッドのみが実行できるようにしたいなどという場合には計数セマフォというものが用意されている。

使い方は簡単で次のような感じ