From e7a4b8e24eb5fc27e36b6e494f1b42098572857a Mon Sep 17 00:00:00 2001
From: Marcel Greter <marcel.greter@ocbnet.ch>
Date: Sun, 19 May 2019 00:57:45 +0200
Subject: [PATCH 12/12] Revert shared pointer implementation

# Conflicts:
#	src/memory/SharedPtr.hpp

Revert shared pointer implementation

# Conflicts:
#	src/memory/SharedPtr.hpp
---
 src/memory/SharedPtr.cpp |  85 ++++++++++++-
 src/memory/SharedPtr.hpp | 267 +++++++++++++++++++++------------------
 2 files changed, 230 insertions(+), 122 deletions(-)

diff --git a/src/memory/SharedPtr.cpp b/src/memory/SharedPtr.cpp
index db0ff1d4..05d01136 100644
--- a/src/memory/SharedPtr.cpp
+++ b/src/memory/SharedPtr.cpp
@@ -18,7 +18,7 @@ namespace Sass {
       std::cerr << "# REPORTING MISSING DEALLOCATIONS #\n";
       std::cerr << "###################################\n";
       for (SharedObj* var : all) {
-        if (AST_Node* ast = dynamic_cast<AST_Node*>(var)) {
+        if (AST_Node_Ptr ast = dynamic_cast<AST_Node*>(var)) {
           debug_ast(ast);
         } else {
           std::cerr << "LEAKED " << var << "\n";
@@ -30,4 +30,85 @@ namespace Sass {
   #endif
 
   bool SharedObj::taint = false;
-}
+
+  SharedObj::SharedObj()
+  : detached(false)
+    #ifdef DEBUG_SHARED_PTR
+    , dbg(false)
+    #endif
+  {
+    refcounter = 0;
+    #ifdef DEBUG_SHARED_PTR
+      if (taint) all.push_back(this);
+    #endif
+  };
+
+  SharedObj::~SharedObj() {
+    #ifdef DEBUG_SHARED_PTR
+      if (dbg) std::cerr << "Destruct " << this << "\n";
+      if(!all.empty()) { // check needed for MSVC (no clue why?)
+        all.erase(std::remove(all.begin(), all.end(), this), all.end());
+      }
+    #endif
+  };
+
+  void SharedPtr::decRefCount() {
+    if (node) {
+      -- node->refcounter;
+      #ifdef DEBUG_SHARED_PTR
+        if (node->dbg)  std::cerr << "- " << node << " X " << node->refcounter << " (" << this << ") " << "\n";
+      #endif
+      if (node->refcounter == 0) {
+        #ifdef DEBUG_SHARED_PTR
+          // AST_Node_Ptr ast = dynamic_cast<AST_Node*>(node);
+          if (node->dbg) std::cerr << "DELETE NODE " << node << "\n";
+        #endif
+        if (!node->detached) {
+          delete(node);
+        }
+      }
+    }
+  }
+
+  void SharedPtr::incRefCount() {
+    if (node) {
+      ++ node->refcounter;
+      node->detached = false;
+      #ifdef DEBUG_SHARED_PTR
+        if (node->dbg) {
+          std::cerr << "+ " << node << " X " << node->refcounter << " (" << this << ") " << "\n";
+        }
+      #endif
+    }
+  }
+
+  SharedPtr::~SharedPtr() {
+    decRefCount();
+  }
+
+
+  // the create constructor
+  SharedPtr::SharedPtr(SharedObj* ptr)
+  : node(ptr) {
+    incRefCount();
+  }
+  // copy assignment operator
+  SharedPtr& SharedPtr::operator=(const SharedPtr& rhs) {
+    void* cur_ptr = (void*) node;
+    void* rhs_ptr = (void*) rhs.node;
+    if (cur_ptr == rhs_ptr) {
+      return *this;
+    }
+    decRefCount();
+    node = rhs.node;
+    incRefCount();
+    return *this;
+  }
+
+  // the copy constructor
+  SharedPtr::SharedPtr(const SharedPtr& obj)
+  : node(obj.node) {
+    incRefCount();
+  }
+
+}
\ No newline at end of file
diff --git a/src/memory/SharedPtr.hpp b/src/memory/SharedPtr.hpp
index 1c9d5653..09bfe72c 100644
--- a/src/memory/SharedPtr.hpp
+++ b/src/memory/SharedPtr.hpp
@@ -3,8 +3,6 @@
 
 #include "sass/base.h"
 
-#include <iostream>
-#include <string>
 #include <vector>
 
 namespace Sass {
@@ -41,148 +39,177 @@ namespace Sass {
   #endif
 
   class SharedObj {
-   public:
-    SharedObj() : refcount(0), detached(false) {
-      #ifdef DEBUG_SHARED_PTR
-      if (taint) all.push_back(this);
-      #endif
-    }
-    virtual ~SharedObj() {
-      #ifdef DEBUG_SHARED_PTR
-      all.clear();
-      #endif
-    }
-
+  protected:
+  friend class SharedPtr;
+  friend class Memory_Manager;
     #ifdef DEBUG_SHARED_PTR
-    static void dumpMemLeaks();
-    SharedObj* trace(std::string file, size_t line) {
-      this->file = file;
-      this->line = line;
-      return this;
-    }
-    std::string getDbgFile() { return file; }
-    size_t getDbgLine() { return line; }
-    void setDbg(bool dbg) { this->dbg = dbg; }
-    size_t getRefCount() const { return refcount; }
+      static std::vector<SharedObj*> all;
+      std::string file;
+      size_t line;
     #endif
-
-    static void setTaint(bool val) { taint = val; }
-
-    virtual const std::string to_string() const = 0;
-   protected:
-    friend class SharedPtr;
-    friend class Memory_Manager;
-    size_t refcount;
-    bool detached;
     static bool taint;
+    long refcounter;
+    // long refcount;
+    bool detached;
     #ifdef DEBUG_SHARED_PTR
-    std::string file;
-    size_t line;
-    bool dbg = false;
-    static std::vector<SharedObj*> all;
+      bool dbg;
     #endif
-  };
-
-  class SharedPtr {
-   public:
-    SharedPtr() : node(nullptr) {}
-    SharedPtr(SharedObj* ptr) : node(ptr) {
-      incRefCount();
-    }
-    SharedPtr(const SharedPtr& obj) : SharedPtr(obj.node) {}
-    ~SharedPtr() {
-      decRefCount();
-    }
-
-    SharedPtr& operator=(SharedObj* other_node) {
-      if (node != other_node) {
-        decRefCount();
-        node = other_node;
-        incRefCount();
-      } else if (node != nullptr) {
-        node->detached = false;
+  public:
+    #ifdef DEBUG_SHARED_PTR
+      static void dumpMemLeaks();
+      SharedObj* trace(std::string file, size_t line) {
+        this->file = file;
+        this->line = line;
+        return this;
       }
-      return *this;
+    #endif
+    SharedObj();
+    #ifdef DEBUG_SHARED_PTR
+      std::string getDbgFile() {
+        return file;
+      }
+      size_t getDbgLine() {
+        return line;
+      }
+      void setDbg(bool dbg) {
+        this->dbg = dbg;
+      }
+    #endif
+    static void setTaint(bool val) {
+      taint = val;
     }
 
-    SharedPtr& operator=(const SharedPtr& obj) {
-      return *this = obj.node;
-    }
+    virtual const std::string to_string() const = 0;
 
-    // Prevents all SharedPtrs from freeing this node until it is assigned to another SharedPtr.
-    SharedObj* detach() {
-      if (node != nullptr) node->detached = true;
-      return node;
+    virtual ~SharedObj();
+    long getRefCount() {
+      return refcounter;
     }
+  };
 
-    SharedObj* obj() const { return node; }
-    SharedObj* operator->() const { return node; }
-    bool isNull() const { return node == nullptr; }
-    operator bool() const { return node != nullptr; }
 
-   protected:
+  class SharedPtr {
+  protected:
     SharedObj* node;
-    void decRefCount() {
-      if (node == nullptr) return;
-      --node->refcount;
-      #ifdef DEBUG_SHARED_PTR
-      if (node->dbg) std::cerr << "- " << node << " X " << node->refcount << " (" << this << ") " << "\n";
-      #endif
-      if (node->refcount == 0 && !node->detached) {
-        #ifdef DEBUG_SHARED_PTR
-        if (node->dbg) std::cerr << "DELETE NODE " << node << "\n";
-        #endif
-        delete node;
+  protected:
+    void decRefCount();
+    void incRefCount();
+  public:
+    // the empty constructor
+    SharedPtr()
+    : node(NULL) {};
+    // the create constructor
+    SharedPtr(SharedObj* ptr);
+    // the copy constructor
+    SharedPtr(const SharedPtr& obj);
+    // the move constructor
+    SharedPtr(SharedPtr&& obj);
+    // copy assignment operator
+    SharedPtr& operator=(const SharedPtr& obj);
+    // move assignment operator
+    SharedPtr& operator=(SharedPtr&& obj);
+    // pure virtual destructor
+    virtual ~SharedPtr() = 0;
+  public:
+    SharedObj* obj () const {
+      return node;
+    };
+    SharedObj* operator-> () const {
+      return node;
+    };
+    bool isNull () {
+      return node == NULL;
+    };
+    bool isNull () const {
+      return node == NULL;
+    };
+    SharedObj* detach() const {
+      if (node) {
+        node->detached = true;
       }
-    }
-    void incRefCount() {
-      if (node == nullptr) return;
-      node->detached = false;
-      ++node->refcount;
-      #ifdef DEBUG_SHARED_PTR
-      if (node->dbg) std::cerr << "+ " << node << " X " << node->refcount << " (" << this << ") " << "\n";
-      #endif
-    }
+      return node;
+    };
+    operator bool() const {
+      return node != NULL;
+    };
+
   };
 
-  template <class T>
+  template < class T >
   class SharedImpl : private SharedPtr {
-   public:
-    SharedImpl() : SharedPtr(nullptr) {}
-
-    template <class U>
-    SharedImpl(U* node) :
-      SharedPtr(static_cast<T*>(node)) {}
-
-    template <class U>
-    SharedImpl(const SharedImpl<U>& impl) :
-      SharedImpl(impl.ptr()) {}
-
-    template <class U>
-    SharedImpl<T>& operator=(U *rhs) {
-      return static_cast<SharedImpl<T>&>(
-        SharedPtr::operator=(static_cast<T*>(rhs)));
+  public:
+    SharedImpl()
+    : SharedPtr(NULL) {};
+    SharedImpl(T* node)
+    : SharedPtr(node) {};
+    template < class U >
+    SharedImpl(SharedImpl<U> obj)
+    : SharedPtr(static_cast<T*>(obj.ptr())) {}
+    SharedImpl(T&& node)
+    : SharedPtr(node) {};
+    SharedImpl(const T& node)
+    : SharedPtr(node) {};
+    // the copy constructor
+    SharedImpl(const SharedImpl<T>& impl)
+    : SharedPtr(impl.node) {};
+    // the move constructor
+    SharedImpl(SharedImpl<T>&& impl)
+    : SharedPtr(impl.node) {};
+    // copy assignment operator
+    SharedImpl<T>& operator=(const SharedImpl<T>& rhs) {
+      if (node) decRefCount();
+      node = rhs.node;
+      incRefCount();
+      return *this;
     }
-
-    template <class U>
-    SharedImpl<T>& operator=(const SharedImpl<U>& rhs) {
-      return static_cast<SharedImpl<T>&>(
-        SharedPtr::operator=(static_cast<const SharedImpl<T>&>(rhs)));
+    // move assignment operator
+    SharedImpl<T>& operator=(SharedImpl<T>&& rhs) {
+      // don't move our self
+      if (this != &rhs) {
+        if (node) decRefCount();
+        node = std::move(rhs.node);
+        rhs.node = NULL;
+      }
+      return *this;
     }
 
+    // allow implicit conversion to string
+    // relies on base class implementation
     operator const std::string() const {
       if (node) return node->to_string();
-      return "[nullptr]";
+      else return std::string("[NULLPTR]");
     }
 
-    using SharedPtr::isNull;
-    using SharedPtr::operator bool;
-    operator T*() const { return static_cast<T*>(this->obj()); }
-    operator T&() const { return *static_cast<T*>(this->obj()); }
-    T& operator* () const { return *static_cast<T*>(this->obj()); };
-    T* operator-> () const { return static_cast<T*>(this->obj()); };
-    T* ptr () const { return static_cast<T*>(this->obj()); };
-    T* detach() { return static_cast<T*>(SharedPtr::detach()); }
+    ~SharedImpl() {};
+  public:
+    operator T*() const {
+      return static_cast<T*>(this->obj());
+    }
+    operator T&() const {
+      return *static_cast<T*>(this->obj());
+    }
+    T& operator* () const {
+      return *static_cast<T*>(this->obj());
+    };
+    T* operator-> () const {
+      return static_cast<T*>(this->obj());
+    };
+    T* ptr () const {
+      return static_cast<T*>(this->obj());
+    };
+    T* detach() const {
+      if (this->obj() == NULL) return NULL;
+      return static_cast<T*>(SharedPtr::detach());
+    }
+    bool isNull() const {
+      return this->obj() == NULL;
+    }
+    bool operator<(const T& rhs) const {
+      return *this->ptr() < rhs;
+    };
+    operator bool() const {
+      return this->obj() != NULL;
+    };
   };
 
 }
-- 
2.21.0.windows.1