9d72035ce5
each isolate or native port had a dedicated thread. Refactored the MessageHandler api... - Added a Run function to allow a MessageHandler to run on a ThreadPool. These functions take a start and end callback to allow for isolate initialization and shutdown. - Made the queue private to the MessageHandler and moved all message processing code inside the MessageHandler (got rid of all of the different flavors of RunLoop). This helps remove some code duplication and hides the details of how messages are handled. - Moved all locking and notification out of MessageQueue and moved it up to MessageHandler. Moved OOB support out of MessageQueue and up to MessageHandler. These changes make the MessageQueue much simpler. - Refactored native port and isolate MessageHandlers to share more code. - Improved --trace_isolates output. - Added tests for MessageHandler. Refactored lib/isolate code... - Use the new MessageHandler::Run api. - Got rid of the LongJump stuff in RunIsolate. No longer needed. - Use the new StartIsolateScope/SwitchIsolateScope to make the code less verbose and less error-prone. - Store top-level isolate errors in the sticky_error. Added StartIsolateScope/SwitchIsolateScope classes. Review URL: https://chromiumcodereview.appspot.com//9924015 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@6762 260f80e4-7a28-3924-810f-c04153c831b5
157 lines
3.8 KiB
C++
157 lines
3.8 KiB
C++
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#include "platform/assert.h"
|
|
#include "vm/message.h"
|
|
#include "vm/unit_test.h"
|
|
|
|
namespace dart {
|
|
|
|
|
|
// Provide access to private members of MessageQueue for testing.
|
|
class MessageQueueTestPeer {
|
|
public:
|
|
explicit MessageQueueTestPeer(MessageQueue* queue) : queue_(queue) {}
|
|
|
|
bool HasMessage() const {
|
|
// We don't really need to grab the monitor during the unit test,
|
|
// but it doesn't hurt.
|
|
bool result = (queue_->head_ != NULL);
|
|
return result;
|
|
}
|
|
|
|
private:
|
|
MessageQueue* queue_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(MessageQueueTestPeer);
|
|
};
|
|
|
|
|
|
static uint8_t* AllocMsg(const char* str) {
|
|
return reinterpret_cast<uint8_t*>(strdup(str));
|
|
}
|
|
|
|
|
|
TEST_CASE(MessageQueue_BasicOperations) {
|
|
MessageQueue queue;
|
|
MessageQueueTestPeer queue_peer(&queue);
|
|
EXPECT(!queue_peer.HasMessage());
|
|
|
|
Dart_Port port = 1;
|
|
|
|
// Add two messages.
|
|
Message* msg1 =
|
|
new Message(port, 0, AllocMsg("msg1"), Message::kNormalPriority);
|
|
queue.Enqueue(msg1);
|
|
EXPECT(queue_peer.HasMessage());
|
|
|
|
Message* msg2 =
|
|
new Message(port, 0, AllocMsg("msg2"), Message::kNormalPriority);
|
|
|
|
queue.Enqueue(msg2);
|
|
EXPECT(queue_peer.HasMessage());
|
|
|
|
// Remove two messages.
|
|
Message* msg = queue.Dequeue();
|
|
EXPECT(msg != NULL);
|
|
EXPECT_STREQ("msg1", reinterpret_cast<char*>(msg->data()));
|
|
EXPECT(queue_peer.HasMessage());
|
|
|
|
msg = queue.Dequeue();
|
|
EXPECT(msg != NULL);
|
|
EXPECT_STREQ("msg2", reinterpret_cast<char*>(msg->data()));
|
|
EXPECT(!queue_peer.HasMessage());
|
|
|
|
delete msg1;
|
|
delete msg2;
|
|
}
|
|
|
|
|
|
TEST_CASE(MessageQueue_FlushAll) {
|
|
MessageQueue queue;
|
|
MessageQueueTestPeer queue_peer(&queue);
|
|
Dart_Port port1 = 1;
|
|
Dart_Port port2 = 2;
|
|
|
|
// Add two messages.
|
|
Message* msg1 =
|
|
new Message(port1, 0, AllocMsg("msg1"), Message::kNormalPriority);
|
|
queue.Enqueue(msg1);
|
|
Message* msg2 =
|
|
new Message(port2, 0, AllocMsg("msg2"), Message::kNormalPriority);
|
|
queue.Enqueue(msg2);
|
|
|
|
EXPECT(queue_peer.HasMessage());
|
|
queue.FlushAll();
|
|
EXPECT(!queue_peer.HasMessage());
|
|
|
|
// msg1 and msg2 already delete by FlushAll.
|
|
}
|
|
|
|
|
|
TEST_CASE(MessageQueue_Flush) {
|
|
MessageQueue queue;
|
|
MessageQueueTestPeer queue_peer(&queue);
|
|
Dart_Port port1 = 1;
|
|
Dart_Port port2 = 2;
|
|
|
|
// Add two messages on different ports.
|
|
Message* msg1 =
|
|
new Message(port1, 0, AllocMsg("msg1"), Message::kNormalPriority);
|
|
queue.Enqueue(msg1);
|
|
Message* msg2 =
|
|
new Message(port2, 0, AllocMsg("msg2"), Message::kNormalPriority);
|
|
queue.Enqueue(msg2);
|
|
EXPECT(queue_peer.HasMessage());
|
|
|
|
queue.Flush(port1);
|
|
|
|
// One message is left in the queue.
|
|
EXPECT(queue_peer.HasMessage());
|
|
Message* msg = queue.Dequeue();
|
|
EXPECT(msg != NULL);
|
|
EXPECT_STREQ("msg2", reinterpret_cast<char*>(msg->data()));
|
|
|
|
EXPECT(!queue_peer.HasMessage());
|
|
|
|
// msg1 is already deleted by Flush.
|
|
delete msg2;
|
|
}
|
|
|
|
|
|
TEST_CASE(MessageQueue_Flush_MultipleMessages) {
|
|
MessageQueue queue;
|
|
MessageQueueTestPeer queue_peer(&queue);
|
|
Dart_Port port1 = 1;
|
|
|
|
Message* msg1 =
|
|
new Message(port1, 0, AllocMsg("msg1"), Message::kNormalPriority);
|
|
queue.Enqueue(msg1);
|
|
Message* msg2 =
|
|
new Message(port1, 0, AllocMsg("msg2"), Message::kNormalPriority);
|
|
queue.Enqueue(msg2);
|
|
EXPECT(queue_peer.HasMessage());
|
|
|
|
queue.Flush(port1);
|
|
|
|
// Queue is empty.
|
|
EXPECT(!queue_peer.HasMessage());
|
|
// msg1 and msg2 are already deleted by Flush.
|
|
}
|
|
|
|
|
|
TEST_CASE(MessageQueue_Flush_EmptyQueue) {
|
|
MessageQueue queue;
|
|
MessageQueueTestPeer queue_peer(&queue);
|
|
Dart_Port port1 = 1;
|
|
|
|
EXPECT(!queue_peer.HasMessage());
|
|
queue.Flush(port1);
|
|
|
|
// Queue is still empty.
|
|
EXPECT(!queue_peer.HasMessage());
|
|
}
|
|
|
|
} // namespace dart
|