xpcom/glue/nsBaseHashtable.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/xpcom/glue/nsBaseHashtable.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,418 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#ifndef nsBaseHashtable_h__
    1.10 +#define nsBaseHashtable_h__
    1.11 +
    1.12 +#include "mozilla/MemoryReporting.h"
    1.13 +#include "mozilla/Move.h"
    1.14 +#include "nsTHashtable.h"
    1.15 +#include "prlock.h"
    1.16 +#include "nsDebug.h"
    1.17 +
    1.18 +template<class KeyClass,class DataType,class UserDataType>
    1.19 +class nsBaseHashtable; // forward declaration
    1.20 +
    1.21 +/**
    1.22 + * the private nsTHashtable::EntryType class used by nsBaseHashtable
    1.23 + * @see nsTHashtable for the specification of this class
    1.24 + * @see nsBaseHashtable for template parameters
    1.25 + */
    1.26 +template<class KeyClass,class DataType>
    1.27 +class nsBaseHashtableET : public KeyClass
    1.28 +{
    1.29 +public:
    1.30 +  DataType mData;
    1.31 +  friend class nsTHashtable< nsBaseHashtableET<KeyClass,DataType> >;
    1.32 +
    1.33 +private:
    1.34 +  typedef typename KeyClass::KeyType KeyType;
    1.35 +  typedef typename KeyClass::KeyTypePointer KeyTypePointer;
    1.36 +  
    1.37 +  nsBaseHashtableET(KeyTypePointer aKey);
    1.38 +  nsBaseHashtableET(nsBaseHashtableET<KeyClass,DataType>&& toMove);
    1.39 +  ~nsBaseHashtableET();
    1.40 +};
    1.41 +
    1.42 +/**
    1.43 + * templated hashtable for simple data types
    1.44 + * This class manages simple data types that do not need construction or
    1.45 + * destruction.
    1.46 + *
    1.47 + * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
    1.48 + *   for a complete specification.
    1.49 + * @param DataType the datatype stored in the hashtable,
    1.50 + *   for example, uint32_t or nsCOMPtr.  If UserDataType is not the same,
    1.51 + *   DataType must implicitly cast to UserDataType
    1.52 + * @param UserDataType the user sees, for example uint32_t or nsISupports*
    1.53 + */
    1.54 +template<class KeyClass,class DataType,class UserDataType>
    1.55 +class nsBaseHashtable :
    1.56 +  protected nsTHashtable< nsBaseHashtableET<KeyClass,DataType> >
    1.57 +{
    1.58 +  typedef mozilla::fallible_t fallible_t;
    1.59 +
    1.60 +public:
    1.61 +  typedef typename KeyClass::KeyType KeyType;
    1.62 +  typedef nsBaseHashtableET<KeyClass,DataType> EntryType;
    1.63 +
    1.64 +  using nsTHashtable<EntryType>::Contains;
    1.65 +
    1.66 +  nsBaseHashtable()
    1.67 +  {
    1.68 +  }
    1.69 +  explicit nsBaseHashtable(uint32_t aInitSize)
    1.70 +    : nsTHashtable<EntryType>(aInitSize)
    1.71 +  {
    1.72 +  }
    1.73 +
    1.74 +  /**
    1.75 +   * Return the number of entries in the table.
    1.76 +   * @return    number of entries
    1.77 +   */
    1.78 +  uint32_t Count() const
    1.79 +  { return nsTHashtable<EntryType>::Count(); }
    1.80 +
    1.81 +  /**
    1.82 +   * retrieve the value for a key.
    1.83 +   * @param aKey the key to retreive
    1.84 +   * @param pData data associated with this key will be placed at this
    1.85 +   *   pointer.  If you only need to check if the key exists, pData
    1.86 +   *   may be null.
    1.87 +   * @return true if the key exists. If key does not exist, pData is not
    1.88 +   *   modified.
    1.89 +   */
    1.90 +  bool Get(KeyType aKey, UserDataType* pData) const
    1.91 +  {
    1.92 +    EntryType* ent = this->GetEntry(aKey);
    1.93 +
    1.94 +    if (!ent)
    1.95 +      return false;
    1.96 +
    1.97 +    if (pData)
    1.98 +      *pData = ent->mData;
    1.99 +
   1.100 +    return true;
   1.101 +  }
   1.102 +
   1.103 +  /**
   1.104 +   * For pointer types, get the value, returning nullptr if the entry is not
   1.105 +   * present in the table.
   1.106 +   *
   1.107 +   * @param aKey the key to retrieve
   1.108 +   * @return The found value, or nullptr if no entry was found with the given key.
   1.109 +   * @note If nullptr values are stored in the table, it is not possible to
   1.110 +   *       distinguish between a nullptr value and a missing entry.
   1.111 +   */
   1.112 +  UserDataType Get(KeyType aKey) const
   1.113 +  {
   1.114 +    EntryType* ent = this->GetEntry(aKey);
   1.115 +    if (!ent)
   1.116 +      return 0;
   1.117 +
   1.118 +    return ent->mData;
   1.119 +  }
   1.120 +
   1.121 +  /**
   1.122 +   * put a new value for the associated key
   1.123 +   * @param aKey the key to put
   1.124 +   * @param aData the new data
   1.125 +   * @return always true, unless memory allocation failed
   1.126 +   */
   1.127 +  void Put(KeyType aKey, const UserDataType& aData)
   1.128 +  {
   1.129 +    if (!Put(aKey, aData, fallible_t()))
   1.130 +      NS_ABORT_OOM(this->mTable.entrySize * this->mTable.entryCount);
   1.131 +  }
   1.132 +
   1.133 +  bool Put(KeyType aKey, const UserDataType& aData, const fallible_t&) NS_WARN_UNUSED_RESULT
   1.134 +  {
   1.135 +    EntryType* ent = this->PutEntry(aKey);
   1.136 +
   1.137 +    if (!ent)
   1.138 +      return false;
   1.139 +
   1.140 +    ent->mData = aData;
   1.141 +
   1.142 +    return true;
   1.143 +  }
   1.144 +
   1.145 +  /**
   1.146 +   * remove the data for the associated key
   1.147 +   * @param aKey the key to remove from the hashtable
   1.148 +   */
   1.149 +  void Remove(KeyType aKey) { this->RemoveEntry(aKey); }
   1.150 +
   1.151 +  /**
   1.152 +   * function type provided by the application for enumeration.
   1.153 +   * @param aKey the key being enumerated
   1.154 +   * @param aData data being enumerated
   1.155 +   * @parm userArg passed unchanged from Enumerate
   1.156 +   * @return either
   1.157 +   *   @link PLDHashOperator::PL_DHASH_NEXT PL_DHASH_NEXT @endlink or
   1.158 +   *   @link PLDHashOperator::PL_DHASH_STOP PL_DHASH_STOP @endlink
   1.159 +   */
   1.160 +  typedef PLDHashOperator
   1.161 +    (* EnumReadFunction)(KeyType      aKey,
   1.162 +                         UserDataType aData,
   1.163 +                         void*        userArg);
   1.164 +
   1.165 +  /**
   1.166 +   * enumerate entries in the hashtable, without allowing changes
   1.167 +   * @param enumFunc enumeration callback
   1.168 +   * @param userArg passed unchanged to the EnumReadFunction
   1.169 +   */
   1.170 +  uint32_t EnumerateRead(EnumReadFunction enumFunc, void* userArg) const
   1.171 +  {
   1.172 +    NS_ASSERTION(this->mTable.entrySize,
   1.173 +                 "nsBaseHashtable was not initialized properly.");
   1.174 +
   1.175 +    s_EnumReadArgs enumData = { enumFunc, userArg };
   1.176 +    return PL_DHashTableEnumerate(const_cast<PLDHashTable*>(&this->mTable),
   1.177 +                                  s_EnumReadStub,
   1.178 +                                  &enumData);
   1.179 +  }
   1.180 +
   1.181 +  /**
   1.182 +   * function type provided by the application for enumeration.
   1.183 +   * @param aKey the key being enumerated
   1.184 +   * @param aData Reference to data being enumerated, may be altered. e.g. for
   1.185 +   *        nsInterfaceHashtable this is an nsCOMPtr reference...
   1.186 +   * @parm userArg passed unchanged from Enumerate
   1.187 +   * @return bitflag combination of
   1.188 +   *   @link PLDHashOperator::PL_DHASH_REMOVE @endlink,
   1.189 +   *   @link PLDHashOperator::PL_DHASH_NEXT PL_DHASH_NEXT @endlink, or
   1.190 +   *   @link PLDHashOperator::PL_DHASH_STOP PL_DHASH_STOP @endlink
   1.191 +   */
   1.192 +  typedef PLDHashOperator
   1.193 +    (* EnumFunction)(KeyType       aKey,
   1.194 +                     DataType&     aData,
   1.195 +                     void*         userArg);
   1.196 +
   1.197 +  /**
   1.198 +   * enumerate entries in the hashtable, allowing changes. This
   1.199 +   * functions write-locks the hashtable.
   1.200 +   * @param enumFunc enumeration callback
   1.201 +   * @param userArg passed unchanged to the EnumFunction
   1.202 +   */
   1.203 +  uint32_t Enumerate(EnumFunction enumFunc, void* userArg)
   1.204 +  {
   1.205 +    NS_ASSERTION(this->mTable.entrySize,
   1.206 +                 "nsBaseHashtable was not initialized properly.");
   1.207 +
   1.208 +    s_EnumArgs enumData = { enumFunc, userArg };
   1.209 +    return PL_DHashTableEnumerate(&this->mTable,
   1.210 +                                  s_EnumStub,
   1.211 +                                  &enumData);
   1.212 +  }
   1.213 +
   1.214 +  /**
   1.215 +   * reset the hashtable, removing all entries
   1.216 +   */
   1.217 +  void Clear() { nsTHashtable<EntryType>::Clear(); }
   1.218 +
   1.219 +  /**
   1.220 +   * client must provide a SizeOfEntryExcludingThisFun function for
   1.221 +   *   SizeOfExcludingThis.
   1.222 +   * @param     aKey the key being enumerated
   1.223 +   * @param     aData Reference to data being enumerated.
   1.224 +   * @param     mallocSizeOf the function used to measure heap-allocated blocks
   1.225 +   * @param     userArg passed unchanged from SizeOf{In,Ex}cludingThis
   1.226 +   * @return    summed size of the things pointed to by the entries
   1.227 +   */
   1.228 +  typedef size_t
   1.229 +    (* SizeOfEntryExcludingThisFun)(KeyType           aKey,
   1.230 +                                    const DataType    &aData,
   1.231 +                                    mozilla::MallocSizeOf mallocSizeOf,
   1.232 +                                    void*             userArg);
   1.233 +
   1.234 +  /**
   1.235 +   * Measure the size of the table's entry storage and the table itself.
   1.236 +   * If |sizeOfEntryExcludingThis| is non-nullptr, measure the size of things
   1.237 +   * pointed to by entries.
   1.238 +   *
   1.239 +   * @param    sizeOfEntryExcludingThis
   1.240 +   *           the <code>SizeOfEntryExcludingThisFun</code> function to call
   1.241 +   * @param    mallocSizeOf the function used to meeasure heap-allocated blocks
   1.242 +   * @param    userArg a point to pass to the
   1.243 +   *           <code>SizeOfEntryExcludingThisFun</code> function
   1.244 +   * @return   the summed size of the entries, the table, and the table's storage
   1.245 +   */
   1.246 +  size_t SizeOfIncludingThis(SizeOfEntryExcludingThisFun sizeOfEntryExcludingThis,
   1.247 +                             mozilla::MallocSizeOf mallocSizeOf, void *userArg = nullptr)
   1.248 +  {
   1.249 +    return mallocSizeOf(this) + this->SizeOfExcludingThis(sizeOfEntryExcludingThis,
   1.250 +                                                          mallocSizeOf, userArg);
   1.251 +  }
   1.252 +
   1.253 +  /**
   1.254 +   * Measure the size of the table's entry storage, and if
   1.255 +   * |sizeOfEntryExcludingThis| is non-nullptr, measure the size of things pointed
   1.256 +   * to by entries.
   1.257 +   * 
   1.258 +   * @param     sizeOfEntryExcludingThis the
   1.259 +   *            <code>SizeOfEntryExcludingThisFun</code> function to call
   1.260 +   * @param     mallocSizeOf the function used to measure heap-allocated blocks
   1.261 +   * @param     userArg a pointer to pass to the
   1.262 +   *            <code>SizeOfEntryExcludingThisFun</code> function
   1.263 +   * @return    the summed size of all the entries
   1.264 +   */
   1.265 +  size_t SizeOfExcludingThis(SizeOfEntryExcludingThisFun sizeOfEntryExcludingThis,
   1.266 +                             mozilla::MallocSizeOf mallocSizeOf, void *userArg = nullptr) const
   1.267 +  {
   1.268 +    if (sizeOfEntryExcludingThis) {
   1.269 +      s_SizeOfArgs args = { sizeOfEntryExcludingThis, userArg };
   1.270 +      return PL_DHashTableSizeOfExcludingThis(&this->mTable, s_SizeOfStub,
   1.271 +                                              mallocSizeOf, &args);
   1.272 +    }
   1.273 +    return PL_DHashTableSizeOfExcludingThis(&this->mTable, nullptr,
   1.274 +                                            mallocSizeOf);
   1.275 +  }
   1.276 +
   1.277 +#ifdef DEBUG
   1.278 +  using nsTHashtable<EntryType>::MarkImmutable;
   1.279 +#endif
   1.280 +
   1.281 +protected:
   1.282 +  /**
   1.283 +   * used internally during EnumerateRead.  Allocated on the stack.
   1.284 +   * @param func the enumerator passed to EnumerateRead
   1.285 +   * @param userArg the userArg passed to EnumerateRead
   1.286 +   */
   1.287 +  struct s_EnumReadArgs
   1.288 +  {
   1.289 +    EnumReadFunction func;
   1.290 +    void* userArg;
   1.291 +  };
   1.292 +
   1.293 +  static PLDHashOperator s_EnumReadStub(PLDHashTable    *table,
   1.294 +                                        PLDHashEntryHdr *hdr,
   1.295 +                                        uint32_t         number,
   1.296 +                                        void            *arg);
   1.297 +
   1.298 +  struct s_EnumArgs
   1.299 +  {
   1.300 +    EnumFunction func;
   1.301 +    void* userArg;
   1.302 +  };
   1.303 +
   1.304 +  static PLDHashOperator s_EnumStub(PLDHashTable      *table,
   1.305 +                                    PLDHashEntryHdr   *hdr,
   1.306 +                                    uint32_t           number,
   1.307 +                                    void              *arg);
   1.308 +
   1.309 +  struct s_SizeOfArgs
   1.310 +  {
   1.311 +    SizeOfEntryExcludingThisFun func;
   1.312 +    void* userArg;
   1.313 +  };
   1.314 +  
   1.315 +  static size_t s_SizeOfStub(PLDHashEntryHdr *entry,
   1.316 +                             mozilla::MallocSizeOf mallocSizeOf,
   1.317 +                             void *arg);
   1.318 +};
   1.319 +
   1.320 +class nsCycleCollectionTraversalCallback;
   1.321 +
   1.322 +struct MOZ_STACK_CLASS nsBaseHashtableCCTraversalData
   1.323 +{
   1.324 +  nsBaseHashtableCCTraversalData(nsCycleCollectionTraversalCallback& aCallback,
   1.325 +                                 const char* aName,
   1.326 +                                 uint32_t aFlags)
   1.327 +  : mCallback(aCallback),
   1.328 +    mName(aName),
   1.329 +    mFlags(aFlags)
   1.330 +  {
   1.331 +  }
   1.332 +
   1.333 +  nsCycleCollectionTraversalCallback& mCallback;
   1.334 +  const char* mName;
   1.335 +  uint32_t mFlags;
   1.336 +
   1.337 +};
   1.338 +
   1.339 +template <typename K, typename T>
   1.340 +PLDHashOperator
   1.341 +ImplCycleCollectionTraverse_EnumFunc(K aKey,
   1.342 +                                     T aData,
   1.343 +                                     void* aUserData)
   1.344 +{
   1.345 +  nsBaseHashtableCCTraversalData* userData =
   1.346 +    static_cast<nsBaseHashtableCCTraversalData*>(aUserData);
   1.347 +
   1.348 +  CycleCollectionNoteChild(userData->mCallback,
   1.349 +                           aData,
   1.350 +                           userData->mName,
   1.351 +                           userData->mFlags);
   1.352 +  return PL_DHASH_NEXT;
   1.353 +}
   1.354 +
   1.355 +//
   1.356 +// nsBaseHashtableET definitions
   1.357 +//
   1.358 +
   1.359 +template<class KeyClass,class DataType>
   1.360 +nsBaseHashtableET<KeyClass,DataType>::nsBaseHashtableET(KeyTypePointer aKey) :
   1.361 +  KeyClass(aKey)
   1.362 +{ }
   1.363 +
   1.364 +template<class KeyClass,class DataType>
   1.365 +nsBaseHashtableET<KeyClass,DataType>::nsBaseHashtableET
   1.366 +  (nsBaseHashtableET<KeyClass,DataType>&& toMove) :
   1.367 +  KeyClass(mozilla::Move(toMove)),
   1.368 +  mData(mozilla::Move(toMove.mData))
   1.369 +{ }
   1.370 +
   1.371 +template<class KeyClass,class DataType>
   1.372 +nsBaseHashtableET<KeyClass,DataType>::~nsBaseHashtableET()
   1.373 +{ }
   1.374 +
   1.375 +
   1.376 +//
   1.377 +// nsBaseHashtable definitions
   1.378 +//
   1.379 +
   1.380 +template<class KeyClass,class DataType,class UserDataType>
   1.381 +PLDHashOperator
   1.382 +nsBaseHashtable<KeyClass,DataType,UserDataType>::s_EnumReadStub
   1.383 +  (PLDHashTable *table, PLDHashEntryHdr *hdr, uint32_t number, void* arg)
   1.384 +{
   1.385 +  EntryType* ent = static_cast<EntryType*>(hdr);
   1.386 +  s_EnumReadArgs* eargs = (s_EnumReadArgs*) arg;
   1.387 +
   1.388 +  PLDHashOperator res = (eargs->func)(ent->GetKey(), ent->mData, eargs->userArg);
   1.389 +
   1.390 +  NS_ASSERTION( !(res & PL_DHASH_REMOVE ),
   1.391 +                "PL_DHASH_REMOVE return during const enumeration; ignoring.");
   1.392 +
   1.393 +  if (res & PL_DHASH_STOP)
   1.394 +    return PL_DHASH_STOP;
   1.395 +
   1.396 +  return PL_DHASH_NEXT;
   1.397 +}
   1.398 +
   1.399 +template<class KeyClass,class DataType,class UserDataType>
   1.400 +PLDHashOperator
   1.401 +nsBaseHashtable<KeyClass,DataType,UserDataType>::s_EnumStub
   1.402 +  (PLDHashTable *table, PLDHashEntryHdr *hdr, uint32_t number, void* arg)
   1.403 +{
   1.404 +  EntryType* ent = static_cast<EntryType*>(hdr);
   1.405 +  s_EnumArgs* eargs = (s_EnumArgs*) arg;
   1.406 +
   1.407 +  return (eargs->func)(ent->GetKey(), ent->mData, eargs->userArg);
   1.408 +}
   1.409 +
   1.410 +template<class KeyClass,class DataType,class UserDataType>
   1.411 +size_t
   1.412 +nsBaseHashtable<KeyClass,DataType,UserDataType>::s_SizeOfStub
   1.413 +  (PLDHashEntryHdr *hdr, mozilla::MallocSizeOf mallocSizeOf, void *arg)
   1.414 +{
   1.415 +  EntryType* ent = static_cast<EntryType*>(hdr);
   1.416 +  s_SizeOfArgs* eargs = static_cast<s_SizeOfArgs*>(arg);
   1.417 +
   1.418 +  return (eargs->func)(ent->GetKey(), ent->mData, mallocSizeOf, eargs->userArg);
   1.419 +}
   1.420 +
   1.421 +#endif // nsBaseHashtable_h__

mercurial