1 // Copyright (c) 2012 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.
5 #include "build/build_config.h"
12 #include "base/atomic_sequence_num.h"
13 #include "base/lazy_instance.h"
14 #include "base/logging.h"
15 #include "base/synchronization/waitable_event.h"
16 #include "ipc/ipc_sync_message.h"
20 struct WaitableEventLazyInstanceTraits
21 : public base::DefaultLazyInstanceTraits
<base::WaitableEvent
> {
22 static base::WaitableEvent
* New(void* instance
) {
23 // Use placement new to initialize our instance in our preallocated space.
24 return new (instance
) base::WaitableEvent(true, true);
28 base::LazyInstance
<base::WaitableEvent
, WaitableEventLazyInstanceTraits
>
29 dummy_event
= LAZY_INSTANCE_INITIALIZER
;
31 base::StaticAtomicSequenceNumber g_next_id
;
37 #define kSyncMessageHeaderSize 4
39 SyncMessage::SyncMessage(
42 PriorityValue priority
,
43 MessageReplyDeserializer
* deserializer
)
44 : Message(routing_id
, type
, priority
),
45 deserializer_(deserializer
),
46 pump_messages_event_(NULL
)
51 // Add synchronous message data before the message payload.
53 header
.message_id
= g_next_id
.GetNext();
54 WriteSyncHeader(this, header
);
57 SyncMessage::~SyncMessage() {
60 MessageReplyDeserializer
* SyncMessage::GetReplyDeserializer() {
61 DCHECK(deserializer_
.get());
62 return deserializer_
.release();
65 void SyncMessage::EnableMessagePumping() {
66 DCHECK(!pump_messages_event_
);
67 set_pump_messages_event(dummy_event
.Pointer());
70 bool SyncMessage::IsMessageReplyTo(const Message
& msg
, int request_id
) {
74 return GetMessageId(msg
) == request_id
;
77 base::PickleIterator
SyncMessage::GetDataIterator(const Message
* msg
) {
78 base::PickleIterator
iter(*msg
);
79 if (!iter
.SkipBytes(kSyncMessageHeaderSize
))
80 return base::PickleIterator();
85 int SyncMessage::GetMessageId(const Message
& msg
) {
86 if (!msg
.is_sync() && !msg
.is_reply())
90 if (!ReadSyncHeader(msg
, &header
))
93 return header
.message_id
;
96 Message
* SyncMessage::GenerateReply(const Message
* msg
) {
97 DCHECK(msg
->is_sync());
99 Message
* reply
= new Message(msg
->routing_id(), IPC_REPLY_ID
,
105 // use the same message id, but this time reply bit is set
106 header
.message_id
= GetMessageId(*msg
);
107 WriteSyncHeader(reply
, header
);
112 bool SyncMessage::ReadSyncHeader(const Message
& msg
, SyncHeader
* header
) {
113 DCHECK(msg
.is_sync() || msg
.is_reply());
115 base::PickleIterator
iter(msg
);
116 bool result
= iter
.ReadInt(&header
->message_id
);
125 bool SyncMessage::WriteSyncHeader(Message
* msg
, const SyncHeader
& header
) {
126 DCHECK(msg
->is_sync() || msg
->is_reply());
127 DCHECK(msg
->payload_size() == 0);
128 bool result
= msg
->WriteInt(header
.message_id
);
134 // Note: if you add anything here, you need to update kSyncMessageHeaderSize.
135 DCHECK(kSyncMessageHeaderSize
== msg
->payload_size());
141 bool MessageReplyDeserializer::SerializeOutputParameters(const Message
& msg
) {
142 return SerializeOutputParameters(msg
, SyncMessage::GetDataIterator(&msg
));