OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "mojo/system/channel.h" | 5 #include "mojo/system/channel.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 DVLOG_IF(2, num_live || num_zombies) << "Shut down Channel with " << num_live | 85 DVLOG_IF(2, num_live || num_zombies) << "Shut down Channel with " << num_live |
86 << " live endpoints and " << num_zombies | 86 << " live endpoints and " << num_zombies |
87 << " zombies"; | 87 << " zombies"; |
88 } | 88 } |
89 | 89 |
90 void Channel::WillShutdownSoon() { | 90 void Channel::WillShutdownSoon() { |
91 base::AutoLock locker(lock_); | 91 base::AutoLock locker(lock_); |
92 is_shutting_down_ = true; | 92 is_shutting_down_ = true; |
93 } | 93 } |
94 | 94 |
95 MessageInTransit::EndpointId Channel::AttachMessagePipeEndpoint( | 95 // Note: |endpoint| being a |scoped_refptr| makes this function safe, since it |
96 scoped_refptr<MessagePipe> message_pipe, | 96 // keeps the endpoint alive even after the lock is released. Otherwise, there's |
97 unsigned port) { | 97 // the temptation to simply pass the result of |new ChannelEndpoint(...)| |
98 DCHECK(message_pipe.get()); | 98 // directly to this function, which wouldn't be sufficient for safety. |
99 DCHECK(port == 0 || port == 1); | 99 MessageInTransit::EndpointId Channel::AttachEndpoint( |
| 100 scoped_refptr<ChannelEndpoint> endpoint) { |
| 101 DCHECK(endpoint.get()); |
100 | 102 |
101 scoped_refptr<ChannelEndpoint> endpoint; | |
102 MessageInTransit::EndpointId local_id; | 103 MessageInTransit::EndpointId local_id; |
103 { | 104 { |
104 base::AutoLock locker(lock_); | 105 base::AutoLock locker(lock_); |
105 | 106 |
106 DLOG_IF(WARNING, is_shutting_down_) | 107 DLOG_IF(WARNING, is_shutting_down_) |
107 << "AttachMessagePipeEndpoint() while shutting down"; | 108 << "AttachMessagePipeEndpoint() while shutting down"; |
108 | 109 |
109 while (next_local_id_ == MessageInTransit::kInvalidEndpointId || | 110 while (next_local_id_ == MessageInTransit::kInvalidEndpointId || |
110 local_id_to_endpoint_map_.find(next_local_id_) != | 111 local_id_to_endpoint_map_.find(next_local_id_) != |
111 local_id_to_endpoint_map_.end()) | 112 local_id_to_endpoint_map_.end()) |
112 next_local_id_++; | 113 next_local_id_++; |
113 | 114 |
114 local_id = next_local_id_; | 115 local_id = next_local_id_; |
115 next_local_id_++; | 116 next_local_id_++; |
116 endpoint = new ChannelEndpoint(message_pipe.get(), port); | |
117 local_id_to_endpoint_map_[local_id] = endpoint; | 117 local_id_to_endpoint_map_[local_id] = endpoint; |
118 } | 118 } |
119 | 119 |
120 endpoint->AttachToChannel(this, local_id); | 120 endpoint->AttachToChannel(this, local_id); |
121 // This might fail if that port got an |OnPeerClose()| before attaching. | 121 // This might fail if that port got an |OnPeerClose()| before attaching. |
122 if (message_pipe->Attach(port, endpoint.get())) | 122 if (endpoint->message_pipe_->Attach(endpoint->port_, endpoint.get())) |
123 return local_id; | 123 return local_id; |
124 | 124 |
125 // Note: If it failed, quite possibly the endpoint info was removed from that | 125 // Note: If it failed, quite possibly the endpoint info was removed from that |
126 // map (there's a race between us adding it to the map above and calling | 126 // map (there's a race between us adding it to the map above and calling |
127 // |Attach()|). And even if an entry exists for |local_id|, we need to check | 127 // |Attach()|). And even if an entry exists for |local_id|, we need to check |
128 // that it's the one we added (and not some other one that was added since). | 128 // that it's the one we added (and not some other one that was added since). |
129 { | 129 { |
130 base::AutoLock locker(lock_); | 130 base::AutoLock locker(lock_); |
131 IdToEndpointMap::iterator it = local_id_to_endpoint_map_.find(local_id); | 131 IdToEndpointMap::iterator it = local_id_to_endpoint_map_.find(local_id); |
132 if (it != local_id_to_endpoint_map_.end() && | 132 if (it != local_id_to_endpoint_map_.end() && |
133 it->second->message_pipe_.get() == message_pipe.get() && | 133 it->second->message_pipe_.get() == endpoint->message_pipe_.get() && |
134 it->second->port_ == port) { | 134 it->second->port_ == endpoint->port_) { |
135 DCHECK_EQ(it->second->state_, ChannelEndpoint::STATE_NORMAL); | 135 DCHECK_EQ(it->second->state_, ChannelEndpoint::STATE_NORMAL); |
136 // TODO(vtl): FIXME -- This is wrong. We need to specify (to | 136 // TODO(vtl): FIXME -- This is wrong. We need to specify (to |
137 // |AttachMessagePipeEndpoint()| who's going to be responsible for calling | 137 // |AttachMessagePipeEndpoint()| who's going to be responsible for calling |
138 // |RunMessagePipeEndpoint()| ("us", or the remote by sending us a | 138 // |RunMessagePipeEndpoint()| ("us", or the remote by sending us a |
139 // |kSubtypeChannelRunMessagePipeEndpoint|). If the remote is going to | 139 // |kSubtypeChannelRunMessagePipeEndpoint|). If the remote is going to |
140 // run, then we'll get messages to an "invalid" local ID (for running, for | 140 // run, then we'll get messages to an "invalid" local ID (for running, for |
141 // removal). | 141 // removal). |
142 local_id_to_endpoint_map_.erase(it); | 142 local_id_to_endpoint_map_.erase(it); |
143 } | 143 } |
144 } | 144 } |
145 endpoint->DetachFromChannel(); | 145 endpoint->DetachFromChannel(); |
146 return MessageInTransit::kInvalidEndpointId; | 146 return MessageInTransit::kInvalidEndpointId; |
147 } | 147 } |
148 | 148 |
| 149 MessageInTransit::EndpointId Channel::AttachMessagePipeEndpoint( |
| 150 scoped_refptr<MessagePipe> message_pipe, |
| 151 unsigned port) { |
| 152 DCHECK(message_pipe.get()); |
| 153 DCHECK(port == 0 || port == 1); |
| 154 |
| 155 return AttachEndpoint( |
| 156 make_scoped_refptr(new ChannelEndpoint(message_pipe.get(), port))); |
| 157 } |
| 158 |
149 bool Channel::RunMessagePipeEndpoint(MessageInTransit::EndpointId local_id, | 159 bool Channel::RunMessagePipeEndpoint(MessageInTransit::EndpointId local_id, |
150 MessageInTransit::EndpointId remote_id) { | 160 MessageInTransit::EndpointId remote_id) { |
151 scoped_refptr<ChannelEndpoint> endpoint; | 161 scoped_refptr<ChannelEndpoint> endpoint; |
152 ChannelEndpoint::State state; | 162 ChannelEndpoint::State state; |
153 scoped_refptr<MessagePipe> message_pipe; | 163 scoped_refptr<MessagePipe> message_pipe; |
154 unsigned port; | 164 unsigned port; |
155 { | 165 { |
156 base::AutoLock locker(lock_); | 166 base::AutoLock locker(lock_); |
157 | 167 |
158 DLOG_IF(WARNING, is_shutting_down_) | 168 DLOG_IF(WARNING, is_shutting_down_) |
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
551 // TODO(vtl): Is this how we really want to handle this? | 561 // TODO(vtl): Is this how we really want to handle this? |
552 // Sometimes we'll want to propagate the error back to the message pipe | 562 // Sometimes we'll want to propagate the error back to the message pipe |
553 // (endpoint), and notify it that the remote is (effectively) closed. | 563 // (endpoint), and notify it that the remote is (effectively) closed. |
554 // Sometimes we'll want to kill the channel (and notify all the endpoints that | 564 // Sometimes we'll want to kill the channel (and notify all the endpoints that |
555 // their remotes are dead. | 565 // their remotes are dead. |
556 LOG(WARNING) << error_message; | 566 LOG(WARNING) << error_message; |
557 } | 567 } |
558 | 568 |
559 } // namespace system | 569 } // namespace system |
560 } // namespace mojo | 570 } // namespace mojo |
OLD | NEW |