Bumping manifests a=b2g-bump
[gecko.git] / media / mtransport / transportflow.h
blobeddff571659d0fec3447fa30ca75ea1951a9fc66
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
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.
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.
43 // Eventually we hope to relax the "no listeners"
44 // restriction by thread-locking the signals, but previous
45 // attempts have caused deadlocks.
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 explicit TransportFlow(const std::string id)
60 : id_(id),
61 state_(TransportLayer::TS_NONE),
62 layers_(new std::deque<TransportLayer *>) {}
64 const std::string& id() const { return id_; }
66 // Layer management. Note PushLayer() is not thread protected, so
67 // either:
68 // (a) Do it in the thread handling the I/O
69 // (b) Do it before you activate the I/O system
71 // The flow takes ownership of the layers after a successful
72 // push.
73 nsresult PushLayer(TransportLayer *layer);
75 // Convenience function to push multiple layers on. Layers
76 // are pushed on in the order that they are in the queue.
77 // Any failures cause the flow to become inoperable and
78 // destroys all the layers including those already pushed.
79 // TODO(ekr@rtfm.com): Change layers to be ref-counted.
80 nsresult PushLayers(nsAutoPtr<std::queue<TransportLayer *> > layers);
82 TransportLayer *top() const;
83 TransportLayer *GetLayer(const std::string& id) const;
85 // Wrappers for whatever TLayer happens to be the top layer
86 // at the time. This way you don't need to do top()->Foo().
87 TransportLayer::State state(); // Current state
88 TransportResult SendPacket(const unsigned char *data, size_t len);
90 // State has changed. Reflects the top flow.
91 sigslot::signal2<TransportFlow *, TransportLayer::State>
92 SignalStateChange;
94 // Data received on the flow
95 sigslot::signal3<TransportFlow*, const unsigned char *, size_t>
96 SignalPacketReceived;
98 bool Contains(TransportLayer *layer) const;
100 NS_DECL_THREADSAFE_ISUPPORTS
102 private:
103 ~TransportFlow();
105 DISALLOW_COPY_ASSIGN(TransportFlow);
107 // Check if we are on the right thread
108 void CheckThread() const {
109 if (!CheckThreadInt())
110 MOZ_CRASH();
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;
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_;
142 } // close namespace
143 #endif