1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/threads/nsEventQueue.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,92 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim:set ts=2 sw=2 sts=2 et cindent: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef nsEventQueue_h__ 1.11 +#define nsEventQueue_h__ 1.12 + 1.13 +#include <stdlib.h> 1.14 +#include "mozilla/ReentrantMonitor.h" 1.15 +#include "nsIRunnable.h" 1.16 + 1.17 +// A threadsafe FIFO event queue... 1.18 +class nsEventQueue 1.19 +{ 1.20 + typedef mozilla::ReentrantMonitor ReentrantMonitor; 1.21 + 1.22 +public: 1.23 + nsEventQueue(); 1.24 + ~nsEventQueue(); 1.25 + 1.26 + // This method adds a new event to the pending event queue. The event object 1.27 + // is AddRef'd if this method succeeds. This method returns true if the 1.28 + // event was stored in the event queue, and it returns false if it could 1.29 + // not allocate sufficient memory. 1.30 + bool PutEvent(nsIRunnable *event); 1.31 + 1.32 + // This method gets an event from the event queue. If mayWait is true, then 1.33 + // the method will block the calling thread until an event is available. If 1.34 + // the event is null, then the method returns immediately indicating whether 1.35 + // or not an event is pending. When the resulting event is non-null, the 1.36 + // caller is responsible for releasing the event object. This method does 1.37 + // not alter the reference count of the resulting event. 1.38 + bool GetEvent(bool mayWait, nsIRunnable **event); 1.39 + 1.40 + // This method returns true if there is a pending event. 1.41 + bool HasPendingEvent() { 1.42 + return GetEvent(false, nullptr); 1.43 + } 1.44 + 1.45 + // This method returns the next pending event or null. 1.46 + bool GetPendingEvent(nsIRunnable **runnable) { 1.47 + return GetEvent(false, runnable); 1.48 + } 1.49 + 1.50 + // This method waits for and returns the next pending event. 1.51 + bool WaitPendingEvent(nsIRunnable **runnable) { 1.52 + return GetEvent(true, runnable); 1.53 + } 1.54 + 1.55 + // Expose the event queue's monitor for "power users" 1.56 + ReentrantMonitor& GetReentrantMonitor() { 1.57 + return mReentrantMonitor; 1.58 + } 1.59 + 1.60 +private: 1.61 + 1.62 + bool IsEmpty() { 1.63 + return !mHead || (mHead == mTail && mOffsetHead == mOffsetTail); 1.64 + } 1.65 + 1.66 + enum { EVENTS_PER_PAGE = 255 }; 1.67 + 1.68 + // Page objects are linked together to form a simple deque. 1.69 + 1.70 + struct Page { 1.71 + struct Page *mNext; 1.72 + nsIRunnable *mEvents[EVENTS_PER_PAGE]; 1.73 + }; 1.74 + 1.75 + static_assert((sizeof(Page) & (sizeof(Page) - 1)) == 0, 1.76 + "sizeof(Page) should be a power of two to avoid heap slop."); 1.77 + 1.78 + static Page *NewPage() { 1.79 + return static_cast<Page *>(calloc(1, sizeof(Page))); 1.80 + } 1.81 + 1.82 + static void FreePage(Page *p) { 1.83 + free(p); 1.84 + } 1.85 + 1.86 + ReentrantMonitor mReentrantMonitor; 1.87 + 1.88 + Page *mHead; 1.89 + Page *mTail; 1.90 + 1.91 + uint16_t mOffsetHead; // offset into mHead where next item is removed 1.92 + uint16_t mOffsetTail; // offset into mTail where next item is added 1.93 +}; 1.94 + 1.95 +#endif // nsEventQueue_h__