2013年12月10日火曜日

CentOS6.2にgcc4.8.2を入れた時のメモ

CentOS6.2のgcc4.7.2が入っている環境に、gcc4.8.2を入れた時、最後のgccのmakeではまったので記録。

まず、gcc4.8のコンパイルについては超親切で丁寧なページがあるので、それを参考に進めるのだが、最後のgccのmakeで少しはまったので、解決した時のconfigureオプションを残しておきます。

./configure --with-gmp=/usr/local --with-mpfr=/usr/local --with-mpc=/usr/local --with-ppl=/usr/local --with-cloog=/usr/local --program-suffix=-4.8 --enable-languages=c,c++ --disable-multilib

gccをc/c++しか使わない人用です。
なぜか、各コンポーネントを見つけてこないことがあるので全部ディレクトリ指定しました。
あと、64bit環境しかいらないので、--disable-multilib を指定しています。

2013年11月25日月曜日

[c++11] えっc++って__METHOD__ないの?

プログラム書いてて、エラーメッセージのところで発生箇所のメソッド名を付けたかったんだけど、よくわからんから何となく __METHOD__ とか書いてみたら当然エラーになった。
__func__じゃ短いし、__PRETTY_FUNCTION__じゃ長いので、
// class::method みたいな文字列を取るマクロ
#define __METHOD__ [](std::string s){int sp=s.find(' ')+1;int pa=s.find('(');if(sp>pa)sp=0;return s.substr(sp,pa-sp);}(__PRETTY_FUNCTION__)
ってやったら欲しいのができた。
type_info::name()を使ってもよかったんだけど、デマングルとか面倒くさそうだったので、上の形にした。
自分でよく使いそうなのでメモ。

2013年11月21日木曜日

[linux] mozcで、かな入力。入力できない文字への対処。

mozcのかな入力で、はまった。

実際は、mozcの問題というよりもキーボード設定の問題だと思うんだけど、入力できない文字があって困った。
例えば、自分の場合、macbookからvncを通して、Ubuntu12.04のmozcでかな入力しようとするとどうしても小さい「ゃ」が打てなくて大きい「や」になってしまう。「ゅ」「ょ」はOKなのにである。
ちなみにシングルクォーテーションはちゃんと入力できる。

{むむぅ。随分、微妙な症状だなぁ・・・}
もちろん、ぐぐっても微妙すぎて解決法どころか同じ症状すら出てこない。

キーボードの設定を調べたが、すぐにわからなかったのと、
 ・ ディストリとかが違うとどうせ設定も違う。
 ・ vncを通すので問題がややこしい。
 ・ macからもwindowsからも操作したりするのでややこしい。
ので、
{追いかけるのも面倒だぞ、これは。}
と思い、頭に来たので、禁断の
ローマ字テーブル「かな」化作戦!!
を決行することにした。ダメ作戦と思いきや、意外に快適になったので、ローマ字テーブルをmozc設定画面からexportしたファイルをリンクしておきます。
そのままmozc設定画面からimportして使用できます。

使用時に注意するところは、
・ aを叩くと「ち」ではなく「a」と表示されるが変換するとちゃんと「ち」で変換できるので気にしないこと。(他のキーも同様)
・ 「0」のshiftは登録できないので、「を」を出すのは「ほ」のshiftになっている。
・ 自分の環境だと漢字入力モードでも、¥キーだけ押すと直接¥になってしまったので、「ー」は、shift+¥になっている。
・ 「」をshiftなし、『』をshift付きで出したいのだが「む」とバッティングするので、「」とセットで打ち込んだ時に「」が表示されるようになっている。
くらいかなー。

これを元に、好きにカスタマイズするといいかもしれません。

この方法で結構良かったのは、キーボードの微妙なカスタマイズが、ローマ字変換テーブルの調整でできちゃうところで、自分の環境にあわせて作れます。
また、ローマ字変換テーブルには、かなり複雑な入力パターンも登録できるので、IMEのカスタマイズとしても変な使い方が出来そうです。

2013年10月24日木曜日

[c++11] finallyみたいなことしたいけど、専用のRAIIクラス作るの嫌なんだけど・・・

c++には、javaみたいなfinallyがないんだけど、あーゆーの欲しいなーとおもって調べてみると、結局、

RAII用のクラス作れよ
boost/scope_exit使えよ

ということのようだ、前者はそれ用のクラス毎回作るのもなんだかなーだし、後者はちょっとぐじゃぐじゃしてて嫌だった。

頭に来たので、RAII用にshared_ptrを流用することにしたので、以下にメモっておく。
あ、c++11必須ね。
#include <iostream>
#include <string>
#include <memory>
#include <stdexcept>

using namespace std;
#define FINALLY(CLAUSE) shared_ptr<void> f_i_n_a_l_l_y(nullptr, [&](void*){CLAUSE});

class SomeResource {
public:
 void open() {cout << "some resource open." << endl;}
 void close() {cout << "some resource close." << endl;}
};

int main() {
 try {
  SomeResource res;
  FINALLY(
    res.close();
  )

  res.open();
  cout << "before throw exception." << endl;
  throw runtime_error("xxx error.");
  cout << "end of try block." << endl;
 } catch (runtime_error &e) {
  cout << "Error: " << e.what() << endl;
 }
 cout << "out of try block." << endl;
}
実行した結果は、
some resource open.
before throw exception.
some resource close.
Error: xxx error.
out of try block.
マクロ使って少し見やすくしました。
注意点は、FINALLYを解放したいリソースの宣言と例外が出る可能性のある場所の「間」に入れるところです。

こう見ると、shared_ptrのカスタムデリーターって、いろんなことに流用できそうですね。ちゃんとカウント取ってるからそこの一部のスコープだけに限らず使えるし。
後処理という発想だけでなく、なんかのトリガー的なことに使うと面白そう。

2013年9月12日木曜日

scalaで調子に乗ってfuture{でスレッド量産してたらはまった

注・この記事は、scala2.10を使用しています。

scalaで、
import ExecutionContext.Implicits.global
とfuture使ってて、
「あれ? futureで作った別スレッドの処理がなんか始まらないことがあるんだけど・・・」
ということがある人のための記事です。

scala使ってて便利なのにスレッドを超簡単に作れるってのがあるんだけど、
import ExecutionContext.Implicits.global // どこか上の方でimport

future {
・ なんかいろいろ
・ なんかいろいろ
}
こんな感じね。

ただ単に、future{やると、エラーが出るんで、いろんなサイトのサンプル(こことかこことかここ。みんな良サイト) を参考に、先にimportしてscalaが持ってるデフォルトのExecutionContextであるExecutionContext.Implicits.global を利用するようにしてた。

ところが、調子に乗ってメインのスレッドでやりたくないことをfuture{でがんがん切り離して処理したんだけど、そのプログラムをコア数1のマシンで動かそうとしたら動かない。コア数2のマシンで動かしたらなんか動くけど、プログラムがよく固まる。

固まった状態ではほとんどCPUは食っていない。
ちなみに自分の開発マシンは、4core&ハイパースレッドで8スレッドだったのでその現象は出なかった。
{うげー、マルチスレッド周りの問題は追いかけにくくて嫌だなー・・・}
と思ったのだが、printlnとか入れてみるとどうやら処理がfutureの中身に来ていないようだ。

仕方ないのでサンプルを書いて自機(8スレマシン)で実験してみた。
import scala.concurrent._
import ExecutionContext.Implicits.global

object ThreadSample {
  def main(args: Array[String]) {
    val startTime = System.currentTimeMillis()

    for (idx <- 1 to 24) {
     future {
      println(f"idx = $idx%2d, time = ${System.currentTimeMillis() - startTime}%4d ms")
      Thread.sleep(1000)
     }
    }
    Thread.sleep(3000)
    println(s"end of main.     ${System.currentTimeMillis() - startTime} ms")
  }
}
実行結果
idx =  1, time =   73 ms
idx =  3, time =   73 ms
idx =  8, time =   73 ms
idx =  2, time =   73 ms
idx =  7, time =   73 ms
idx =  4, time =   73 ms
idx =  5, time =   73 ms
idx =  6, time =   73 ms
idx = 13, time = 1099 ms
idx = 16, time = 1099 ms
idx = 15, time = 1099 ms
idx = 10, time = 1099 ms
idx =  9, time = 1099 ms
idx = 14, time = 1099 ms
idx = 11, time = 1099 ms
idx = 12, time = 1099 ms
idx = 21, time = 2100 ms
idx = 23, time = 2100 ms
idx = 20, time = 2100 ms
idx = 19, time = 2100 ms
idx = 18, time = 2100 ms
idx = 17, time = 2100 ms
idx = 22, time = 2100 ms
idx = 24, time = 2100 ms
end of main.     3074 ms
{なんじゃこりゃ、8個ずつしか動いてないじゃん。}
sleepしたからって、次のthreadを処理してくれる訳じゃなく御丁寧にsleepが終わるまで次のスレッドを処理しないで待ってるではないか!
で、どうやらこの同時に動けるfutureの数がマシンのコア数によって変るので、コア数の少ないマシンで自分のプログラムを動かしてた時にfutureで切り離したthreadが実行されなかった模様。

何か他のやり方ないかな、と探していたら、spawnというものがあるようなのでこんなふうに変えてみたら
import scala.concurrent._
import scala.concurrent.ops.spawn

object ThreadSample {
  def main(args: Array[String]) {
    val startTime = System.currentTimeMillis()

 for (idx <- 1 to 24) {
     spawn {
      println(f"idx = $idx%2d, time = ${System.currentTimeMillis() - startTime}%4d ms")
      Thread.sleep(1000)
     }
    }
    Thread.sleep(3000)
    println(s"end of main.     ${System.currentTimeMillis() - startTime} ms")
  }
}
実行結果
idx = 16, time =   56 ms
idx = 23, time =   57 ms
idx =  7, time =   55 ms
idx =  8, time =   55 ms
idx = 21, time =   56 ms
idx = 12, time =   56 ms
idx = 14, time =   56 ms
idx =  5, time =   55 ms
idx = 15, time =   56 ms
idx = 20, time =   56 ms
idx = 19, time =   56 ms
idx = 11, time =   56 ms
idx =  3, time =   55 ms
idx = 13, time =   56 ms
idx =  2, time =   55 ms
idx = 10, time =   55 ms
idx =  1, time =   55 ms
idx = 17, time =   56 ms
idx =  4, time =   55 ms
idx = 18, time =   56 ms
idx = 24, time =   57 ms
idx =  9, time =   55 ms
idx = 22, time =   57 ms
idx =  6, time =   55 ms
end of main.     3058 ms
欲しかった結果になった。しかしコンパイル時に、こんな警告が出た。
[warn] /Users/xxx.scala:97: object ops in package concurrent is deprecated: Use `Future` instead.
[warn]   spawn {
[warn]   ^
{なにー、future使えだとー!?}
仕方ないのでもう少し調べてみると、ちゃんと理解せずに使っていた、
import ExecutionContext.Implicits.global
が元のスレッドの動作を制御していたようで、こいつを変更する必要があった。 しかし、ここで活躍するのが何とjavaのスレッド管理機能であるExecutorsってやつだった。(わかりやすい解説)
で、変更したコードがこれ
import scala.concurrent._
import java.util.concurrent.Executors

object ThreadSample {
  def main(args: Array[String]) {
    val startTime = System.currentTimeMillis()

    val pool = Executors.newCachedThreadPool()
    implicit val execctx = ExecutionContext.fromExecutorService(pool)
 for (idx <- 1 to 24) {
     future {
      println(f"idx = $idx%2d, time = ${System.currentTimeMillis() - startTime}%4d ms")
      Thread.sleep(1000)
     }
    }
    Thread.sleep(3000)
    println(s"end of main.     ${System.currentTimeMillis() - startTime} ms")
  }
}
実行結果
idx = 18, time =   60 ms
idx =  6, time =   59 ms
idx =  5, time =   59 ms
idx =  2, time =   59 ms
idx = 10, time =   59 ms
idx = 13, time =   60 ms
idx = 11, time =   60 ms
idx =  7, time =   59 ms
idx =  8, time =   59 ms
idx =  9, time =   59 ms
idx =  4, time =   59 ms
idx =  3, time =   59 ms
idx = 17, time =   60 ms
idx = 19, time =   60 ms
idx = 15, time =   60 ms
idx = 21, time =   60 ms
idx = 22, time =   61 ms
idx = 12, time =   60 ms
idx = 16, time =   60 ms
idx = 24, time =   61 ms
idx = 23, time =   61 ms
idx = 20, time =   60 ms
idx =  1, time =   59 ms
idx = 14, time =   60 ms
end of main.     3062 ms
で、うまくいった。
Executor辺りのことは、上で紹介したサイトにも書いてあったのだが、そこを読んだときは、ExecutionContext.Implicits.globalで動くんだからいいじゃん。とちゃんと理解してなかった。

ちなみにPlayFrameworkとかいじっててakkaが使える状態のときは、javaのExecutorsを呼ばずに
 val system = ActorSystem("xxxxx")
 import system.dispatcher

future {
・ なんかいろいろ
・ なんかいろいろ
}
で、ActorSystemのdispatcherをインポートしてあげれば、ExecutionContext.Implicits.globalを使わないでいい感じになった。

2013年7月18日木曜日

mac版 gnucash日本語入力への道 (gtkimcocoa使用)

この記事の情報は古くなっています。
2013/7当時は、普通にダウンロードしたgnucashでは、日本語入力できませんでしたが、2014/12現在の版(Ver. 2.6.5)では、何も考えずに普通に日本語入力できました。
(OSX Yosemite 10.10.1使用。OSX標準とgoogleの日本語入力で確認。)

最近macを使いだしたので、gnucashをmacにも入れて、どのマシンからでもgnucashからdropboxに置いたデータを更新できたら便利だなと思って、公式のmac用バイナリをインストールしてみた。

で、レシートそろえて「いざ入力!」と勇んでみたが、なんと日本語の入力が出来ない。
{まじすかーーっ!?}

いろいろ調べてみると、

だ、そうだ。おいおい。

そんな状況なのだが、gtk+にパッチを当てて、日本語入力できるようにした人もいるらしい
それをやってみようとも思ったが、後でgtk+のバージョンが上がったときに、もしパッチが当てられなくなったら手も足も出なくなりそうなのでパッチは嫌だなーと二の足を踏んでいたら、gtk+にパッチを当てなくても、偉い人がgtkimcocoaというgtk+のアドイン?を作っていて、これを使うと日本語入力できるらしいことを発見。

それを利用して、なんとか日本語入力できるところまで行ったので、後でもう一回出来るように記録を残します。

ただ、かなりややこしかったので、このページに検索で迷い込んできた人は、以下の俺のスペックを参考にやってみるか決めてください。
・ macを使い始めたばかりで、mac特有の仕組み等は全然わからない。
・ GTK+の仕組みについては全く知らない。
・ もちろん、GTK+の日本語入力の仕組みも知らない。
・ ソースをダウンロードしてビルドしてインストールとかは、変なオプションを駆使したりしないケースならできる。(./configure; make; make install; 位で勘弁してくれるeasyなケースね)
・ configureやmakeの途中でエラーで止まったりしたときは、エラーを見て足らないファイルをどこかから探して持ってくる位は出来ることが多い。
・ configureでエラーが出た時に、configure.acとかconfigure.inをいじってみたりすると、失敗することの方が多い。← configureについてちゃんと理解してない。

スペックを見て、こいつに出来るなら大丈夫そうだな等の参考にしてください。
ただ、なんのことやらわからない人は、手を出さない方がいいでしょう。

以下、やった作業をいろいろ書いていきますが、無駄な試行も含めてかなりいろいろやったので、全部は書ききれませんでした。なんとなくな書き方ですみません。(←性格の問題だろ)
また、自分がやった手順なので、無駄な手順も含まれていると思います。

大まかな順序は、
 gtk+のビルド・インストール →
 gtkimcocoaのビルド・インストール →
 gtk-demoで日本語入力確認 →
 gnucashのビルド・インストール →
 gnucash環境下へのgtkimcocoaのビルド・インストール →
 gnucash環境下のgtk-demoで日本語入力確認 →
 gnucashで日本語入力確認

注意点: 現時点のgnucashは、ver.2.5.3(Unstable)で、Gtk+-2.24 を使っていますが、今後GTL+3系に移行する予定があるようです。その場合、そのあたりの手順が変更になります。

なお、当方のOSバージョンは、OS X 10.8.4 です。日本語入力には「ことえり」を使用しています。

◎ GTK+のビルド・インストール
GTK+のインストール前にやってだめだったこと。
brew install gtk+
homebrewで、インストールしたgtk+だと、GTK+日本語入力モジュールのgtkimcocoaのコンパイルがうまくいかず挫折した。

いきなり{jhbuildってなんじゃ}とつまづくが、GTK+そのものやGTK+を使用したアプリをbuildする環境らしい。
ホームディレクトリで作業した。
$ curl -s -O https://git.gnome.org/browse/gtk-osx/plain/gtk-osx-build-setup.sh
$ sh gtk-osx-build-setup.sh  ← これでjhbuildがインストールされる
$ ~/.local/bin/jhbuild bootstrap
$ ~/.local/bin/jhbuild build meta-gtk-osx-bootstrap
$ ~/.local/bin/jhbuild build meta-gtk-osx-core

☆出会ったトラブルと対処
・ libffiのインストール時に、必要なダウンロードサイトがダウン(?)していてエラーで止まったが、エラー後のメニューで[4]を選択しjhbuildのシェルに入って、失敗したcurlコマンドのURLをググって他のサイトに変更しダウンロードする。ダウンロード後、そのshellでexitすると、先ほどのエラーメニューに戻るので[1]を選択すると次のステージに進む。
・ gettextのインストール(たぶん)で、autopointコマンドのエラーで止まったが、[4]shellから
autopoint --force
で切り抜ける。参考URL:http://lists.sourceforge.jp/mailman/archives/scim-imengine-dev/2007-March.txt
またexit→[1] で続行。
・ どこかで、configureの無限ループに落ち入るが、いっぺんctrl+cで強制終了して、もう一度
$ ~/.local/bin/jhbuild build meta-gtk-osx-core
の実行でなぜか切り抜ける。

◎ gtkimcocoaのビルド・インストール
テキトウにgitのsrcを展開するフォルダを作ってcdで移動
$ git clone git://github.com/ashie/gtkimcocoa.git
$ cd gtkimcocoa
$ ~/.local/bin/jhbuild shell
$ ./autogen.sh
$ ./configure   ← メッセージの最後の方の GTK+2: yes を確認
$ make
$ make install
◎ gtkimcocoaの設定
$ gtk-query-immodules-2.0 > ~/gtk/inst/etc/gtk-2.0/gtk.immodules
$ gtk-demo でデモ起動 OK
「Text Widget」→「Hypertext」を開いても日本語入力できた。

gtkimcocoaが正しくインストールされていると、バイナリ配布のGTK+使用アプリでも日本語入力可になるはずらしいのだが、この時点でバイナリ配布のgnucashを動かしても日本語入力がされなかった。

バイナリ配布のgnucashが32bitコンパイルされているのが原因かもしれない。ここで、GTK+を32bitでコンパイルして試すか、gnucashを64bitでコンパイルするかの選択を迫られるが、前者の方が大変そうな予感がするので、gnucashのコンパイルに賭けることにした。

◎ gnucash-unstableのビルド・インストール
$ ホームディレクトリで作業した。
$ ホームディレクトリにある .jhbuildrc-custom をバックアップを取った後
https://raw.github.com/jralls/gnucash-on-osx/master/.jhbuildrc-custom を参考に編集
$ ~/.local/bin/jhbuild bootstrap
$ ~/.local/bin/jhbuild build
編集した.jhbuildrc-customを参考に置いておきます。(unstableのgnucash用です。)

☆出会ったトラブルと対処
・ 何度も
AM_CONFIG_HEADER を使うな AC_CONFIG_HEADER を使え!というエラーに遭遇して止まるので、その度に[4]shellからconfigure.acまたはconfigure.inのAM_CONFIG_HEADERをAC_CONFIG_HEADERに変更する。
・ gmpのconfigureで、OS or マシンのarchitecture の認識がうまくいかなくて止まる。オプションでarchitectureを指定してもconfigureは通るがmakeで止まるので、gmpのコンパイルをあきらめる。
gmpは、brew install gmp でインストールしてskip連打で次に進んだ。
本来ここで入るgmpとバージョンも結構違うのでどうかと思ったが、後でこれが問題になることはなく最後まで行った。
・ どこかで、configureの無限ループに落ち入るが、いっぺんctrl+cで強制終了して、もう一度
$ ~/.local/bin/jhbuild build
の実行でなぜか切り抜ける。
・ ビルド中に何度かエラーで止まって冷や汗をかくが、なぜかいっぺんctrl+cで強制終了して、また
$ ~/.local/bin/jhbuild build
の再実行で、止まらずに次に行けるという現象と数回遭遇する。

◎ gnucashの環境でもgtkimcocoaをインストール
上でgtkimcocoaをインストールしたときと同じフォルダに移動
$ ~/.local/bin/jhbuild shell
$ ./autogen.sh
$ ./configure  ← メッセージの最後の方の GTK+2: yes を確認
$ make
$ make install ← 今度はgnucash-unstableのフォルダの奥にインストールされる
◎ gnucashの環境でgtkimcocoaの設定
$ gtk-query-immodules-2.0 > ~/gnucash-unstable/etc/gtk-2.0/gtk.immodules
$ ~/gnucash-unstable/bin/gtk-demo でデモ起動 OK
「Text Widget」→「Hypertext」を開いても日本語入力できた。

◎ GnuCashで日本語入力確認
$ ~/gnucash-unstable/bin/gnucash-launcher &
でgnucash起動。
日本語入力できることを確認した。

うへー、結構長い道のりだった。
証拠写真は、これ。

ただし、まだ日本語入力周りが原因で落ちることがあるようですので、こまめに記録を取った方がいいでしょう。

2013年6月4日火曜日

PlayFramework2.1.1環境で、ScalaからJNAへセットしたコールバックが戻ってこなくなる件

先日の投稿で、scalaからJNAのコールバックを設定するところを
object Tekito {
 lib.setFunction(idx, new JnaCallback {
  def onMessage(msg: String) = println("onMessage " + idx + ": " + msg)
 })
}
こんな感じで書いていたんだけど、実際の環境で上の書き方でコールバックをセットした後、しばらくすると不規則なタイミングでコールバックが返ってこなくなるケースが多発して困っていた。
で、なんとなく次のように変えてみる。
object Tekito {
 def callback = new JnaCallback {
  def onMessage(msg: String) = println("onMessage " + idx + ": " + msg)
 }
 lib.setFunction(idx, callback)
}
これでも状況は変わらず、しばらくするとコールバックが返ってこなくなる。
ただ、コールバックのセットをし直すと、コールバックがまた返ってくるようになることを発見したので、症状が出る前と後で
println(Tekito.callback)
してみると、
正常時
models.Tekito$$anon$1@5ca99bc
コールバックが返ってこなくなった後
models.Tekito$$anon$1@3833089c
{ぬおーっ!アドレス変ってるじゃないかー!}
c側でコールバックを保持しているのは、ただの関数ポインタなので、これではコールバックは返ってこない。
{これ、どうしてくれようか}
と思ったが、素直に下のようにしてみたら
object Tekito {
 val callback = new JnaCallback {
  def onMessage(msg: String) = println("onMessage " + idx + ": " + msg)
 }
 lib.setFunction(idx, callback)
}
こうしてみたら、Tekito.callbackのアドレスが固定されてコールバックが安定して返ってくるようになった。
私は、JVMやscalaのメモリ管理を詳しく知らないので、これで本当にアドレスが固定されるのか確信がないのだが、とりあえず今のところはアドレスが変ってしまうケースはなくなった。
なので、
「scalaからJNAのコールバックをセットする時は、コールバックをvalに入れておく」
をお勧めします。

追記 2013/06/19
後で気が付いたのですが、コールバックオブジェクトを変数に入れておかないと、そのオブジェクトはどこからも参照されていない状態になりGCが動いた時に掃除されてしまうので、コールバックが迷子になる。が正解っぽいです。
コールバックが迷子になるタイミングが不規則だったのは、GCが動くタイミングが不規則だからで、c側でコールバックを保持していてもJVMのメモリとは当然関係ないので、GCに片付けられてしまうということのようです。