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

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: fix ipc_fuzzer build again Created 4 years, 11 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
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 int32_t id;
62 };
63
64 // We want to restrict MessageT's constructors so that a routing_id is always
65 // provided for ROUTED messages and never provided for CONTROL messages, so
66 // use the SFINAE technique from N4387's "Implementation Hint" section.
67 #if defined(COMPILER_MSVC)
68 // MSVC 2013 doesn't support default arguments for template member functions
69 // of templated classes, so there we have to rely on the DCHECKs instead.
70 // TODO(mdempsky): Reevaluate once MSVC 2015.
vmpstr 2016/02/04 23:43:27 I'm not really up to date, but is MSVC2015 here? O
mdempsky 2016/02/05 00:32:32 No idea.
danakj 2016/02/05 00:41:04 https://groups.google.com/a/chromium.org/forum/#!t
vmpstr 2016/02/05 01:24:31 My point was simply that this seems to already wor
mdempsky 2016/02/05 02:06:10 Understood. I'm going to lean towards something m
71 #define IPC_MESSAGET_SFINAE(x)
72 #else
73 #define IPC_MESSAGET_SFINAE(x) \
74 template <bool X = (x), typename std::enable_if<X, bool>::type = false>
vmpstr 2016/02/04 23:43:27 Is the extra bool X = (x) just convenience? Or doe
mdempsky 2016/02/05 00:32:32 I'm pretty sure it's necessary. I think it's beca
vmpstr 2016/02/05 01:24:31 I guess my initial concern was that if one explici
mdempsky 2016/02/05 02:06:10 I did too, but alas, that's not what the C++ commi
75 #endif
76
77 // MessageT is the common template used for all user-defined message types.
78 // It's intended to be used via the macros defined in ipc_message_macros.h.
79 template <typename Meta,
80 typename InTuple = typename Meta::InTuple,
81 typename OutTuple = typename Meta::OutTuple>
82 class MessageT;
83
84 // Asynchronous message partial specialization.
85 template <typename Meta, typename... Ins>
86 class MessageT<Meta, base::Tuple<Ins...>, void> : public Message {
87 public:
88 using Param = base::Tuple<Ins...>;
89 enum { ID = Meta::ID };
90
91 // TODO(mdempsky): Remove.
vmpstr 2016/02/04 23:43:27 Can you elaborate on this todo?
mdempsky 2016/02/05 00:32:32 Done.
92 using Schema = MessageT;
93
94 IPC_MESSAGET_SFINAE(Meta::kKind == MessageKind::CONTROL)
95 MessageT(const Ins&... ins) : MessageT(Routing{MSG_ROUTING_CONTROL}, ins...) {
vmpstr 2016/02/04 23:43:27 Is this syntax allowed? I keep being confused betw
mdempsky 2016/02/05 00:32:32 Blah, looks like still no. Done.
96 DCHECK(Meta::kKind == MessageKind::CONTROL) << Meta::kName;
97 }
98
99 IPC_MESSAGET_SFINAE(Meta::kKind == MessageKind::ROUTED)
100 MessageT(int32_t routing_id, const Ins&... ins)
101 : MessageT(Routing{routing_id}, ins...) {
102 DCHECK(Meta::kKind == MessageKind::ROUTED) << Meta::kName;
103 }
104
105 static bool Read(const Message* msg, Param* p);
106 static void Log(std::string* name, const Message* msg, std::string* l);
107
108 template <class T, class S, class P, class Method>
109 static bool Dispatch(const Message* msg,
110 T* obj,
111 S* sender,
112 P* parameter,
113 Method func) {
114 Param p;
115 if (Read(msg, &p)) {
116 DispatchToMethod(obj, func, parameter, p);
117 return true;
118 }
119 return false;
120 }
121
122 private:
123 MessageT(Routing routing, const Ins&... ins);
124 };
125
126 // Synchronous message partial specialization.
127 template <typename Meta, typename... Ins, typename... Outs>
128 class MessageT<Meta, base::Tuple<Ins...>, base::Tuple<Outs...>>
129 : public SyncMessage {
130 public:
131 using SendParam = base::Tuple<Ins...>;
132 using ReplyParam = base::Tuple<Outs...>;
133 enum { ID = Meta::ID };
134
135 // TODO(mdempsky): Remove.
136 using Schema = MessageT;
137
138 IPC_MESSAGET_SFINAE(Meta::kKind == MessageKind::CONTROL)
139 MessageT(const Ins&... ins, Outs*... outs)
140 : MessageT(Routing{MSG_ROUTING_CONTROL}, ins..., outs...) {
141 DCHECK(Meta::kKind == MessageKind::CONTROL) << Meta::kName;
142 }
143
144 IPC_MESSAGET_SFINAE(Meta::kKind == MessageKind::ROUTED)
145 MessageT(int32_t routing_id, const Ins&... ins, Outs*... outs)
146 : MessageT(Routing{routing_id}, ins..., outs...) {
147 DCHECK(Meta::kKind == MessageKind::ROUTED) << Meta::kName;
148 }
149
150 static bool ReadSendParam(const Message* msg, SendParam* p);
151 static bool ReadReplyParam(const Message* msg, ReplyParam* p);
152 static void WriteReplyParams(Message* reply, const Outs&... outs);
153 static void Log(std::string* name, const Message* msg, std::string* l);
154
155 template <class T, class S, class P, class Method>
156 static bool Dispatch(const Message* msg,
157 T* obj,
158 S* sender,
159 P* parameter,
160 Method func) {
161 SendParam send_params;
162 bool ok = ReadSendParam(msg, &send_params);
163 Message* reply = SyncMessage::GenerateReply(msg);
164 if (ok) {
165 ReplyParam reply_params;
166 base::DispatchToMethod(obj, func, send_params, &reply_params);
167 WriteParam(reply, reply_params);
168 LogReplyParamsToMessage(reply_params, msg);
169 } else {
170 NOTREACHED() << "Error deserializing message " << msg->type();
171 reply->set_reply_error();
172 }
173 sender->Send(reply);
174 return ok;
175 }
176
177 template <class T, class P, class Method>
178 static bool DispatchDelayReply(const Message* msg,
179 T* obj,
180 P* parameter,
181 Method func) {
182 SendParam send_params;
183 bool ok = ReadSendParam(msg, &send_params);
184 Message* reply = SyncMessage::GenerateReply(msg);
185 if (ok) {
186 base::Tuple<Message&> t = base::MakeRefTuple(*reply);
187 ConnectMessageAndReply(msg, reply);
188 base::DispatchToMethod(obj, func, send_params, &t);
189 } else {
190 NOTREACHED() << "Error deserializing message " << msg->type();
191 reply->set_reply_error();
192 obj->Send(reply);
193 }
194 return ok;
195 }
196
197 private:
198 MessageT(Routing routing, const Ins&... ins, Outs*... outs);
199 };
200
201 } // namespace IPC
202
203 #if defined(IPC_MESSAGE_IMPL)
204 #include "ipc/ipc_message_templates_impl.h"
205 #endif
206
207 #endif // IPC_IPC_MESSAGE_TEMPLATES_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698