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 | |
15 | namespace dart { |
16 | namespace bin { |
17 | |
18 | void 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 | |
58 | static EventHandler* event_handler = NULL; |
59 | static Monitor* shutdown_monitor = NULL; |
60 | |
61 | void 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 | |
75 | void EventHandler::NotifyShutdownDone() { |
76 | MonitorLocker ml(shutdown_monitor); |
77 | ml.Notify(); |
78 | } |
79 | |
80 | void 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 | |
104 | EventHandlerImplementation* EventHandler::delegate() { |
105 | if (event_handler == NULL) { |
106 | return NULL; |
107 | } |
108 | return &event_handler->delegate_; |
109 | } |
110 | |
111 | void 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 | */ |
119 | void 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 | |
144 | void 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 | |