Bug 1758753 - Migrate XPCOM hashtable documentation from MDN to Firefox Source Docs. r=nika

Differential Revision: https://phabricator.services.mozilla.com/D140671
This commit is contained in:
Mike Conley 2022-03-17 14:23:27 +00:00
parent 809783b17a
commit f29b80b95b
5 changed files with 270 additions and 6 deletions

View File

@ -377,7 +377,7 @@ Data structures
* - ``nsClassHashtable``
- ``nsClassHashtable.h``
-
- Adaptation of nsTHashtable, see `XPCOM hashtable guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Hashtables>`__
- Adaptation of nsTHashtable, see :ref:`XPCOM Hashtable Guide`
* - ``nsCOMArray``
- ``nsCOMArray.h``
-
@ -385,7 +385,7 @@ Data structures
* - ``nsDataHashtable``
- ``nsClassHashtable.h``
- ``std::unordered_map``
- Adaptation of ``nsTHashtable``, see `XPCOM hashtable guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Hashtables>`__
- Adaptation of ``nsTHashtable``, see :ref:`XPCOM Hashtable Guide`
* - ``nsDeque``
- ``nsDeque.h``
- ``std::deque<void *>``
@ -401,7 +401,7 @@ Data structures
* - ``nsInterfaceHashtable``
- ``nsInterfaceHashtable.h``
- ``std::unordered_map``
- Adaptation of ``nsTHashtable``, see `XPCOM hashtable guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Hashtables>`__
- Adaptation of ``nsTHashtable``, see :ref:`XPCOM Hashtable Guide`
* - ``mozilla::LinkedList``
- ``mozilla/LinkedList.h``
- ``std::list``
@ -409,7 +409,7 @@ Data structures
* - ``nsRef PtrHashtable``
- ``nsRefPtrHashtable.h``
- ``std::unordered_map``
- Adaptation of ``nsTHashtable``, see `XPCOM hashtable guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Hashtables>`__
- Adaptation of ``nsTHashtable``, see :ref:`XPCOM Hashtable Guide`
* - ``mozilla::SegmentedVector``
- ``mozilla/SegmentedVector.h``
- ``std::deque`` w/o O(1) pop_front
@ -425,7 +425,7 @@ Data structures
* - ``nsTHashtable``
- ``nsTHashtable.h``
- ``std::unordered_{map,set}``
- See `XPCOM hashtable guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Hashtables>`__, you probably want a subclass
- See :ref:`XPCOM Hashtable Guide`, you probably want a subclass
* - ``nsTObserverArray``
- ``nsTObserverArray.h``
-

View File

@ -14590,7 +14590,7 @@ void Document::GetWireframeWithoutFlushing(bool aIncludeNodes,
FrameForPointOptions options;
options.mBits += FrameForPointOption::IgnoreCrossDoc;
options.mBits += FrameForPointOption::IgnorePaintSuppression;
options.mBits += FrameForPointOption::OnlyVisible;
// options.mBits += FrameForPointOption::OnlyVisible;
AutoTArray<nsIFrame*, 32> frames;
const RelativeTo relativeTo{rootFrame, mozilla::ViewportType::Layout};

141
xpcom/docs/hashtables.rst Normal file
View File

@ -0,0 +1,141 @@
XPCOM Hashtable Guide
=====================
.. note::
For a deep-dive into the underlying mechanisms that power our hashtables,
check out the :ref:`XPCOM Hashtable Technical Details`
document.
What Is a Hashtable?
--------------------
A hashtable is a data construct that stores a set of **items**. Each
item has a **key** that identifies the item. Items are found, added, and
removed from the hashtable by using the key. Hashtables may seem like
arrays, but there are important differences:
+-------------------------+----------------------+----------------------+
| | Array | Hashtable |
+=========================+======================+======================+
| **Keys** | *integer:* arrays | *any type:* almost |
| | are always keyed on | any datatype can be |
| | integers and must | used as key, |
| | be contiguous. | including strings, |
| | | integers, XPCOM |
| | | interface pointers, |
| | | IIDs, and almost |
| | | anything else. Keys |
| | | can be disjunct |
| | | (i.e. you can store |
| | | entries with keys 1, |
| | | 5, and 3000). |
+-------------------------+----------------------+----------------------+
| **Lookup Time** | *O(1):* lookup time | *O(1):* lookup time |
| | is a simple constant | is mostly-constant, |
| | | but the constant |
| | | time can be larger |
| | | than an array lookup |
+-------------------------+----------------------+----------------------+
| **Sorting** | *sorted:* stored | *unsorted:* stored |
| | sorted; iterated | unsorted; cannot be |
| | over in a sorted | iterated over in a |
| | fashion. | sorted manner. |
+-------------------------+----------------------+----------------------+
| **Inserting/Removing** | *O(n):* adding and | *O(1):* adding and |
| | removing items from | removing items from |
| | a large array can be | hashtables is a |
| | time-consuming | quick operation |
+-------------------------+----------------------+----------------------+
| **Wasted space** | *none:* Arrays are | *some:* hashtables |
| | packed structures, | are not packed |
| | so there is no | structures; |
| | wasted space. | depending on the |
| | | implementation, |
| | | there may be |
| | | significant wasted |
| | | memory. |
+-------------------------+----------------------+----------------------+
In their implementation, hashtables take the key and apply a
mathematical **hash function** to **randomize** the key and then use the
hash to find the location in the hashtable. Good hashtable
implementations will automatically resize the hashtable in memory if
extra space is needed, or if too much space has been allocated.
.. _When_Should_I_Use_a_Hashtable.3F:
When Should I Use a Hashtable?
------------------------------
Hashtables are useful for
- sets of data that need swift **random access**
- with **non-integral keys** or **non-contiguous integral keys**
- or where **items will be frequently added or removed**
Hashtables should *not* be used for
- Sets that need to be **sorted**
- Very small datasets (less than 12-16 items)
- Data that does not need random access
In these situations, an array, a linked-list, or various tree data
structures are more efficient.
.. _Which_Hashtable_Should_I_Use.3F:
Which Hashtable Should I Use?
-----------------------------
If there is **no** key type, you should use an ``nsTHashSet``.
If there is a key type, you should use an ``nsTHashMap``.
``nsTHashMap`` is a template with two parameters. The first is the hash key
and the second is the data to be stored as the value in the map. Most of
the time, you can simply pass the raw key type as the first parameter,
so long as its supported by `nsTHashMap.h <https://searchfox.org/mozilla-central/source/xpcom/ds/nsTHashMap.h>`_.
It is also possible to specify custom keys if necessary. See `nsHashKeys.h
<https://searchfox.org/mozilla-central/source/xpcom/ds/nsHashKeys.h>`_ for examples.
There are a number of more esoteric hashkey classes in nsHashKeys.h, and
you can always roll your own if none of these fit your needs (make sure
you're not duplicating an existing hashkey class though!)
Once you've determined what hashtable and hashkey classes you need, you
can put it all together. A few examples:
- A hashtable that maps UTF-8 origin names to a DOM Window -
``nsTHashMap<nsCString, nsCOMPtr<nsIDOMWindow>>``
- A hashtable that maps 32-bit integers to floats -
``nsTHashMap<uint32_t, float>``
- A hashtable that maps ``nsISupports`` pointers to reference counted
``CacheEntry``\ s -
``nsTHashMap<nsCOMPtr<nsISupports>, RefPtr<CacheEntry>>``
- A hashtable that maps ``JSContext`` pointers to a ``ContextInfo``
struct - ``nsTHashMap<JSContext*, UniquePtr<ContextInfo>>``
- A hashset of strings - ``nsTHashSet<nsString>``
.. _nsBaseHashtable_and_friends:_nsDataHashtable.2C_nsInterfaceHashtable.2C_and_nsClassHashtable:
Hashtable API
-------------
The hashtable classes all expose the same basic API. There are three
key methods, ``Get``, ``InsertOrUpdate``, and ``Remove``, which retrieve entries from the
hashtable, write entries into the hashtable, and remove entries from the
hashtable respectively. See `nsBaseHashtable.h <https://searchfox.org/mozilla-central/source/xpcom/ds/nsBaseHashtable.h>`_
for more details.
The hashtables that hold references to pointers (nsRefPtrHashtable and
nsInterfaceHashtable) also have GetWeak methods that return non-AddRefed
pointers.
Note that ``nsRefPtrHashtable``, ``nsInterfaceHashtable`` and ``nsClassHashtable``
are legacy hashtable types which have some extra methods, and don't have automatic
key type handling.
All of these hashtable classes can be iterated over via the ``Iterator``
class, with normal C++11 iterators or using the ``Keys()`` / ``Values()`` ranges,
and all can be cleared via the ``Clear`` method.

View File

@ -0,0 +1,121 @@
XPCOM Hashtable Technical Details
=================================
.. note::
This is a deep-dive into the underlying mechanisms that power the XPCOM
hashtables. Some of this information is quite old and may be out of date. If
you're looking for how to use XPCOM hashtables, you should consider reading
the :ref:`XPCOM Hashtable Guide` instead.
Mozilla's Hashtable Implementations
-----------------------------------
Mozilla has several hashtable implementations, which have been tested
and tuned, and hide the inner complexities of hashtable implementations:
- ``PLHashTable`` - low-level C API; entry class pointers are constant;
more efficient for large entry structures; often wastes memory making
many small heap allocations.
- ``nsTHashtable`` - low-level C++ wrapper around ``PLDHash``;
generates callback functions and handles most casting automagically.
Client writes their own entry class which can include complex key and
data types.
- ``nsTHashMap/nsInterfaceHashtable/nsClassHashtable`` -
simplifies the common usage pattern mapping a simple keytype to a
simple datatype; client does not need to declare or manage an entry class;
``nsTHashMap`` datatype is a scalar such as ``uint64_t``;
``nsInterfaceHashtable`` datatype is an XPCOM interface;
``nsClassHashtable`` datatype is a class pointer owned by the
hashtable.
.. _PLHashTable:
PLHashTable
~~~~~~~~~~~
``PLHashTable`` is a part of NSPR. The header file can be found at `plhash.h
<https://searchfox.org/mozilla-central/source/nsprpub/lib/ds/plhash.h>`_.
There are two situations where ``PLHashTable`` may be preferable:
- You need entry-pointers to remain constant.
- The entries stored in the table are very large (larger than 12
words).
.. _nsTHashtable:
nsTHashtable
~~~~~~~~~~~~
To use ``nsTHashtable``, you must declare an entry-class. This
entry class contains the key and the data that you are hashing. It also
declares functions that manipulate the key. In most cases, the functions
of this entry class can be entirely inline. For examples of entry classes,
see the declarations at `nsHashKeys.h
<https://searchfox.org/mozilla-central/source/xpcom/ds/nsHashKeys.h>`_.
The template parameter is the entry class. After construction, use the
functions ``PutEntry/GetEntry/RemoveEntry`` to alter the hashtable. The
``Iterator`` class will do iteration, but beware that the iteration will
occur in a seemingly-random order (no sorting).
- ``nsTHashtable``\ s can be allocated on the stack, as class members,
or on the heap.
- Entry pointers can and do change when items are added to or removed
from the hashtable. Do not keep long-lasting pointers to entries.
- because of this, ``nsTHashtable`` is not inherently thread-safe. If
you use a hashtable in a multi-thread environment, you must provide
locking as appropriate.
Before using ``nsTHashtable``, see if ``nsBaseHashtable`` and relatives
will work for you. They are much easier to use, because you do not have
to declare an entry class. If you are hashing a simple key type to a
simple data type, they are generally a better choice.
.. _nsBaseHashtable_and_friends:nsTHashMap.2C_nsInterfaceHashtable.2C_and_nsClassHashtable:
nsBaseHashtable and friends: nsTHashMap, nsInterfaceHashtable, and nsClassHashtable
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
These C++ templates provide a high-level interface for using hashtables
that hides most of the complexities of the underlying implementation. They
provide the following features:
- hashtable operations can be completed without using an entry class,
making code easier to read
- optional thread-safety: the hashtable can manage a read-write lock
around the table
- predefined key classes provide automatic cleanup of
strings/interfaces
- ``nsInterfaceHashtable`` and ``nsClassHashtable`` automatically
release/delete objects to avoid leaks.
``nsBaseHashtable`` is not used directly; choose one of the three
derivative classes based on the data type you want to store. The
``KeyClass`` is taken from `nsHashKeys.h
<https://searchfox.org/mozilla-central/source/xpcom/ds/nsHashKeys.h>`_ and is the same for all
three classes:
- ``nsTHashMap<KeyClass, DataType>`` - ``DataType`` is a simple
type such as ``uint32_t`` or ``bool``.
- ``nsInterfaceHashtable<KeyClass, Interface>`` - ``Interface`` is an
XPCOM interface such as ``nsISupports`` or ``nsIDocShell``
- ``nsClassHashtable<KeyClass, T>`` - ``T`` is any C++ class. The
hashtable stores a pointer to the object, and deletes that object
when the entry is removed.
The important files to read are
`nsBaseHashtable.h <https://searchfox.org/mozilla-central/source/xpcom/ds/nsBaseHashtable.h>`_
and
`nsHashKeys.h <https://searchfox.org/mozilla-central/source/xpcom/ds/nsHashKeys.h>`_.
These classes can be used on the stack, as a class member, or on the heap.
.. _Using_nsTHashtable_as_a_hash-set:
Using nsTHashtable as a hash-set
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A hash set only tracks the existence of keys: it does not associate data
with the keys. This can be done using ``nsTHashtable<nsSomeHashKey>``.
The appropriate entries are GetEntry and PutEntry.

View File

@ -14,3 +14,5 @@ These pages contain documentation for Mozilla's Cross-Platform Component Object
collections
xpidl
dmd
hashtables
hashtables_detailed