dom/workers/Queue.h

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

     1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #ifndef mozilla_dom_workers_queue_h__
     7 #define mozilla_dom_workers_queue_h__
     9 #include "Workers.h"
    11 #include "mozilla/Mutex.h"
    12 #include "nsTArray.h"
    14 BEGIN_WORKERS_NAMESPACE
    16 template <typename T, int TCount>
    17 struct StorageWithTArray
    18 {
    19   typedef nsAutoTArray<T, TCount> StorageType;
    21   static void Reverse(StorageType& aStorage)
    22   {
    23     uint32_t length = aStorage.Length();
    24     for (uint32_t index = 0; index < length / 2; index++) {
    25       uint32_t reverseIndex = length - 1 - index;
    27       T t1 = aStorage.ElementAt(index);
    28       T t2 = aStorage.ElementAt(reverseIndex);
    30       aStorage.ReplaceElementsAt(index, 1, t2);
    31       aStorage.ReplaceElementsAt(reverseIndex, 1, t1);
    32     }
    33   }
    35   static bool IsEmpty(const StorageType& aStorage)
    36   {
    37     return !!aStorage.IsEmpty();
    38   }
    40   static bool Push(StorageType& aStorage, const T& aEntry)
    41   {
    42     return !!aStorage.AppendElement(aEntry);
    43   }
    45   static bool Pop(StorageType& aStorage, T& aEntry)
    46   {
    47     if (IsEmpty(aStorage)) {
    48       return false;
    49     }
    51     uint32_t index = aStorage.Length() - 1;
    52     aEntry = aStorage.ElementAt(index);
    53     aStorage.RemoveElementAt(index);
    54     return true;
    55   }
    57   static void Clear(StorageType& aStorage)
    58   {
    59     aStorage.Clear();
    60   }
    62   static void Compact(StorageType& aStorage)
    63   {
    64     aStorage.Compact();
    65   }
    66 };
    68 class LockingWithMutex
    69 {
    70   mozilla::Mutex mMutex;
    72 protected:
    73   LockingWithMutex()
    74   : mMutex("LockingWithMutex::mMutex")
    75   { }
    77   void Lock()
    78   {
    79     mMutex.Lock();
    80   }
    82   void Unlock()
    83   {
    84     mMutex.Unlock();
    85   }
    87   class AutoLock
    88   {
    89     LockingWithMutex& mHost;
    91   public:
    92     AutoLock(LockingWithMutex& aHost)
    93     : mHost(aHost)
    94     {
    95       mHost.Lock();
    96     }
    98     ~AutoLock()
    99     {
   100       mHost.Unlock();
   101     }
   102   };
   104   friend class AutoLock;
   105 };
   107 class NoLocking
   108 {
   109 protected:
   110   void Lock()
   111   { }
   113   void Unlock()
   114   { }
   116   class AutoLock
   117   {
   118   public:
   119     AutoLock(NoLocking& aHost)
   120     { }
   122     ~AutoLock()
   123     { }
   124   };
   125 };
   127 template <typename T,
   128           int TCount = 256,
   129           class LockingPolicy = NoLocking,
   130           class StoragePolicy = StorageWithTArray<T, TCount % 2 ?
   131                                                      TCount / 2 + 1 :
   132                                                      TCount / 2> >
   133 class Queue : public LockingPolicy
   134 {
   135   typedef typename StoragePolicy::StorageType StorageType;
   136   typedef typename LockingPolicy::AutoLock AutoLock;
   138   StorageType mStorage1;
   139   StorageType mStorage2;
   141   StorageType* mFront;
   142   StorageType* mBack;
   144 public:
   145   Queue()
   146   : mFront(&mStorage1), mBack(&mStorage2)
   147   { }
   149   bool IsEmpty()
   150   {
   151     AutoLock lock(*this);
   152     return StoragePolicy::IsEmpty(*mFront) &&
   153            StoragePolicy::IsEmpty(*mBack);
   154   }
   156   bool Push(const T& aEntry)
   157   {
   158     AutoLock lock(*this);
   159     return StoragePolicy::Push(*mBack, aEntry);
   160   }
   162   bool Pop(T& aEntry)
   163   {
   164     AutoLock lock(*this);
   165     if (StoragePolicy::IsEmpty(*mFront)) {
   166       StoragePolicy::Compact(*mFront);
   167       StoragePolicy::Reverse(*mBack);
   168       StorageType* tmp = mFront;
   169       mFront = mBack;
   170       mBack = tmp;
   171     }
   172     return StoragePolicy::Pop(*mFront, aEntry);
   173   }
   175   void Clear()
   176   {
   177     AutoLock lock(*this);
   178     StoragePolicy::Clear(*mFront);
   179     StoragePolicy::Clear(*mBack);
   180   }
   182   // XXX Do we need this?
   183   void Lock()
   184   {
   185     LockingPolicy::Lock();
   186   }
   188   // XXX Do we need this?
   189   void Unlock()
   190   {
   191     LockingPolicy::Unlock();
   192   }
   194 private:
   195   // Queue is not copyable.
   196   Queue(const Queue&);
   197   Queue & operator=(const Queue&);
   198 };
   200 END_WORKERS_NAMESPACE
   202 #endif /* mozilla_dom_workers_queue_h__ */

mercurial