Index: ipc/ipc_message_macros.h |
=================================================================== |
--- ipc/ipc_message_macros.h (revision 74341) |
+++ ipc/ipc_message_macros.h (working copy) |
@@ -1,18 +1,122 @@ |
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
+// Copyright (c) 2011 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. |
-// This header is meant to be included in multiple passes, hence no traditional |
-// header guard. |
+// Defining IPC Messages |
// |
-// In your XXX_messages_internal.h file, before defining any messages do: |
-// #define IPC_MESSAGE_START XMsgStart |
-// XMstStart value is from the IPCMessageStart enum in ipc_message_utils.h, and |
-// needs to be unique for each different file. |
-// In your XXX_messages.cc file, after all the includes for param types: |
+// 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 |
+// implemation 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_utils.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 to surrond your message declatation macros: |
+// #define IPC_MESSAGE_START XXXMsgStart |
+// ( ... your macro invocations go here ... ) |
+// #undef IPC_MESSAGE_START |
+// |
+// 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 and |
+// common_message_generator.h in /chrome/common), but there are circumstances |
+// where you may add a new one. |
+ |
+// In the rare cicrucmstances 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 "X_messages.h" |
+// #include "path/to/YYY_message_generator.h" |
+// // Generate constructors. |
+// #include "ipc/struct_constructor_macros.h" |
+// #include "path/to/YYY_message_generator.h" |
+// // Generate destructors. |
+// #include "ipc/struct_destructor_macros.h" |
+// #include "path/to/YYY_message_generator.h" |
+// namespace IPC { |
+// // Generate param traits write methods. |
+// #include "ipc/ipc_param_traits_write_macros.h" |
+// #include "path/to/YYY_message_generator.h" |
+// // Generate param traits read methods. |
+// #include "ipc/ipc_param_traits_read_macros.h" |
+// #include "path/to/YYY_message_generator.h" |
+// // Generate param traits log methods. |
+// #include "ipc/ipc_param_traits_log_macros.h" |
+// #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 "XXXX_messages.h" |
+// |
+// The XXX_messages.h file will be multiply-included by the |
+// YYY_message_generator.cc file, so your XXX_messages file must be |
+// specially guarded. There will be two sections of the file, one of |
+// which declares types and is singly-evaluated, and another which invokes |
+// macros and is multiply-evaluated. The convention used is as follows: |
+// #ifndef XXX_MESSAGES_H_ |
+// #define XXX_MESSAGES_H_ |
+// (... the type definition section goes here ...) |
+// #endif // XXX_MESSAGES_H_ |
+// #define IPC_MESSAGE_START XXXMsgStart |
+// (... the message macro invocations go here ...) |
+// #undef IPC_MESSAGE_START |
+// |
+// Note that there is no #pragma once; 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. |
+// |
+// Inside the type definition section, you include all of the headers |
+// required to define the types later used in your message macro invocations. |
+// Sometimes is it convenient to provide an incomplete class type declaration |
+// to avoid pulling in a long chain of headers. This is acceptable when |
+// your XXX_messages.h header is being included by the message sending code, |
+// but not when the YYY_message_generator.c is building the messages. In |
+// these cases, follow a convention like: |
+// class some_class; // One incomplete class declaration |
+// class_some_other_class; // Another incomplete class declaration |
+// #ifdef IPC_MESSAGE_IMPL |
+// #inlcude "path/to/some_class.h" // Full class declaration |
+// #inlcude "path/to/some_other_class.h" // Full class declaration |
+// #endif // IPC_MESSAGE_IMPL |
+// |
+// Inside the message macro invocation secton, use macros 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(). |
+// |
+// 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. Note that |
+// IPC_STRUCT_TRAITS_MEMBER() is only permitted inside matching calls |
+// to IPC_STRUCT_TRAITS_BEGIN() / IPC_STRUCT_TRAITS_END(). |
+// |
+// Enum types are registered with a single IPC_ENUM_TRAITS() macro. There |
+// is no need to enumerate each value to the IPC mechanism. |
+// |
+// 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. Input parameters are first (const TYPE&), and |
// To declare a sync message, use the IPC_SYNC_ macros. The numbers at the |
@@ -21,7 +125,6 @@ |
// 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 |
@@ -38,12 +141,13 @@ |
// ViewHostMsg_SyncMessageName::WriteReplyParams(reply_msg, out1, out2); |
// Send(reply_msg); |
+#ifndef IPC_IPC_MESSAGE_MACROS_H_ |
+#define IPC_IPC_MESSAGE_MACROS_H_ |
+// Can use #pragma once all XXX_messages.h files clean up IPC_MESSAGE_START |
+ |
#include "ipc/ipc_message_utils.h" |
+#include "ipc/ipc_param_traits_macros.h" |
-// In case a file includes several X_messages.h files, we don't want to get |
-// errors because each X_messages_internal.h file will define this. |
-#undef IPC_MESSAGE_START |
- |
#if defined(IPC_MESSAGE_IMPL) |
#include "ipc/ipc_message_impl_macros.h" |
#elif defined(IPC_MESSAGE_MACROS_LOG_ENABLED) |
@@ -60,7 +164,7 @@ |
typedef base::hash_map<uint32, LogFunction > LogFunctionMap; |
LogFunctionMap g_log_function_mapping; |
-#endif |
+#endif // IPC_LOG_TABLE_CREATED |
#define IPC_MESSAGE_LOG(msg_class) \ |
@@ -280,7 +384,7 @@ |
#define IPC_SYNC_MESSAGE_ROUTED5_4_EXTRA(msg_class, type1_in, type2_in, type3_in, type4_in, type5_in, type1_out, type2_out, type3_out, type4_out) \ |
IPC_MESSAGE_LOG(msg_class) |
-#else |
+#else // defined(IPC_MESSAGE_MACROS_LOG_ENABLED) |
#define IPC_MESSAGE_CONTROL0_EXTRA(msg_class) |
#define IPC_MESSAGE_CONTROL1_EXTRA(msg_class, type1) |
@@ -352,8 +456,19 @@ |
#define IPC_SYNC_MESSAGE_ROUTED5_3_EXTRA(msg_class, type1_in, type2_in, type3_in, type4_in, type5_in, type1_out, type2_out, type3_out) |
#define IPC_SYNC_MESSAGE_ROUTED5_4_EXTRA(msg_class, type1_in, type2_in, type3_in, type4_in, type5_in, type1_out, type2_out, type4_out) |
-#endif |
+#endif // defined(IPC_MESSAGE_MACROS_LOG_ENABLED) |
+// Macros for defining structs. May be subsequently redefined. |
+#define IPC_STRUCT_BEGIN(struct_name) \ |
+ struct struct_name; \ |
+ IPC_STRUCT_TRAITS_BEGIN(struct_name) \ |
+ IPC_STRUCT_TRAITS_END() \ |
+ struct struct_name : IPC::NoParams { \ |
+ struct_name(); \ |
+ ~struct_name(); |
+#define IPC_STRUCT_MEMBER(type, name) type name; |
+#define IPC_STRUCT_END() }; |
+ |
// 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. |
// Ideally, we wouldn't use line numbers, but instead use the __COUNTER__ macro, |
@@ -1243,3 +1358,10 @@ |
// This corresponds to an enum value from IPCMessageStart. |
#define IPC_MESSAGE_CLASS(message) \ |
message.type() >> 16 |
+ |
+#endif // IPC_IPC_MESSAGE_MACROS_H_ |
+ |
+// Clean up IPC_MESSAGE_START in this unguarded section in case some |
+// XXX_message.h files fail do so themselves. |
jam
2011/02/10 00:22:19
nit: since we'll only want to undef in this file,
|
+#undef IPC_MESSAGE_START |
+ |