Bug 1326028 - Allow moving a reference into nsInterfaceHashtable. r=smaug draft
authorBlake Kaplan <mrbkap@gmail.com>
Thu, 22 Feb 2018 14:09:26 -0800
changeset 766537 a3e842bf9dfe202134c58e447ecf4fa79851c076
parent 766504 c2d022018003ac2746632933b1049d2c21a5f74f
child 766538 d51e63783c156b2ecebbaed98d530a83bcb3f6b8
push id102349
push userbmo:mrbkap@mozilla.com
push dateTue, 13 Mar 2018 00:10:59 +0000
reviewerssmaug
bugs1326028
milestone61.0a1
Bug 1326028 - Allow moving a reference into nsInterfaceHashtable. r=smaug Without this patch, it's impossible for clients to move a reference into an nsInterfaceHashtable. That causes at least one extra addref/release pair when they otherwise could. With this patch, a client can do `hashTable.Put(key, comptr.forget());` to avoid the additional refcounting. MozReview-Commit-ID: Ghm7n41ziZp
xpcom/ds/nsInterfaceHashtable.h
--- a/xpcom/ds/nsInterfaceHashtable.h
+++ b/xpcom/ds/nsInterfaceHashtable.h
@@ -50,16 +50,31 @@ public:
    * Gets a weak reference to the hashtable entry.
    * @param aFound If not nullptr, will be set to true if the entry is found,
    *               to false otherwise.
    * @return The entry, or nullptr if not found. Do not release this pointer!
    */
   Interface* GetWeak(KeyType aKey, bool* aFound = nullptr) const;
 
   /**
+   * Allows inserting a value into the hashtable, moving its owning reference
+   * count into the hashtable, avoiding an AddRef.
+   */
+  void Put(KeyType aKey, already_AddRefed<Interface>&& aData)
+  {
+    if (!Put(aKey, mozilla::Move(aData), mozilla::fallible)) {
+      NS_ABORT_OOM(this->mTable.EntrySize() * this->mTable.EntryCount());
+    }
+  }
+
+  MOZ_MUST_USE bool Put(KeyType aKey, already_AddRefed<Interface>&& aData,
+                        const mozilla::fallible_t&);
+  using base_type::Put;
+
+  /**
    * Remove the entry associated with aKey (if any), optionally _moving_ its
    * current value into *aData, thereby avoiding calls to AddRef and Release.
    * Return true if found.
    * @param aKey the key to remove from the hashtable
    * @param aData where to move the value (if non-null).  If an entry is not
    *              found it will be set to nullptr.
    * @return true if an entry for aKey was found (and removed)
    */
@@ -147,16 +162,31 @@ nsInterfaceHashtable<KeyClass, Interface
   if (aFound) {
     *aFound = false;
   }
   return nullptr;
 }
 
 template<class KeyClass, class Interface>
 bool
+nsInterfaceHashtable<KeyClass, Interface>::Put(KeyType aKey,
+                                               already_AddRefed<Interface>&& aValue,
+                                               const mozilla::fallible_t&)
+{
+  typename base_type::EntryType* ent = this->PutEntry(aKey);
+  if (!ent) {
+    return false;
+  }
+
+  ent->mData = aValue;
+  return true;
+}
+
+template<class KeyClass, class Interface>
+bool
 nsInterfaceHashtable<KeyClass, Interface>::Remove(KeyType aKey,
                                                   Interface** aData)
 {
   typename base_type::EntryType* ent = this->GetEntry(aKey);
 
   if (ent) {
     if (aData) {
       ent->mData.forget(aData);