OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 #include "vm/message_queue.h" | |
6 | |
7 namespace dart { | |
8 | |
9 MessageQueue::MessageQueue() { | |
10 for (int p = Message::kFirstPriority; p < Message::kNumPriorities; p++) { | |
11 head_[p] = NULL; | |
12 tail_[p] = NULL; | |
13 } | |
14 } | |
15 | |
16 | |
17 MessageQueue::~MessageQueue() { | |
18 // Ensure that all pending messages have been released. | |
19 #if defined(DEBUG) | |
20 for (int p = Message::kFirstPriority; p < Message::kNumPriorities; p++) { | |
21 ASSERT(head_[p] == NULL); | |
22 } | |
23 #endif | |
24 } | |
25 | |
26 | |
27 void MessageQueue::Enqueue(Message* msg) { | |
28 // TODO(turnidge): Add a scoped locker for monitors which is not a | |
29 // stack resource. This would probably be useful in the platform | |
30 // headers. | |
31 monitor_.Enter(); | |
32 | |
33 Message::Priority p = msg->priority(); | |
34 // Make sure messages are not reused. | |
35 ASSERT(msg->next_ == NULL); | |
36 if (head_[p] == NULL) { | |
37 // Only element in the queue. | |
38 head_[p] = msg; | |
39 tail_[p] = msg; | |
40 | |
41 // We only need to notify if the queue was empty. | |
42 monitor_.Notify(); | |
43 } else { | |
44 ASSERT(tail_[p] != NULL); | |
45 // Append at the tail. | |
46 tail_[p]->next_ = msg; | |
47 tail_[p] = msg; | |
48 } | |
49 | |
50 monitor_.Exit(); | |
51 } | |
52 | |
53 Message* MessageQueue::DequeueNoWait() { | |
54 MonitorLocker ml(&monitor_); | |
55 return DequeueNoWaitHoldsLock(); | |
56 } | |
57 | |
58 Message* MessageQueue::DequeueNoWaitHoldsLock() { | |
59 // Look for the highest priority available message. | |
60 for (int p = Message::kNumPriorities-1; p >= Message::kFirstPriority; p--) { | |
61 Message* result = head_[p]; | |
62 if (result != NULL) { | |
63 head_[p] = result->next_; | |
64 // The following update to tail_ is not strictly needed. | |
65 if (head_[p] == NULL) { | |
66 tail_[p] = NULL; | |
67 } | |
68 #if defined(DEBUG) | |
69 result->next_ = result; // Make sure to trigger ASSERT in Enqueue. | |
70 #endif // DEBUG | |
71 return result; | |
72 } | |
73 } | |
74 return NULL; | |
75 } | |
76 | |
77 | |
78 Message* MessageQueue::Dequeue(int64_t millis) { | |
79 ASSERT(millis >= 0); | |
80 MonitorLocker ml(&monitor_); | |
81 | |
82 Message* result = DequeueNoWaitHoldsLock(); | |
83 if (result == NULL) { | |
84 // No message available at any priority. | |
85 ml.Wait(millis); | |
86 result = DequeueNoWaitHoldsLock(); | |
87 } | |
88 return result; | |
89 } | |
90 | |
91 | |
92 void MessageQueue::Flush(Dart_Port port) { | |
93 MonitorLocker ml(&monitor_); | |
94 for (int p = Message::kFirstPriority; p < Message::kNumPriorities; p++) { | |
95 Message* cur = head_[p]; | |
96 Message* prev = NULL; | |
97 while (cur != NULL) { | |
98 Message* next = cur->next_; | |
99 // If the message matches, then remove it from the queue and delete it. | |
100 if (cur->dest_port() == port) { | |
101 if (prev != NULL) { | |
102 prev->next_ = next; | |
103 } else { | |
104 head_[p] = next; | |
105 } | |
106 delete cur; | |
107 } else { | |
108 // Move prev forward. | |
109 prev = cur; | |
110 } | |
111 // Advance to the next message in the queue. | |
112 cur = next; | |
113 } | |
114 tail_[p] = prev; | |
115 } | |
116 } | |
117 | |
118 | |
119 void MessageQueue::FlushAll() { | |
120 MonitorLocker ml(&monitor_); | |
121 for (int p = Message::kFirstPriority; p < Message::kNumPriorities; p++) { | |
122 Message* cur = head_[p]; | |
123 head_[p] = NULL; | |
124 tail_[p] = NULL; | |
125 while (cur != NULL) { | |
126 Message* next = cur->next_; | |
127 delete cur; | |
128 cur = next; | |
129 } | |
130 } | |
131 } | |
132 | |
133 | |
134 } // namespace dart | |
OLD | NEW |