tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

transportflow.h (3214B)


      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/. */
      6 
      7 // Original author: ekr@rtfm.com
      8 
      9 #ifndef transportflow_h__
     10 #define transportflow_h__
     11 
     12 #include <deque>
     13 #include <string>
     14 
     15 #include "m_cpp_utils.h"
     16 #include "mozilla/UniquePtr.h"
     17 #include "nsISupportsImpl.h"
     18 #include "nscore.h"
     19 #include "transportlayer.h"
     20 
     21 // A stack of transport layers acts as a flow.
     22 // Generally, one reads and writes to the top layer.
     23 
     24 // This code has a confusing hybrid threading model which
     25 // probably needs some eventual refactoring.
     26 // TODO(ekr@rtfm.com): Bug 844891
     27 //
     28 // TransportFlows are not inherently bound to a thread *but*
     29 // TransportLayers can be. If any layer in a flow is bound
     30 // to a given thread, then all layers in the flow MUST be
     31 // bound to that thread and you can only manipulate the
     32 // flow (push layers, write, etc.) on that thread.
     33 //
     34 // The sole official exception to this is that you are
     35 // allowed to *destroy* a flow off the bound thread provided
     36 // that there are no listeners on its signals. This exception
     37 // is designed to allow idioms where you create the flow
     38 // and then something goes wrong and you destroy it and
     39 // you don't want to bother with a thread dispatch.
     40 //
     41 // Eventually we hope to relax the "no listeners"
     42 // restriction by thread-locking the signals, but previous
     43 // attempts have caused deadlocks.
     44 //
     45 // Most of these invariants are enforced by hard asserts
     46 // (i.e., those which fire even in production builds).
     47 
     48 namespace mozilla {
     49 
     50 class TransportFlow final : public nsISupports {
     51 public:
     52  TransportFlow()
     53      : id_("(anonymous)"), layers_(new std::deque<TransportLayer*>) {}
     54  explicit TransportFlow(const std::string id)
     55      : id_(id), layers_(new std::deque<TransportLayer*>) {}
     56 
     57  const std::string& id() const { return id_; }
     58 
     59  // Layer management. Note PushLayer() is not thread protected, so
     60  // either:
     61  // (a) Do it in the thread handling the I/O
     62  // (b) Do it before you activate the I/O system
     63  //
     64  // The flow takes ownership of the layers after a successful
     65  // push.
     66  void PushLayer(TransportLayer* layer);
     67 
     68  TransportLayer* GetLayer(const std::string& id) const;
     69 
     70  NS_DECL_THREADSAFE_ISUPPORTS
     71 
     72 private:
     73  ~TransportFlow();
     74 
     75  DISALLOW_COPY_ASSIGN(TransportFlow);
     76 
     77  // Check if we are on the right thread
     78  void CheckThread() const {
     79    if (!CheckThreadInt()) MOZ_CRASH();
     80  }
     81 
     82  bool CheckThreadInt() const {
     83    bool on;
     84 
     85    if (!target_)  // OK if no thread set.
     86      return true;
     87    if (NS_FAILED(target_->IsOnCurrentThread(&on))) return false;
     88 
     89    return on;
     90  }
     91 
     92  void EnsureSameThread(TransportLayer* layer);
     93 
     94  static void DestroyFinal(UniquePtr<std::deque<TransportLayer*>> layers);
     95 
     96  // Overload needed because we use deque internally and queue externally.
     97  static void ClearLayers(std::deque<TransportLayer*>* layers);
     98 
     99  std::string id_;
    100  UniquePtr<std::deque<TransportLayer*>> layers_;
    101  nsCOMPtr<nsIEventTarget> target_;
    102 };
    103 
    104 }  // namespace mozilla
    105 #endif