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 "ipc/ipc_sync_message.h"
9 #include "base/atomic_sequence_num.h"
10 #include "base/lazy_instance.h"
11 #include "base/logging.h"
12 #include "base/synchronization/waitable_event.h"
13 #include "build/build_config.h"
17 struct WaitableEventLazyInstanceTraits
18 : public base::DefaultLazyInstanceTraits
<base::WaitableEvent
> {
19 static base::WaitableEvent
* New(void* instance
) {
20 // Use placement new to initialize our instance in our preallocated space.
21 return new (instance
) base::WaitableEvent(true, true);
25 base::LazyInstance
<base::WaitableEvent
, WaitableEventLazyInstanceTraits
>
26 dummy_event
= LAZY_INSTANCE_INITIALIZER
;
28 base::StaticAtomicSequenceNumber g_next_id
;
34 #define kSyncMessageHeaderSize 4
36 SyncMessage::SyncMessage(int32_t routing_id
,
38 PriorityValue priority
,
39 MessageReplyDeserializer
* deserializer
)
40 : Message(routing_id
, type
, priority
),
41 deserializer_(deserializer
),
42 pump_messages_event_(NULL
) {
46 // Add synchronous message data before the message payload.
48 header
.message_id
= g_next_id
.GetNext();
49 WriteSyncHeader(this, header
);
52 SyncMessage::~SyncMessage() {
55 MessageReplyDeserializer
* SyncMessage::GetReplyDeserializer() {
56 DCHECK(deserializer_
.get());
57 return deserializer_
.release();
60 void SyncMessage::EnableMessagePumping() {
61 DCHECK(!pump_messages_event_
);
62 set_pump_messages_event(dummy_event
.Pointer());
65 bool SyncMessage::IsMessageReplyTo(const Message
& msg
, int request_id
) {
69 return GetMessageId(msg
) == request_id
;
72 base::PickleIterator
SyncMessage::GetDataIterator(const Message
* msg
) {
73 base::PickleIterator
iter(*msg
);
74 if (!iter
.SkipBytes(kSyncMessageHeaderSize
))
75 return base::PickleIterator();
80 int SyncMessage::GetMessageId(const Message
& msg
) {
81 if (!msg
.is_sync() && !msg
.is_reply())
85 if (!ReadSyncHeader(msg
, &header
))
88 return header
.message_id
;
91 Message
* SyncMessage::GenerateReply(const Message
* msg
) {
92 DCHECK(msg
->is_sync());
94 Message
* reply
= new Message(msg
->routing_id(), IPC_REPLY_ID
,
100 // use the same message id, but this time reply bit is set
101 header
.message_id
= GetMessageId(*msg
);
102 WriteSyncHeader(reply
, header
);
107 bool SyncMessage::ReadSyncHeader(const Message
& msg
, SyncHeader
* header
) {
108 DCHECK(msg
.is_sync() || msg
.is_reply());
110 base::PickleIterator
iter(msg
);
111 bool result
= iter
.ReadInt(&header
->message_id
);
120 bool SyncMessage::WriteSyncHeader(Message
* msg
, const SyncHeader
& header
) {
121 DCHECK(msg
->is_sync() || msg
->is_reply());
122 DCHECK(msg
->payload_size() == 0);
123 bool result
= msg
->WriteInt(header
.message_id
);
129 // Note: if you add anything here, you need to update kSyncMessageHeaderSize.
130 DCHECK(kSyncMessageHeaderSize
== msg
->payload_size());
136 bool MessageReplyDeserializer::SerializeOutputParameters(const Message
& msg
) {
137 return SerializeOutputParameters(msg
, SyncMessage::GetDataIterator(&msg
));