media/mtransport/transportflow.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ts=2 et sw=2 tw=80: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     5  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 // Original author: ekr@rtfm.com
     9 #ifndef transportflow_h__
    10 #define transportflow_h__
    12 #include <deque>
    13 #include <queue>
    14 #include <string>
    16 #include "nscore.h"
    17 #include "nsISupportsImpl.h"
    18 #include "mozilla/Scoped.h"
    19 #include "transportlayer.h"
    20 #include "m_cpp_utils.h"
    21 #include "nsAutoPtr.h"
    23 // A stack of transport layers acts as a flow.
    24 // Generally, one reads and writes to the top layer.
    26 // This code has a confusing hybrid threading model which
    27 // probably needs some eventual refactoring.
    28 // TODO(ekr@rtfm.com): Bug 844891
    29 //
    30 // TransportFlows are not inherently bound to a thread *but*
    31 // TransportLayers can be. If any layer in a flow is bound
    32 // to a given thread, then all layers in the flow MUST be
    33 // bound to that thread and you can only manipulate the
    34 // flow (push layers, write, etc.) on that thread.
    35 //
    36 // The sole official exception to this is that you are
    37 // allowed to *destroy* a flow off the bound thread provided
    38 // that there are no listeners on its signals. This exception
    39 // is designed to allow idioms where you create the flow
    40 // and then something goes wrong and you destroy it and
    41 // you don't want to bother with a thread dispatch.
    42 //
    43 // Eventually we hope to relax the "no listeners"
    44 // restriction by thread-locking the signals, but previous
    45 // attempts have caused deadlocks.
    46 //
    47 // Most of these invariants are enforced by hard asserts
    48 // (i.e., those which fire even in production builds).
    50 namespace mozilla {
    52 class TransportFlow : public nsISupports,
    53                       public sigslot::has_slots<> {
    54  public:
    55   TransportFlow()
    56     : id_("(anonymous)"),
    57       state_(TransportLayer::TS_NONE),
    58       layers_(new std::deque<TransportLayer *>) {}
    59   TransportFlow(const std::string id)
    60     : id_(id),
    61       state_(TransportLayer::TS_NONE),
    62       layers_(new std::deque<TransportLayer *>) {}
    64   ~TransportFlow();
    66   const std::string& id() const { return id_; }
    68   // Layer management. Note PushLayer() is not thread protected, so
    69   // either:
    70   // (a) Do it in the thread handling the I/O
    71   // (b) Do it before you activate the I/O system
    72   //
    73   // The flow takes ownership of the layers after a successful
    74   // push.
    75   nsresult PushLayer(TransportLayer *layer);
    77   // Convenience function to push multiple layers on. Layers
    78   // are pushed on in the order that they are in the queue.
    79   // Any failures cause the flow to become inoperable and
    80   // destroys all the layers including those already pushed.
    81   // TODO(ekr@rtfm.com): Change layers to be ref-counted.
    82   nsresult PushLayers(nsAutoPtr<std::queue<TransportLayer *> > layers);
    84   TransportLayer *top() const;
    85   TransportLayer *GetLayer(const std::string& id) const;
    87   // Wrappers for whatever TLayer happens to be the top layer
    88   // at the time. This way you don't need to do top()->Foo().
    89   TransportLayer::State state(); // Current state
    90   TransportResult SendPacket(const unsigned char *data, size_t len);
    92   // State has changed. Reflects the top flow.
    93   sigslot::signal2<TransportFlow *, TransportLayer::State>
    94     SignalStateChange;
    96   // Data received on the flow
    97   sigslot::signal3<TransportFlow*, const unsigned char *, size_t>
    98     SignalPacketReceived;
   100   bool Contains(TransportLayer *layer) const;
   102   NS_DECL_THREADSAFE_ISUPPORTS
   104  private:
   105   DISALLOW_COPY_ASSIGN(TransportFlow);
   107   // Check if we are on the right thread
   108   void CheckThread() const {
   109     if (!CheckThreadInt())
   110       MOZ_CRASH();
   111   }
   113   bool CheckThreadInt() const {
   114     bool on;
   116     if (!target_)  // OK if no thread set.
   117       return true;
   118     if (NS_FAILED(target_->IsOnCurrentThread(&on)))
   119       return false;
   121     return on;
   122   }
   124   void EnsureSameThread(TransportLayer *layer);
   126   void StateChange(TransportLayer *layer, TransportLayer::State state);
   127   void StateChangeInt(TransportLayer::State state);
   128   void PacketReceived(TransportLayer* layer, const unsigned char *data,
   129       size_t len);
   130   static void DestroyFinal(nsAutoPtr<std::deque<TransportLayer *> > layers);
   132   // Overload needed because we use deque internally and queue externally.
   133   static void ClearLayers(std::deque<TransportLayer *>* layers);
   134   static void ClearLayers(std::queue<TransportLayer *>* layers);
   136   std::string id_;
   137   TransportLayer::State state_;
   138   ScopedDeletePtr<std::deque<TransportLayer *> > layers_;
   139   nsCOMPtr<nsIEventTarget> target_;
   140 };
   142 }  // close namespace
   143 #endif

mercurial