OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 #ifndef MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_ID_H_ | 5 #ifndef MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_ID_H_ |
6 #define MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_ID_H_ | 6 #define MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_ID_H_ |
7 | 7 |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 #include <stdint.h> | 9 #include <stdint.h> |
10 | 10 |
11 #include <ostream> | 11 #include <ostream> |
12 | 12 |
13 #include "base/containers/hash_tables.h" | 13 #include "base/containers/hash_tables.h" |
14 #include "base/gtest_prod_util.h" | 14 #include "base/gtest_prod_util.h" |
15 #include "base/macros.h" | 15 #include "base/macros.h" |
16 #include "build/build_config.h" | 16 #include "build/build_config.h" |
17 #include "mojo/edk/system/system_impl_export.h" | 17 #include "mojo/edk/system/system_impl_export.h" |
18 | 18 |
19 namespace mojo { | 19 namespace mojo { |
20 namespace system { | 20 namespace system { |
21 | 21 |
22 // ChannelEndpointId ----------------------------------------------------------- | 22 // ChannelEndpointId ----------------------------------------------------------- |
23 | 23 |
24 class LocalChannelEndpointIdGenerator; | 24 class LocalChannelEndpointIdGenerator; |
25 FORWARD_DECLARE_TEST(LocalChannelEndpointIdGeneratorTest, WrapAround); | 25 FORWARD_DECLARE_TEST(LocalChannelEndpointIdGeneratorTest, WrapAround); |
| 26 FORWARD_DECLARE_TEST(RemoteChannelEndpointIdGeneratorTest, WrapAround); |
26 | 27 |
27 // Represents an ID for an endpoint (i.e., one side of a message pipe) on a | 28 // Represents an ID for an endpoint (i.e., one side of a message pipe) on a |
28 // |Channel|. This class must be POD. | 29 // |Channel|. This class must be POD. |
29 // | 30 // |
30 // Note: The terminology "remotely allocated ID" is for destination IDs with | 31 // Note: The terminology "remote" for a |ChannelEndpointId| means a destination |
31 // respect to the receiver. I.e., a destination ID in a message is remotely | 32 // ID that was actually allocated by the sender, or similarly a source ID that |
32 // allocated if the ID was allocated by the sender (i.e., the remote side with | |
33 // respect to the receiver). Conversely, a source ID is remotely allocated if it | |
34 // was allocated by the receiver. | 33 // was allocated by the receiver. |
| 34 // |
| 35 // From the standpoint of the |Channel| with such a remote ID in its endpoint |
| 36 // table, such an ID is a "remotely-allocated local ID". From the standpoint of |
| 37 // the |Channel| allocating such a remote ID (for its peer |Channel|), it's a |
| 38 // "locally-allocated remote ID". |
35 class MOJO_SYSTEM_IMPL_EXPORT ChannelEndpointId { | 39 class MOJO_SYSTEM_IMPL_EXPORT ChannelEndpointId { |
36 public: | 40 public: |
37 ChannelEndpointId() : value_(0) {} | 41 ChannelEndpointId() : value_(0) {} |
38 ChannelEndpointId(const ChannelEndpointId& other) : value_(other.value_) {} | 42 ChannelEndpointId(const ChannelEndpointId& other) : value_(other.value_) {} |
39 | 43 |
40 // Returns the local ID to use for the first message pipe endpoint on a | 44 // Returns the local ID to use for the first message pipe endpoint on a |
41 // channel. | 45 // channel. |
42 static ChannelEndpointId GetBootstrap() { | 46 static ChannelEndpointId GetBootstrap() { return ChannelEndpointId(1); } |
43 ChannelEndpointId rv; | |
44 rv.value_ = 1; | |
45 return rv; | |
46 } | |
47 | 47 |
48 bool operator==(const ChannelEndpointId& other) const { | 48 bool operator==(const ChannelEndpointId& other) const { |
49 return value_ == other.value_; | 49 return value_ == other.value_; |
50 } | 50 } |
51 bool operator!=(const ChannelEndpointId& other) const { | 51 bool operator!=(const ChannelEndpointId& other) const { |
52 return !operator==(other); | 52 return !operator==(other); |
53 } | 53 } |
54 // So that we can be used in |std::map|, etc. | 54 // So that we can be used in |std::map|, etc. |
55 bool operator<(const ChannelEndpointId& other) const { | 55 bool operator<(const ChannelEndpointId& other) const { |
56 return value_ < other.value_; | 56 return value_ < other.value_; |
57 } | 57 } |
58 | 58 |
59 bool is_valid() const { return !!value_; } | 59 bool is_valid() const { return !!value_; } |
60 bool is_remotely_allocated() const { | 60 bool is_remote() const { return !!(value_ & kRemoteFlag); } |
61 return !!(value_ & kRemotelyAllocatedFlag); | |
62 } | |
63 uint32_t value() const { return value_; } | 61 uint32_t value() const { return value_; } |
64 | 62 |
| 63 // Flag set in |value()| if this is a remote ID. |
| 64 static const uint32_t kRemoteFlag = 0x80000000u; |
| 65 |
65 private: | 66 private: |
66 friend class LocalChannelEndpointIdGenerator; | 67 friend class LocalChannelEndpointIdGenerator; |
67 FRIEND_TEST_ALL_PREFIXES(LocalChannelEndpointIdGeneratorTest, WrapAround); | 68 FRIEND_TEST_ALL_PREFIXES(LocalChannelEndpointIdGeneratorTest, WrapAround); |
| 69 friend class RemoteChannelEndpointIdGenerator; |
| 70 FRIEND_TEST_ALL_PREFIXES(RemoteChannelEndpointIdGeneratorTest, WrapAround); |
| 71 |
| 72 explicit ChannelEndpointId(uint32_t value) : value_(value) {} |
68 | 73 |
69 uint32_t value_; | 74 uint32_t value_; |
70 | 75 |
71 static const uint32_t kRemotelyAllocatedFlag = 0x80000000u; | |
72 static const uint32_t kLocallyAllocatedMask = ~kRemotelyAllocatedFlag; | |
73 | |
74 // Copying and assignment allowed. | 76 // Copying and assignment allowed. |
75 }; | 77 }; |
76 // This wrapper should add no overhead. | 78 // This wrapper should add no overhead. |
77 // TODO(vtl): Rewrite |sizeof(uint32_t)| as |sizeof(ChannelEndpointId::value)| | 79 // TODO(vtl): Rewrite |sizeof(uint32_t)| as |sizeof(ChannelEndpointId::value)| |
78 // once we have sufficient C++11 support. | 80 // once we have sufficient C++11 support. |
79 static_assert(sizeof(ChannelEndpointId) == sizeof(uint32_t), | 81 static_assert(sizeof(ChannelEndpointId) == sizeof(uint32_t), |
80 "ChannelEndpointId has incorrect size"); | 82 "ChannelEndpointId has incorrect size"); |
81 | 83 |
82 // So logging macros and |DCHECK_EQ()|, etc. work. | 84 // So logging macros and |DCHECK_EQ()|, etc. work. |
83 inline std::ostream& operator<<(std::ostream& out, | 85 inline std::ostream& operator<<(std::ostream& out, |
84 const ChannelEndpointId& channel_endpoint_id) { | 86 const ChannelEndpointId& channel_endpoint_id) { |
85 return out << channel_endpoint_id.value(); | 87 return out << channel_endpoint_id.value(); |
86 } | 88 } |
87 | 89 |
88 // LocalChannelEndpointIdGenerator --------------------------------------------- | 90 // LocalChannelEndpointIdGenerator --------------------------------------------- |
89 | 91 |
90 // A simple generator for "new" local |ChannelEndpointId|s. It does not track | 92 // A generator for "new" local |ChannelEndpointId|s. It does not track |
91 // used/existing IDs; that must be done separately. (This class is not | 93 // used/existing IDs; that must be done separately. (This class is not |
92 // thread-safe.) | 94 // thread-safe.) |
93 class MOJO_SYSTEM_IMPL_EXPORT LocalChannelEndpointIdGenerator { | 95 class MOJO_SYSTEM_IMPL_EXPORT LocalChannelEndpointIdGenerator { |
94 public: | 96 public: |
95 LocalChannelEndpointIdGenerator() | 97 LocalChannelEndpointIdGenerator() |
96 : next_channel_endpoint_id_(ChannelEndpointId::GetBootstrap()) {} | 98 : next_(ChannelEndpointId::GetBootstrap()) {} |
97 | 99 |
98 ChannelEndpointId GetNext(); | 100 ChannelEndpointId GetNext(); |
99 | 101 |
100 private: | 102 private: |
101 FRIEND_TEST_ALL_PREFIXES(LocalChannelEndpointIdGeneratorTest, WrapAround); | 103 FRIEND_TEST_ALL_PREFIXES(LocalChannelEndpointIdGeneratorTest, WrapAround); |
102 | 104 |
103 ChannelEndpointId next_channel_endpoint_id_; | 105 ChannelEndpointId next_; |
104 | 106 |
105 DISALLOW_COPY_AND_ASSIGN(LocalChannelEndpointIdGenerator); | 107 DISALLOW_COPY_AND_ASSIGN(LocalChannelEndpointIdGenerator); |
106 }; | 108 }; |
107 | 109 |
| 110 // RemoteChannelEndpointIdGenerator -------------------------------------------- |
| 111 |
| 112 // A generator for "new" remote |ChannelEndpointId|s, for |Channel|s to |
| 113 // locally allocate remote IDs. (See the comment above |ChannelEndpointId| for |
| 114 // an explanatory note.) It does not track used/existing IDs; that must be done |
| 115 // separately. (This class is not thread-safe.) |
| 116 class MOJO_SYSTEM_IMPL_EXPORT RemoteChannelEndpointIdGenerator { |
| 117 public: |
| 118 RemoteChannelEndpointIdGenerator() : next_(ChannelEndpointId::kRemoteFlag) {} |
| 119 |
| 120 ChannelEndpointId GetNext(); |
| 121 |
| 122 private: |
| 123 FRIEND_TEST_ALL_PREFIXES(RemoteChannelEndpointIdGeneratorTest, WrapAround); |
| 124 |
| 125 ChannelEndpointId next_; |
| 126 |
| 127 DISALLOW_COPY_AND_ASSIGN(RemoteChannelEndpointIdGenerator); |
| 128 }; |
| 129 |
108 } // namespace system | 130 } // namespace system |
109 } // namespace mojo | 131 } // namespace mojo |
110 | 132 |
111 // Define "hash" functions for |ChannelEndpointId|s, so they can be used in hash | 133 // Define "hash" functions for |ChannelEndpointId|s, so they can be used in hash |
112 // tables. | 134 // tables. |
113 // TODO(vtl): Once we can use |std::unordered_{map,set}|, update this (and | 135 // TODO(vtl): Once we can use |std::unordered_{map,set}|, update this (and |
114 // remove the base/containers/hash_tables.h and build/build_config.h includes). | 136 // remove the base/containers/hash_tables.h and build/build_config.h includes). |
115 namespace BASE_HASH_NAMESPACE { | 137 namespace BASE_HASH_NAMESPACE { |
116 | 138 |
117 #if defined(COMPILER_GCC) | 139 #if defined(COMPILER_GCC) |
118 | 140 |
119 template <> | 141 template <> |
120 struct hash<mojo::system::ChannelEndpointId> { | 142 struct hash<mojo::system::ChannelEndpointId> { |
121 size_t operator()(mojo::system::ChannelEndpointId channel_endpoint_id) const { | 143 size_t operator()(mojo::system::ChannelEndpointId channel_endpoint_id) const { |
122 return static_cast<size_t>(channel_endpoint_id.value()); | 144 return static_cast<size_t>(channel_endpoint_id.value()); |
123 } | 145 } |
124 }; | 146 }; |
125 | 147 |
126 #elif defined(COMPILER_MSVC) | 148 #elif defined(COMPILER_MSVC) |
127 | 149 |
128 inline size_t hash_value(mojo::system::ChannelEndpointId channel_endpoint_id) { | 150 inline size_t hash_value(mojo::system::ChannelEndpointId channel_endpoint_id) { |
129 return static_cast<size_t>(channel_endpoint_id.value()); | 151 return static_cast<size_t>(channel_endpoint_id.value()); |
130 } | 152 } |
131 #endif | 153 #endif |
132 | 154 |
133 } // namespace BASE_HASH_NAMESPACE | 155 } // namespace BASE_HASH_NAMESPACE |
134 | 156 |
135 #endif // MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_ID_H_ | 157 #endif // MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_ID_H_ |
OLD | NEW |