MroongaというMySQLのストレージエンジンを開発している須藤です。MySQLのAPIはよく変わるのでMroongaの開発をしているとMySQLのソースコードを読む機会がよくあります。今日、MySQLのコードを読んでいて「お!」と思うコードがあったので4回目のノータブルコードとして紹介します。
MySQLは基本的なデータ構造も独自に実装していることが多いです。今日紹介するList
も独自に実装しています。
多くの場合、リストは次のように「要素データへのポインタ」と「次の要素へのポインタ」を持つ構造をつなげて実装します。
struct List {
void *data;
List *next;
};
そして、リストの終端にNULL
を置いてリストの終わりを表現します。
if (list->next) {
printf("have more elements\n");
} else {
printf("no more elements\n");
}
MySQLのリストの実装はNULL
ではなくリストの終端を示す番兵オブジェクトを使っていました。
extern MYSQL_PLUGIN_IMPORT list_node end_of_list;
class base_list {
inline void empty() {
elements = 0;
first = &end_of_list;
last = &first;
}
};
私が「お!」と思ったのはGDBでデバッグしていたときです。GDBではp
で出力したアドレスが既知のグローバル変数や関数などの場合はその名前も出力してくれます。ここでend_of_list
という名前が出てきたのです。
(gdb) p (((const Item_cond *)select_lex->where_cond())->argument_list()->first->next->next
$1 = (list_node *) 0x555557f77550 <end_of_list>
(gdb) p (list_node *)0x555557f77550
$2 = (list_node *) 0x555557f77550 <end_of_list>
->next
としたらNULL
が返ってきても「あぁ、ここでリストは終わりなんだな」ということはわかるのですが、end_of_list
という名前が見えてもたしかにリストが終わりだとことがわかるなと思いました。リストのときはNULL
で十分だとは思いますが、もう少し複雑なもののときはNULL
よりもなにか名前が付いた番兵オブジェクトを使うとデバッグが捗るときがあるんじゃないかと思いました。このテクニックを使う機会を見つけることが楽しみです。
今回はMySQLのリスト実装のコードで「お!」と思った名前付きの番兵オブジェクトを紹介しました。みなさんもNULL
ではなく名前付きの番兵オブジェクトを使った方がよさそうなケースがないか考えてみてください。
ところで、そろそろみなさんも自分が「お!」と思ったコードを「ノータブルコード」として紹介してみたくなってきませんか?ということで、このブログへの寄稿も受け付けることにしました。まだ仕組みは整えていないのですが、とりあえず、 https://gitlab.com/clear-code/blog/issues にMarkdownっぽいマークアップで書いた原稿を投稿してもらえばいい感じに調整してここに載せます。寄稿したいという人がたくさんいるならもう少しちゃんとした仕組みを整えようと思っていますので、興味のある人はご連絡ください。寄稿してもらった記事の著作者は作者本人のままですが、ライセンスはCC BY-SA 4.0とGFDL(バージョンなし、変更不可部分なし、表表紙テキストなし、裏表紙テキストなし)のデュアルライセンスにしてください。参考:ククログのライセンス
それでは、次のノータブルコードをお楽しみに!