| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #pragma once
- class MessageBase
- {
- private:
- unsigned int m_time;
- unsigned int m_id;
- static unsigned int s_messageCount;
- MessageBase(const MessageBase&);
- public:
- MessageBase(unsigned int time) : m_time(time), m_id(s_messageCount++) { }
- virtual ~MessageBase() { }
- void BeginTimer() { m_time += GetTickCount(); };
- unsigned int GetTime() { return m_time; };
- unsigned int GetId() { return m_id; };
- virtual HRESULT Call(LPCSTR fileName) = 0;
- };
- template <typename T>
- class SortedList
- {
- template <typename T>
- struct DListNode
- {
- T data;
- DListNode<T>* prev;
- DListNode<T>* next;
- public:
- DListNode(const T& data) :
- data(data),
- prev(nullptr),
- next(nullptr)
- { }
- };
- public:
- SortedList():
- head(nullptr)
- {
- }
- ~SortedList()
- {
- while (head != nullptr)
- {
- Remove(head);
- }
- }
- // Scan through the sorted list
- // Insert before the first node that satisfies the LessThan function
- // This function maintains the invariant that the list is always sorted
- void Insert(const T& data)
- {
- DListNode<T>* curr = head;
- DListNode<T>* node = new DListNode<T>(data);
- DListNode<T>* prev = nullptr;
- // Now, if we have to insert, we have to insert *after* some node
- while (curr != nullptr)
- {
- if (T::LessThan(data, curr->data))
- {
- break;
- }
- prev = curr;
- curr = curr->next;
- }
- InsertAfter(node, prev);
- }
- T Pop()
- {
- T data = head->data;
- Remove(head);
- return data;
- }
- template <typename PredicateFn>
- void Remove(PredicateFn fn)
- {
- DListNode<T>* node = head;
- while (node != nullptr)
- {
- if (fn(node->data))
- {
- Remove(node);
- return;
- }
- }
- }
- template <typename PredicateFn>
- void RemoveAll(PredicateFn fn)
- {
- while (head != nullptr)
- {
- fn(head->data);
- Remove(head);
- }
- }
- bool IsEmpty()
- {
- return head == nullptr;
- }
- private:
- void Remove(DListNode<T>* node)
- {
- if (node->prev == nullptr)
- {
- head = node->next;
- }
- else
- {
- node->prev->next = node->next;
- }
- if (node->next != nullptr)
- {
- node->next->prev = node->prev;
- }
- delete node;
- }
- void InsertAfter(DListNode<T>* newNode, DListNode<T>* node)
- {
- // If the list is empty, just set head to newNode
- if (head == nullptr)
- {
- Assert(node == nullptr);
- head = newNode;
- return;
- }
- // If node is null here, we must be trying to insert before head
- if (node == nullptr)
- {
- newNode->next = head;
- head->prev = newNode;
- head = newNode;
- return;
- }
- Assert(node);
- newNode->next = node->next;
- newNode->prev = node;
- if (node->next)
- {
- node->next->prev = newNode;
- }
- node->next = newNode;
- }
- DListNode<T>* head;
- };
- class MessageQueue
- {
- struct ListEntry
- {
- unsigned int time;
- MessageBase* message;
- ListEntry(unsigned int time, MessageBase* message):
- time(time),
- message(message)
- { }
- static bool LessThan(const ListEntry& first, const ListEntry& second)
- {
- return first.time < second.time;
- }
- };
- SortedList<ListEntry> m_queue;
- public:
- void InsertSorted(MessageBase *message)
- {
- message->BeginTimer();
- unsigned int time = message->GetTime();
- m_queue.Insert(ListEntry(time, message));
- }
- MessageBase* PopAndWait()
- {
- Assert(!m_queue.IsEmpty());
- ListEntry entry = m_queue.Pop();
- MessageBase *tmp = entry.message;
- int waitTime = tmp->GetTime() - GetTickCount();
- if(waitTime > 0)
- {
- Sleep(waitTime);
- }
- return tmp;
- }
- bool IsEmpty()
- {
- return m_queue.IsEmpty();
- }
- void RemoveById(unsigned int id)
- {
- // Search for the message with the correct id, and delete it. Can be updated
- // to a hash to improve speed, if necessary.
- m_queue.Remove([id](const ListEntry& entry)
- {
- MessageBase *msg = entry.message;
- if(msg->GetId() == id)
- {
- delete msg;
- return true;
- }
- return false;
- });
- }
- void RemoveAll()
- {
- m_queue.RemoveAll([](const ListEntry& entry) {
- MessageBase* msg = entry.message;
- delete msg;
- });
- }
- HRESULT ProcessAll(LPCSTR fileName)
- {
- while(!IsEmpty())
- {
- MessageBase *msg = PopAndWait();
- // Omit checking return value for async function, since it shouldn't affect others.
- msg->Call(fileName);
- delete msg;
- ChakraRTInterface::JsTTDNotifyYield();
- }
- return S_OK;
- }
- };
- //
- // A custom message helper class to assist defining messages handled by callback functions.
- //
- template <class Func, class CustomBase>
- class CustomMessage : public CustomBase
- {
- private:
- Func m_func;
- public:
- CustomMessage(unsigned int time, JsValueRef customArg, const Func& func) :
- CustomBase(time, customArg), m_func(func)
- {}
- virtual HRESULT Call(LPCSTR fileName) override
- {
- return m_func(*this);
- }
- };
|