1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
|
---
title: XPCOM ハッシュテーブル・ガイド
slug: Mozilla/Tech/XPCOM/Guide/XPCOM_hashtable_guide
translation_of: Mozilla/Tech/XPCOM/Guide/Hashtables
---
<h2 id="What_Is_a_Hashtable.3F" name="What_Is_a_Hashtable.3F">ハッシュテーブルとは何ですか?</h2>
<p>ハッシュテーブルは、<strong>アイテム</strong>を格納するための構造体です。個々のアイテムは、それぞれを識別するための<strong>キー</strong>を持ちます。ハッシュテーブルからアイテムを検索・追加・削除するためにはキーを使います。ハッシュテーブルは<a href="/ja/XPCOM_array_guide" title="https://developer.mozilla.org/ja/XPCOM_array_guide">配列</a>に似ていますが、以下に示すような大きな違いがあります。</p>
<table class="standard-table">
<tbody>
<tr>
<th> </th>
<th class="header">配列</th>
<th class="header">ハッシュテーブル</th>
</tr>
<tr>
<td class="header">キー:</td>
<td><em>整数。</em>配列ではキーとして常に整数が利用され、またキーは連続している必要があります。</td>
<td><em>任意の型。</em>文字列、整数、 XPCOM インターフェースのポインタ、 IID を含む、ほとんどすべてのデータ型がキーとして利用できます。また、キーは連続している必要はありません(たとえば 1, 5, 3000 を利用できます)。</td>
</tr>
<tr>
<td class="header">検索にかかる時間:</td>
<td><em>O(1)。</em>検索時間は定数時間です。</td>
<td><em>O(1)。</em>検索時間は一般に定数時間ですが、配列よりも定数時間だけ長くかかる可能性があります。</td>
</tr>
<tr>
<td class="header">ソート:</td>
<td><em>ソートされています。</em>アイテムはソートされて保管されます。また、ソートされた順序で列挙されます。</td>
<td><em>ソートされていません。</em>アイテムはソートされずに保管されます。また、ソートされずに列挙されます。</td>
</tr>
<tr>
<td class="header">追加・削除:</td>
<td><em>O(n)。</em>大きな配列へのアイテムの追加・削除は時間がかかる可能性があります。</td>
<td><em>O(1)。</em>ハッシュテーブルへのアイテムの追加・削除は高速に行われます。</td>
</tr>
<tr>
<td class="header">余計に消費される領域:</td>
<td><em>なし。</em>配列は中が詰まった構造体であり、アイテムのサイズ以上に消費される領域はありません。</td>
<td><em>あり。</em>ハッシュテーブルは中が詰まった構造体ではありません。実装によりますが、大量のメモリが無駄に消費される可能性があります。</td>
</tr>
</tbody>
</table>
<p>実装としては、ハッシュテーブルはキーを渡されるとそのキーに数学的な<strong>ハッシュ関数</strong>を適用してキーを<strong>乱数化</strong>します。以後、キーのハッシュ値がアイテムの場所の検索に利用されます。優れたハッシュテーブルの実装は、メモリが余計に必要になったとき、または多すぎる量のメモリが割り当てられているとき、自動的にハッシュテーブルのサイズを変更します。</p>
<h2 id="When_Should_I_Use_a_Hashtable.3F" name="When_Should_I_Use_a_Hashtable.3F">どんなときにハッシュテーブルを使うべきですか?</h2>
<p>ハッシュテーブルは以下のような場合に有用です。</p>
<ul>
<li>高速なランダムアクセスが必要なデータのセット</li>
<li>非整数のキー、連続しない整数のキーを持ったデータ</li>
<li>アイテムの追加・削除が大量に発生するデータ</li>
</ul>
<p>以下のような場合、ハッシュテーブルは利用されるべきでは<em>ありません</em>。</p>
<ul>
<li>データのセットがソートされている必要がある場合</li>
<li>アイテムの数が非常に少ない場合(おおむね12-16個未満)</li>
<li>ランダムアクセスを必要としないデータ</li>
</ul>
<p>このような状況では、配列、連結リスト、様々な木構造などが効果的です。</p>
<h2 id="Mozilla.27s_Hashtable_Implementations" name="Mozilla.27s_Hashtable_Implementations">Mozilla のハッシュテーブル実装</h2>
<p>Mozilla ではいくつかのハッシュテーブルの実装を用意しています。これらはテスト・調整されており、また実装にかかわる内部の複雑さが隠蔽されています。</p>
<ul>
<li><code><a href="#PLDHash_.28JSDHash.29">PLDHash</a></code> - C の低レベルAPI。キーとデータを単独の大きな構造体としてメモリ上に格納します。ヒープ領域を効果的に利用します。利用者は「エントリークラス」(訳注:保管するアイテムを表すクラス・構造体)を宣言する必要があります。 また、アイテムへのポインタを別に持っておくことはできません。</li>
<li><code><a href="#PLHashTable">PLHashTable</a></code> - C の低レベルAPI。エントリークラスへのポインタは変化しません。大きな構造体を利用する場合は効果的です。細かなヒープ領域を大量に確保する結果、メモリを無駄に使用することがよくあります。</li>
<li><code><a href="#nsTHashtable">nsTHashtable</a></code> - <code>低レベル C++ による</code><code> PLDHash の</code>ラッパです。コールバック関数を生成し、ほとんどのキャストを自動的に行います。利用者はキーとデータを保持するエントリークラスを自分で用意します。</li>
<li><code><a href="#nsBaseHashtable_and_friends:_nsDataHashtable.2C_nsInterfaceHashtable.2C_and_nsClassHashtable">nsDataHashtable/nsInterfaceHashtable/nsClassHashtable</a></code> - 高レベル C++ による <code>PLDHash のラッパです。</code>単純なキー型・データ型を利用する一般的な使い方をする場合は簡単に利用できます。 利用者はエントリークラスを宣言・使用する必要がありません。 <code><strong>nsDataHashtable</strong></code> 型は <code>PRUint32</code> のようなスカラー値を扱います。 <code><strong>nsInterfaceHashtable</strong></code> 型はインタフェースを、 <code><strong>nsClassHashtable</strong></code> 型はクラスへのポインタ型を扱います。</li>
</ul>
<h3 id="Which_Hashtable_Should_I_Use.3F" name="Which_Hashtable_Should_I_Use.3F">どのハッシュテーブルを使えば良いですか?</h3>
<table class="standard-table">
<tbody>
<tr>
<th class="header" colspan="2" rowspan="2"> </th>
<th class="header" colspan="5">キーの型:</th>
</tr>
<tr>
<th class="header">integer</th>
<th class="header">String/CString</th>
<th class="header">nsID</th>
<th class="header">nsISupports*</th>
<th class="header">Complex</th>
</tr>
<tr>
<td class="header" rowspan="8">データ型:</td>
<td class="header">None (Hash Set)</td>
<td><code>nsInt32HashSet</code></td>
<td><code>ns(C)StringHashSet</code></td>
<td colspan="3"><code>nsTHashtable<...></code></td>
</tr>
<tr>
<td class="header" rowspan="2">Simple (PRUint32)</td>
<td colspan="4"><code>nsDataHashtable</code></td>
<td rowspan="6"><code>nsTHashtable<...></code></td>
</tr>
<tr>
<td><code><nsUint32HashKey,<br>
PRUint32></code></td>
<td><code><ns(C)StringHashKey,<br>
PRUint32></code></td>
<td><code><nsIDHashKey,<br>
PRUint32></code></td>
<td><code><nsISupportsHashKey,<br>
PRUint32></code></td>
</tr>
<tr>
<td class="header" rowspan="2">Interface (nsISupports)</td>
<td colspan="4"><code>nsInterfaceHashtable</code></td>
</tr>
<tr>
<td><code><nsUint32HashKey,<br>
nsISupports></code></td>
<td><code><ns(C)StringHashKey,<br>
nsISupports></code></td>
<td><code><nsIDHashKey,<br>
nsISupports></code></td>
<td><code><nsISupportsHashKey,<br>
nsISupports></code></td>
</tr>
<tr>
<td class="header" rowspan="2">Class (nsString*)</td>
<td colspan="4"><code>nsClassHashtable</code></td>
</tr>
<tr>
<td><code><nsUint32HashKey,<br>
nsString></code></td>
<td><code><ns(C)StringHashKey,<br>
nsString></code></td>
<td><code><nsIDHashKey,<br>
nsString></code></td>
<td><code><nsISupportsHashKey,<br>
nsString></code></td>
</tr>
<tr>
<td class="header">Complex<br>
(structures, etc.)</td>
<td colspan="5"><code>nsTHashtable<...></code></td>
</tr>
</tbody>
</table>
<h3 id="PLDHash_.28JSDHash.29" name="PLDHash_.28JSDHash.29">PLDHash (JSDHash)</h3>
<p><code>PLDHash</code> <span style="font-family: monospace;">と</span><code> JSDHash</code> は同じものです。 <code>PLDHash は</code> XPCOM ライブラリから、 <code>JSDHash は</code> JavaScript のライブラリからリンクされています。 <code>JSDHash</code> は SpiderMonkey の JavaScript エンジンで広く利用されています。</p>
<p><code>PLDHash</code> は C で書かれた低レベルな実装です。非常に柔軟ですが、 <code>PLDHash</code> を理解し、利用するためには多少の時間がかかります。基本的なガイドはここにありますが、 <code>PLDHash を利用するつもりであれば、 </code><code><a href="https://dxr.mozilla.org/mozilla-central/source/xpcom/glue/pldhash.h" rel="custom">xpcom/glue/pldhash.h</a></code> のほとんどを読む必要があります。 C++ のコードから利用する場合、キャストにかかわるエラーの可能性を容易に避けられるため、 C++ によるラッパ(後述)の方がずっと易しく、また安全です。</p>
<p>利用者はまず <a href="https://dxr.mozilla.org/mozilla-central/source/xpcom/glue/pldhash.h#81" rel="custom"><code>PLDHashEntryHdr</code></a> から派生する<strong>エントリー構造体</strong>を宣言する必要があります。エントリー構造体はハッシュテーブルに格納するデータ(任意のポインタ、固定長のデータ型)を持ちます。<strong>ノート:</strong> double-hashing 実装のため、ハッシュテーブルの内容が変更された際、エントリーはメモリ上で移動される可能性があります。エントリーへのポインタを定数としたい場合は、 <code><a href="#PLHashTable">PLHashTable</a></code> が代わりに利用できます。</p>
<p>また、利用者は <a href="https://dxr.mozilla.org/mozilla-central/source/xpcom/glue/pldhash.h#312" rel="custom"><code>PLDHashTableOps</code></a> 構造体を初期化しなくてはいけません。この構造体は C++ の vtable と似たようなもので、エントリーを初期化・比較・検索するための適切なユーザ定義関数へのポインタを提供します。 <code>PLDHash</code> はキーの型が何であるかを知らないため、キーを扱う全ての関数は <code><a href="https://dxr.mozilla.org/mozilla-central/source/xpcom/glue/pldhash.h#354" rel="custom">const void*</a></code> で宣言されなければなりません。また、利用者のコードはこれらのポインタを適切な型にキャストする必要があります。</p>
<p>PLDHashTables は、スタック・ヒープのどちらにも配置することができます。:</p>
<ul>
<li>スタックに配置する場合、または C++ のクラスメンバとして利用される場合、テーブルは <code><a href="https://dxr.mozilla.org/mozilla-central/source/xpcom/glue/pldhash.h#427" rel="custom">PL_DHashTableInit</a> で初期化され</code>、 <code><a href="https://dxr.mozilla.org/mozilla-central/source/xpcom/glue/pldhash.h#459" rel="custom">PL_DHashTableFinish</a></code> で破棄される必要があります。</li>
<li>ヒープに配置する場合、 <code><a href="https://dxr.mozilla.org/mozilla-central/source/xpcom/glue/pldhash.h#410" rel="custom">PL_NewDHashTable</a></code>, <code><a href="https://dxr.mozilla.org/mozilla-central/source/xpcom/glue/pldhash.h#420" rel="custom">PL_DHashTableDestroy</a></code> でテーブルの割り当て・削除を行ってください。</li>
</ul>
<h3 id="PLHashTable" name="PLHashTable">PLHashTable</h3>
<p><code>PLHashTable</code> は NSPR の一部です。ヘッダファイルは <code><code><a href="https://dxr.mozilla.org/mozilla-central/source/nsprpub/lib/ds/plhash.h" rel="custom">nsprpub/lib/ds/plhash.h</a></code></code> にあります。 <code>PLHashTable</code> はヒープに多数の領域を割り当てようとするため、一般的には <code><a href="#PLDHash_.28JSDHash.29">PLDHash</a></code> の方が <code>PLHashTable よりも優れています。</code></p>
<p><code>PLDHash よりも </code><code>PLHashTable</code> の方が好ましい状況は以下の2つです。</p>
<ul>
<li>エントリーへのポインタが定数である必要がある場合。</li>
<li>ハッシュテーブルに格納されているエントリーが非常に大きい場合(12ワード以上)。 <code>PLDHash</code> は大きな構造体を効率的に扱えません。</li>
</ul>
<h3 id="nsTHashtable" name="nsTHashtable">nsTHashtable</h3>
<p><code>nsTHashtable</code> は <code>PLDHash をラップする C++ のテンプレートで、</code> <code>PLDHash</code> の複雑な部分(コールバック関数、構造体など)を隠蔽します。 <code><a href="https://dxr.mozilla.org/mozilla-central/source/xpcom/glue/nsTHashtable.h" rel="custom">xpcom/glue/nsTHashtable.h</a></code> に目を通しておいてください。</p>
<p><code>nsTHashtable を利用するためには、利用者は</code> <a href="https://dxr.mozilla.org/mozilla-central/source/xpcom/glue/nsTHashtable.h#65" rel="custom">pre-defined format</a> にある通りに<code>エントリークラスを宣言する必要があります。このエントリークラスは、ハッシュテーブルに格納するキーとデータを保持します(上記の </code><code>PLDHash と同様です</code><code>)。また、クラスの中でキーを処理する関数も宣言します。<span style="font-family: Verdana,Tahoma,sans-serif;">ほとんどの場合、エントリークラスは完全にインラインで書くことができます。</span></code>エントリークラスの例については <code><a href="https://dxr.mozilla.org/mozilla-central/source/xpcom/glue/nsHashKeys.h" rel="custom">xpcom/glue/nsHashKeys.h</a></code> を参照してください。</p>
<p>テンプレートのパラメータはエントリークラスです。テーブルを正しく初期化するためには <code>Init()</code> を利用しなくてはいけません。また現在のところ、テーブルの内容を変更するためには <code>PutEntry/GetEntry/RemoveEntry</code> 関数を利用してください。 <code>EnumerateEntries</code> 関数では列挙ができますが、並び順は見かけ上ランダムである(ソートされていない)ことに気をつけてください。</p>
<ul>
<li><code>nsTHashtable</code> はスタック、クラスメンバ、ヒープに割り当てることができます。</li>
<li>エントリーへのポインタは、ハッシュテーブルにアイテムが追加・削除された際に変更されることがあります。エントリーへのポインタを長時間保持しないでください。</li>
<li>このため、 <code>nsTHashtable</code> は本質的にスレッドセーフではありません。マルチスレッドで利用する場合、適切なロック機構を用意する必要があります。</li>
</ul>
<p><code>nsTHashtable を使用する前に、</code> <code>nsBaseHashtable</code> とその関連クラスが利用用途に合うかどうか確認してください。エントリークラスを宣言する必要がないため、それらの方がずっと使いやすくなっています。もし単純なキー型・データ型を利用するのであれば、多くの場合こちらの方が良い選択肢です。</p>
<h3 id="nsBaseHashtable_and_friends_nsDataHashtable.2C_nsInterfaceHashtable.2C_and_nsClassHashtable" name="nsBaseHashtable_and_friends:_nsDataHashtable.2C_nsInterfaceHashtable.2C_and_nsClassHashtable">nsBaseHashtable とその関連クラス: nsDataHashtable, nsInterfaceHashtable, nsClassHashtable</h3>
<p>これらの C++ テンプレートは、 <code>PLDHash</code> の複雑な部分のほとんどを隠蔽しつつ、ハッシュテーブルを利用するための高レベルなインタフェースを提供します。以下のような機能を持ちます:</p>
<ul>
<li>ハッシュテーブルの操作はエントリークラスを使わずに行うことができます。コードの可読性を高めます。</li>
<li>スレッドセーフ性(オプション)。ハッシュテーブルは読み書きの際にロックを設定することができます。</li>
<li>予め定義されたキークラス。strings, インタフェースを自動的にクリーンアップします。</li>
<li><code>nsInterfaceHashtable</code> <span style="font-family: monospace;">と</span><code> nsClassHashtable</code> は自動的にオブジェクトを解放・削除し、メモリリークを防ぎます。</li>
</ul>
<p><code>nsBaseHashtable</code> は直接利用しません。ここから派生した3つの派生クラスから、保持するデータ型に合わせて利用するクラスを1つ選んでください。 <code>KeyClass</code> は <code>nsHashKeys.h</code> で定義されています。他3つも同様です:</p>
<ul>
<li><code>nsDataHashtable<KeyClass, <em>DataType</em>></code> - <code>DataType</code> は <code>PRUint32</code> or <code>PRBool</code> のような単純型です。</li>
<li><code>nsInterfaceHashtable<KeyClass, <em>Interface</em>></code> - <code>Interface</code> は <code>nsISupports</code>, <code>nsIDOMNode</code> のような XPCOM インタフェースです。</li>
<li><code>nsClassHashtable<KeyClass, <em>T</em>></code> - <code>T</code> は任意の C++ クラスです。ハッシュテーブルはオブジェクトへのポインタを格納します。また、オブジェクトがハッシュテーブルから取り去られた場合、そのオブジェクトを削除します。</li>
</ul>
<p>目を通しておくべき重要なファイルは <code><a href="https://dxr.mozilla.org/mozilla-central/source/xpcom/glue/nsBaseHashtable.h" rel="custom">xpcom/glue/nsBaseHashtable.h</a></code> と <code><a href="https://dxr.mozilla.org/mozilla-central/source/xpcom/glue/nsHashKeys.h" rel="custom">xpcom/glue/nsHashKeys.h</a></code> です。これらのクラスはスタック、クラスメンバ、ヒープに置くことができます。初期化には <code>Init()</code> 関数を利用してください。このとき、スレッドセーフな排他制御を行うかどうかを決められます。ハッシュテーブルの内容を変更するには <code>Put()</code>, <code>Get()</code>, <code>Remove()</code> 関数を利用してください。</p>
<p>2つの列挙関数が用意されています:</p>
<ul>
<li><code>EnumerateRead()</code> は読み取り専用の列挙型を提供します。内容の変更や削除はできません。</li>
<li><code>Enumerate()</code> は読み書きのできる列挙型を提供します。必要に応じて内容の変更・削除ができます。</li>
</ul>
<h3 id="Using_nsTHashtable_as_a_hash-set" name="Using_nsTHashtable_as_a_hash-set">nsTHashtable をハッシュセットとして利用する</h3>
<p>ハッシュセットはキーの存在だけを追跡します。キーとデータとの関連づけは行いません。このような動作は、 <code>nsTHashtable<nsSomeHashKey></code> を利用することで実現できます。The appropriate entries are GetEntry and PutEntry.</p>
<h2 id="Future_Plans" name="Future_Plans">Future Plans</h2>
<h3 id="nsISimpleEnumerator_support" name="nsISimpleEnumerator_support">nsISimpleEnumerator support</h3>
<p>The (obsolete) <code>nsHashtable</code> has a wrapper that exposes an <code>nsISimpleEnumerator</code> on its items. I will add this support to the various <code>nsBaseHashtable</code> classes as well, as needed.</p>
<h2 id="Hash_Functions" name="Hash_Functions">Hash Functions</h2>
<p>All of the above hashtables need a <a class="external" href="http://www.nist.gov/dads/HTML/hash.html">Hash Function</a>. This function converts the key into a semi-unique integer. The mozilla codebase already contains hash functions for most key types, including narrow and wide strings, pointers, and most binary data:</p>
<table class="standard-table">
<tbody>
<tr>
<td><code>void*<br>
(or nsISupports*)</code></td>
<td>cast using <code><a href="https://dxr.mozilla.org/mozilla-central/source/xpcom/base/nscore.h#443" rel="custom">NS_PTR_TO_INT32</a></code></td>
</tr>
<tr>
<td><code>char*</code> string</td>
<td rowspan="2"><code><a href="https://dxr.mozilla.org/mozilla-central/source/xpcom/ds/nsCRT.h#228" rel="custom">nsCRT::HashCode()</a></code></td>
</tr>
<tr>
<td><code>PRUnichar*</code> string</td>
</tr>
<tr>
<td><code>nsAString</code></td>
<td rowspan="2"><code><a href="https://dxr.mozilla.org/mozilla-central/source/xpcom/glue/nsTHashtable.cpp#41" rel="custom">HashString()</a></code></td>
</tr>
<tr>
<td><code>nsACString</code></td>
</tr>
<tr>
<td><code>nsID&</code></td>
<td><code><a href="https://dxr.mozilla.org/mozilla-central/source/xpcom/glue/nsHashKeys.h#227" rel="custom">nsIDHashKey::HashKey()</a></code></td>
</tr>
</tbody>
</table>
<p>Writing a good hash function is well beyond the scope of this document, and has been discussed extensively in computer-science circles for many years. There are many different types of hash functions. Mozilla has tuned a good general-purpose hash algorithm for strings and <code>nsID</code>.</p>
<h2 id="Mozilla.27s_Old.2FObsolete.2FDeprecated.2FDecrepit_Hashtables" name="Mozilla.27s_Old.2FObsolete.2FDeprecated.2FDecrepit_Hashtables">Mozilla's Old/Obsolete/Deprecated/Decrepit Hashtables</h2>
<h3 id="nsHashtable" name="nsHashtable">nsHashtable</h3>
<p><code><a href="https://dxr.mozilla.org/mozilla-central/source/xpcom/ds/nsHashtable.h" rel="custom">nsHashtable</a></code> was a C++ wrapper around <code>PLHashTable</code>, and now wraps <code>PLDHash</code>. The design of the key classes is not optimal, however, and <code>nsHashtable</code> has been deprecated in favor of <code>nsDataHashtable</code> and friends.</p>
<h3 id="nsObjectHashtable" name="nsObjectHashtable">nsObjectHashtable</h3>
<p><code><a href="https://dxr.mozilla.org/mozilla-central/source/xpcom/ds/nsHashtable.h#163" rel="custom">nsObjectHashtable</a></code> is a form of <code>nsHashtable</code>. It has been replaced by <code>nsClassHashtable</code>.</p>
<h3 id="nsSupportsHashtable" name="nsSupportsHashtable">nsSupportsHashtable</h3>
<p><code><a href="https://dxr.mozilla.org/mozilla-central/source/xpcom/ds/nsHashtable.h#193" rel="custom">nsSupportsHashtable</a></code> is a form of <code>nsHashtable</code>. It has been replaced by <code>nsInterfaceHashtable</code>.</p>
<h3 id="nsHashSets" name="nsHashSets">nsHashSets</h3>
<p><code>nsHashSets</code> has predefined hash sets for common keys, which are trivially easy to use. See <code><a href="https://dxr.mozilla.org/mozilla-central/source/xpcom/ds/nsHashSets.h" rel="custom">xpcom/ds/nsHashSets.h</a></code>. This functionality has been replaced by <code>nsTHashtable<nsSomeHashKey></code>.</p>
<h3 id="nsDoubleHashtable" name="nsDoubleHashtable">nsDoubleHashtable</h3>
<p><code><a href="https://dxr.mozilla.org/mozilla-central/source/xpcom/ds/nsDoubleHashtable.h" rel="custom">nsDoubleHashtable</a></code> is the (obsolete) precursor to <code>nsTHashtable</code>. It uses macros instead of C++ templates.</p>
<div class="originaldocinfo">
<h2 id="Original_Document_Information" name="Original_Document_Information">Original Document Information</h2>
<ul>
<li>Author(s): Benjamin Smedberg <<a class="link-mailto" href="mailto:benjamin@smedbergs.us" rel="freelink">benjamin@smedbergs.us</a>></li>
</ul>
</div>
<p> </p>
|