Hatena::ブログ(Diary)

GANAwareはてな版 RSSフィード

2012-02-28

Storyboardsを使っている時のUITableViewのdequeueReusableCellWithIdentifier:の挙動

この情報に行き当たるのに苦労したのでメモ

https://developer.apple.com/library/ios/#releasenotes/Miscellaneous/RN-AdoptingStoryboards/_index.html#//apple_ref/doc/uid/TP40011297-CH1-DontLinkElementID_5

2011-11-24

Objective-C の __block の参照カウンタを調査中…

と呟いたところ、本の著者さんから

というお返事をいただいたので、 splhack: 『iOS 4プログラミングブック』 第5章マルチスレッド 補遺 その2 の例を自分でも確かめてみました。

という設定で上記の @ さんの記事のコード(以下に再掲)をビルドし、

#import <Foundation/Foundation.h>
#import <stdio.h>

extern const char *_Block_byref_dump(void *);

void dump(int line, int *p)
{
    p -= 4;
    printf("\ndump line:%d\n", line);
    puts(_Block_byref_dump(p));
}

int *test()
{
    __block int total = 11;
    
    dump(__LINE__, &total);
    
    void (^block_on_stack)() = ^{
        
        ++total;
        
        dump(__LINE__, &total);
    };
    
    block_on_stack();
    
    printf("\n___ Block_copy ___\n");
    void (^block_on_heap)() = Block_copy(block_on_stack);
    
    dump(__LINE__, &total);
    
    block_on_stack();
    
    block_on_heap();
    
    printf("\n___ Block_release ___\n");
    Block_release(block_on_heap);
    
    dump(__LINE__, &total);
    
    block_on_stack();
    
    return &total;
}

int main()
{
    dump(__LINE__, test());
}

Assembly を見ると、test() の最後で以下のようなコードが実行されているのが見つかります。

	.loc	1 45 1                  ## (略)/main.m:45:1
	movl	-112(%ebp), %eax        ## 4-byte Reload
	movl	%eax, (%esp)
	movl	$8, 4(%esp)
	calll	__Block_object_dispose

どうやら __block 変数の __forwarding 先の参照カウントは、Block_copy() した時にスタックからの参照分とヒープから参照分だけカウンタを増やしておいて、Block_release() 時とスコープの終わりに挿入される _Block_object_dispose() 時に減らしているようですね。

https://llvm.org/svn/llvm-project/compiler-rt/trunk/BlocksRuntime/runtime.c

void _Block_object_dispose(const void *object, const int flags) {
    // (略)
    if (flags & BLOCK_FIELD_IS_BYREF)  {
        // get rid of the __block data structure held in a Block
        _Block_byref_release(object);
    }
    // (略)
}

というわけで

という心配杞憂のようでした。

ところで、実行してみたところ次のような出力を得ました。

dump line:17
byref data block 0xbffff9c0 contents:
  forwarding: 0xbffff9c0
  flags: 0x0
  size: 20


dump line:23
byref data block 0xbffff9c0 contents:
  forwarding: 0xbffff9c0
  flags: 0x0
  size: 20


___ Block_copy ___

dump line:31
byref data block 0x13e450 contents:
  forwarding: 0x13e450
  flags: 0x1000004
  size: 20


dump line:23
byref data block 0x13e450 contents:
  forwarding: 0x13e450
  flags: 0x1000004
  size: 20


dump line:23
byref data block 0x13e450 contents:
  forwarding: 0x13e450
  flags: 0x1000004
  size: 20


___ Block_release ___

dump line:40
byref data block 0x13e450 contents:
  forwarding: 0x13e450
  flags: 0x1000002
  size: 20


dump line:23
byref data block 0x13e450 contents:
  forwarding: 0x13e450
  flags: 0x1000002
  size: 20


dump line:49
byref data block 0x13e450 contents:
  forwarding: 0x13e450
  flags: 0x1000001
  size: 20

@ さんの記事の結果とは以下の点が若干異なっています。

  • 謎1: flags の下位 16bit の参照カウントが、Block_copy() で 4 増え、Block_release() で 2 減る
    • _Block_object_dispose() 内では flags を 1 しか減らしていないように見えるのですが…
  • 謎2: 最後dump line:49 では参照カウントが 1 のまま
    • 参照カウントは OSAtomicCompareAndSwapInt() で減らされるので、最後はちゃんと 0 になるべきであるはず


というお返事をいただいたので libclosure-53 を覗いてみると、

http://www.opensource.apple.com/source/libclosure/libclosure-53/Block_private.h

enum {
    BLOCK_DEALLOCATING =      (0x0001),
    BLOCK_REFCOUNT_MASK =     (0xfffe),
    BLOCK_NEEDS_FREE =        (1 << 24),
    (略)
};

となっており、参照カウントは1bit左へシフトされていました。上記の結果になるのも納得です。

2010-01-10

iTunesライブラリをWindowsからMacへコピーした

多数のブクマを集めている no title を参考にしてコピーしてみました。しかし、この記事はどうやら古いバージョンの iTunes の英語版を元に記述されているようで*1、日本語版の 9.0.2 ではあてはまらないことが多いのでとても戸惑いました。

今回行った手順のメモ:

Windows (XP) で

  1. (iTunes) 最新バージョンにします (現在は 9.0.2)
  2. (iTunes) 「ファイル」⇒「ライブラリ」⇒「ライブラリを整理...」をして、ファイルを "マイ ミュージック\iTunes" 以下へ集めます。
  3. (iTunes) 「ファイル」⇒「ライブラリ」⇒「ライブラリを書出し...」をして、"ライブラリ.xml" を作成します。
  4. (エクスプローラ) USBハードディスクへ、"マイ ミュージック\iTunes" と "ライブラリ.xml" をすべてコピーします。

Mac (Snow Leopard) で

  1. (iTunes) 最新バージョンにします (現在は 9.0.2)
  2. (Finder) USBハードディスクから、"iTunes" と "ライブラリ.xml" を適当なフォルダ (※) へコピーします。
  3. (Emacs) "ライブラリ.xml" を編集して、"file://localhost/.../iTunes" 部分を Mac 上のパスとして正しくなるように修正します。 (ファイル名の濁点が分離される Unicode NFD 問題は特に影響はありませんでした)
  4. (iTunes) 「ファイル」⇒「ライブラリ」⇒「プレイリストを読み込み...」をして、"ライブラリ.xml" を指定して読み込みます。
  5. (iTunes) (時間がかかるのでしばらくお待ちください)
  6. (Finder⇒iTunes) 念のため "※/iTunes/iTunes Musc" フォルダを iTunes のライブラリへドロップして、コピーしそびれたファイルもコピーします。(この手順を行わない場合、PDF ファイルは iTunes へ入らないようです)
  7. (iTunes) 「ファイル」⇒「ライブラリ」⇒「ライブラリを整理...」をして、ファイルを "ミュージック/iTunes" 以下へ集めます。
  8. (iTunes) 左のペインでライブラリのミュージックを選んだ後「ファイル」⇒「重複するものを表示」をして表示される曲を調べて、重複していて不要なものを削除します。
  9. (iTunes) スマートプレイリストに「!」がついているものを修正します。スマートプレイリスト中で、他のプレイリストを参照するような項目があると「!」がつくようです。
  10. (iTunes) ビデオのオプションの「メディアの種類」と「再生位置を記憶する」オプションの内容はコピーされないので、設定しなおします。
  11. (Finder) ※フォルダを削除します。
  12. (Time Machine) 就寝前に「今すぐバックアップを作成」してから寝ます。

曲のメタデータのうちどの部分が正しくコピーできたのかは確認していませんが、少なくとも「再生回数」は正しくコピーされているようです (gizmode の記事ではできないと書かれています)


実は、上記のようなややこしい手順を行わなくても、USBハードディスクへコピーした "iTunes" フォルダをiTunes のライブラリへドロップするだけで曲をコピーすることは可能です。

しかし、この場合様々なメタデータがコピーされないという欠点があります。少なくとも「再生回数」はコピーされませんでした。また、プレイリストがコピーされないことも問題です。

上記のややこしい手順を利用した場合は、「再生回数」「プレイリスト」「スマートプレイリスト」をコピーすることが可能です。

*1:2010-01-05 に公開された記事ですけれども

2009-12-10

iPod がお亡くなりに。

Please wait.

Very low battery.

起動して、りんごマークが表示され、こんなメッセージがしばらく表示されたりされなかったりカタカタ音がしたりしたあと、また起動しなおして以下無限ループ、といった感じです。トホホ。

最近電池はあっという間になくなるようになっていましたし、寿命でしょうか。

2008-08-30

MacBook Air Update sd20564 (Re: CPUシングル化現象)

http://d.hatena.ne.jp/ganaware/20080510/1210443635

このアップデートを入れると、CPUシングル化現象 - GANAwareはてな版が劇的に改善されました。

以前は動画を再生中に TimeMachine がバックアップを開始したりすると、esc キーのあたりがとても熱くなって CPU が片方しか動作しない状態になり、動画はマトモに見ることができなかったのですが、このアップデートを導入後はそれほど熱くもならず、様々な負荷をかけても動画はほぼ通常通り再生しつづけてくれました。