netwerk/ipc/ChannelEventQueue.h

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     2  * vim: set sw=2 ts=8 et tw=80 :
     3  */
     4 /* This Source Code Form is subject to the terms of the Mozilla Public
     5  * License, v. 2.0. If a copy of the MPL was not distributed with this
     6  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     8 #ifndef mozilla_net_ChannelEventQueue_h
     9 #define mozilla_net_ChannelEventQueue_h
    11 #include <nsTArray.h>
    12 #include <nsAutoPtr.h>
    14 class nsISupports;
    15 class nsIEventTarget;
    16 class nsIThread;
    18 namespace mozilla {
    19 namespace net {
    21 class ChannelEvent
    22 {
    23  public:
    24   ChannelEvent() { MOZ_COUNT_CTOR(ChannelEvent); }
    25   virtual ~ChannelEvent() { MOZ_COUNT_DTOR(ChannelEvent); }
    26   virtual void Run() = 0;
    27 };
    29 // Workaround for Necko re-entrancy dangers. We buffer IPDL messages in a
    30 // queue if still dispatching previous one(s) to listeners/observers.
    31 // Otherwise synchronous XMLHttpRequests and/or other code that spins the
    32 // event loop (ex: IPDL rpc) could cause listener->OnDataAvailable (for
    33 // instance) to be dispatched and called before mListener->OnStartRequest has
    34 // completed.
    36 class AutoEventEnqueuerBase;
    38 class ChannelEventQueue MOZ_FINAL
    39 {
    40   NS_INLINE_DECL_REFCOUNTING(ChannelEventQueue)
    42  public:
    43   ChannelEventQueue(nsISupports *owner)
    44     : mSuspendCount(0)
    45     , mSuspended(false)
    46     , mForced(false)
    47     , mFlushing(false)
    48     , mOwner(owner) {}
    50   // Checks to determine if an IPDL-generated channel event can be processed
    51   // immediately, or needs to be queued using Enqueue().
    52   inline bool ShouldEnqueue();
    54   // Puts IPDL-generated channel event into queue, to be run later
    55   // automatically when EndForcedQueueing and/or Resume is called.
    56   inline void Enqueue(ChannelEvent* callback);
    58   // After StartForcedQueueing is called, ShouldEnqueue() will return true and
    59   // no events will be run/flushed until EndForcedQueueing is called.
    60   // - Note: queueing may still be required after EndForcedQueueing() (if the
    61   //   queue is suspended, etc):  always call ShouldEnqueue() to determine
    62   //   whether queueing is needed.
    63   inline void StartForcedQueueing();
    64   inline void EndForcedQueueing();
    66   // Suspend/resume event queue.  ShouldEnqueue() will return true and no events
    67   // will be run/flushed until resume is called.  These should be called when
    68   // the channel owning the event queue is suspended/resumed.
    69   inline void Suspend();
    70   // Resume flushes the queue asynchronously, i.e. items in queue will be
    71   // dispatched in a new event on the current thread.
    72   void Resume();
    74   // Retargets delivery of events to the target thread specified.
    75   nsresult RetargetDeliveryTo(nsIEventTarget* aTargetThread);
    77  private:
    78   // Private destructor, to discourage deletion outside of Release():
    79   ~ChannelEventQueue()
    80   {
    81   }
    83   inline void MaybeFlushQueue();
    84   void FlushQueue();
    85   inline void CompleteResume();
    87   nsTArray<nsAutoPtr<ChannelEvent> > mEventQueue;
    89   uint32_t mSuspendCount;
    90   bool     mSuspended;
    91   bool mForced;
    92   bool mFlushing;
    94   // Keep ptr to avoid refcount cycle: only grab ref during flushing.
    95   nsISupports *mOwner;
    97   // Target thread for delivery of events.
    98   nsCOMPtr<nsIThread> mTargetThread;
   100   friend class AutoEventEnqueuer;
   101 };
   103 inline bool
   104 ChannelEventQueue::ShouldEnqueue()
   105 {
   106   bool answer =  mForced || mSuspended || mFlushing;
   108   NS_ABORT_IF_FALSE(answer == true || mEventQueue.IsEmpty(),
   109                     "Should always enqueue if ChannelEventQueue not empty");
   111   return answer;
   112 }
   114 inline void
   115 ChannelEventQueue::Enqueue(ChannelEvent* callback)
   116 {
   117   mEventQueue.AppendElement(callback);
   118 }
   120 inline void
   121 ChannelEventQueue::StartForcedQueueing()
   122 {
   123   mForced = true;
   124 }
   126 inline void
   127 ChannelEventQueue::EndForcedQueueing()
   128 {
   129   mForced = false;
   130   MaybeFlushQueue();
   131 }
   133 inline void
   134 ChannelEventQueue::Suspend()
   135 {
   136   mSuspended = true;
   137   mSuspendCount++;
   138 }
   140 inline void
   141 ChannelEventQueue::CompleteResume()
   142 {
   143   // channel may have been suspended again since Resume fired event to call this.
   144   if (!mSuspendCount) {
   145     // we need to remain logically suspended (for purposes of queuing incoming
   146     // messages) until this point, else new incoming messages could run before
   147     // queued ones.
   148     mSuspended = false;
   149     MaybeFlushQueue();
   150   }
   151 }
   153 inline void
   154 ChannelEventQueue::MaybeFlushQueue()
   155 {
   156   // Don't flush if forced queuing on, we're already being flushed, or
   157   // suspended, or there's nothing to flush
   158   if (!mForced && !mFlushing && !mSuspended && !mEventQueue.IsEmpty())
   159     FlushQueue();
   160 }
   162 // Ensures that ShouldEnqueue() will be true during its lifetime (letting
   163 // caller know incoming IPDL msgs should be queued). Flushes the queue when it
   164 // goes out of scope.
   165 class AutoEventEnqueuer
   166 {
   167  public:
   168   AutoEventEnqueuer(ChannelEventQueue *queue) : mEventQueue(queue) {
   169     mEventQueue->StartForcedQueueing();
   170   }
   171   ~AutoEventEnqueuer() {
   172     mEventQueue->EndForcedQueueing();
   173   }
   174  private:
   175   ChannelEventQueue* mEventQueue;
   176 };
   178 }
   179 }
   181 #endif

mercurial