123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554 |
- // Copyright (c) 2012 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- // Defining IPC Messages
- //
- // Your IPC messages will be defined by macros inside of an XXX_messages.h
- // header file. Most of the time, the system can automatically generate all
- // of messaging mechanism from these definitions, but sometimes some manual
- // coding is required. In these cases, you will also have an XXX_messages.cc
- // implementation file as well.
- //
- // The senders of your messages will include your XXX_messages.h file to
- // get the full set of definitions they need to send your messages.
- //
- // Each XXX_messages.h file must be registered with the IPC system. This
- // requires adding two things:
- // - An XXXMsgStart value to the IPCMessageStart enum in ipc_message_start.h
- // - An inclusion of XXX_messages.h file in a message generator .h file
- //
- // The XXXMsgStart value is an enumeration that ensures uniqueness for
- // each different message file. Later, you will use this inside your
- // XXX_messages.h file before invoking message declaration macros:
- // #define IPC_MESSAGE_START XXXMsgStart
- // ( ... your macro invocations go here ... )
- //
- // Message Generator Files
- //
- // A message generator .h header file pulls in all other message-declaring
- // headers for a given component. It is included by a message generator
- // .cc file, which is where all the generated code will wind up. Typically,
- // you will use an existing generator (e.g. common_message_generator.cc
- // in /chrome/common), but there are circumstances where you may add a
- // new one.
- //
- // In the rare circumstances where you can't re-use an existing file,
- // your YYY_message_generator.cc file for a component YYY would contain
- // the following code:
- // // Get basic type definitions.
- // #define IPC_MESSAGE_IMPL
- // #include "path/to/YYY_message_generator.h"
- // // Generate constructors.
- // #include "ipc/struct_constructor_macros.h"
- // #include "path/to/YYY_message_generator.h"
- // // Generate param traits write methods.
- // #include "ipc/param_traits_write_macros.h"
- // namespace IPC {
- // #include "path/to/YYY_message_generator.h"
- // } // namespace IPC
- // // Generate param traits read methods.
- // #include "ipc/param_traits_read_macros.h"
- // namespace IPC {
- // #include "path/to/YYY_message_generator.h"
- // } // namespace IPC
- // // Generate param traits log methods.
- // #include "ipc/param_traits_log_macros.h"
- // namespace IPC {
- // #include "path/to/YYY_message_generator.h"
- // } // namespace IPC
- //
- // In cases where manual generation is required, in your XXX_messages.cc
- // file, put the following after all the includes for param types:
- // #define IPC_MESSAGE_IMPL
- // #include "XXX_messages.h"
- // (... implementation of traits not auto-generated ...)
- //
- // Multiple Inclusion
- //
- // The XXX_messages.h file will be multiply-included by the
- // YYY_message_generator.cc file, so your XXX_messages file can't be
- // guarded in the usual manner. Ideally, there will be no need for any
- // inclusion guard, since the XXX_messages.h file should consist solely
- // of inclusions of other headers (which are self-guarding) and IPC
- // macros (which are multiply evaluating).
- //
- // Note that #pragma once cannot be used here; doing so would mark the whole
- // file as being singly-included. Since your XXX_messages.h file is only
- // partially-guarded, care must be taken to ensure that it is only included
- // by other .cc files (and the YYY_message_generator.h file). Including an
- // XXX_messages.h file in some other .h file may result in duplicate
- // declarations and a compilation failure.
- //
- // Type Declarations
- //
- // It is generally a bad idea to have type definitions in a XXX_messages.h
- // file; most likely the typedef will then be used in the message, as opposed
- // to the struct itself. Later, an IPC message dispatcher will need to call
- // a function taking that type, and that function is declared in some other
- // header. Thus, in order to get the type definition, the other header
- // would have to include the XXX_messages.h file, violating the rule above
- // about not including XXX_messages.h file in other .h files.
- //
- // One approach here is to move these type definitions to another (guarded)
- // .h file and include this second .h in your XXX_messages.h file. This
- // is still less than ideal, because the dispatched function would have to
- // redeclare the typedef or include this second header. This may be
- // reasonable in a few cases.
- //
- // Failing all of the above, then you will want to bracket the smallest
- // possible section of your XXX_messages.h file containing these types
- // with an include guard macro. Be aware that providing an incomplete
- // class type declaration to avoid pulling in a long chain of headers is
- // acceptable when your XXX_messages.h header is being included by the
- // message sending caller's code, but not when the YYY_message_generator.c
- // is building the messages. In addition, due to the multiple inclusion
- // restriction, these type ought to be guarded. Follow a convention like:
- // #ifndef SOME_GUARD_MACRO
- // #define SOME_GUARD_MACRO
- // class some_class; // One incomplete class declaration
- // class_some_other_class; // Another incomplete class declaration
- // #endif // SOME_GUARD_MACRO
- // #ifdef IPC_MESSAGE_IMPL
- // #include "path/to/some_class.h" // Full class declaration
- // #include "path/to/some_other_class.h" // Full class declaration
- // #endif // IPC_MESSAGE_IMPL
- // (.. IPC macros using some_class and some_other_class ...)
- //
- // Macro Invocations
- //
- // You will use IPC message macro invocations for three things:
- // - New struct definitions for IPC
- // - Registering existing struct and enum definitions with IPC
- // - Defining the messages themselves
- //
- // New structs are defined with IPC_STRUCT_BEGIN(), IPC_STRUCT_MEMBER(),
- // IPC_STRUCT_END() family of macros. These cause the XXX_messages.h
- // to proclaim equivalent struct declarations for use by callers, as well
- // as later registering the type with the message generation. Note that
- // IPC_STRUCT_MEMBER() is only permitted inside matching calls to
- // IPC_STRUCT_BEGIN() / IPC_STRUCT_END(). There is also an
- // IPC_STRUCT_BEGIN_WITH_PARENT(), which behaves like IPC_STRUCT_BEGIN(),
- // but also accommodates structs that inherit from other structs.
- //
- // Externally-defined structs are registered with IPC_STRUCT_TRAITS_BEGIN(),
- // IPC_STRUCT_TRAITS_MEMBER(), and IPC_STRUCT_TRAITS_END() macros. These
- // cause registration of the types with message generation only.
- // There's also IPC_STRUCT_TRAITS_PARENT, which is used to register a parent
- // class (whose own traits are already defined). Note that
- // IPC_STRUCT_TRAITS_MEMBER() and IPC_STRUCT_TRAITS_PARENT are only permitted
- // inside matching calls to IPC_STRUCT_TRAITS_BEGIN() /
- // IPC_STRUCT_TRAITS_END().
- //
- // Enum types are registered with a single IPC_ENUM_TRAITS_VALIDATE() macro.
- // There is no need to enumerate each value to the IPC mechanism. Instead,
- // pass an expression in terms of the parameter |value| to provide
- // range-checking. For convenience, the IPC_ENUM_TRAITS() is provided which
- // performs no checking, passing everything including out-of-range values.
- // Its use is discouraged. The IPC_ENUM_TRAITS_MAX_VALUE() macro can be used
- // for the typical case where the enum must be in the range 0..maxvalue
- // inclusive. The IPC_ENUM_TRAITS_MIN_MAX_VALUE() macro can be used for the
- // less typical case where the enum must be in the range minvalue..maxvalue
- // inclusive.
- //
- // Do not place semicolons following these IPC_ macro invocations. There
- // is no reason to expect that their expansion corresponds one-to-one with
- // C++ statements.
- //
- // Once the types have been declared / registered, message definitions follow.
- // "Sync" messages are just synchronous calls, the Send() call doesn't return
- // until a reply comes back. To declare a sync message, use the IPC_SYNC_
- // macros. The numbers at the end show how many input/output parameters there
- // are (i.e. 1_2 is 1 in, 2 out). Input parameters are first, followed by
- // output parameters. The caller uses Send([route id, ], in1, &out1, &out2).
- // The receiver's handler function will be
- // void OnSyncMessageName(const type1& in1, type2* out1, type3* out2)
- //
- // A caller can also send a synchronous message, while the receiver can respond
- // at a later time. This is transparent from the sender's side. The receiver
- // needs to use a different handler that takes in a IPC::Message* as the output
- // type, stash the message, and when it has the data it can Send the message.
- //
- // Use the IPC_MESSAGE_HANDLER_DELAY_REPLY macro instead of IPC_MESSAGE_HANDLER
- // IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_SyncMessageName,
- // OnSyncMessageName)
- // Unlike IPC_MESSAGE_HANDLER which works with IPC_BEGIN_MESSAGE_MAP as well as
- // IPC_BEGIN_MESSAGE_MAP_WITH_PARAM, one needs to use
- // IPC_MESSAGE_HANDLER_WITH_PARAM_DELAY_REPLY to properly handle the param.
- //
- // The handler function will look like:
- // void OnSyncMessageName(const type1& in1, IPC::Message* reply_msg);
- //
- // Receiver stashes the IPC::Message* pointer, and when it's ready, it does:
- // ViewHostMsg_SyncMessageName::WriteReplyParams(reply_msg, out1, out2);
- // Send(reply_msg);
- // Files that want to export their ipc messages should do
- // #undef IPC_MESSAGE_EXPORT
- // #define IPC_MESSAGE_EXPORT VISIBILITY_MACRO
- // after including this header, but before using any of the macros below.
- // (This needs to be before the include guard.)
- #undef IPC_MESSAGE_EXPORT
- #define IPC_MESSAGE_EXPORT
- #ifndef IPC_IPC_MESSAGE_MACROS_H_
- #define IPC_IPC_MESSAGE_MACROS_H_
- #include <stdint.h>
- #include <tuple>
- #include "base/export_template.h"
- #include "base/hash/md5_constexpr.h"
- #include "base/notreached.h"
- #include "base/task/common/task_annotator.h"
- #include "ipc/ipc_message_templates.h"
- #include "ipc/ipc_message_utils.h"
- #include "ipc/param_traits_macros.h"
- // Convenience macro for defining structs without inheritance. Should not need
- // to be subsequently redefined.
- #define IPC_STRUCT_BEGIN(struct_name) \
- IPC_STRUCT_BEGIN_WITH_PARENT(struct_name, IPC::NoParams)
- // Macros for defining structs. Will be subsequently redefined.
- #define IPC_STRUCT_BEGIN_WITH_PARENT(struct_name, parent) \
- struct struct_name; \
- IPC_STRUCT_TRAITS_BEGIN(struct_name) \
- IPC_STRUCT_TRAITS_END() \
- struct IPC_MESSAGE_EXPORT struct_name : parent { \
- struct_name();
- // Optional variadic parameters specify the default value for this struct
- // member. They are passed through to the constructor for |type|.
- #define IPC_STRUCT_MEMBER(type, name, ...) type name;
- #define IPC_STRUCT_END() };
- // Message macros collect arguments and funnel them into the common message
- // generation macro. These should never be redefined.
- // Asynchronous messages have only in parameters and are declared like:
- // IPC_MESSAGE_CONTROL(FooMsg, int, float)
- #define IPC_MESSAGE_CONTROL(msg_class, ...) \
- IPC_MESSAGE_DECL(msg_class, CONTROL, IPC_TUPLE(__VA_ARGS__), void)
- #define IPC_MESSAGE_ROUTED(msg_class, ...) \
- IPC_MESSAGE_DECL(msg_class, ROUTED, IPC_TUPLE(__VA_ARGS__), void)
- // Synchronous messages have both in and out parameters, so the lists need to
- // be parenthesized to disambiguate:
- // IPC_SYNC_MESSAGE_CONTROL(BarMsg, (int, int), (bool))
- //
- // Implementation detail: The parentheses supplied by the caller for
- // disambiguation are also used to trigger the IPC_TUPLE invocations below,
- // so "IPC_TUPLE in" and "IPC_TUPLE out" are intentional.
- #define IPC_SYNC_MESSAGE_CONTROL(msg_class, in, out) \
- IPC_MESSAGE_DECL(msg_class, CONTROL, IPC_TUPLE in, IPC_TUPLE out)
- #define IPC_SYNC_MESSAGE_ROUTED(msg_class, in, out) \
- IPC_MESSAGE_DECL(msg_class, ROUTED, IPC_TUPLE in, IPC_TUPLE out)
- #define IPC_TUPLE(...) IPC::CheckedTuple<__VA_ARGS__>::Tuple
- #define IPC_MESSAGE_DECL(msg_name, kind, in_tuple, out_tuple) \
- struct IPC_MESSAGE_EXPORT msg_name##_Meta { \
- using InTuple = in_tuple; \
- using OutTuple = out_tuple; \
- enum { ID = IPC_MESSAGE_ID() }; \
- static const IPC::MessageKind kKind = IPC::MessageKind::kind; \
- static const char kName[]; \
- }; \
- extern template class EXPORT_TEMPLATE_DECLARE(IPC_MESSAGE_EXPORT) \
- IPC::MessageT<msg_name##_Meta>; \
- using msg_name = IPC::MessageT<msg_name##_Meta>; \
- IPC_MESSAGE_EXTRA(msg_name)
- #if defined(IPC_MESSAGE_IMPL)
- // "Implementation" inclusion provides the explicit template definition
- // for msg_name.
- #define IPC_MESSAGE_EXTRA(msg_name) \
- const char msg_name##_Meta::kName[] = #msg_name; \
- IPC_MESSAGE_DEFINE_KIND(msg_name) \
- template class EXPORT_TEMPLATE_DEFINE(IPC_MESSAGE_EXPORT) \
- IPC::MessageT<msg_name##_Meta>;
- #define IPC_MESSAGE_DEFINE_KIND(msg_name) \
- const IPC::MessageKind msg_name##_Meta::kKind;
- #elif defined(IPC_MESSAGE_MACROS_LOG_ENABLED)
- #ifndef IPC_LOG_TABLE_ADD_ENTRY
- #error You need to define IPC_LOG_TABLE_ADD_ENTRY(msg_id, logger)
- #endif
- // "Log table" inclusion produces extra logging registration code.
- #define IPC_MESSAGE_EXTRA(msg_name) \
- class LoggerRegisterHelper##msg_name { \
- public: \
- LoggerRegisterHelper##msg_name() { \
- const uint32_t msg_id = static_cast<uint32_t>(msg_name::ID); \
- IPC_LOG_TABLE_ADD_ENTRY(msg_id, msg_name::Log); \
- } \
- }; \
- LoggerRegisterHelper##msg_name g_LoggerRegisterHelper##msg_name;
- #else
- // Normal inclusion produces nothing extra.
- #define IPC_MESSAGE_EXTRA(msg_name)
- #endif // defined(IPC_MESSAGE_IMPL)
- // Message IDs
- // Note: we currently use __LINE__ to give unique IDs to messages within
- // a file. They're globally unique since each file defines its own
- // IPC_MESSAGE_START.
- #define IPC_MESSAGE_ID() ((IPC_MESSAGE_START << 16) + __LINE__)
- #define IPC_MESSAGE_ID_CLASS(id) ((id) >> 16)
- #define IPC_MESSAGE_ID_LINE(id) ((id) & 0xffff)
- // Message crackers and handlers. Usage:
- //
- // bool MyClass::OnMessageReceived(const IPC::Message& msg) {
- // bool handled = true;
- // IPC_BEGIN_MESSAGE_MAP(MyClass, msg)
- // IPC_MESSAGE_HANDLER(MsgClassOne, OnMsgClassOne)
- // ...more handlers here ...
- // IPC_MESSAGE_HANDLER(MsgClassTen, OnMsgClassTen)
- // IPC_MESSAGE_UNHANDLED(handled = false)
- // IPC_END_MESSAGE_MAP()
- // return handled;
- // }
- #define IPC_TASK_ANNOTATOR_STRINGIFY(s) #s
- // A macro to be used from within the IPC_MESSAGE_FORWARD macros, for providing
- // the IPC message context to the TaskAnnotator. This allows posted tasks to be
- // associated with the incoming IPC message that caused them to be posted.
- #define IPC_TASK_ANNOTATOR_CONTEXT(msg_class) \
- static constexpr uint32_t kMessageHash = \
- base::MD5Hash32Constexpr(IPC_TASK_ANNOTATOR_STRINGIFY(msg_class)); \
- base::TaskAnnotator::ScopedSetIpcHash scoped_ipc_hash(kMessageHash);
- #define IPC_BEGIN_MESSAGE_MAP(class_name, msg) \
- { \
- using _IpcMessageHandlerClass [[maybe_unused]] = class_name; \
- [[maybe_unused]] void* param__ = nullptr; \
- const IPC::Message& ipc_message__ = msg; \
- switch (ipc_message__.type()) {
- #define IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(class_name, msg, param) \
- { \
- using _IpcMessageHandlerClass [[maybe_unused]] = class_name; \
- decltype(param) param__ = param; \
- const IPC::Message& ipc_message__ = msg; \
- switch (ipc_message__.type()) {
- #define IPC_MESSAGE_FORWARD(msg_class, obj, member_func) \
- case msg_class::ID: { \
- IPC_TASK_ANNOTATOR_CONTEXT(msg_class) \
- if (!msg_class::Dispatch(&ipc_message__, obj, this, param__, \
- &member_func)) \
- ipc_message__.set_dispatch_error(); \
- } break;
- #define IPC_MESSAGE_HANDLER(msg_class, member_func) \
- IPC_MESSAGE_FORWARD(msg_class, this, _IpcMessageHandlerClass::member_func)
- #define IPC_MESSAGE_FORWARD_DELAY_REPLY(msg_class, obj, member_func) \
- case msg_class::ID: { \
- IPC_TASK_ANNOTATOR_CONTEXT(msg_class) \
- if (!msg_class::DispatchDelayReply(&ipc_message__, obj, param__, \
- &member_func)) \
- ipc_message__.set_dispatch_error(); \
- } break;
- #define IPC_MESSAGE_HANDLER_DELAY_REPLY(msg_class, member_func) \
- IPC_MESSAGE_FORWARD_DELAY_REPLY(msg_class, this, \
- _IpcMessageHandlerClass::member_func)
- #define IPC_MESSAGE_FORWARD_WITH_PARAM_DELAY_REPLY(msg_class, obj, \
- member_func) \
- case msg_class::ID: { \
- IPC_TASK_ANNOTATOR_CONTEXT(msg_class) \
- if (!msg_class::DispatchWithParamDelayReply(&ipc_message__, obj, \
- param__, \ & member_func)) \
- ipc_message__.set_dispatch_error(); \
- } break;
- #define IPC_MESSAGE_HANDLER_WITH_PARAM_DELAY_REPLY(msg_class, member_func) \
- IPC_MESSAGE_FORWARD_WITH_PARAM_DELAY_REPLY( \
- msg_class, this, _IpcMessageHandlerClass::member_func)
- #define IPC_MESSAGE_HANDLER_GENERIC(msg_class, code) \
- case msg_class::ID: { \
- IPC_TASK_ANNOTATOR_CONTEXT(msg_class) { code; } \
- } break;
- #define IPC_REPLY_HANDLER(func) \
- case IPC_REPLY_ID: { \
- func(ipc_message__); \
- } \
- break;
- #define IPC_MESSAGE_UNHANDLED(code) \
- default: { \
- code; \
- } \
- break;
- #define IPC_MESSAGE_UNHANDLED_ERROR() \
- IPC_MESSAGE_UNHANDLED(NOTREACHED() << \
- "Invalid message with type = " << \
- ipc_message__.type())
- #define IPC_END_MESSAGE_MAP() \
- } \
- }
- // This corresponds to an enum value from IPCMessageStart.
- #define IPC_MESSAGE_CLASS(message) IPC_MESSAGE_ID_CLASS((message).type())
- // Deprecated legacy macro names.
- // TODO(mdempsky): Replace uses with generic names.
- #define IPC_MESSAGE_CONTROL0(msg) IPC_MESSAGE_CONTROL(msg)
- #define IPC_MESSAGE_CONTROL1(msg, a) IPC_MESSAGE_CONTROL(msg, a)
- #define IPC_MESSAGE_CONTROL2(msg, a, b) IPC_MESSAGE_CONTROL(msg, a, b)
- #define IPC_MESSAGE_CONTROL3(msg, a, b, c) IPC_MESSAGE_CONTROL(msg, a, b, c)
- #define IPC_MESSAGE_CONTROL4(msg, a, b, c, d) \
- IPC_MESSAGE_CONTROL(msg, a, b, c, d)
- #define IPC_MESSAGE_CONTROL5(msg, a, b, c, d, e) \
- IPC_MESSAGE_CONTROL(msg, a, b, c, d, e)
- #define IPC_MESSAGE_ROUTED0(msg) IPC_MESSAGE_ROUTED(msg)
- #define IPC_MESSAGE_ROUTED1(msg, a) IPC_MESSAGE_ROUTED(msg, a)
- #define IPC_MESSAGE_ROUTED2(msg, a, b) IPC_MESSAGE_ROUTED(msg, a, b)
- #define IPC_MESSAGE_ROUTED3(msg, a, b, c) IPC_MESSAGE_ROUTED(msg, a, b, c)
- #define IPC_MESSAGE_ROUTED4(msg, a, b, c, d) IPC_MESSAGE_ROUTED(msg, a, b, c, d)
- #define IPC_MESSAGE_ROUTED5(msg, a, b, c, d, e) \
- IPC_MESSAGE_ROUTED(msg, a, b, c, d, e)
- #define IPC_SYNC_MESSAGE_CONTROL0_0(msg) IPC_SYNC_MESSAGE_CONTROL(msg, (), ())
- #define IPC_SYNC_MESSAGE_CONTROL0_1(msg, a) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (), (a))
- #define IPC_SYNC_MESSAGE_CONTROL0_2(msg, a, b) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (), (a, b))
- #define IPC_SYNC_MESSAGE_CONTROL0_3(msg, a, b, c) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (), (a, b, c))
- #define IPC_SYNC_MESSAGE_CONTROL0_4(msg, a, b, c, d) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (), (a, b, c, d))
- #define IPC_SYNC_MESSAGE_CONTROL1_0(msg, a) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (a), ())
- #define IPC_SYNC_MESSAGE_CONTROL1_1(msg, a, b) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (a), (b))
- #define IPC_SYNC_MESSAGE_CONTROL1_2(msg, a, b, c) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (a), (b, c))
- #define IPC_SYNC_MESSAGE_CONTROL1_3(msg, a, b, c, d) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (a), (b, c, d))
- #define IPC_SYNC_MESSAGE_CONTROL1_4(msg, a, b, c, d, e) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (a), (b, c, d, e))
- #define IPC_SYNC_MESSAGE_CONTROL2_0(msg, a, b) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (a, b), ())
- #define IPC_SYNC_MESSAGE_CONTROL2_1(msg, a, b, c) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (a, b), (c))
- #define IPC_SYNC_MESSAGE_CONTROL2_2(msg, a, b, c, d) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (a, b), (c, d))
- #define IPC_SYNC_MESSAGE_CONTROL2_3(msg, a, b, c, d, e) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (a, b), (c, d, e))
- #define IPC_SYNC_MESSAGE_CONTROL2_4(msg, a, b, c, d, e, f) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (a, b), (c, d, e, f))
- #define IPC_SYNC_MESSAGE_CONTROL3_0(msg, a, b, c) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c), ())
- #define IPC_SYNC_MESSAGE_CONTROL3_1(msg, a, b, c, d) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c), (d))
- #define IPC_SYNC_MESSAGE_CONTROL3_2(msg, a, b, c, d, e) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c), (d, e))
- #define IPC_SYNC_MESSAGE_CONTROL3_3(msg, a, b, c, d, e, f) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c), (d, e, f))
- #define IPC_SYNC_MESSAGE_CONTROL3_4(msg, a, b, c, d, e, f, g) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c), (d, e, f, g))
- #define IPC_SYNC_MESSAGE_CONTROL4_0(msg, a, b, c, d) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c, d), ())
- #define IPC_SYNC_MESSAGE_CONTROL4_1(msg, a, b, c, d, e) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c, d), (e))
- #define IPC_SYNC_MESSAGE_CONTROL4_2(msg, a, b, c, d, e, f) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c, d), (e, f))
- #define IPC_SYNC_MESSAGE_CONTROL4_3(msg, a, b, c, d, e, f, g) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c, d), (e, f, g))
- #define IPC_SYNC_MESSAGE_CONTROL4_4(msg, a, b, c, d, e, f, g, h) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c, d), (e, f, g, h))
- #define IPC_SYNC_MESSAGE_CONTROL5_0(msg, a, b, c, d, e) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c, d, e), ())
- #define IPC_SYNC_MESSAGE_CONTROL5_1(msg, a, b, c, d, e, f) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c, d, e), (f))
- #define IPC_SYNC_MESSAGE_CONTROL5_2(msg, a, b, c, d, e, f, g) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c, d, e), (f, g))
- #define IPC_SYNC_MESSAGE_CONTROL5_3(msg, a, b, c, d, e, f, g, h) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c, d, e), (f, g, h))
- #define IPC_SYNC_MESSAGE_CONTROL5_4(msg, a, b, c, d, e, f, g, h, i) \
- IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c, d, e), (f, g, h, i))
- #define IPC_SYNC_MESSAGE_ROUTED0_0(msg) IPC_SYNC_MESSAGE_ROUTED(msg, (), ())
- #define IPC_SYNC_MESSAGE_ROUTED0_1(msg, a) IPC_SYNC_MESSAGE_ROUTED(msg, (), (a))
- #define IPC_SYNC_MESSAGE_ROUTED0_2(msg, a, b) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (), (a, b))
- #define IPC_SYNC_MESSAGE_ROUTED0_3(msg, a, b, c) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (), (a, b, c))
- #define IPC_SYNC_MESSAGE_ROUTED0_4(msg, a, b, c, d) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (), (a, b, c, d))
- #define IPC_SYNC_MESSAGE_ROUTED1_0(msg, a) IPC_SYNC_MESSAGE_ROUTED(msg, (a), ())
- #define IPC_SYNC_MESSAGE_ROUTED1_1(msg, a, b) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (a), (b))
- #define IPC_SYNC_MESSAGE_ROUTED1_2(msg, a, b, c) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (a), (b, c))
- #define IPC_SYNC_MESSAGE_ROUTED1_3(msg, a, b, c, d) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (a), (b, c, d))
- #define IPC_SYNC_MESSAGE_ROUTED1_4(msg, a, b, c, d, e) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (a), (b, c, d, e))
- #define IPC_SYNC_MESSAGE_ROUTED2_0(msg, a, b) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (a, b), ())
- #define IPC_SYNC_MESSAGE_ROUTED2_1(msg, a, b, c) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (a, b), (c))
- #define IPC_SYNC_MESSAGE_ROUTED2_2(msg, a, b, c, d) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (a, b), (c, d))
- #define IPC_SYNC_MESSAGE_ROUTED2_3(msg, a, b, c, d, e) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (a, b), (c, d, e))
- #define IPC_SYNC_MESSAGE_ROUTED2_4(msg, a, b, c, d, e, f) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (a, b), (c, d, e, f))
- #define IPC_SYNC_MESSAGE_ROUTED3_0(msg, a, b, c) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c), ())
- #define IPC_SYNC_MESSAGE_ROUTED3_1(msg, a, b, c, d) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c), (d))
- #define IPC_SYNC_MESSAGE_ROUTED3_2(msg, a, b, c, d, e) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c), (d, e))
- #define IPC_SYNC_MESSAGE_ROUTED3_3(msg, a, b, c, d, e, f) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c), (d, e, f))
- #define IPC_SYNC_MESSAGE_ROUTED3_4(msg, a, b, c, d, e, f, g) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c), (d, e, f, g))
- #define IPC_SYNC_MESSAGE_ROUTED4_0(msg, a, b, c, d) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c, d), ())
- #define IPC_SYNC_MESSAGE_ROUTED4_1(msg, a, b, c, d, e) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c, d), (e))
- #define IPC_SYNC_MESSAGE_ROUTED4_2(msg, a, b, c, d, e, f) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c, d), (e, f))
- #define IPC_SYNC_MESSAGE_ROUTED4_3(msg, a, b, c, d, e, f, g) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c, d), (e, f, g))
- #define IPC_SYNC_MESSAGE_ROUTED4_4(msg, a, b, c, d, e, f, g, h) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c, d), (e, f, g, h))
- #define IPC_SYNC_MESSAGE_ROUTED5_0(msg, a, b, c, d, e) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c, d, e), ())
- #define IPC_SYNC_MESSAGE_ROUTED5_1(msg, a, b, c, d, e, f) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c, d, e), (f))
- #define IPC_SYNC_MESSAGE_ROUTED5_2(msg, a, b, c, d, e, f, g) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c, d, e), (f, g))
- #define IPC_SYNC_MESSAGE_ROUTED5_3(msg, a, b, c, d, e, f, g, h) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c, d, e), (f, g, h))
- #define IPC_SYNC_MESSAGE_ROUTED5_4(msg, a, b, c, d, e, f, g, h, i) \
- IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c, d, e), (f, g, h, i))
- #endif // IPC_IPC_MESSAGE_MACROS_H_
- // Clean up IPC_MESSAGE_START in this unguarded section so that the
- // XXX_messages.h files need not do so themselves. This makes the
- // XXX_messages.h files easier to write.
- #undef IPC_MESSAGE_START
|