Coverage Report

Created: 2018-09-25 14:53

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