Skip to content

File memory_private_allocator.hpp

File List > base > memory_private_allocator.hpp

Go to the documentation of this file

/*
 * Copyright 2008 Search Solution Corporation
 * Copyright 2016 CUBRID Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

//
// memory_private_allocator.hpp - extension to memory_alloc.h private allocation
//

#ifndef _MEMORY_PRIVATE_ALLOCATOR_HPP_
#define _MEMORY_PRIVATE_ALLOCATOR_HPP_

#include "mem_block.hpp"
#include "memory_alloc.h"

// forward definitions
namespace cubthread
{
  class entry;
};

namespace cubmem
{
  /* private_allocator -
   *
   *  Implementation of C++ allocator concept using CUBRID private allocator.
   *
   *
   *
   *  Templates:
   *
   *      T: base allocation type.
   *
   *
   *  How to use:
   *
   *      Specialize template classes/functions that require dynamic memory allocation.
   *
   *
   *  note:
   *
   *    1. Cannot be used with typenames T that overload operator &
   */
  template <typename T>
  class private_allocator
  {
    public:
      /* standard allocator type definitions */
      typedef T value_type;
      typedef value_type *pointer;
      typedef const value_type *const_pointer;
      typedef value_type &reference;
      typedef const value_type &const_reference;
      typedef size_t size_type;
      typedef ptrdiff_t difference_type;

      /* convert an allocator<T> to allocator<U> */
      template <typename U>
      struct rebind
      {
    typedef private_allocator<U> other;
      };

      inline explicit private_allocator (cubthread::entry *thread_p = NULL);
      inline ~private_allocator ();
      inline explicit private_allocator (const private_allocator &other);
      template <typename U>
      inline explicit private_allocator (const private_allocator<U> &other);

      /* address */
      inline pointer address (reference r)
      {
    return &r;
      }
      inline const_pointer address (const_reference r)
      {
    return &r;
      }

      /* memory allocation */
      inline pointer allocate (size_type count);
      inline void deallocate (pointer p, size_type ignored = 0);

      /* maximum number of allocations */
      size_type max_size () const;

      /* construction/destruction */
      inline void construct (pointer p, const_reference t);
      inline void destroy (pointer p);

      /* db_private_alloc accessors */
      cubthread::entry *get_thread_entry () const;
      HL_HEAPID get_heapid () const;

    private:

      cubthread::entry *m_thread_p;
      HL_HEAPID m_heapid;
  };

  /* interchangeable specializations */
  template <typename T, typename U>
  bool
  operator== (const private_allocator<T> &, const private_allocator<U> &)
  {
    return true;
  }

  template <typename T, typename U>
  bool
  operator!= (const private_allocator<T> &, const private_allocator<U> &)
  {
    return false;
  }

  // private allocator helper functions
  HL_HEAPID get_private_heapid (cubthread::entry *&thread_p);
  void *private_heap_allocate (cubthread::entry *thread_p, HL_HEAPID heapid, size_t size);
  void private_heap_deallocate (cubthread::entry *thread_p, HL_HEAPID heapid, void *ptr);
  void register_private_allocator (cubthread::entry *thread_p);
  void deregister_private_allocator (cubthread::entry *thread_p);

  // private_pointer_deleter - deleter for pointer allocated with private allocator
  //
  template <class T>
  class private_pointer_deleter
  {
    public:
      private_pointer_deleter ();
      private_pointer_deleter (cubthread::entry *thread_p);

      inline void operator () (T *ptr) const;

    private:
      cubthread::entry *thread_p;
  };

  // private_unique_ptr - unique pointer allocated with private allocator
  //
  template <class T>
  class private_unique_ptr
  {
    public:
      private_unique_ptr (T *ptr, cubthread::entry *thread_p);

      inline T *get () const;   // get and keep ownership
      inline T *release ();     // get and release ownership

      inline void swap (private_unique_ptr <T> &other);

      inline void reset (T *ptr);

      inline T *operator-> () const;
      inline T &operator* () const;

    private:
      std::unique_ptr<T, private_pointer_deleter<T>> m_smart_ptr;
  };

  extern const block_allocator PRIVATE_BLOCK_ALLOCATOR;

  // Calls func with the global heap set for allocating memory
  template <typename Func, typename ...Args>
  inline void switch_to_global_allocator_and_call (Func &&func, Args &&... args);

} // namespace cubmem

//
// inline/template implementation
//

namespace cubmem
{
  //
  // private_allocator
  //
  template <typename T>
  private_allocator<T>::private_allocator (cubthread::entry *thread_p /* = NULL */)
    : m_thread_p (thread_p)
  {
    m_heapid = get_private_heapid (m_thread_p);
    register_private_allocator (m_thread_p);
  }

  template <typename T>
  private_allocator<T>::private_allocator (const private_allocator &other)
  {
    m_thread_p = other.m_thread_p;
    m_heapid = other.m_heapid;
    register_private_allocator (m_thread_p);
  }

  template <typename T>
  template <typename U>
  private_allocator<T>::private_allocator (const private_allocator<U> &other)
  {
    m_thread_p = other.get_thread_entry ();
    m_heapid = other.get_heapid ();
    register_private_allocator (m_thread_p);
  }

  template <typename T>
  private_allocator<T>::~private_allocator ()
  {
    deregister_private_allocator (m_thread_p);
  }

  template <typename T>
  typename private_allocator<T>::pointer
  private_allocator<T>::allocate (size_type count)
  {
    return reinterpret_cast<T *> (private_heap_allocate (m_thread_p, m_heapid, count * sizeof (T)));
  }

  template <typename T>
  void
  private_allocator<T>::deallocate (pointer p, size_type ignored)
  {
    (void) ignored; // unused
    private_heap_deallocate (m_thread_p, m_heapid, p);
  }

  template <typename T>
  typename private_allocator<T>::size_type
  private_allocator<T>::max_size () const
  {
    const size_type DB_PRIVATE_ALLOCATOR_MAX_SIZE = 0x7FFFFFFF;
    return DB_PRIVATE_ALLOCATOR_MAX_SIZE / sizeof (T);
  }

  template <typename T>
  void
  private_allocator<T>::construct (pointer p, const_reference t)
  {
    new (p) value_type (t);
  }

  template <typename T>
  void
  private_allocator<T>::destroy (pointer p)
  {
    p->~value_type ();
  }

  template <typename T>
  cubthread::entry *
  private_allocator<T>::get_thread_entry () const
  {
    return m_thread_p;
  }

  template <typename T>
  HL_HEAPID
  private_allocator<T>::get_heapid () const
  {
    return m_heapid;
  }

  //
  // private_pointer_deleter
  //
  template <class T>
  private_pointer_deleter<T>::private_pointer_deleter ()
    : thread_p (NULL)
  {
  }

  template <class T>
  private_pointer_deleter<T>::private_pointer_deleter (cubthread::entry *thread_p)
    : thread_p (thread_p)
  {
  }

  template <class T>
  void
  private_pointer_deleter<T>::operator () (T *ptr) const
  {
    if (ptr != NULL)
      {
    db_private_free (thread_p, ptr);
      }
  }

  //
  // private_unique_ptr
  //
  template <class T>
  private_unique_ptr<T>::private_unique_ptr (T *ptr, cubthread::entry *thread_p)
  {
    m_smart_ptr = std::unique_ptr<T, private_pointer_deleter<T>> (ptr, private_pointer_deleter<T> (thread_p));
  }

  template <class T>
  T *
  private_unique_ptr<T>::get () const
  {
    return m_smart_ptr.get ();
  }
  template <class T>
  T *
  private_unique_ptr<T>::release ()
  {
    return m_smart_ptr.release ();
  }

  template <class T>
  void
  private_unique_ptr<T>::swap (private_unique_ptr<T> &other)
  {
    m_smart_ptr.swap (other.m_smart_ptr);
  }

  template <class T>
  void
  private_unique_ptr<T>::reset (T *ptr)
  {
    m_smart_ptr.reset (ptr);
  }

  template <class T>
  T *
  private_unique_ptr<T>::operator-> () const
  {
    return m_smart_ptr.get ();
  }

  template <class T>
  T &
  private_unique_ptr<T>::operator* () const
  {
    return *m_smart_ptr.get ();
  }

  template < typename Func, typename...Args >
  void
  switch_to_global_allocator_and_call (Func &&func, Args &&... args)
  {
    HL_HEAPID save_id;

    // Switch to global
    save_id = db_change_private_heap (NULL, 0);

    func (std::forward < Args > (args)...);

    // Switch back
    (void) db_change_private_heap (NULL, save_id);
  }
} // namespace cubmem



#endif // _MEMORY_PRIVATE_ALLOCATOR_HPP_