Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(62)

Side by Side Diff: ipc/ipc_message_templates.h

Issue 1532053002: use variadic macros/templates in IPC message implementation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: move for real Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ipc/ipc_message_null_macros.h ('k') | ipc/ipc_message_templates_impl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef IPC_IPC_MESSAGE_TEMPLATES_H_
6 #define IPC_IPC_MESSAGE_TEMPLATES_H_
7
8 #include <stdint.h>
9
10 #include <type_traits>
11
12 #include "base/logging.h"
13 #include "base/tuple.h"
14 #include "build/build_config.h"
15 #include "ipc/ipc_message.h"
16 #include "ipc/ipc_message_utils.h"
17
18 namespace IPC {
19
20 // This function is for all the async IPCs that don't pass an extra parameter
21 // using IPC_BEGIN_MESSAGE_MAP_WITH_PARAM.
22 template <typename ObjT, typename Method, typename P, typename Tuple>
23 void DispatchToMethod(ObjT* obj, Method method, P*, const Tuple& tuple) {
24 base::DispatchToMethod(obj, method, tuple);
25 }
26
27 template <typename ObjT,
28 typename Method,
29 typename P,
30 typename Tuple,
31 size_t... Ns>
32 void DispatchToMethodImpl(ObjT* obj,
33 Method method,
34 P* parameter,
35 const Tuple& tuple,
36 base::IndexSequence<Ns...>) {
37 // TODO(mdempsky): Apply UnwrapTraits like base::DispatchToMethod?
38 (obj->*method)(parameter, base::get<Ns>(tuple)...);
39 }
40
41 // The following function is for async IPCs which have a dispatcher with an
42 // extra parameter specified using IPC_BEGIN_MESSAGE_MAP_WITH_PARAM.
43 template <typename ObjT, typename P, typename... Args, typename... Ts>
44 typename std::enable_if<sizeof...(Args) == sizeof...(Ts)>::type
45 DispatchToMethod(ObjT* obj,
46 void (ObjT::*method)(P*, Args...),
47 P* parameter,
48 const base::Tuple<Ts...>& tuple) {
49 DispatchToMethodImpl(obj, method, parameter, tuple,
50 base::MakeIndexSequence<sizeof...(Ts)>());
51 }
52
53 enum class MessageKind {
54 CONTROL,
55 ROUTED,
56 };
57
58 // Routing is a helper struct so MessageT's private common constructor has a
59 // different type signature than the public "int32_t routing_id" one.
60 struct Routing {
61 explicit Routing(int32_t id) : id(id) {}
62 int32_t id;
63 };
64
65 // We want to restrict MessageT's constructors so that a routing_id is always
66 // provided for ROUTED messages and never provided for CONTROL messages, so
67 // use the SFINAE technique from N4387's "Implementation Hint" section.
68 #if defined(COMPILER_MSVC)
69 // MSVC 2013 doesn't support default arguments for template member functions
70 // of templated classes, so there we have to rely on the DCHECKs instead.
71 // TODO(mdempsky): Reevaluate once MSVC 2015.
72 #define IPC_MESSAGET_SFINAE(x)
73 #else
74 #define IPC_MESSAGET_SFINAE(x) \
75 template <bool X = (x), typename std::enable_if<X, bool>::type = false>
76 #endif
77
78 // MessageT is the common template used for all user-defined message types.
79 // It's intended to be used via the macros defined in ipc_message_macros.h.
80 template <typename Meta,
81 typename InTuple = typename Meta::InTuple,
82 typename OutTuple = typename Meta::OutTuple>
83 class MessageT;
84
85 // Asynchronous message partial specialization.
86 template <typename Meta, typename... Ins>
87 class MessageT<Meta, base::Tuple<Ins...>, void> : public Message {
88 public:
89 using Param = base::Tuple<Ins...>;
90 enum { ID = Meta::ID };
91
92 // TODO(mdempsky): Remove. Uses of MyMessage::Schema::Param can be replaced
93 // with just MyMessage::Param.
94 using Schema = MessageT;
95
96 IPC_MESSAGET_SFINAE(Meta::kKind == MessageKind::CONTROL)
97 MessageT(const Ins&... ins) : MessageT(Routing(MSG_ROUTING_CONTROL), ins...) {
98 DCHECK(Meta::kKind == MessageKind::CONTROL) << Meta::kName;
99 }
100
101 IPC_MESSAGET_SFINAE(Meta::kKind == MessageKind::ROUTED)
102 MessageT(int32_t routing_id, const Ins&... ins)
103 : MessageT(Routing(routing_id), ins...) {
104 DCHECK(Meta::kKind == MessageKind::ROUTED) << Meta::kName;
105 }
106
107 static bool Read(const Message* msg, Param* p);
108 static void Log(std::string* name, const Message* msg, std::string* l);
109
110 template <class T, class S, class P, class Method>
111 static bool Dispatch(const Message* msg,
112 T* obj,
113 S* sender,
114 P* parameter,
115 Method func) {
116 Param p;
117 if (Read(msg, &p)) {
118 DispatchToMethod(obj, func, parameter, p);
119 return true;
120 }
121 return false;
122 }
123
124 private:
125 MessageT(Routing routing, const Ins&... ins);
126 };
127
128 // Synchronous message partial specialization.
129 template <typename Meta, typename... Ins, typename... Outs>
130 class MessageT<Meta, base::Tuple<Ins...>, base::Tuple<Outs...>>
131 : public SyncMessage {
132 public:
133 using SendParam = base::Tuple<Ins...>;
134 using ReplyParam = base::Tuple<Outs...>;
135 enum { ID = Meta::ID };
136
137 // TODO(mdempsky): Remove. Uses of MyMessage::Schema::{Send,Reply}Param can
138 // be replaced with just MyMessage::{Send,Reply}Param.
139 using Schema = MessageT;
140
141 IPC_MESSAGET_SFINAE(Meta::kKind == MessageKind::CONTROL)
142 MessageT(const Ins&... ins, Outs*... outs)
143 : MessageT(Routing(MSG_ROUTING_CONTROL), ins..., outs...) {
144 DCHECK(Meta::kKind == MessageKind::CONTROL) << Meta::kName;
145 }
146
147 IPC_MESSAGET_SFINAE(Meta::kKind == MessageKind::ROUTED)
148 MessageT(int32_t routing_id, const Ins&... ins, Outs*... outs)
149 : MessageT(Routing(routing_id), ins..., outs...) {
150 DCHECK(Meta::kKind == MessageKind::ROUTED) << Meta::kName;
151 }
152
153 static bool ReadSendParam(const Message* msg, SendParam* p);
154 static bool ReadReplyParam(const Message* msg, ReplyParam* p);
155 static void WriteReplyParams(Message* reply, const Outs&... outs);
156 static void Log(std::string* name, const Message* msg, std::string* l);
157
158 template <class T, class S, class P, class Method>
159 static bool Dispatch(const Message* msg,
160 T* obj,
161 S* sender,
162 P* parameter,
163 Method func) {
164 SendParam send_params;
165 bool ok = ReadSendParam(msg, &send_params);
166 Message* reply = SyncMessage::GenerateReply(msg);
167 if (ok) {
168 ReplyParam reply_params;
169 base::DispatchToMethod(obj, func, send_params, &reply_params);
170 WriteParam(reply, reply_params);
171 LogReplyParamsToMessage(reply_params, msg);
172 } else {
173 NOTREACHED() << "Error deserializing message " << msg->type();
174 reply->set_reply_error();
175 }
176 sender->Send(reply);
177 return ok;
178 }
179
180 template <class T, class P, class Method>
181 static bool DispatchDelayReply(const Message* msg,
182 T* obj,
183 P* parameter,
184 Method func) {
185 SendParam send_params;
186 bool ok = ReadSendParam(msg, &send_params);
187 Message* reply = SyncMessage::GenerateReply(msg);
188 if (ok) {
189 base::Tuple<Message&> t = base::MakeRefTuple(*reply);
190 ConnectMessageAndReply(msg, reply);
191 base::DispatchToMethod(obj, func, send_params, &t);
192 } else {
193 NOTREACHED() << "Error deserializing message " << msg->type();
194 reply->set_reply_error();
195 obj->Send(reply);
196 }
197 return ok;
198 }
199
200 private:
201 MessageT(Routing routing, const Ins&... ins, Outs*... outs);
202 };
203
204 } // namespace IPC
205
206 #if defined(IPC_MESSAGE_IMPL)
207 #include "ipc/ipc_message_templates_impl.h"
208 #endif
209
210 #endif // IPC_IPC_MESSAGE_TEMPLATES_H_
OLDNEW
« no previous file with comments | « ipc/ipc_message_null_macros.h ('k') | ipc/ipc_message_templates_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698