Chromium Code Reviews| Index: runtime/bin/eventhandler_linux.h |
| diff --git a/runtime/bin/eventhandler_linux.h b/runtime/bin/eventhandler_linux.h |
| index f6f3f9a2ac6f3885e76cbfee8c0f2b379778b8a6..a4e4e52e0aaf2d709c96493b2629f2f168d9ccd4 100644 |
| --- a/runtime/bin/eventhandler_linux.h |
| +++ b/runtime/bin/eventhandler_linux.h |
| @@ -28,13 +28,72 @@ class InterruptMessage { |
| int64_t data; |
| }; |
| +template<typename T> |
| +class LinkedList { |
|
Søren Gjesse
2014/04/25 12:24:44
Maybe call this CircularLinkedList as it is circul
Anders Johnsen
2014/05/01 11:34:50
Done.
|
| + public: |
| + LinkedList() : head_(NULL) {} |
| + |
| + bool Add(T t) { |
| + Entry* e = new Entry(t); |
| + if (head_ == NULL) { |
| + e->next_ = e; |
| + e->prev_ = e; |
| + head_ = e; |
| + return true; |
| + } else { |
| + e->prev_ = head_->prev_; |
| + e->next_ = head_; |
| + e->prev_->next_ = e; |
| + e->next_->prev_ = e; |
| + return false; |
| + } |
| + } |
| + void RemoveHead() { |
| + Entry* e = head_; |
| + if (e->next_ == e) { |
| + head_ = NULL; |
| + } else { |
| + e->prev_->next_ = e->next_; |
| + e->next_->prev_ = e->prev_; |
| + head_ = e->next_; |
| + } |
| + delete e; |
| + } |
| + |
| + T head() const { return head_->t; } |
| + |
| + bool HasHead() { |
| + return head_ != NULL; |
| + } |
| + |
| + void MoveNext() { |
| + head_ = head_->next_; |
| + } |
| + |
| + private: |
| + struct Entry { |
| + explicit Entry(const T& t) : t(t) {} |
| + const T t; |
| + Entry* next_; |
| + Entry* prev_; |
| + }; |
| + |
| + Entry* head_; |
| +}; |
| + |
| + |
| +class ListeningSocketData; |
| class SocketData { |
| public: |
| - explicit SocketData(intptr_t fd) : fd_(fd), port_(0), mask_(0), tokens_(16) { |
| + explicit SocketData(intptr_t fd) |
| + : fd_(fd), port_(0), mask_(0), tokens_(16) { |
| ASSERT(fd_ != -1); |
| } |
| + virtual ~SocketData() { |
| + } |
| + |
| intptr_t GetPollEvents(); |
| void Close() { |
| @@ -44,32 +103,46 @@ class SocketData { |
| fd_ = -1; |
| } |
| - void SetPortAndMask(Dart_Port port, intptr_t mask) { |
| + void SetMask(intptr_t mask) { |
| ASSERT(fd_ != -1); |
| - port_ = port; |
| mask_ = mask; |
| } |
| intptr_t fd() { return fd_; } |
| - Dart_Port port() { return port_; } |
| + virtual Dart_Port port() { return port_; } |
| + |
| + virtual bool IsListeningSocket() const { return false; } |
| - bool IsListeningSocket() { return (mask_ & (1 << kListeningSocket)) != 0; } |
| + virtual bool AddPort(Dart_Port port) { |
| + ASSERT(port_ = 0); |
| + port_ = port; |
| + return true; |
| + } |
| + |
| + virtual bool RemovePort(Dart_Port port) { |
| + ASSERT(port_ == port); |
| + return true; |
| + } |
| // Returns true if the last token was taken. |
| - bool TakeToken() { |
| + virtual bool TakeToken() { |
| ASSERT(tokens_ > 0); |
| tokens_--; |
| return tokens_ == 0; |
| } |
| // Returns true if the tokens was 0 before adding. |
| - bool ReturnToken() { |
| + virtual bool ReturnToken(Dart_Port port, int count) { |
| + ASSERT(port_ == port); |
| ASSERT(tokens_ >= 0); |
| - tokens_++; |
| - return tokens_ == 1; |
| + bool was_empty = tokens_ == 0; |
| + tokens_ += count; |
| + return was_empty; |
| } |
| - private: |
| + bool HasTokens() const { return tokens_ > 0; } |
| + |
| + protected: |
| intptr_t fd_; |
| Dart_Port port_; |
| intptr_t mask_; |
| @@ -77,6 +150,106 @@ class SocketData { |
| }; |
| +class ListeningSocketData : public SocketData { |
| + private: |
| + static bool SamePortValue(void* key1, void* key2) { |
| + return reinterpret_cast<Dart_Port>(key1) == |
| + reinterpret_cast<Dart_Port>(key2); |
| + } |
| + |
| + static uint32_t GetHashmapHashFromPort(Dart_Port port) { |
| + return static_cast<uint32_t>(port); |
|
Søren Gjesse
2014/04/25 12:24:44
Use (port & 0xffffffff).
Anders Johnsen
2014/05/01 11:34:50
Done.
|
| + } |
| + |
| + static void* GetHashmapKeyFromPort(Dart_Port port) { |
| + return reinterpret_cast<void*>(port); |
| + } |
| + |
| + public: |
| + explicit ListeningSocketData(intptr_t fd) |
| + : SocketData(fd), |
| + tokens_map_(&SamePortValue, 4) {} |
| + |
| + bool IsListeningSocket() const { return true; } |
| + |
| + bool AddPort(Dart_Port port) { |
| + HashMap::Entry* entry = tokens_map_.Lookup( |
| + GetHashmapKeyFromPort(port), GetHashmapHashFromPort(port), true); |
| + entry->value = reinterpret_cast<void*>(4); |
|
Søren Gjesse
2014/04/25 12:24:44
Please add a constant for this.
Anders Johnsen
2014/05/01 11:34:50
Done.
|
| + return live_ports_.Add(port); |
| + } |
| + |
| + virtual bool RemovePort(Dart_Port port) { |
| + HashMap::Entry* entry = tokens_map_.Lookup( |
| + GetHashmapKeyFromPort(port), GetHashmapHashFromPort(port), false); |
| + ASSERT(entry != NULL); |
| + intptr_t tokens = reinterpret_cast<intptr_t>(entry->value); |
| + if (tokens == 0) { |
| + while (idle_ports_.head() != port) { |
| + idle_ports_.MoveNext(); |
| + } |
| + idle_ports_.RemoveHead(); |
| + } else { |
| + while (live_ports_.head() != port) { |
| + live_ports_.MoveNext(); |
| + } |
| + live_ports_.RemoveHead(); |
| + } |
| + tokens_map_.Remove( |
| + GetHashmapKeyFromPort(port), GetHashmapHashFromPort(port)); |
| + return !live_ports_.HasHead(); |
| + } |
| + |
| + bool TakeToken() { |
| + ASSERT(live_ports_.HasHead()); |
| + Dart_Port port = live_ports_.head(); |
| + HashMap::Entry* entry = tokens_map_.Lookup( |
| + GetHashmapKeyFromPort(port), GetHashmapHashFromPort(port), false); |
| + ASSERT(entry != NULL); |
| + intptr_t tokens = reinterpret_cast<intptr_t>(entry->value); |
| + tokens--; |
| + entry->value = reinterpret_cast<void*>(tokens); |
| + if (tokens == 0) { |
| + live_ports_.RemoveHead(); |
| + idle_ports_.Add(port); |
| + if (!live_ports_.HasHead()) { |
| + return true; |
| + } |
| + } else { |
| + live_ports_.MoveNext(); |
| + } |
| + return false; |
| + } |
| + |
| + Dart_Port port() { return live_ports_.head(); } |
| + |
| + bool ReturnToken(Dart_Port port, int count) { |
| + HashMap::Entry* entry = tokens_map_.Lookup( |
| + GetHashmapKeyFromPort(port), GetHashmapHashFromPort(port), false); |
| + ASSERT(entry != NULL); |
| + intptr_t tokens = reinterpret_cast<intptr_t>(entry->value); |
| + tokens += count; |
| + entry->value = reinterpret_cast<void*>(tokens); |
| + if (tokens == count) { |
| + // Return to live_ports_. |
| + while (idle_ports_.head() != port) { |
| + idle_ports_.MoveNext(); |
| + } |
| + idle_ports_.RemoveHead(); |
| + bool was_empty = !live_ports_.HasHead(); |
| + live_ports_.Add(port); |
| + return was_empty; |
| + } |
| + return false; |
| + } |
| + |
| + private: |
| + LinkedList<Dart_Port> live_ports_; |
| + LinkedList<Dart_Port> idle_ports_; |
| + HashMap tokens_map_; |
| +}; |
| + |
| + |
| class EventHandlerImplementation { |
| public: |
| EventHandlerImplementation(); |
| @@ -84,7 +257,7 @@ class EventHandlerImplementation { |
| // Gets the socket data structure for a given file |
| // descriptor. Creates a new one if one is not found. |
| - SocketData* GetSocketData(intptr_t fd); |
| + SocketData* GetSocketData(intptr_t fd, bool is_listening); |
| void SendData(intptr_t id, Dart_Port dart_port, int64_t data); |
| void Start(EventHandler* handler); |
| void Shutdown(); |