2012年12月28日金曜日

SpamAssassin for xmailserver (windows) の解説を増やしました

 どもども、SpamAssassin Filter for XMailServer (Windows)に関する記事です。  最近、Windows にSpamAssassinをインストールするのがしんどいので、Ubuntu に SpamAssassin 日本語パッチ版をインストールする手順を書き加えました。 UbuntuにSpamAssassin日本語パッチ版をインストール  まぁ、仮想サーバも一般的になってきた事だし、こういう構成も気楽にできるようになってきたのでは?と思います。SpamAssassinの導入が、どうにも・・・と、お悩みの方も、これを機会に導入を検討されてみては、いかがでしょうか?

2017/4/18追記:https://github.com/oki-miyuki/xmspamc に移しました。Wikiとか放置ですみませんorz

2012年12月26日水曜日

std::move と asio

いやー、C++11 素晴らしいですね〜。 とりあえず、頭に描いたシナリオどおりに事が運ぶか、実験くんしてみました。 シナリオは、

  1. 所有権のあるコピーできない Foo クラスがあり
  2. ref では、まずいので、shared_ptr で asio のハンドラに Foo を保持させ
  3. io_service で処理されたら所定の vector へ move しながら Foo をぶっ込む
  4. へっへっへっ、リソース管理しなくても、適当に処理できるぜ!

#include <iostream>
#include <vector>
#include <boost/bind.hpp>
#include <boost/range/algorithm/for_each.hpp>
#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/ref.hpp>

class Foo {
private:
  int n_;
public:
  Foo() : n_() {}
  Foo(int n) : n_(n)  {
    std::cout << "Foo(" << n << ");" << std::endl;
  }
  
  Foo(Foo&& f) : n_(f.n_) {
    f.n_ = 0;
  }
  
  ~Foo() { std::cout << "~Foo(); /* " << n_ << " */" << std::endl; }
  
  Foo& operator = (Foo&& rhs) { n_ = rhs.n_; rhs.n_ = 0; return *this; }
  
  int n() const { return n_; }
};

void post_move( boost::shared_ptr<Foo> f, std::vector<Foo>& v ) {
  std::cout << "post_move push_back : " << f.get()->n() << std::endl;
  v.push_back( std::move( *f.get() ) );
}

int main() {
  boost::asio::io_service service;
  std::vector<Foo> v;
  
  for( int i = 0; i < 10; ++i ) {
    Foo f(i+1);
    boost::shared_ptr<Foo> nf( new Foo( std::move(f) ) );
    service.post( boost::bind( post_move, nf, boost::ref(v) ) );
  }  

  std::cout << ">>> run! <<<" << std::endl;
  service.run();
  
  std::cout << ">>> done! <<<" << std::endl;
  
  boost::for_each( v, [](const Foo& f) { std::cout << f.n() << std::endl; } );

  return 0;
}
結果
Foo(1);
~Foo(); /* 0 */
Foo(2);
~Foo(); /* 0 */
Foo(3);
~Foo(); /* 0 */
Foo(4);
~Foo(); /* 0 */
Foo(5);
~Foo(); /* 0 */
Foo(6);
~Foo(); /* 0 */
Foo(7);
~Foo(); /* 0 */
Foo(8);
~Foo(); /* 0 */
Foo(9);
~Foo(); /* 0 */
Foo(10);
~Foo(); /* 0 */
>>> run! <<<
post_move push_back : 1
~Foo(); /* 0 */
post_move push_back : 2
~Foo(); /* 0 */
~Foo(); /* 0 */
post_move push_back : 3
~Foo(); /* 0 */
~Foo(); /* 0 */
~Foo(); /* 0 */
post_move push_back : 4
~Foo(); /* 0 */
post_move push_back : 5
~Foo(); /* 0 */
~Foo(); /* 0 */
~Foo(); /* 0 */
~Foo(); /* 0 */
~Foo(); /* 0 */
post_move push_back : 6
~Foo(); /* 0 */
post_move push_back : 7
~Foo(); /* 0 */
post_move push_back : 8
~Foo(); /* 0 */
post_move push_back : 9
~Foo(); /* 0 */
~Foo(); /* 0 */
~Foo(); /* 0 */
~Foo(); /* 0 */
~Foo(); /* 0 */
~Foo(); /* 0 */
~Foo(); /* 0 */
~Foo(); /* 0 */
~Foo(); /* 0 */
post_move push_back : 10
~Foo(); /* 0 */
>>> done! <<<
1
2
3
4
5
6
7
8
9
10
~Foo(); /* 1 */
~Foo(); /* 2 */
~Foo(); /* 3 */
~Foo(); /* 4 */
~Foo(); /* 5 */
~Foo(); /* 6 */
~Foo(); /* 7 */
~Foo(); /* 8 */
~Foo(); /* 9 */
~Foo(); /* 10 */

2012年12月21日金曜日

std::move と std::set_difference

 ウィンドウズ系のプログラムは、win2k をサポートしないといけないとかいう理由で、vc8 を変える訳にはいかないのであった。そんな理由から、C++03 以外に選択肢が無い現状なのであった。  ただ、今回 android ndk でコードを書いてまして、所有権のあるクラスを管理する事になりました。そうなんです。コピー禁止で、std::move が、使いたくて使いたくてしょうがない症候群。これ、今までだと、リソースをマネージャクラスに保持させて管理するとかいう設計にしなくてはならず、スレッドが絡んでくると煩雑になってしょうがない部分でした。  android ndk r8b なんか Foo::Foo( Foo&& foo ) とかしてもコンパイル通るし、いろいろ調べてると、どうも c++11も使えるっぽい。まじめに gcc の状況を見たら、gcc-4.4.3 と gcc-4.6 が入っていて、gcc-4.6 の gnu-stl だと、まさに表にある通りで -std=gnu++0x のオプションでも一部機能には対応していました。ヘッダーの中身を確認しましたが、std::swap も std::move で実装されてます。  と、ここで std::set_difference の move を使うバージョンみたいなんが欲しくなって、実装してみました。コンパイルが通ってしまったんで、ついつい嬉しくなって、晒してみる事に…。あくまで、コンパイルが通っただけなんで、動作の保証はありません。はい。
#pragma once
#ifndef MOVE_DIFFERENCE_HPP
#define MOVE_DIFFERENCE_HPP

  template<typename ITER1, typename ITER2>
  ITER2 move(
    ITER1 first1, ITER1 last1,
    ITER2 first2
  ) {
    while( first1 != last1 ) {
      *first2 = std::move( *first1 );
      ++first1; ++first2;
    }
    return first2;
  }

  template<typename ITER1, typename ITER2, typename ITER3>
  void move_difference(
    ITER1& first1, ITER1 last1,
    ITER2  first2, ITER2 last2,
    ITER3& first3
  ) {
    ITER1 pos1 = first1;
    while( pos1 != last1 ) {
      if( first2 == last2) {
        first3 = std::move(pos1, last1, first3);
        return;
      }
      if( *pos1 < *first2 ) { // 取り除く候補
        *first3 = std::move( *pos1 );
        ++pos1;
        ++first3;
      } else if( *first2 < *pos1 ) { // 関係無い候補はスキップ
        ++first2;
      } else { // 等しいので双方インクリメント
        std::swap( *first1, *pos1 );
        ++first1; ++pos1;
        ++first2;
      }
    }
    return;
  }

  template<typename ITER1, typename ITER2, typename ITER3, typename COMP>
  void move_difference(
    ITER1& first1, ITER1 last1,
    ITER2  first2, ITER2 last2,
    ITER3& first3, COMP ope
  ) {
    ITER1 pos1 = first1;
    while( pos1 != last1 ) {
      if( first2 == last2) {
        first3 = std::move(pos1, last1, first3);
        return;
      }
      if( ope( *pos1, *first2) ) { // 取り除く候補
        *first3 = std::move( *pos1 );
        ++pos1;
        ++first3;
      } else if( ope( *first2, *pos1 ) ) { // 関係無い候補はスキップ
        ++first2;
      } else { // 等しいので双方インクリメント
        std::swap( *first1, *pos1 );
        ++first1; ++pos1;
        ++first2;
      }
    }
    return;
  }
  
#endif // MOVE_DIFFERENCE_HPP

2012年12月12日水曜日

カラーレーザープリンターを買った


 年賀状の季節。インクジェットプリンターの調子が悪く、いくらノズルをクリーニングして、ノズルチェックパターンを印刷しても、一向によくなる気配が無い。もうプリンターなんて、エア・プリントで良いし、年賀状は印刷頼んだ方が安上がりじゃね?と嫁さんに言った事があるけども、家にプリンターは必須なんだそうで・・・。

 正直、インクジェットプリンターには嫌気がさしていたのだ。インクは高いし、すぐにプリンターの調子は悪くなるし、ノズルを連続クリーニングすると、吹付け口のスポンジがベタベタになって、しばらく使えなくなるし、印刷は遅いし・・・。

 昨年、まじめにカラーレーザープリンタの購入を検討したけれども、インクジェット用紙の年賀状を買ってしまったのと、いまいち値段が高かったので諦めていました。ところが、価格.com で調べたら、NEC MultiWriter 5750cが 12,800円!!! これは凄いでー!!!

 嫁さんと相談した結果、インクジェット用紙の年賀状を交換してでも、カラーレーザープリンターを買おうという事になりました。

 そして・・・来ました・・・来ました・・・!
まぁ、プリンターは、ドデカイけれども、A4普通紙に印刷してみたら、めっちゃ綺麗!!!

先日、室蘭に行って食べた焼き鳥(豚串)が、美味しそうに印刷できました。もう、これ感動もんです。

 しかも、標準でネットワーク・ポートが付いてるので、ルータ(Time Capsule)に接続して、ネットワーク・プリンタに変身!!!今まで、印刷する時には、プリンタを用意してケーブルを繋いでとかしていたのが嘘のようです。

印刷も速い速い!

 気になるランニング・コストですが、トナー(小)でおよそ1000枚ほど印刷できるようなので、12,800/1,000 = 12.8 円です。実はプリンターを買うよりトナーを買った方が高いという・・・。トナーが3色 x 8,800 黒 4,100 なので、通常のランニングコストは (8,800 * 3 + 4,100) / 2,000 = 15.25円 となります。
 ただ、この枚数は、NECのHPより拝借した数字で、カラーが各色5%程度という前提で計算されております。従って、イラストや写真をA4フルで印刷すると、コストは6.7倍(5x3=15%より算出)になります。
 考えてもみてください。インクジェットプリンターで印刷されるのをジーっと見守りながら無駄な時間を過ごしたり、インクジェット用紙を買ったりとか、プリンターだめになったり印刷結果がすぐ汚くなったりとかストレス抱え込むぐらいなら、カラーレーザー買った方がマシってもんです。

 いやー、テンション上がるわwww 2012/12/13 コスト計算について訂正:トナーの型番を勘違いしていて1000枚計算していた部分を訂正しました。カラートナーは4色ではなく3色だったので計算式を訂正しました。Amazon で売っているトナーは新品とうたったリサイクル品なので正規価格による計算に修正しました。リサイクル品のトナーは品質が異なるので、考えて使わった方が良いと思います。

2012年12月5日水曜日

Android ndk 突っ込んでます

 忙しいとかで、ブログの更新も滞ってます。一応、アウトプットもしておかないと…。
最近は、Android ndk を突っ込んでます。まぁ、Java では限界があるんです。Java で大規模開発した事が無いので、パッケージの構成とかも失敗しました。もうちょい、ちゃんとパッケージを分けて作っておくんだったと…。モジュールの分離が、なかなか難しくて四苦八苦してたのも事実としてあります。

 ndk の情報で有益なサイトを見つけました。
  1. Windows 環境にて Android アプリを Eclipse と Cygwin を使わずにビルドする。
  2. Android NDKの中身はどうなっている? - アプリの定義を記す「Application.mk」 
  3. ファイルやライブラリの情報を定義する「Android.mk」
です。(1.)の構成は、Linux や mac の環境でも同じ事が言えます。android-cmake を使って楽したいです。(2.)(3.)Android NDK に付属のドキュメントを眺めましたが、書いてある事が要領を得ない感じでピンと来ませんでした。実際、適当に書いてると、ディレクトリの構成と Application.mk や Android.mk の配置で嵌りました。NDK のドキュメントには、jni ディレクトリ下の Application.mk が option であるかのような記述がされてますが、APP_ABI を指定できるのは、jni 直下の Application.mk だけであり、プロジェクト直下の Application.mk に記述しても丸無視されます。NDKの必要なポイントがコンパクトに記述されていて、分かりやすいです。

 しばらく ndk の話題が続きそう…