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 MessageReplyDeserializer
* deserializer
)
43 : Message(routing_id
, type
),
44 deserializer_(deserializer
),
45 pump_messages_event_(NULL
)
50 // Add synchronous message data before the message payload.
52 header
.message_id
= g_next_id
.GetNext();
53 WriteSyncHeader(this, header
);
56 SyncMessage::~SyncMessage() {
59 MessageReplyDeserializer
* SyncMessage::GetReplyDeserializer() {
60 DCHECK(deserializer_
.get());
61 return deserializer_
.release();
64 void SyncMessage::EnableMessagePumping() {
65 DCHECK(!pump_messages_event_
);
66 set_pump_messages_event(dummy_event
.Pointer());
69 bool SyncMessage::IsMessageReplyTo(const Message
& msg
, int request_id
) {
73 return GetMessageId(msg
) == request_id
;
76 PickleIterator
SyncMessage::GetDataIterator(const Message
* msg
) {
77 PickleIterator
iter(*msg
);
78 if (!iter
.SkipBytes(kSyncMessageHeaderSize
))
79 return PickleIterator();
84 int SyncMessage::GetMessageId(const Message
& msg
) {
85 if (!msg
.is_sync() && !msg
.is_reply())
89 if (!ReadSyncHeader(msg
, &header
))
92 return header
.message_id
;
95 Message
* SyncMessage::GenerateReply(const Message
* msg
) {
96 DCHECK(msg
->is_sync());
98 Message
* reply
= new Message(msg
->routing_id(), IPC_REPLY_ID
);
103 // use the same message id, but this time reply bit is set
104 header
.message_id
= GetMessageId(*msg
);
105 WriteSyncHeader(reply
, header
);
110 bool SyncMessage::ReadSyncHeader(const Message
& msg
, SyncHeader
* header
) {
111 DCHECK(msg
.is_sync() || msg
.is_reply());
113 PickleIterator
iter(msg
);
114 bool result
= msg
.ReadInt(&iter
, &header
->message_id
);
123 bool SyncMessage::WriteSyncHeader(Message
* msg
, const SyncHeader
& header
) {
124 DCHECK(msg
->is_sync() || msg
->is_reply());
125 DCHECK(msg
->payload_size() == 0);
126 bool result
= msg
->WriteInt(header
.message_id
);
132 // Note: if you add anything here, you need to update kSyncMessageHeaderSize.
133 DCHECK(kSyncMessageHeaderSize
== msg
->payload_size());
139 bool MessageReplyDeserializer::SerializeOutputParameters(const Message
& msg
) {
140 return SerializeOutputParameters(msg
, SyncMessage::GetDataIterator(&msg
));