5#ifndef RUNTIME_BIN_EVENTHANDLER_H_
6#define RUNTIME_BIN_EVENTHANDLER_H_
39#define COMMAND_MASK ((1 << kCloseCommand) | \
40 (1 << kShutdownReadCommand) | \
41 (1 << kShutdownWriteCommand) | \
42 (1 << kReturnTokenCommand) | \
43 (1 << kSetEventMaskCommand))
44#define EVENT_MASK ((1 << kInEvent) | \
46 (1 << kErrorEvent) | \
47 (1 << kCloseEvent) | \
48 (1 << kDestroyedEvent))
49#define IS_COMMAND(data, command_bit) \
50 ((data & COMMAND_MASK) == (1 << command_bit))
51#define IS_EVENT(data, event_bit) \
52 ((data & EVENT_MASK) == (1 << event_bit))
53#define IS_IO_EVENT(data) \
54 ((data & (1 << kInEvent | 1 << kOutEvent | 1 << kCloseEvent)) != 0 && \
55 (data & ~(1 << kInEvent | 1 << kOutEvent | 1 << kCloseEvent)) == 0)
56#define IS_LISTENING_SOCKET(data) \
57 ((data & (1 << kListeningSocket)) != 0)
58#define IS_SIGNAL_SOCKET(data) \
59 ((data & (1 << kSignalSocket)) != 0)
60#define TOKEN_COUNT(data) (data & ((1 << kCloseCommand) - 1))
76 return timeouts_.
Minimum().priority;
81 return timeouts_.
Minimum().value;
121 Entry* e =
new Entry(t);
122 if (head_ ==
nullptr) {
130 e->prev_ = head_->prev_;
145 e->prev_->next_ = e->next_;
146 e->next_->prev_ = e->prev_;
149 if (clear !=
nullptr) {
150 clear(
reinterpret_cast<void*
>(e->t));
156 if (head_ ==
nullptr) {
158 }
else if (head_ == head_->next_) {
159 if (head_->t == item) {
165 Entry* current = head_;
167 if (current->t == item) {
168 Entry*
next = current->next_;
169 Entry*
prev = current->prev_;
173 if (current == head_) {
174 head_ = head_->next_;
180 current = current->next_;
181 }
while (current != head_);
193 bool HasHead()
const {
return head_ !=
nullptr; }
196 if (head_ !=
nullptr) {
197 ASSERT(head_->next_ !=
nullptr);
198 head_ = head_->next_;
204 explicit Entry(
const T& t) : t(t), next_(nullptr), prev_(nullptr) {}
266template <
typename DI>
269 static constexpr int kTokenCount = 16;
275 tokens_(kTokenCount),
277 disable_tokens_(disable_tokens) {}
284 ASSERT(port_ == 0 || port == port_);
292 ASSERT(port_ == 0 || port_ == port);
305 if (!disable_tokens_) {
320 if (!disable_tokens_) {
327 if (!disable_tokens_) {
330 ASSERT(tokens_ <= kTokenCount);
340 virtual void Close() { DI::Close(); }
346 bool disable_tokens_;
356template <
typename DI>
359 static constexpr int kTokenCount = 4;
361 static bool SamePortValue(
void* key1,
void* key2) {
362 return reinterpret_cast<Dart_Port>(key1) ==
366 static uint32_t GetHashmapHashFromPort(
Dart_Port port) {
367 return static_cast<uint32_t
>(port & 0xFFFFFFFF);
370 static void* GetHashmapKeyFromPort(
Dart_Port port) {
371 return reinterpret_cast<void*
>(port);
374 static bool IsReadingMask(intptr_t mask) {
386 intptr_t token_count;
388 bool IsReady() {
return token_count > 0 && is_reading != 0; }
394 tokens_map_(&SamePortValue, kTokenCount),
395 disable_tokens_(disable_tokens) {}
403 GetHashmapKeyFromPort(port), GetHashmapHashFromPort(port),
true);
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);
412 if (pentry->IsReady()) {
413 active_readers_.
Add(pentry);
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();
421 if (was_ready && !is_ready) {
422 active_readers_.
Remove(pentry);
423 }
else if (!was_ready && is_ready) {
424 active_readers_.
Add(pentry);
432 if (active_readers_.
HasHead()) {
433 PortEntry* root =
reinterpret_cast<PortEntry*
>(active_readers_.
head());
434 PortEntry* current = root;
436 ASSERT(current->IsReady());
439 current = active_readers_.
head();
440 }
while (current != root);
444 entry = tokens_map_.
Next(entry)) {
445 PortEntry* pentry =
reinterpret_cast<PortEntry*
>(entry->
value);
446 if (pentry->IsReady()) {
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);
463 tokens_map_.
Remove(GetHashmapKeyFromPort(port),
464 GetHashmapHashFromPort(port));
481 entry = tokens_map_.
Next(entry)) {
482 PortEntry* pentry =
reinterpret_cast<PortEntry*
>(entry->value);
483 entry->value =
nullptr;
484 active_readers_.
Remove(pentry);
488 active_readers_.
RemoveAll(DeletePortEntry);
497 if (active_readers_.
HasHead()) {
498 PortEntry* pentry =
reinterpret_cast<PortEntry*
>(active_readers_.
head());
501 if (!disable_tokens_) {
502 pentry->token_count--;
504 if (pentry->token_count <= 0) {
510 return pentry->dart_port;
522 entry = tokens_map_.
Next(entry)) {
523 PortEntry* pentry =
reinterpret_cast<PortEntry*
>(entry->value);
527 bool was_ready = pentry->IsReady();
528 if (!disable_tokens_) {
529 pentry->token_count--;
532 if (was_ready && (pentry->token_count <= 0)) {
533 active_readers_.
Remove(pentry);
540 GetHashmapKeyFromPort(port), GetHashmapHashFromPort(port),
false);
543 PortEntry* pentry =
reinterpret_cast<PortEntry*
>(entry->
value);
544 bool was_ready = pentry->IsReady();
545 if (!disable_tokens_) {
546 pentry->token_count +=
count;
548 ASSERT(pentry->token_count <= kTokenCount);
549 bool is_ready = pentry->IsReady();
550 if (!was_ready && is_ready) {
551 active_readers_.
Add(pentry);
556 if (active_readers_.
HasHead()) {
562 virtual void Close() { DI::Close(); }
565 static void DeletePortEntry(
void*
data) {
566 PortEntry* entry =
reinterpret_cast<PortEntry*
>(
data);
573 CircularLinkedList<PortEntry*> active_readers_;
579 bool disable_tokens_;
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)
597#error Unknown target os.
static float next(float f)
static float prev(float f)
bool RemoveByValue(const V &value)
const Entry & Minimum() const
bool InsertOrChangePriority(const P &priority, const V &value)
void Clear(ClearFun clear=nullptr)
Entry * Lookup(void *key, uint32_t hash, bool insert)
void Remove(void *key, uint32_t hash)
Entry * Next(Entry *p) const
void RemoveAll(ClearFun clear=nullptr)
void(* ClearFun)(void *value)
void RemoveHead(ClearFun clear=nullptr)
static bool PostInt32(Dart_Port port_id, int32_t value)
virtual void RemoveAllPorts()=0
virtual void RemovePort(Dart_Port port)=0
virtual void ReturnTokens(Dart_Port port, int count)=0
virtual ~DescriptorInfoBase()
virtual void SetPortAndMask(Dart_Port port, intptr_t mask)=0
virtual void NotifyAllDartPorts(uintptr_t events)=0
virtual Dart_Port NextNotifyDartPort(intptr_t events_ready)=0
virtual intptr_t Mask()=0
DescriptorInfoBase(intptr_t fd)
virtual bool IsListeningSocket() const =0
virtual ~DescriptorInfoMultipleMixin()
virtual void SetPortAndMask(Dart_Port port, intptr_t mask)
DescriptorInfoMultipleMixin(intptr_t fd, bool disable_tokens)
virtual void RemovePort(Dart_Port port)
virtual void NotifyAllDartPorts(uintptr_t events)
virtual Dart_Port NextNotifyDartPort(intptr_t events_ready)
virtual void RemoveAllPorts()
virtual void ReturnTokens(Dart_Port port, int count)
virtual bool IsListeningSocket() const
virtual bool IsListeningSocket() const
virtual Dart_Port NextNotifyDartPort(intptr_t events_ready)
virtual void ReturnTokens(Dart_Port port, int count)
virtual void SetPortAndMask(Dart_Port port, intptr_t mask)
DescriptorInfoSingleMixin(intptr_t fd, bool disable_tokens)
virtual void NotifyAllDartPorts(uintptr_t events)
virtual void RemoveAllPorts()
virtual void RemovePort(Dart_Port port)
virtual ~DescriptorInfoSingleMixin()
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)
Dart_Port CurrentPort() const
void UpdateTimeout(Dart_Port port, int64_t timeout)
int64_t CurrentTimeout() const
#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]