/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 |