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 static base::LazyInstance
<base::WaitableEvent
, WaitableEventLazyInstanceTraits
>
29 dummy_event
= LAZY_INSTANCE_INITIALIZER
;
35 #define kSyncMessageHeaderSize 4
37 static base::AtomicSequenceNumber
g_next_id(base::LINKER_INITIALIZED
);
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 void* SyncMessage::GetDataIterator(const Message
* msg
) {
78 void* iter
= const_cast<char*>(msg
->payload());
79 UpdateIter(&iter
, kSyncMessageHeaderSize
);
83 int SyncMessage::GetMessageId(const Message
& msg
) {
84 if (!msg
.is_sync() && !msg
.is_reply())
88 if (!ReadSyncHeader(msg
, &header
))
91 return header
.message_id
;
94 Message
* SyncMessage::GenerateReply(const Message
* msg
) {
95 DCHECK(msg
->is_sync());
97 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());
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
));