2
0
Эх сурвалжийг харах

Fixed crash in FileWatcher on exit when FileSystem had already been destroyed.
Added start/end caching to Map & Set.
Container code cleanup.

Lasse Öörni 13 жил өмнө
parent
commit
9baf3bad64

+ 2 - 2
Engine/Container/HashMap.h

@@ -391,9 +391,9 @@ public:
     bool Empty() const { return size_ == 0; }
     
 private:
-    /// Return the head pointer with correct type.
+    /// Return the head node.
     Node* Head() const { return reinterpret_cast<Node*>(head_); }
-    /// Return the tail pointer with correct type.
+    /// Return the tail node.
     Node* Tail() const { return reinterpret_cast<Node*>(tail_); }
     
     /// Find a node from the buckets. Do not call if the buckets have not been allocated.

+ 2 - 2
Engine/Container/HashSet.h

@@ -361,9 +361,9 @@ public:
     bool Empty() const { return size_ == 0; }
     
 private:
-    /// Return the head pointer with correct type.
+    /// Return the head node.
     Node* Head() const { return reinterpret_cast<Node*>(head_); }
-    /// Return the tail pointer with correct type.
+    /// Return the tail node.
     Node* Tail() const { return reinterpret_cast<Node*>(tail_); }
     
     /// Find a node from the buckets. Do not call if the buckets have not been allocated.

+ 2 - 2
Engine/Container/List.h

@@ -328,9 +328,9 @@ public:
     bool Empty() const { return size_ == 0; }
     
 private:
-    /// Return the head pointer with correct type.
+    /// Return the head node.
     Node* Head() const { return reinterpret_cast<Node*>(head_); }
-    /// Return the tail pointer with correct type.
+    /// Return the tail node.
     Node* Tail() const { return reinterpret_cast<Node*>(tail_); }
     
     /// Allocate and insert a node into the list.

+ 72 - 33
Engine/Container/Map.h

@@ -160,7 +160,7 @@ public:
     /// Construct from another map.
     Map(const Map<T, U>& map)
     {
-        allocator_ = AllocatorInitialize(sizeof(Node), map.Size());
+        allocator_ = AllocatorInitialize(sizeof(Node), map.Size() + 1);
         *this = map;
     }
     
@@ -168,6 +168,13 @@ public:
     ~Map()
     {
         Clear();
+        
+        if (head_)
+        {
+            FreeNode(reinterpret_cast<Node*>(head_));
+            head_ = 0;
+        }
+        
         AllocatorUninitialize(allocator_);
     }
     
@@ -253,7 +260,7 @@ public:
             return;
         
         EraseNodes(root);
-        root_ = 0;
+        head_->parent_ = 0;
     }
     
     /// Insert a pair and return iterator to it.
@@ -318,26 +325,42 @@ public:
     bool Empty() const { return size_ == 0; }
     
 private:
-    /// Return the root pointer with correct type.
-    Node* Root() const { return reinterpret_cast<Node*>(root_); }
+    /// Return the root node, or 0 if empty.
+    Node* Root() const { return head_ ? reinterpret_cast<Node*>(head_->parent_) : 0; }
     
     /// Find the node with smallest key.
-    /// \todo Should be cached
     Node* FindFirst() const
     {
-        Node* node = Root();
+        if (!head_)
+            return 0;
+        
+        // Check cached node first
+        if (head_->link_[0])
+            return reinterpret_cast<Node*>(head_->link_[0]);
+        
+        Node* node = reinterpret_cast<Node*>(head_->parent_);
         while (node && node->link_[0])
             node = node->Child(0);
+        
+        head_->link_[0] = node;
         return node;
     }
     
     /// Find the node with largest key.
-    /// \todo Should be cached
     Node* FindLast() const
     {
-        Node* node = Root();
+        if (!head_)
+            return 0;
+        
+        // Check cached node first
+        if (head_->link_[1])
+            return reinterpret_cast<Node*>(head_->link_[1]);
+        
+        Node* node = reinterpret_cast<Node*>(head_->parent_);
         while (node && node->link_[1])
             node = node->Child(1);
+        
+        head_->link_[1] = node;
         return node;
     }
     
@@ -360,23 +383,33 @@ private:
     {
         Node* ret = 0;
         
-        if (!root_)
+        if (!allocator_)
+            allocator_ = AllocatorInitialize(sizeof(Node));
+        if (!head_)
+            head_ = ReserveNode();
+        
+        if (!head_->parent_)
         {
-            root_ = ret = ReserveNode(key, value);
+            head_->parent_ = ret = ReserveNode(key, value);
+            head_->link_[0] = head_->parent_;
+            head_->link_[1] = head_->parent_;
             ++size_;
         }
         else
         {
-            Node head;
-            Node* g, * t, * p, * q;
+            Node h;
+            Node* g;
+            Node* t;
+            Node* p;
+            Node* q;
             
             unsigned dir = 0;
             unsigned last = 0;
             
-            t = &head;
+            t = &h;
             g = p = 0;
-            q = Root();
-            t->SetChild(1, Root());
+            q = reinterpret_cast<Node*>(head_->parent_);
+            t->SetChild(1, q);
             
             for (;;)
             {
@@ -418,11 +451,15 @@ private:
                 q = q->Child(dir);
             }
             
-            root_ = head.Child(1);
+            head_->parent_ = h.Child(1);
+            
+            // Invalidate cached first and last nodes
+            head_->link_[0] = 0;
+            head_->link_[1] = 0;
         }
         
-        root_->isRed_ = false;
-        root_->parent_ = 0;
+        head_->parent_->isRed_ = false;
+        head_->parent_->parent_ = 0;
         
         return ret;
     }
@@ -430,18 +467,20 @@ private:
     /// Erase a node. Return true if was erased.
     bool EraseNode(const T& key)
     {
-        if (!root_)
+        if (!head_ || !head_->parent_)
             return false;
         
-        Node head;
-        Node* q, * p, *g;
-        Node* f = 0;
+        Node h;
+        Node* q;
+        Node* p;
+        Node* g;
+        Node* f;
         unsigned dir = 1;
         bool removed = false;
         
-        q = &head;
-        g = p = 0;
-        q->SetChild(1, Root());
+        q = &h;
+        f = g = p = 0;
+        q->SetChild(1, head_->parent_);
         
         while (q->link_[dir])
         {
@@ -501,13 +540,17 @@ private:
             removed = true;
         }
         
-        root_ = head.Child(1);
-        if (root_)
+        head_->parent_ = h.Child(1);
+        if (head_->parent_)
         {
-            root_->isRed_ = false;
-            root_->parent_ = 0;
+            head_->parent_->isRed_ = false;
+            head_->parent_->parent_ = 0;
         }
         
+        // Invalidate cached first and last nodes
+        head_->link_[0] = 0;
+        head_->link_[1] = 0;
+        
         return removed;
     }
     
@@ -528,8 +571,6 @@ private:
     /// Reserve a node.
     Node* ReserveNode()
     {
-        if (!allocator_)
-            allocator_ = AllocatorInitialize(sizeof(Node));
         Node* newNode = static_cast<Node*>(AllocatorReserve(allocator_));
         new(newNode) Node();
         return newNode;
@@ -538,8 +579,6 @@ private:
     /// Reserve a node with specified key and value.
     Node* ReserveNode(const T& key, const U& value)
     {
-        if (!allocator_)
-            allocator_ = AllocatorInitialize(sizeof(Node));
         Node* newNode = static_cast<Node*>(AllocatorReserve(allocator_));
         new(newNode) Node(key, value);
         return newNode;

+ 72 - 34
Engine/Container/Set.h

@@ -131,7 +131,7 @@ public:
     /// Construct from another set.
     Set(const Set<T>& set)
     {
-        allocator_ = AllocatorInitialize(sizeof(Node), set.Size());
+        allocator_ = AllocatorInitialize(sizeof(Node), set.Size() + 1);
         *this = set;
     }
     
@@ -139,6 +139,13 @@ public:
     ~Set()
     {
         Clear();
+        
+        if (head_)
+        {
+            FreeNode(reinterpret_cast<Node*>(head_));
+            head_ = 0;
+        }
+        
         AllocatorUninitialize(allocator_);
     }
     
@@ -211,7 +218,7 @@ public:
             return;
         
         EraseNodes(root);
-        root_ = 0;
+        head_->parent_ = 0;
     }
     
     /// Insert a key. Return iterator to the value.
@@ -269,26 +276,42 @@ public:
     bool Empty() const { return size_ == 0; }
     
 private:
-    /// Return the root pointer with correct type.
-    Node* Root() const { return reinterpret_cast<Node*>(root_); }
+    /// Return the root node, or 0 if empty.
+    Node* Root() const { return head_ ? reinterpret_cast<Node*>(head_->parent_) : 0; }
     
     /// Find the node with smallest key.
-    /// \todo Should be cached
     Node* FindFirst() const
     {
-        Node* node = Root();
+        if (!head_)
+            return 0;
+        
+        // Check cached node first
+        if (head_->link_[0])
+            return reinterpret_cast<Node*>(head_->link_[0]);
+        
+        Node* node = reinterpret_cast<Node*>(head_->parent_);
         while (node && node->link_[0])
             node = node->Child(0);
+        
+        head_->link_[0] = node;
         return node;
     }
     
     /// Find the node with largest key.
-    /// \todo Should be cached
     Node* FindLast() const
     {
-        Node* node = Root();
+        if (!head_)
+            return 0;
+        
+        // Check cached node first
+        if (head_->link_[1])
+            return reinterpret_cast<Node*>(head_->link_[1]);
+        
+        Node* node = reinterpret_cast<Node*>(head_->parent_);
         while (node && node->link_[1])
             node = node->Child(1);
+        
+        head_->link_[1] = node;
         return node;
     }
     
@@ -311,23 +334,33 @@ private:
     {
         Node* ret = 0;
         
-        if (!root_)
+        if (!allocator_)
+            allocator_ = AllocatorInitialize(sizeof(Node));
+        if (!head_)
+            head_ = ReserveNode();
+        
+        if (!head_->parent_)
         {
-            root_ = ret = ReserveNode(key);
+            head_->parent_ = ret = ReserveNode(key);
+            head_->link_[0] = head_->parent_;
+            head_->link_[1] = head_->parent_;
             ++size_;
         }
         else
         {
-            Node head;
-            Node* g, * t, * p, * q;
+            Node h;
+            Node* g;
+            Node* t;
+            Node* p;
+            Node* q;
             
             unsigned dir = 0;
             unsigned last = 0;
             
-            t = &head;
+            t = &h;
             g = p = 0;
-            q = Root();
-            t->SetChild(1, Root());
+            q = reinterpret_cast<Node*>(head_->parent_);
+            t->SetChild(1, q);
             
             for (;;)
             {
@@ -368,11 +401,15 @@ private:
                 q = q->Child(dir);
             }
             
-            root_ = head.Child(1);
+            head_->parent_ = h.Child(1);
+            
+            // Invalidate cached first and last nodes
+            head_->link_[0] = 0;
+            head_->link_[1] = 0;
         }
         
-        root_->isRed_ = false;
-        root_->parent_ = 0;
+        head_->parent_->isRed_ = false;
+        head_->parent_->parent_ = 0;
         
         return ret;
     }
@@ -380,18 +417,20 @@ private:
     /// Erase a node. Return true if was erased.
     bool EraseNode(const T& key)
     {
-        if (!root_)
+        if (!head_ || !head_->parent_)
             return false;
         
-        Node head;
-        Node* q, * p, *g;
-        Node* f = 0;
+        Node h;
+        Node* q;
+        Node* p;
+        Node* g;
+        Node* f;
         unsigned dir = 1;
         bool removed = false;
         
-        q = &head;
-        g = p = 0;
-        q->SetChild(1, Root());
+        q = &h;
+        f = g = p = 0;
+        q->SetChild(1, head_->parent_);
         
         while (q->link_[dir])
         {
@@ -450,13 +489,17 @@ private:
             removed = true;
         }
         
-        root_ = head.Child(1);
-        if (root_)
+        head_->parent_ = h.Child(1);
+        if (head_->parent_)
         {
-            root_->isRed_ = false;
-            root_->parent_ = 0;
+            head_->parent_->isRed_ = false;
+            head_->parent_->parent_ = 0;
         }
         
+        // Invalidate cached first and last nodes
+        head_->link_[0] = 0;
+        head_->link_[1] = 0;
+        
         return removed;
     }
     
@@ -477,19 +520,14 @@ private:
     /// Reserve a node.
     Node* ReserveNode()
     {
-        if (!allocator_)
-            allocator_ = AllocatorInitialize(sizeof(Node));
         Node* newNode = static_cast<Node*>(AllocatorReserve(allocator_));
         new(newNode) Node();
-        
         return newNode;
     }
     
     /// Reserve a node with specified key.
     Node* ReserveNode(const T& key)
     {
-        if (!allocator_)
-            allocator_ = AllocatorInitialize(sizeof(Node));
         Node* newNode = static_cast<Node*>(AllocatorReserve(allocator_));
         new(newNode) Node(key);
         return newNode;

+ 4 - 4
Engine/Container/TreeBase.h

@@ -140,7 +140,7 @@ class TreeBase
 public:
     /// Construct.
     TreeBase() :
-        root_(0),
+        head_(0),
         allocator_(0),
         size_(0)
     {
@@ -149,7 +149,7 @@ public:
     /// Swap with another tree.
     void Swap(TreeBase& rhs)
     {
-        ::Swap(root_, rhs.root_);
+        ::Swap(head_, rhs.head_);
         ::Swap(allocator_, rhs.allocator_);
         ::Swap(size_, rhs.size_);
     }
@@ -179,8 +179,8 @@ protected:
         return RotateSingle(node, dir);
     }
     
-    /// Root node.
-    TreeNodeBase* root_;
+    /// Head node.
+    TreeNodeBase* head_;
     /// Node allocator.
     AllocatorBlock* allocator_;
     /// Number of nodes.

+ 0 - 3
Engine/Core/Context.cpp

@@ -57,9 +57,6 @@ Context::Context() :
 
 Context::~Context()
 {
-    // Release the subsystems before the event receiver maps are destroyed
-    //for (HashMap<ShortStringHash, SharedPtr<Object> >::Iterator i = subsystems_.Begin(); i != subsystems_.End(); ++i)
-    //    i->second_.Reset();
     subsystems_.Clear();
     factories_.Clear();
 }

+ 9 - 1
Engine/IO/FileWatcher.cpp

@@ -37,6 +37,7 @@ OBJECTTYPESTATIC(FileWatcher);
 
 FileWatcher::FileWatcher(Context* context) :
     Object(context),
+    fileSystem_(GetSubsystem<FileSystem>()),
     watchSubDirs_(false)
 {
 }
@@ -48,6 +49,12 @@ FileWatcher::~FileWatcher()
 
 bool FileWatcher::StartWatching(const String& pathName, bool watchSubDirs)
 {
+    if (!fileSystem_)
+    {
+        LOGERROR("No FileSystem, can not start watching");
+        return false;
+    }
+    
     // Stop any previous watching
     StopWatching();
     
@@ -93,7 +100,8 @@ void FileWatcher::StopWatching()
         String dummyFileName = path_ + "dummy.tmp";
         File file(context_, dummyFileName, FILE_WRITE);
         file.Close();
-        GetSubsystem<FileSystem>()->Delete(dummyFileName);
+        if (fileSystem_)
+            fileSystem_->Delete(dummyFileName);
         
         Stop();
         

+ 4 - 0
Engine/IO/FileWatcher.h

@@ -28,6 +28,8 @@
 #include "Object.h"
 #include "Thread.h"
 
+class FileSystem;
+
 /// Watches a directory and its subdirectories for files being modified
 class FileWatcher : public Object, public Thread
 {
@@ -53,6 +55,8 @@ public:
     const String& GetPath() const { return path_; }
     
 private:
+    /// Filesystem.
+    SharedPtr<FileSystem> fileSystem_;
     /// The path being watched.
     String path_;
     /// Buffered file changes.