1// Copyright (c) 2012, 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 "bin/eventhandler.h"
6
7#include "bin/builtin.h"
8#include "bin/dartutils.h"
9#include "bin/lockers.h"
10#include "bin/socket.h"
11#include "bin/thread.h"
12
13#include "include/dart_api.h"
14
15namespace dart {
16namespace bin {
17
18void TimeoutQueue::UpdateTimeout(Dart_Port port, int64_t timeout) {
19 // Find port if present.
20 Timeout* last = NULL;
21 Timeout* current = timeouts_;
22 while (current != NULL) {
23 if (current->port() == port) {
24 // Found.
25 if (timeout < 0) {
26 // Remove from list and delete existing.
27 if (last != NULL) {
28 last->set_next(current->next());
29 } else {
30 timeouts_ = current->next();
31 }
32 delete current;
33 } else {
34 // Update timeout.
35 current->set_timeout(timeout);
36 }
37 break;
38 }
39 last = current;
40 current = current->next();
41 }
42 if (current == NULL && timeout >= 0) {
43 // Not found, create a new.
44 timeouts_ = new Timeout(port, timeout, timeouts_);
45 }
46 // Clear and find next timeout.
47 next_timeout_ = NULL;
48 current = timeouts_;
49 while (current != NULL) {
50 if ((next_timeout_ == NULL) ||
51 (current->timeout() < next_timeout_->timeout())) {
52 next_timeout_ = current;
53 }
54 current = current->next();
55 }
56}
57
58static EventHandler* event_handler = NULL;
59static Monitor* shutdown_monitor = NULL;
60
61void EventHandler::Start() {
62 // Initialize global socket registry.
63 ListeningSocketRegistry::Initialize();
64
65 ASSERT(event_handler == NULL);
66 shutdown_monitor = new Monitor();
67 event_handler = new EventHandler();
68 event_handler->delegate_.Start(event_handler);
69
70 if (!SocketBase::Initialize()) {
71 FATAL("Failed to initialize sockets");
72 }
73}
74
75void EventHandler::NotifyShutdownDone() {
76 MonitorLocker ml(shutdown_monitor);
77 ml.Notify();
78}
79
80void EventHandler::Stop() {
81 if (event_handler == NULL) {
82 return;
83 }
84
85 // Wait until it has stopped.
86 {
87 MonitorLocker ml(shutdown_monitor);
88
89 // Signal to event handler that we want it to stop.
90 event_handler->delegate_.Shutdown();
91 ml.Wait(Monitor::kNoTimeout);
92 }
93
94 // Cleanup
95 delete event_handler;
96 event_handler = NULL;
97 delete shutdown_monitor;
98 shutdown_monitor = NULL;
99
100 // Destroy the global socket registry.
101 ListeningSocketRegistry::Cleanup();
102}
103
104EventHandlerImplementation* EventHandler::delegate() {
105 if (event_handler == NULL) {
106 return NULL;
107 }
108 return &event_handler->delegate_;
109}
110
111void EventHandler::SendFromNative(intptr_t id, Dart_Port port, int64_t data) {
112 event_handler->SendData(id, port, data);
113}
114
115/*
116 * Send data to the EventHandler thread to register for a given instance
117 * args[0] a ReceivePort args[1] with a notification event args[2].
118 */
119void FUNCTION_NAME(EventHandler_SendData)(Dart_NativeArguments args) {
120 // Get the id out of the send port. If the handle is not a send port
121 // we will get an error and propagate that out.
122 Dart_Handle handle = Dart_GetNativeArgument(args, 1);
123 Dart_Port dart_port;
124 handle = Dart_SendPortGetId(handle, &dart_port);
125 if (Dart_IsError(handle)) {
126 Dart_PropagateError(handle);
127 UNREACHABLE();
128 }
129 Dart_Handle sender = Dart_GetNativeArgument(args, 0);
130 intptr_t id;
131 if (Dart_IsNull(sender)) {
132 id = kTimerId;
133 } else {
134 Socket* socket = Socket::GetSocketIdNativeField(sender);
135 ASSERT(dart_port != ILLEGAL_PORT);
136 socket->set_port(dart_port);
137 socket->Retain(); // inc refcount before sending to the eventhandler.
138 id = reinterpret_cast<intptr_t>(socket);
139 }
140 int64_t data = DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 2));
141 event_handler->SendData(id, dart_port, data);
142}
143
144void FUNCTION_NAME(EventHandler_TimerMillisecondClock)(
145 Dart_NativeArguments args) {
146 int64_t now = TimerUtils::GetCurrentMonotonicMillis();
147 Dart_SetReturnValue(args, Dart_NewInteger(now));
148}
149
150} // namespace bin
151} // namespace dart
152