1 // Copyright 2016 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.
4 
5 #ifndef MOJO_CORE_PORTS_MESSAGE_QUEUE_H_
6 #define MOJO_CORE_PORTS_MESSAGE_QUEUE_H_
7 
8 #include <stdint.h>
9 
10 #include <limits>
11 #include <memory>
12 #include <vector>
13 
14 #include "base/component_export.h"
15 #include "base/macros.h"
16 #include "mojo/core/ports/event.h"
17 
18 namespace mojo {
19 namespace core {
20 namespace ports {
21 
22 constexpr uint64_t kInitialSequenceNum = 1;
23 constexpr uint64_t kInvalidSequenceNum = std::numeric_limits<uint64_t>::max();
24 
25 class MessageFilter;
26 
27 // An incoming message queue for a port. MessageQueue keeps track of the highest
28 // known sequence number and can indicate whether the next sequential message is
29 // available. Thus the queue enforces message ordering for the consumer without
30 // enforcing it for the producer (see AcceptMessage() below.)
COMPONENT_EXPORT(MOJO_CORE_PORTS)31 class COMPONENT_EXPORT(MOJO_CORE_PORTS) MessageQueue {
32  public:
33   explicit MessageQueue();
34   explicit MessageQueue(uint64_t next_sequence_num);
35   ~MessageQueue();
36 
37   void set_signalable(bool value) { signalable_ = value; }
38 
39   uint64_t next_sequence_num() const { return next_sequence_num_; }
40 
41   bool HasNextMessage() const;
42 
43   // Gives ownership of the message. If |filter| is non-null, the next message
44   // will only be retrieved if the filter successfully matches it.
45   void GetNextMessage(std::unique_ptr<UserMessageEvent>* message,
46                       MessageFilter* filter);
47 
48   // Takes ownership of the message. Note: Messages are ordered, so while we
49   // have added a message to the queue, we may still be waiting on a message
50   // ahead of this one before we can let any of the messages be returned by
51   // GetNextMessage.
52   //
53   // Furthermore, once has_next_message is set to true, it will remain false
54   // until GetNextMessage is called enough times to return a null message.
55   // In other words, has_next_message acts like an edge trigger.
56   //
57   void AcceptMessage(std::unique_ptr<UserMessageEvent> message,
58                      bool* has_next_message);
59 
60   // Takes all messages from this queue. Used to safely destroy queued messages
61   // without holding any Port lock.
62   void TakeAllMessages(
63       std::vector<std::unique_ptr<UserMessageEvent>>* messages);
64 
65   // The number of messages queued here, regardless of whether the next expected
66   // message has arrived yet.
67   size_t queued_message_count() const { return heap_.size(); }
68 
69   // The aggregate memory size in bytes of all messages queued here, regardless
70   // of whether the next expected message has arrived yet.
71   size_t queued_num_bytes() const { return total_queued_bytes_; }
72 
73  private:
74   std::vector<std::unique_ptr<UserMessageEvent>> heap_;
75   uint64_t next_sequence_num_;
76   bool signalable_ = true;
77   size_t total_queued_bytes_ = 0;
78 
79   DISALLOW_COPY_AND_ASSIGN(MessageQueue);
80 };
81 
82 }  // namespace ports
83 }  // namespace core
84 }  // namespace mojo
85 
86 #endif  // MOJO_CORE_PORTS_MESSAGE_QUEUE_H_
87