Blame src/memory/SharedPtr.hpp

Packit bfcc33
#ifndef SASS_MEMORY_SHARED_PTR_H
Packit bfcc33
#define SASS_MEMORY_SHARED_PTR_H
Packit bfcc33
Packit bfcc33
#include "sass/base.h"
Packit bfcc33
Packit bfcc33
#include <vector>
Packit bfcc33
Packit bfcc33
namespace Sass {
Packit bfcc33
Packit bfcc33
  class SharedPtr;
Packit bfcc33
Packit bfcc33
  ///////////////////////////////////////////////////////////////////////////////
Packit bfcc33
  // Use macros for the allocation task, since overloading operator `new`
Packit bfcc33
  // has been proven to be flaky under certain compilers (see comment below).
Packit bfcc33
  ///////////////////////////////////////////////////////////////////////////////
Packit bfcc33
Packit bfcc33
  #ifdef DEBUG_SHARED_PTR
Packit bfcc33
Packit bfcc33
    #define SASS_MEMORY_NEW(Class, ...) \
Packit bfcc33
      ((Class*)(new Class(__VA_ARGS__))->trace(__FILE__, __LINE__)) \
Packit bfcc33
Packit bfcc33
    #define SASS_MEMORY_COPY(obj) \
Packit bfcc33
      ((obj)->copy(__FILE__, __LINE__)) \
Packit bfcc33
Packit bfcc33
    #define SASS_MEMORY_CLONE(obj) \
Packit bfcc33
      ((obj)->clone(__FILE__, __LINE__)) \
Packit bfcc33
Packit bfcc33
  #else
Packit bfcc33
Packit bfcc33
    #define SASS_MEMORY_NEW(Class, ...) \
Packit bfcc33
      new Class(__VA_ARGS__) \
Packit bfcc33
Packit bfcc33
    #define SASS_MEMORY_COPY(obj) \
Packit bfcc33
      ((obj)->copy()) \
Packit bfcc33
Packit bfcc33
    #define SASS_MEMORY_CLONE(obj) \
Packit bfcc33
      ((obj)->clone()) \
Packit bfcc33
Packit bfcc33
  #endif
Packit bfcc33
Packit bfcc33
  class SharedObj {
Packit bfcc33
  protected:
Packit bfcc33
  friend class SharedPtr;
Packit bfcc33
  friend class Memory_Manager;
Packit bfcc33
    #ifdef DEBUG_SHARED_PTR
Packit bfcc33
      static std::vector<SharedObj*> all;
Packit bfcc33
      std::string file;
Packit bfcc33
      size_t line;
Packit bfcc33
    #endif
Packit bfcc33
    static bool taint;
Packit bfcc33
    long refcounter;
Packit bfcc33
    // long refcount;
Packit bfcc33
    bool detached;
Packit bfcc33
    #ifdef DEBUG_SHARED_PTR
Packit bfcc33
      bool dbg;
Packit bfcc33
    #endif
Packit bfcc33
  public:
Packit bfcc33
    #ifdef DEBUG_SHARED_PTR
Packit bfcc33
      static void dumpMemLeaks();
Packit bfcc33
      SharedObj* trace(std::string file, size_t line) {
Packit bfcc33
        this->file = file;
Packit bfcc33
        this->line = line;
Packit bfcc33
        return this;
Packit bfcc33
      }
Packit bfcc33
    #endif
Packit bfcc33
    SharedObj();
Packit bfcc33
    #ifdef DEBUG_SHARED_PTR
Packit bfcc33
      std::string getDbgFile() {
Packit bfcc33
        return file;
Packit bfcc33
      }
Packit bfcc33
      size_t getDbgLine() {
Packit bfcc33
        return line;
Packit bfcc33
      }
Packit bfcc33
      void setDbg(bool dbg) {
Packit bfcc33
        this->dbg = dbg;
Packit bfcc33
      }
Packit bfcc33
    #endif
Packit bfcc33
    static void setTaint(bool val) {
Packit bfcc33
      taint = val;
Packit bfcc33
    }
Packit bfcc33
    virtual ~SharedObj();
Packit bfcc33
    long getRefCount() {
Packit bfcc33
      return refcounter;
Packit bfcc33
    }
Packit bfcc33
  };
Packit bfcc33
Packit bfcc33
Packit bfcc33
  class SharedPtr {
Packit bfcc33
  protected:
Packit bfcc33
    SharedObj* node;
Packit bfcc33
  protected:
Packit bfcc33
    void decRefCount();
Packit bfcc33
    void incRefCount();
Packit bfcc33
  public:
Packit bfcc33
    // the empty constructor
Packit bfcc33
    SharedPtr()
Packit bfcc33
    : node(NULL) {};
Packit bfcc33
    // the create constructor
Packit bfcc33
    SharedPtr(SharedObj* ptr);
Packit bfcc33
    // the copy constructor
Packit bfcc33
    SharedPtr(const SharedPtr& obj);
Packit bfcc33
    // the move constructor
Packit bfcc33
    SharedPtr(SharedPtr&& obj);
Packit bfcc33
    // copy assignment operator
Packit bfcc33
    SharedPtr& operator=(const SharedPtr& obj);
Packit bfcc33
    // move assignment operator
Packit bfcc33
    SharedPtr& operator=(SharedPtr&& obj);
Packit bfcc33
    // pure virtual destructor
Packit bfcc33
    virtual ~SharedPtr() = 0;
Packit bfcc33
  public:
Packit bfcc33
    SharedObj* obj () const {
Packit bfcc33
      return node;
Packit bfcc33
    };
Packit bfcc33
    SharedObj* operator-> () const {
Packit bfcc33
      return node;
Packit bfcc33
    };
Packit bfcc33
    bool isNull () {
Packit bfcc33
      return node == NULL;
Packit bfcc33
    };
Packit bfcc33
    bool isNull () const {
Packit bfcc33
      return node == NULL;
Packit bfcc33
    };
Packit bfcc33
    SharedObj* detach() const {
Packit bfcc33
      if (node) {
Packit bfcc33
        node->detached = true;
Packit bfcc33
      }
Packit bfcc33
      return node;
Packit bfcc33
    };
Packit bfcc33
    operator bool() const {
Packit bfcc33
      return node != NULL;
Packit bfcc33
    };
Packit bfcc33
Packit bfcc33
  };
Packit bfcc33
Packit bfcc33
  template < class T >
Packit bfcc33
  class SharedImpl : private SharedPtr {
Packit bfcc33
  public:
Packit bfcc33
    SharedImpl()
Packit bfcc33
    : SharedPtr(NULL) {};
Packit bfcc33
    SharedImpl(T* node)
Packit bfcc33
    : SharedPtr(node) {};
Packit bfcc33
    template < class U >
Packit bfcc33
    SharedImpl(SharedImpl<U> obj)
Packit bfcc33
    : SharedPtr(static_cast<T*>(obj.ptr())) {}
Packit bfcc33
    SharedImpl(T&& node)
Packit bfcc33
    : SharedPtr(node) {};
Packit bfcc33
    SharedImpl(const T& node)
Packit bfcc33
    : SharedPtr(node) {};
Packit bfcc33
    // the copy constructor
Packit bfcc33
    SharedImpl(const SharedImpl<T>& impl)
Packit bfcc33
    : SharedPtr(impl.node) {};
Packit bfcc33
    // the move constructor
Packit bfcc33
    SharedImpl(SharedImpl<T>&& impl)
Packit bfcc33
    : SharedPtr(impl.node) {};
Packit bfcc33
    // copy assignment operator
Packit bfcc33
    SharedImpl<T>& operator=(const SharedImpl<T>& rhs) {
Packit bfcc33
      if (node) decRefCount();
Packit bfcc33
      node = rhs.node;
Packit bfcc33
      incRefCount();
Packit bfcc33
      return *this;
Packit bfcc33
    }
Packit bfcc33
    // move assignment operator
Packit bfcc33
    SharedImpl<T>& operator=(SharedImpl<T>&& rhs) {
Packit bfcc33
      // don't move our self
Packit bfcc33
      if (this != &rhs) {
Packit bfcc33
        if (node) decRefCount();
Packit bfcc33
        node = std::move(rhs.node);
Packit bfcc33
        rhs.node = NULL;
Packit bfcc33
      }
Packit bfcc33
      return *this;
Packit bfcc33
    }
Packit bfcc33
    ~SharedImpl() {};
Packit bfcc33
  public:
Packit bfcc33
    operator T*() const {
Packit bfcc33
      return static_cast<T*>(this->obj());
Packit bfcc33
    }
Packit bfcc33
    operator T&() const {
Packit bfcc33
      return *static_cast<T*>(this->obj());
Packit bfcc33
    }
Packit bfcc33
    T& operator* () const {
Packit bfcc33
      return *static_cast<T*>(this->obj());
Packit bfcc33
    };
Packit bfcc33
    T* operator-> () const {
Packit bfcc33
      return static_cast<T*>(this->obj());
Packit bfcc33
    };
Packit bfcc33
    T* ptr () const {
Packit bfcc33
      return static_cast<T*>(this->obj());
Packit bfcc33
    };
Packit bfcc33
    T* detach() const {
Packit bfcc33
      if (this->obj() == NULL) return NULL;
Packit bfcc33
      return static_cast<T*>(SharedPtr::detach());
Packit bfcc33
    }
Packit bfcc33
    bool isNull() const {
Packit bfcc33
      return this->obj() == NULL;
Packit bfcc33
    }
Packit bfcc33
    bool operator<(const T& rhs) const {
Packit bfcc33
      return *this->ptr() < rhs;
Packit bfcc33
    };
Packit bfcc33
    operator bool() const {
Packit bfcc33
      return this->obj() != NULL;
Packit bfcc33
    };
Packit bfcc33
  };
Packit bfcc33
Packit bfcc33
}
Packit bfcc33
Packit bfcc33
#endif