2012/09/06

C# で static class のファイナライザを書く

C# だと static class にはファイナライザを用意できない。

シングルトンを使え、という方針は正しいが、
それでも static class のファイナライザが実装したいときはある。

private 定義のクラスのインスタンスに肩代わりしてもらう方法を考えてみた。
public static class FinalizableStaticClass
{
    private class FinalizeWorkClass
    {
        ~FinalizeWorkClass()
        {
            // ファイナライザ
        }
    }
    private static FinalizeWorkClass finalizeWorkClass = new FinalizeWorkClass();
}

  • FinalizableStaticClass に一度もアクセスしなければ、FinalizeWorkClass のインスタンスは生成されないので、当然ファイナライザも呼ばれない。
  • ファイナライザが呼び出されるタイミングは、通常のフォームアプリケーションだと Main が終了した後。確かめていないけど、多分アプリケーションドメインが終わった時。
  • ファイナライザではアンマネージリソースの後片付けとかぐらいにしておくこと。
Delphi の initialization/finalization が C# にもあればなあ。

2012/08/23

Thinkpad T410i でグラフィックコントロールパネルが再起動するたびに表示される問題を修正する

Thinkpad T410i で Lenovo Update からディスプレイドライバをアップデートしたら、
ログインするたびに、インテル グラフィック メディア コントロールパネル(GfxUI.exe) が
毎回実行されるようになってしまった。

インテルから Intel HD Graphics の最新ドライバをインストールしたら治った。

2012/05/30

NetBSD PR lib/46433 についてのコメント

外野がいきなりツッコミ入れるのもどうかと思うので、ここで。

この問題は、 m68k FPE のデバッグをしている時に、libm の exp() のテストがおかしいんじゃないかという疑問を持ったことに端を発する。

2012/05 時点で、m68k FPE の exp(x) が stub 実装で、常に x を返すという痛々しい事実はまず忘れておいて、そもそもこのテストコードの意味を考えてみる。



テストとは、
「信頼されたもの」を使って、「信頼出来るかわからないもの」が信頼出来るかどうか調べる行為である。

今回問題になってるテストコードは
exp(x + y) - exp(x) * exp(y) < eps

さてここで、「信頼されていないもの=調べたいもの」には .N をつけてみよう。

exp.N(x + y) - exp.N(x) * exp.N(y) < eps

左辺に信頼されていないものを集めて、右辺に信頼出来るものを集める。が、もうこれ以上移項できない。

そうするとこの式を見て分かるように、このテストコードでは、「左辺の式が eps 以下である」ことしかテストできていない。exp 自体が信頼できるかどうかは、このコードでは分からない。

仮に exp 自体がすでに信用出来るものである、とすると、このテストコードがテストすることになるのは、数学領域の「exp(x+y) = exp(x)*exp(y)」という式が数学的に正しいかどうか、であって libm の exp ではない。

このテストコードを、まがりなりにも libm のテストとして成立するように書きなおすとしたら、

#define Ex (計算済みのexp(x)を定数にしたもの)
#define Ey (計算済みのexp(y)を定数にしたもの)
exp(x + y) -  Ex * Ey < eps

とすれば、
exp.N(x + y) < eps + Ex * Ey

となって、「exp(x + y) が信頼出来るかどうか」のテストコードとして成立する。

もちろんこうなると、信頼されている Ex * Ey は事前に計算してよいので、

#define Exy (計算済みの exp(x) * exp(y) を定数にしたもの)
exp.N(x + y) - Exy < eps

としてよい。

また、x+y も信頼されているので事前に計算してよい。z=x+y とおけば、

exp.N(z) - Ez < eps

となる。すでにこれは exp[2f]?_product のテストではない。掛け算どこにも出てこない。

以上、libm のテスト exp[2f]?_product  は意味が無い、という考察でした。






もしかして、数学の正しさをテストしたかったんならごめん、ライブラリのテストコードじゃなくて他所でやって・・・

2012/05/18

IDispose 実装のパターン

忘れやすいので書き残しておく。

class Foo: IDisposable
{
 // アンマネージリソース
 private IntPtr unmanaged;

 // IDisposable を実装している他のクラス(このクラスがオーナー)
 private OtherDisposableClass other;

 // イベントを持ってて、このクラスがイベントをサブスクライブしてる
 // このクラスは参照してるだけ
 private ReferencedWithEvent refwe;

 // 自分のイベント
 public event EventHandler AnyEvent;

 // もし、アンマネージリソースをこのクラスが直接管理していなければ、
 // ファイナライザを用意しなくていい。
 ~Foo()
 {
  Dispose(false);
 }

 public void Dispose()
 {
  Dispose(true);
  GC.SupressFinalize(this);
 }

 protected virtual void Dispose(bool disposing)
 {
  if (disposing) {
   // Dispose() から呼び出された時は、保持しているIDisposableメンバを
   // null チェックしてから Dispose() を呼び出して null にセットしておく。
   // 他の例にあるような disposed フラグは使わない。
   // その理由は、other のインスタンスが Open() などのように
   // コンストラクタ外で確保される場合でも同じパターンでコードを書くため。
   // また、null チェックして null 代入しておけば Dispose() が複数回コールされても大丈夫。
   if (other != null) {
    other.Dispose();
    other = null;
   }
   if (refwe != null) {
    // サブスクライブしたイベントを解除
    // More Effective C# 23
    // イベントハンドラの定義宣言は省略...
    refwe.Event -= refwe_Event;
    refwe = null;
   }
  }

  // 直接このクラスが管理しているアンマネージリソースの解放処理をここに書く。
  // 仮に other がアンマネージリソースを保持していることを知っていても、
  // ここで Dispose を呼び出してはいけない。
  // ここはファイナライザからの呼び出しでも実行される場所で、ファイナライザからの
  // 呼び出しである場合、other はすでにファイナライズされているかもしれない。
  // .Net の GC は参照カウントでなくルート探索で動作するので、自分が参照して
  // いるからといって、そのオブジェクトがファイナライズされていない保証はない。
  // したがって、ここでは他のオブジェクトを参照してはいけない。
  // http://msdn.microsoft.com/ja-jp/library/system.idisposable.dispose.aspx

  // もし、IntPtr.Zero も有効な値なのであれば、
  // 別のフラグを用意して、開放したかどうかを管理する。
  if (unmanaged != IntPtr.Zero) {
   UnmanagedResource.Free(unmanaged);
   unmanaged = IntPtr.Zero;
  }

  // 単なる null 代入でいいものはここに書く。
  AnyEvent = null;

  // ObjectDisposedException を実装したければ、ここでフラグ立てるとかする。

  // もし、このクラスが継承クラスなら、
  // base.Dispose(disposing);
 }
}

2012/05/02

OS X 10.7+XCode 4.3+wxWidgets2.8+cmake で XM6i をmakeしようとして挫折するまで

もともと 10.5 が入っていた mac mini (2007)。これがターゲット。
10.6 DVD を購入。Apple Store で。届くのは速くて、翌日着だった。素晴らしい。
10.6をアップグレードインストール。
...オマチクダサイ
ソフトウェアアップデートで 10.6.8 (だっけ)まで上げる。
10.7 を AppStore で購入しようとして、RAM が 2GB 要ると言われてダウンロードすらできない。
ソフマップまで行って 中古の RAM 1GB と新品RAM 2GB。もう DDR2 667なんて売ってないよ。
そして100円ショップで、スクレイパー2本購入。
ケースの爪を2本折りながら、RAM交換。
10.7を AppStore で購入しようとして、AppleIDの腐った規約に渋々合意。
認証通してダウンロード開始。4GB。
...オマチクダサイ
...
10.7 インストール開始。
...オマチクダサイ
...
XCode 4.3 をダウンロード。1.5GB....
...オマチクダサイ
MacPortsをダウンロードしてインストール。
従来入っていた XCode 3.x と競合。えー、アンインストールするとかしてくんないの。
XCode3.x を手作業でアンインストール。
$ port install cmake +universal
configure が、コンパイラが無いっていうエラーで落ちる。
XCode4.3 が ppc のサポートを打ち切ったのが原因と分かるまで3時間。
$ port install cmake
$ port install nasm
$ port install wxWidgets
こいつ、なかで +universal してて動かない。
$ port install wxWidgets-devel
なんか依存してる perl のコンパイルが出来ないって怒られて動かない。

で。詰んだ。

結論:もうしない。

2012/04/17

MRU と LRU

MRU と LRU って用語が、混乱してる。

キャッシュにおいては、
LRU は、「最後に使われてからの時間が最長 = 使われなかったもの」を「捨てる」
MRU は、「最後に使われてからの時間が最短 = 使われたもの」を「捨てる」

メニューとかに表示してるリストだと、
LRU は、「最後に使われてからの時間が最長 = 使われなかったもの」を「表示する」
MRU は、「最後に使われてからの時間が最短 = 使われたもの」を「表示する」

ええと、「メニューにMRU表示するアイテムをLRUキャッシュする」は、正しいんかのう。

2012/03/30

NetBSD 5.99 fd デバッグ on XM6i for Mac ログ

00000CE0 IOSC 要求していない割り込み  <- dd if=/dev/rfd0c of=/dev/null bs=512 count=1
00000CE0 IOSC 要求していない割り込み
00000CE0 IOSC 要求していない割り込み
00000CE0 IOSC 要求していない割り込み
00000CE0 IOSC 要求していない割り込み
00000CE0 IOSC 要求していない割り込み
00000CE0 IOSC 要求していない割り込み
0003BEF0 FDD  イジェクト禁止 ドライブ0
00000CE0 IOSC 要求していない割り込み
00000CE0 IOSC 要求していない割り込み
00000CE0 IOSC 要求していない割り込み
00000CE0 IOSC 要求していない割り込み
0003AC48 FDD  モータON ドライブ0セレクト
0003ABEE FDC  INVALIDコマンド
0003ABEE FDC  SPECIFYコマンド
0003ABEE FDC  SEEKコマンド
0003ABEE FDC  シーク成功 ドライブ0 シリンダ00
0003ABEE IOSC 割り込み要求 ベクタ$60
00000CE0 IOSC 割り込みACK ベクタ$60
0008C826 IOSC 割り込み要求 ベクタ$60
00000758 IOSC 割り込みACK ベクタ$60
0003BF0C IOSC 割り込み要求 ベクタ$60
0003ABEE FDC  SENSE INTERRUPT STATUSコマンド
0003ABEE IOSC 割り込みキャンセル ベクタ$60
0003B13A FDC  DMA転送完了 0 bytes
0008D082 DMAC CCR STR ON
0008D082 DMAC チャネル0 スタート
0008D082 DMAC Ch=0 DAR=00e94001     <- e94001=FDCステータスレジスタ
0003ABEE FDC  READ DATAコマンド
0003ABEE FDC  (C:00 H:00 R:01 N:02)
0003ABEE FDD  リードセクタ C:00 H:00 R:01 N:02
0003B15A DMAC TransDMA dma[0].type=0   <- なので DMA しまくってもステータスレジスタが読めるだけ
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A DMAC TransDMA dma[0].type=0
0003B15A FDC  DMA転送完了 64 bytes   <- fdc.cpp が1回のイベントで64バイトまで転送する
0003B146 FDC  Read. len=511     <- だれかがやっとデータレジスタ読んだ、が、すでにえらいこっちゃ
00000D0C DMAC TransDMA dma[0].type=0
00000D0C DMAC TransDMA dma[0].type=0
0

2012/02/15

VisualStudio2010 ビルド イベントの不思議な挙動

たとえば

static Main()
{
    Console.WriteLine("Error : hoge");
}


な C# プログラムを書く。これをビルドして hoge.exe とする。

他のプロジェクト(ProjAとする)のビルド後イベントに hoge.exe を実行するように記述する。

で、ProjA をビルドすると、ビルドエラーになる。


どうも、標準出力に
^Error(|¥s+.*):.*

を書き出すと、エラーとして処理を停止してくれる、らしい。

ただ、この挙動、ドキュメントされてないみたい。プロセスの終了コードのことはドキュメント
されているのを見たけど、標準出力のことは書いてないようだ。

2012/01/19

Thinkpad T410i キーボード交換

Thinkpad T410i を二台所有しているんだが、二台ともキーボードとトラックポイント側のマウスボタンが故障。
どこが壊れたかって言うと、キーボードフィルムと接続フレキの間の接触不良。だれだこんな設計した奴。

でごそごそやっても改善しないので、キーボードを交換することにした。


55Y9024の中身がどうも同じものらしい

ので、45N2172 買うより安いか


ってことで買ってみた。NTT-X で 5380円。

で、さっそく 55Y9024 分解。
見えているネジ以外に、ネジが2本、Lenovo シールの下にある。

あと、はめ込みはかなり固いが、中身しかいらないので、割らない程度にガシャっと外す。

元の本体キーボードから、スピーカーボタンとかのベゼルと、電源ボタンを外しておく。
この部品は 55Y9024 には無い。
これを 55Y9024 から外したキーボードに移植。

外した電源ボタン。

55Y9024キーボードにはめたところ。

55Y9024キーボードに貼られていたシール。

出たゴミ(笑)。

で、取り付けたら、それだけ。
あとは ThinkVantage 診断ツールでテストして、「動いた わぁい」。

さて、もう一個買うか。

2012/01/06

ロックアウトゲート

ロックアウトゲートが作りたいのだが。

ロックアウトゲート(いま勝手に考えた言葉)とは:

# ロックアウトされていないときは入りたいスレッド(従業員)が好きなだけ出入りできる。
# あるスレッド(経営者)がロックアウトしようとしたとき、
* いま入っている従業員スレッドが全員出るまで待つ。
* 新たに入ろうとする従業員スレッドは無期限に待たされる。
* 全員出たらロックアウト状態として制御を返す。
# 経営者スレッドがロックアウトを解除するまではだれも入れない。経営者も入れない(笑)。

ReaderWriterLockSlim を使って実装できそうな気がするんだがなんかうまくいかん。

最終目的はロックアウトゲートじゃないから、他の実現方法を考えたほうがいいということか。

2011/12/19

Bazaar 導入メモ

Bazaar 2.4.2 を Windows7 にインストールしてみた。

1.6ぐらいの頃に一度WindowsXPに入れてみて、遅くて使えねー、という
評価をしたが、今回格段に速くなっとる。

さて評価。これまで Subversion を使ってきたので、主にそこと違う点。
よくわかってないので間違ってるかもね。

NULL commit 可能。
これだけでも移行する価値がある。
リポジトリの見た目はディレクトリ。
svn はデータベース(的:FSFS)なリポジトリだが bzr は普通のディレクトリに見える。
svn でリポジトリを分けてプロジェクトを複数管理している場合には、あるファイルがどのプロジェクトにあるかを探すために、svn ls svn://host/{$repo} をまわして調べ上げないといけないが、bzr では find で探せる。
Windowsホストの場合、コマンドラインを使わなければ、svn はリポジトリブラウザでURL切り替えて検索、に対して bzr はエクスプローラで検索一発なので、bzr 優位。
→どうもそういうことじゃなくてリポジトリとツリーを同一の場所に置ける、ということみたい。
ローカルリポジトリ上で直接作業可能。
ローカルリポジトリを作業コピーとみなして、その場でコミットとか可能。
チェックアウトすれば svn ぽい。
ブランチ/マージは格段に賢い。
TortoiseBzr のブランチマージ履歴が楽しい。

あと調べないといけないこと:

タグ。
svn ではタグの使い所が難しい、ていうかタグの意味わかってないだろう、という機構なので、ほとんど使ってなかった。bzr ではどうなのか。
リポジトリのマージ。
リポジトリの分割。
アクセス権限関係。
これは svn が出来過ぎているっぽいので妥協点を見つけること。
ネットワーク越しの動作。

2011/11/24

Task と OperationCanceledException

System.Threading.Task.Task クラス。
Task の開始後に CancellationToken を Cancel 状態にした場合は、自分で ThrowIfCancellationRequested() を呼び出さない限り、OperationCanceledException は発生しない。
しかし、Task の開始前に Cancel 状態にした場合は、Task.Wait() で OperationCanceledException が発生する。

Task 開始前に Cancel 状態にならないようにする
または
Wait() を try-catch して、開始前のキャンセルを処理する
のどちらか。

2011/11/15

C# AllocHGlobal と AllocCoTaskMem

この両者、アロケートするだけではパフォーマンス上の差は観測出来なかった。

http://msdn.microsoft.com/ja-jp/library/s69bkh17(v=vs.80).aspx


GlobalAlloc を使用して、プロセスのアンマネージ メモリからメモリを割り当てます。
...
Marshal クラスにはメモリ割り当て API メソッドが 2 つ用意されていますが、AllocHGlobal はその 1 つです。(なお、もう 1 つはMarshal.AllocCoTaskMem です。このメソッドは Kernel32.dll の LocalAlloc Win32 API を公開します。LocalAlloc の詳細については、MSDN ライブラリを参照してください。

どっちやねん、と思ったら、

http://msdn.microsoft.com/ja-jp/library/s69bkh17(v=VS.100).aspx

指定したバイト数を使用して、プロセスのアンマネージ メモリからメモリを割り当てます。

修正されてた。

2011/11/12

Windows7 で Win-U-U が使えなくなったとお嘆きの方へ。

Windows7。
パスの通ったディレクトリにこれだけは置いとく。

Win-U-U-Enter で電源が切れる。


uu.cmd
shutdown -s -t 0

uh.cmd
shutdown -h -t 0

ur.cmd
shutdown -r -t 0
us.cmd
Rundll32.exe Powrprof.dll,SetSuspendState Sleep

ur.cmd とかプログラムメニュー内の URL ファイルに阻害されて、一番上に候補として
上がらないことがある。どうにかならんかな。

2011/11/04

諸君、私はNetBSDが好きだ

generated by http://wids.net/lab/HELLSING/

一部事実に基づく創作であり、実際の NetBSD オペレーティングシステムとはほんの少ししか関係ありません。


諸君、私はNetBSDが好きだ

諸君、私はNetBSDが好きだ

諸君、私はNetBSDが大好きだ



カーネルが好きだ

ユーザランドが好きだ

ブートローダが好きだ

MI-MD構造が好きだ

クロスビルド環境が好きだ



x68kで

zaurusで

luna68kで

amigaで

alpha,acorn26,acorn32,cats,evbarm,hpcarm,lyonix,netwinder,shark,hp700,i386,xen,sun2,atari,cesfic,hp300,mac68k,mvme68k,news68k,next68k,sun3,emips,evbmips,ews4800mips,mipsco,newsmips,sbmips,sgimips,algor,arc,cobalt,hpcmips,pmax,amigappc,bebox,evbppc,ibmnws,macppc,mvmeppc,ofppc,prep,rs6000,sandpoint,evbsh3,mmeye,dreamcast,landisk,hpcsh,sparc,sparc64,vax,amd64で



この地上に存在するありとあらゆるNetBSDが大好きだ



移植性の高い設計が好きだ

他のOSのコードにNetBSD由来のRCSIDを見つけた時など心がおどる



全くドキュメントに記載されていない#define 定数が好きだ

三週間かかって1にするだけで動作することが分かった時など胸がすくような気持ちだった



i386のブートローダが1文字出力するたびにリアルモードとプロテクトモードを行き来することが好きだ

nop 6個だったところを256個にしたらカーネルが起動した時など感動すらおぼえる



m68k FPEなどもうたまらない

誰一人呼び出したことのなかったコードを正しく実装するのは最高だ



GPLで書かれたのを

BSDライセンスでコードを見ないで再実装した時など絶頂すら覚える



動作するコードが好きだ

謎コミットで動作しないアーキテクチャが増えることはとてもとても悲しいものだ



二条項BSDライセンスが好きだ

山のようなCopyright表示が巻末についていないのは屈辱の極みだ



諸君 私はNetBSDを カーネルが動けば完結する様なNetBSDを望んでいる

諸君 私に付き従うNetBSD好きの諸君 君たちは一体何を望んでいる?

更なるNetBSDを望むか 

糞の様なNetBSDを望むか?

骨董品のようなマシンでもIPv6 Readyだぜヒャッハー!のようなNetBSDを望むか?





NetBSD!! NetBSD!! NetBSD!!





よろしい ならばNetBSDだ



だが、まともなデスクトップが無いので減り続けるdeveloperに耐え続けて来た我々には

ただのNetBSDではもはや足りない!!

大NetBSDを!! 一心不乱の大NetBSDを!!



我々はわずかに小数

NetBSDが移植されていないアーキテクチャに比べれば物の数ではない

だが諸君は一騎当千のカーネルオタクだと私は信じている

ならば我らは諸君と私で総兵力100万と1人の移植大好き集団となる

我らを忘却の彼方へと追いやり、仕様を公開しないメーカーを叩きのめそう

髪の毛をつかんで引きずり下ろし 眼(まなこ)をあけて思い出させよう



連中に真のリバースエンジニアリングを思い出させてやる

連中に割り込みアクノリッジサイクルを思い出させてやる

NetBSDには奴らの哲学では思いもよらない締め切りドリブン開発がある事を思い出させてやる

1000人のカーネルオタクの集団で 世界を``Of course it runs NetBSD''で埋め尽くしてやる



目標 iPhone



どこでもNetBSD作戦 状況を開始せよ



征くぞ 諸君

2011/09/01

C# ポインタを一行でポストインクリメントすると遅くなる

2011/02/06 追記: 実行環境下では JIT 最適化で、関係なくなるようだ。

C# では、*p++ は使わないほうがいい。
*p; p++; に分解すること。


Visual Studio 2010 version 10.0.30319.1
.Net Framework 4.0.30319
の話。/unsafe な release ビルド(最適化ON)。

volatile int r;
int[] a;

...

 unsafe {
  fixed (int* a0 = a) {
   int* p = a0;
   ...
   r = *p++;
   ...



の逆アセンブルウィンドウでの結果。

r = *p++;
0000008f mov  eax,dword ptr [ebp-8]
00000092 mov  dword ptr [ebp-10h],eax
00000095 add  dword ptr [ebp-8],4
00000099 mov  eax,dword ptr [ebp-10h]
0000009c mov  eax,dword ptr [eax]
0000009e mov  dword ptr ds:[007716C0h],eax

[ebp-10h]は一時変数。かなり間抜けだ。

r = *p++;


を
r = *p;
 p++;


に分けると、こうなる。

r = *p;
0000008f mov  eax,dword ptr [ebp-8] 
00000092 mov  eax,dword ptr [eax] 
00000094 mov  dword ptr ds:[005B16C0h],eax 
  p++;
00000099 add  dword ptr [ebp-8],4 

2011/08/26

C# IDeque

IDeque が無いのは納得いかない。
LinkedList<T> があるから実装は簡単だけど、実装がどうこうからインタフェースを切り離したい。
で、こういういかにも後からライブラリデフォルトができそうなインタフェースを手前味噌で決めると命名が大変。

Microsoft.VisualC.StlClr.IDeque<T> はちょっと違うしなぁ。