63 {
64 public:
65 TimeoutQueue() {}
66
67 ~TimeoutQueue() {
68 while (HasTimeout())
69 RemoveCurrent();
70 }
71
72 bool HasTimeout() const { return !timeouts_.IsEmpty(); }
73
74 int64_t CurrentTimeout() const {
75 ASSERT(!timeouts_.IsEmpty());
76 return timeouts_.Minimum().priority;
77 }
78
80 ASSERT(!timeouts_.IsEmpty());
81 return timeouts_.Minimum().value;
82 }
83
84 void RemoveCurrent() { timeouts_.RemoveMinimum(); }
85
86 void UpdateTimeout(
Dart_Port port, int64_t timeout) {
87 if (timeout < 0) {
88 timeouts_.RemoveByValue(port);
89 } else {
90 timeouts_.InsertOrChangePriority(timeout, port);
91 }
92 }
93
94 private:
95 PriorityQueue<int64_t, Dart_Port> timeouts_;
96
98};
99
100class InterruptMessage {
101 public:
105};
106
109static constexpr intptr_t
kTimerId = -1;
111
112template <typename T>
113class CircularLinkedList {
114 public:
115 CircularLinkedList() : head_(nullptr) {}
116
117 typedef void (*ClearFun)(
void*
value);
118
119
122 if (head_ == nullptr) {
123
127 return true;
128 } else {
129
130 e->prev_ = head_->prev_;
134 return false;
135 }
136 }
137
138 void RemoveHead(ClearFun clear = nullptr) {
140
143 head_ = nullptr;
144 } else {
145 e->prev_->next_ =
e->next_;
146 e->next_->prev_ =
e->prev_;
148 }
149 if (clear != nullptr) {
150 clear(
reinterpret_cast<void*
>(
e->t));
151 }
153 }
154
155 void Remove(
T item) {
156 if (head_ == nullptr) {
157 return;
158 } else if (head_ == head_->next_) {
159 if (head_->t == item) {
160 delete head_;
161 head_ = nullptr;
162 return;
163 }
164 } else {
165 Entry* current = head_;
166 do {
167 if (current->t == item) {
172
173 if (current == head_) {
174 head_ = head_->next_;
175 }
176
177 delete current;
178 return;
179 }
180 current = current->next_;
181 } while (current != head_);
182 }
183 }
184
185 void RemoveAll(ClearFun clear = nullptr) {
186 while (HasHead()) {
187 RemoveHead(clear);
188 }
189 }
190
191 T head()
const {
return head_->t; }
192
193 bool HasHead() const { return head_ != nullptr; }
194
195 void Rotate() {
196 if (head_ != nullptr) {
197 ASSERT(head_->next_ !=
nullptr);
198 head_ = head_->next_;
199 }
200 }
201
202 private:
204 explicit Entry(
const T& t) : t(t), next_(nullptr), prev_(nullptr) {}
208 };
209
211
213};
214
215class DescriptorInfoBase {
216 public:
217 explicit DescriptorInfoBase(intptr_t fd) : fd_(fd) {
ASSERT(fd_ != -1); }
218
219 virtual ~DescriptorInfoBase() {}
220
221
222 intptr_t fd() { return fd_; }
223
224
225 virtual bool IsListeningSocket() const = 0;
226
227
228
229 virtual void SetPortAndMask(
Dart_Port port, intptr_t mask) = 0;
230
231
232 virtual void RemovePort(
Dart_Port port) = 0;
233
234
235 virtual void RemoveAllPorts() = 0;
236
237
238
239 virtual Dart_Port NextNotifyDartPort(intptr_t events_ready) = 0;
240
241
242
243 virtual void NotifyAllDartPorts(uintptr_t events) = 0;
244
245
247
248
249
250 virtual intptr_t Mask() = 0;
251
252
253 virtual void Close() = 0;
254
255 protected:
256 intptr_t fd_;
257
258 private:
260};
261
262
263
264
265
266template <typename DI>
267class DescriptorInfoSingleMixin : public DI {
268 private:
269 static constexpr int kTokenCount = 16;
270
271 public:
272 DescriptorInfoSingleMixin(intptr_t fd, bool disable_tokens)
273 : DI(fd),
274 port_(0),
275 tokens_(kTokenCount),
276 mask_(0),
277 disable_tokens_(disable_tokens) {}
278
279 virtual ~DescriptorInfoSingleMixin() {}
280
281 virtual bool IsListeningSocket() const { return false; }
282
283 virtual void SetPortAndMask(
Dart_Port port, intptr_t mask) {
284 ASSERT(port_ == 0 || port == port_);
286 mask_ = mask;
287 }
288
289 virtual void RemovePort(
Dart_Port port) {
290
291
292 ASSERT(port_ == 0 || port_ == port);
293 port_ = 0;
294 mask_ = 0;
295 }
296
297 virtual void RemoveAllPorts() {
298 port_ = 0;
299 mask_ = 0;
300 }
301
302 virtual Dart_Port NextNotifyDartPort(intptr_t events_ready) {
304 IS_EVENT(events_ready, kDestroyedEvent));
305 if (!disable_tokens_) {
306 tokens_--;
307 }
308 return port_;
309 }
310
311 virtual void NotifyAllDartPorts(uintptr_t events) {
312
313
316
317 if (port_ != 0) {
318 DartUtils::PostInt32(port_, events);
319 }
320 if (!disable_tokens_) {
321 tokens_--;
322 }
323 }
324
327 if (!disable_tokens_) {
329 }
330 ASSERT(tokens_ <= kTokenCount);
331 }
332
333 virtual intptr_t Mask() {
334 if (tokens_ <= 0) {
335 return 0;
336 }
337 return mask_;
338 }
339
340 virtual void Close() { DI::Close(); }
341
342 private:
344 int tokens_;
345 intptr_t mask_;
346 bool disable_tokens_;
347
349};
350
351
352
353
354
355
356template <typename DI>
357class DescriptorInfoMultipleMixin : public DI {
358 private:
359 static constexpr int kTokenCount = 4;
360
361 static bool SamePortValue(void* key1, void* key2) {
362 return reinterpret_cast<Dart_Port>(key1) ==
364 }
365
366 static uint32_t GetHashmapHashFromPort(
Dart_Port port) {
367 return static_cast<uint32_t
>(
port & 0xFFFFFFFF);
368 }
369
370 static void* GetHashmapKeyFromPort(
Dart_Port port) {
371 return reinterpret_cast<void*
>(
port);
372 }
373
374 static bool IsReadingMask(intptr_t mask) {
375 if (mask == (1 << kInEvent)) {
376 return true;
377 } else {
379 return false;
380 }
381 }
382
383 struct PortEntry {
385 intptr_t is_reading;
386 intptr_t token_count;
387
388 bool IsReady() { return token_count > 0 && is_reading != 0; }
389 };
390
391 public:
392 DescriptorInfoMultipleMixin(intptr_t fd, bool disable_tokens)
393 : DI(fd),
394 tokens_map_(&SamePortValue, kTokenCount),
395 disable_tokens_(disable_tokens) {}
396
397 virtual ~DescriptorInfoMultipleMixin() { RemoveAllPorts(); }
398
399 virtual bool IsListeningSocket() const { return true; }
400
401 virtual void SetPortAndMask(
Dart_Port port, intptr_t mask) {
402 SimpleHashMap::Entry* entry = tokens_map_.Lookup(
403 GetHashmapKeyFromPort(port), GetHashmapHashFromPort(port), true);
404 PortEntry* pentry;
405 if (entry->value == nullptr) {
406 pentry = new PortEntry();
407 pentry->dart_port =
port;
408 pentry->token_count = kTokenCount;
409 pentry->is_reading = IsReadingMask(mask);
410 entry->value = reinterpret_cast<void*>(pentry);
411
412 if (pentry->IsReady()) {
413 active_readers_.Add(pentry);
414 }
415 } else {
416 pentry = reinterpret_cast<PortEntry*>(entry->value);
417 bool was_ready = pentry->IsReady();
418 pentry->is_reading = IsReadingMask(mask);
419 bool is_ready = pentry->IsReady();
420
421 if (was_ready && !is_ready) {
422 active_readers_.Remove(pentry);
423 } else if (!was_ready && is_ready) {
424 active_readers_.Add(pentry);
425 }
426 }
427
428#ifdef DEBUG
429
430 int ready_count = 0;
431
432 if (active_readers_.HasHead()) {
433 PortEntry*
root =
reinterpret_cast<PortEntry*
>(active_readers_.head());
434 PortEntry* current =
root;
435 do {
436 ASSERT(current->IsReady());
437 ready_count++;
438 active_readers_.Rotate();
439 current = active_readers_.head();
440 } while (current != root);
441 }
442
443 for (SimpleHashMap::Entry* entry = tokens_map_.Start(); entry != nullptr;
444 entry = tokens_map_.Next(entry)) {
445 PortEntry* pentry = reinterpret_cast<PortEntry*>(entry->value);
446 if (pentry->IsReady()) {
447 ready_count--;
448 }
449 }
450
452#endif
453 }
454
455 virtual void RemovePort(
Dart_Port port) {
456 SimpleHashMap::Entry* entry = tokens_map_.Lookup(
457 GetHashmapKeyFromPort(port), GetHashmapHashFromPort(port), false);
458 if (entry != nullptr) {
459 PortEntry* pentry = reinterpret_cast<PortEntry*>(entry->value);
460 if (pentry->IsReady()) {
461 active_readers_.Remove(pentry);
462 }
463 tokens_map_.Remove(GetHashmapKeyFromPort(port),
464 GetHashmapHashFromPort(port));
465 delete pentry;
466 } else {
467
468
469
470
471
472
473
474
475
476 }
477 }
478
479 virtual void RemoveAllPorts() {
480 for (SimpleHashMap::Entry* entry = tokens_map_.Start(); entry != nullptr;
481 entry = tokens_map_.Next(entry)) {
482 PortEntry* pentry = reinterpret_cast<PortEntry*>(entry->value);
483 entry->value = nullptr;
484 active_readers_.Remove(pentry);
485 delete pentry;
486 }
487 tokens_map_.Clear();
488 active_readers_.RemoveAll(DeletePortEntry);
489 }
490
491 virtual Dart_Port NextNotifyDartPort(intptr_t events_ready) {
492
493
495 IS_EVENT(events_ready, kDestroyedEvent));
496
497 if (active_readers_.HasHead()) {
498 PortEntry* pentry = reinterpret_cast<PortEntry*>(active_readers_.head());
499
500
501 if (!disable_tokens_) {
502 pentry->token_count--;
503 }
504 if (pentry->token_count <= 0) {
505 active_readers_.RemoveHead();
506 } else {
507 active_readers_.Rotate();
508 }
509
510 return pentry->dart_port;
511 }
512 return 0;
513 }
514
515 virtual void NotifyAllDartPorts(uintptr_t events) {
516
517
520
521 for (SimpleHashMap::Entry* entry = tokens_map_.Start(); entry != nullptr;
522 entry = tokens_map_.Next(entry)) {
523 PortEntry* pentry = reinterpret_cast<PortEntry*>(entry->value);
524 DartUtils::PostInt32(pentry->dart_port, events);
525
526
527 bool was_ready = pentry->IsReady();
528 if (!disable_tokens_) {
529 pentry->token_count--;
530 }
531
532 if (was_ready && (pentry->token_count <= 0)) {
533 active_readers_.Remove(pentry);
534 }
535 }
536 }
537
539 SimpleHashMap::Entry* entry = tokens_map_.Lookup(
540 GetHashmapKeyFromPort(port), GetHashmapHashFromPort(port), false);
542
543 PortEntry* pentry = reinterpret_cast<PortEntry*>(entry->value);
544 bool was_ready = pentry->IsReady();
545 if (!disable_tokens_) {
546 pentry->token_count +=
count;
547 }
548 ASSERT(pentry->token_count <= kTokenCount);
549 bool is_ready = pentry->IsReady();
550 if (!was_ready && is_ready) {
551 active_readers_.Add(pentry);
552 }
553 }
554
555 virtual intptr_t Mask() {
556 if (active_readers_.HasHead()) {
558 }
559 return 0;
560 }
561
562 virtual void Close() { DI::Close(); }
563
564 private:
565 static void DeletePortEntry(void* data) {
566 PortEntry* entry =
reinterpret_cast<PortEntry*
>(
data);
567 delete entry;
568 }
569
570
571
572
573 CircularLinkedList<PortEntry*> active_readers_;
574
575
576
577 SimpleHashMap tokens_map_;
578
579 bool disable_tokens_;
580
582};
583
584}
585}
586
587
588#if defined(DART_HOST_OS_FUCHSIA)
590#elif defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
592#elif defined(DART_HOST_OS_MACOS)
594#elif defined(DART_HOST_OS_WINDOWS)
596#else
597#error Unknown target os.
598#endif
599
601namespace bin {
602
603class EventHandler {
604 public:
608 }
609
610
611
612
614
615
616
617
619
620
621
622
623
625
627
629
630 private:
633
635};
636
637}
638}
639
640#endif
static float next(float f)
static float prev(float f)
void SendData(intptr_t id, Dart_Port dart_port, int64_t data)
void NotifyShutdownDone()
static EventHandlerImplementation * delegate()
static void SendFromNative(intptr_t id, Dart_Port port, int64_t data)
void SendData(intptr_t id, Dart_Port dart_port, int64_t data)
friend class EventHandlerImplementation
#define IS_IO_EVENT(data)
#define IS_EVENT(data, event_bit)
static constexpr intptr_t kTimerId
static constexpr intptr_t kShutdownId
static constexpr intptr_t kInfinityTimeout
static constexpr intptr_t kInterruptMessageSize
static int8_t data[kExtLength]
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service port
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
void Close(PathBuilder *builder)