Cleanups and split up into _basic options
This commit is contained in:
		@@ -21,10 +21,7 @@ namespace chaiscript {
 | 
			
		||||
      class bad_any_cast : public std::bad_cast
 | 
			
		||||
      {
 | 
			
		||||
        public:
 | 
			
		||||
          bad_any_cast() noexcept
 | 
			
		||||
            : m_what("bad any cast")
 | 
			
		||||
          {
 | 
			
		||||
          }
 | 
			
		||||
          bad_any_cast() = default;
 | 
			
		||||
 | 
			
		||||
          bad_any_cast(const bad_any_cast &) = default;
 | 
			
		||||
 | 
			
		||||
@@ -37,7 +34,7 @@ namespace chaiscript {
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
        private:
 | 
			
		||||
          std::string m_what;
 | 
			
		||||
          std::string m_what = "bad any cast";
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
@@ -151,8 +148,7 @@ namespace chaiscript {
 | 
			
		||||
 | 
			
		||||
        const std::type_info & type() const
 | 
			
		||||
        {
 | 
			
		||||
          if (m_data)
 | 
			
		||||
          {
 | 
			
		||||
          if (m_data) {
 | 
			
		||||
            return m_data->type();
 | 
			
		||||
          } else {
 | 
			
		||||
            return typeid(void);
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,7 @@ namespace chaiscript
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        explicit bad_boxed_cast(std::string t_what) noexcept
 | 
			
		||||
          : to(nullptr), m_what(std::move(t_what))
 | 
			
		||||
          : m_what(std::move(t_what))
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -55,7 +55,7 @@ namespace chaiscript
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Type_Info from; ///< Type_Info contained in the Boxed_Value
 | 
			
		||||
        const std::type_info *to; ///< std::type_info of the desired (but failed) result type
 | 
			
		||||
        const std::type_info *to = nullptr; ///< std::type_info of the desired (but failed) result type
 | 
			
		||||
 | 
			
		||||
      private:
 | 
			
		||||
        std::string m_what;
 | 
			
		||||
 
 | 
			
		||||
@@ -15,18 +15,6 @@ namespace chaiscript
 | 
			
		||||
  /// \brief Classes and functions useful for bootstrapping of ChaiScript and adding of new types
 | 
			
		||||
  namespace bootstrap
 | 
			
		||||
  {
 | 
			
		||||
    namespace detail
 | 
			
		||||
    {
 | 
			
		||||
      /// \brief Constructs a new POD value object from a Boxed_Number
 | 
			
		||||
      /// \param[in] v Boxed_Number to copy into the new object
 | 
			
		||||
      /// \returns The newly created object.
 | 
			
		||||
      template<typename P1>
 | 
			
		||||
      std::shared_ptr<P1> construct_pod(const Boxed_Number &v)
 | 
			
		||||
      {
 | 
			
		||||
        return std::make_shared<P1>(v.get_as<P1>());
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<typename T, typename = typename std::enable_if<std::is_array<T>::value>::type >
 | 
			
		||||
      void array(const std::string &type, Module& m)
 | 
			
		||||
      {
 | 
			
		||||
@@ -110,7 +98,7 @@ namespace chaiscript
 | 
			
		||||
    template<typename T>
 | 
			
		||||
    void construct_pod(const std::string &type, Module& m)
 | 
			
		||||
    {
 | 
			
		||||
      m.add(fun(&detail::construct_pod<T>), type);
 | 
			
		||||
      m.add(fun([](const Boxed_Number &bn){ return bn.get_as<T>(); }), type);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -161,15 +149,14 @@ namespace chaiscript
 | 
			
		||||
    /// for handling of Proxy_Function object (that is,
 | 
			
		||||
    /// function variables.
 | 
			
		||||
    template<typename Type>
 | 
			
		||||
    std::shared_ptr<Type> shared_ptr_clone(const std::shared_ptr<Type> &p)
 | 
			
		||||
    auto shared_ptr_clone(const std::shared_ptr<Type> &p)
 | 
			
		||||
    {
 | 
			
		||||
      return p;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Specific version of shared_ptr_clone just for Proxy_Functions
 | 
			
		||||
    template<typename Type>
 | 
			
		||||
    std::shared_ptr<typename std::remove_const<Type>::type> 
 | 
			
		||||
        shared_ptr_unconst_clone(const std::shared_ptr<typename std::add_const<Type>::type> &p)
 | 
			
		||||
    auto shared_ptr_unconst_clone(const std::shared_ptr<typename std::add_const<Type>::type> &p)
 | 
			
		||||
    {
 | 
			
		||||
      return std::const_pointer_cast<typename std::remove_const<Type>::type>(p);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,6 @@ namespace chaiscript
 | 
			
		||||
        struct Bidir_Range
 | 
			
		||||
        {
 | 
			
		||||
          typedef Container container_type;
 | 
			
		||||
          typedef typename std::iterator_traits<typename Container::iterator>::reference reference_type;
 | 
			
		||||
 | 
			
		||||
          Bidir_Range(Container &c)
 | 
			
		||||
            : m_begin(c.begin()), m_end(c.end())
 | 
			
		||||
@@ -71,16 +70,16 @@ namespace chaiscript
 | 
			
		||||
            --m_end;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          reference_type front() const
 | 
			
		||||
          decltype(auto) front() const
 | 
			
		||||
          {
 | 
			
		||||
            if (empty())
 | 
			
		||||
            {
 | 
			
		||||
              throw std::range_error("Range empty");
 | 
			
		||||
            }
 | 
			
		||||
            return *m_begin;
 | 
			
		||||
            return (*m_begin);
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          reference_type back() const
 | 
			
		||||
          decltype(auto) back() const
 | 
			
		||||
          {
 | 
			
		||||
            if (empty())
 | 
			
		||||
            {
 | 
			
		||||
@@ -88,7 +87,7 @@ namespace chaiscript
 | 
			
		||||
            }
 | 
			
		||||
            typename Container::iterator pos = m_end;
 | 
			
		||||
            --pos;
 | 
			
		||||
            return *(pos);
 | 
			
		||||
            return (*(pos));
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          typename Container::iterator m_begin;
 | 
			
		||||
@@ -129,24 +128,24 @@ namespace chaiscript
 | 
			
		||||
            --m_end;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          const_reference_type front() const
 | 
			
		||||
          decltype(auto) front() const
 | 
			
		||||
          {
 | 
			
		||||
            if (empty())
 | 
			
		||||
            {
 | 
			
		||||
              throw std::range_error("Range empty");
 | 
			
		||||
            }
 | 
			
		||||
            return *m_begin;
 | 
			
		||||
            return (*m_begin);
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          const_reference_type back() const
 | 
			
		||||
          decltype(auto) back() const
 | 
			
		||||
          {
 | 
			
		||||
            if (empty())
 | 
			
		||||
            {
 | 
			
		||||
              throw std::range_error("Range empty");
 | 
			
		||||
            }
 | 
			
		||||
            typename Container::const_iterator pos = m_end;
 | 
			
		||||
            auto pos = m_end;
 | 
			
		||||
            --pos;
 | 
			
		||||
            return *(pos);
 | 
			
		||||
            return (*(pos));
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          typename Container::const_iterator m_begin;
 | 
			
		||||
@@ -482,12 +481,8 @@ namespace chaiscript
 | 
			
		||||
        {
 | 
			
		||||
          m.add(user_type<PairType>(), type);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
          typename PairType::first_type PairType::* f = &PairType::first;
 | 
			
		||||
          typename PairType::second_type PairType::* s = &PairType::second;
 | 
			
		||||
 | 
			
		||||
          m.add(fun(f), "first");
 | 
			
		||||
          m.add(fun(s), "second");
 | 
			
		||||
          m.add(fun(&PairType::first), "first");
 | 
			
		||||
          m.add(fun(&PairType::second), "second");
 | 
			
		||||
 | 
			
		||||
          basic_constructors<PairType>(type, m);
 | 
			
		||||
          m.add(constructor<PairType (const typename PairType::first_type &, const typename PairType::second_type &)>(), type);
 | 
			
		||||
@@ -605,7 +600,6 @@ namespace chaiscript
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      /// hopefully working List type
 | 
			
		||||
      /// http://www.sgi.com/tech/stl/List.html
 | 
			
		||||
      template<typename ListType>
 | 
			
		||||
        void list_type(const std::string &type, Module& m)
 | 
			
		||||
 
 | 
			
		||||
@@ -77,7 +77,7 @@ namespace chaiscript
 | 
			
		||||
 | 
			
		||||
      struct Object_Data
 | 
			
		||||
      {
 | 
			
		||||
        static std::shared_ptr<Data> get(Boxed_Value::Void_Type, bool t_return_value)
 | 
			
		||||
        static auto get(Boxed_Value::Void_Type, bool t_return_value)
 | 
			
		||||
        {
 | 
			
		||||
          return std::make_shared<Data>(
 | 
			
		||||
                detail::Get_Type_Info<void>::get(),
 | 
			
		||||
@@ -89,13 +89,13 @@ namespace chaiscript
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        template<typename T>
 | 
			
		||||
          static std::shared_ptr<Data> get(const std::shared_ptr<T> *obj, bool t_return_value)
 | 
			
		||||
          static auto get(const std::shared_ptr<T> *obj, bool t_return_value)
 | 
			
		||||
          {
 | 
			
		||||
            return get(*obj, t_return_value);
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
        template<typename T>
 | 
			
		||||
          static std::shared_ptr<Data> get(const std::shared_ptr<T> &obj, bool t_return_value)
 | 
			
		||||
          static auto get(const std::shared_ptr<T> &obj, bool t_return_value)
 | 
			
		||||
          {
 | 
			
		||||
            return std::make_shared<Data>(
 | 
			
		||||
                  detail::Get_Type_Info<T>::get(), 
 | 
			
		||||
@@ -107,7 +107,7 @@ namespace chaiscript
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
        template<typename T>
 | 
			
		||||
          static std::shared_ptr<Data> get(std::shared_ptr<T> &&obj, bool t_return_value)
 | 
			
		||||
          static auto get(std::shared_ptr<T> &&obj, bool t_return_value)
 | 
			
		||||
          {
 | 
			
		||||
            auto ptr = obj.get();
 | 
			
		||||
            return std::make_shared<Data>(
 | 
			
		||||
@@ -120,20 +120,20 @@ namespace chaiscript
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
        template<typename T>
 | 
			
		||||
          static std::shared_ptr<Data> get(T *t, bool t_return_value)
 | 
			
		||||
          static auto get(T *t, bool t_return_value)
 | 
			
		||||
          {
 | 
			
		||||
            return get(std::ref(*t), t_return_value);
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
        template<typename T>
 | 
			
		||||
          static std::shared_ptr<Data> get(const T *t, bool t_return_value)
 | 
			
		||||
          static auto get(const T *t, bool t_return_value)
 | 
			
		||||
          {
 | 
			
		||||
            return get(std::cref(*t), t_return_value);
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        template<typename T>
 | 
			
		||||
          static std::shared_ptr<Data> get(std::reference_wrapper<T> obj, bool t_return_value)
 | 
			
		||||
          static auto get(std::reference_wrapper<T> obj, bool t_return_value)
 | 
			
		||||
          {
 | 
			
		||||
            auto p = &obj.get();
 | 
			
		||||
            return std::make_shared<Data>(
 | 
			
		||||
@@ -146,7 +146,7 @@ namespace chaiscript
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
        template<typename T>
 | 
			
		||||
          static std::shared_ptr<Data> get(T t, bool t_return_value)
 | 
			
		||||
          static auto get(T t, bool t_return_value)
 | 
			
		||||
          {
 | 
			
		||||
            auto p = std::make_shared<T>(std::move(t));
 | 
			
		||||
            auto ptr = p.get();
 | 
			
		||||
@@ -182,10 +182,7 @@ namespace chaiscript
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      /// Unknown-type constructor
 | 
			
		||||
      Boxed_Value()
 | 
			
		||||
        : m_data(Object_Data::get())
 | 
			
		||||
      {
 | 
			
		||||
      }
 | 
			
		||||
      Boxed_Value() = default;
 | 
			
		||||
 | 
			
		||||
      Boxed_Value(Boxed_Value&&) = default;
 | 
			
		||||
      Boxed_Value& operator=(Boxed_Value&&) = default;
 | 
			
		||||
@@ -349,7 +346,7 @@ namespace chaiscript
 | 
			
		||||
        : m_data(t_data) {
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      std::shared_ptr<Data> m_data;
 | 
			
		||||
      std::shared_ptr<Data> m_data = Object_Data::get();
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  /// @brief Creates a Boxed_Value. If the object passed in is a value type, it is copied. If it is a pointer, std::shared_ptr, or std::reference_type
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,6 @@
 | 
			
		||||
#define CHAISCRIPT_DISPATCHKIT_HPP_
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <deque>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <list>
 | 
			
		||||
#include <map>
 | 
			
		||||
@@ -31,6 +30,7 @@
 | 
			
		||||
#include "proxy_constructors.hpp"
 | 
			
		||||
#include "proxy_functions.hpp"
 | 
			
		||||
#include "type_info.hpp"
 | 
			
		||||
#include "short_alloc.hpp"
 | 
			
		||||
 | 
			
		||||
namespace chaiscript {
 | 
			
		||||
class Boxed_Number;
 | 
			
		||||
@@ -376,20 +376,55 @@ namespace chaiscript
 | 
			
		||||
  {
 | 
			
		||||
    struct Stack_Holder
 | 
			
		||||
    {
 | 
			
		||||
      typedef std::vector<std::pair<std::string, Boxed_Value>> Scope;
 | 
			
		||||
      typedef std::vector<Scope> StackData;
 | 
			
		||||
      //template <class T, std::size_t BufSize = sizeof(T)*20000>
 | 
			
		||||
      //  using SmallVector = std::vector<T, short_alloc<T, BufSize>>;
 | 
			
		||||
 | 
			
		||||
      template <class T>
 | 
			
		||||
        using SmallVector = std::vector<T>;
 | 
			
		||||
      
 | 
			
		||||
 | 
			
		||||
      typedef SmallVector<std::pair<std::string, Boxed_Value>> Scope;
 | 
			
		||||
      typedef SmallVector<Scope> StackData;
 | 
			
		||||
      typedef SmallVector<StackData> Stacks;
 | 
			
		||||
      typedef SmallVector<Boxed_Value> Call_Param_List;
 | 
			
		||||
      typedef SmallVector<Call_Param_List> Call_Params;
 | 
			
		||||
 | 
			
		||||
      Stack_Holder()
 | 
			
		||||
      {
 | 
			
		||||
        stacks.reserve(2);
 | 
			
		||||
        stacks.emplace_back(1);
 | 
			
		||||
        call_params.emplace_back();
 | 
			
		||||
        call_params.back().reserve(2);
 | 
			
		||||
        push_stack();
 | 
			
		||||
        push_call_params();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      std::vector<StackData> stacks;
 | 
			
		||||
      void push_stack_data()
 | 
			
		||||
      {
 | 
			
		||||
        stacks.back().emplace_back();
 | 
			
		||||
//        stacks.back().emplace_back(Scope(scope_allocator));
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      void push_stack()
 | 
			
		||||
      {
 | 
			
		||||
        stacks.emplace_back(1);
 | 
			
		||||
//        stacks.emplace_back(StackData(1, Scope(scope_allocator), stack_data_allocator));
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      void push_call_params()
 | 
			
		||||
      {
 | 
			
		||||
        call_params.emplace_back();
 | 
			
		||||
//        call_params.emplace_back(Call_Param_List(call_param_list_allocator));
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      //Scope::allocator_type::arena_type scope_allocator;
 | 
			
		||||
      //StackData::allocator_type::arena_type stack_data_allocator;
 | 
			
		||||
      //Stacks::allocator_type::arena_type stacks_allocator;
 | 
			
		||||
      //Call_Param_List::allocator_type::arena_type call_param_list_allocator;
 | 
			
		||||
      //Call_Params::allocator_type::arena_type call_params_allocator;
 | 
			
		||||
 | 
			
		||||
//      Stacks stacks = Stacks(stacks_allocator);
 | 
			
		||||
//      Call_Params call_params = Call_Params(call_params_allocator);
 | 
			
		||||
 | 
			
		||||
      Stacks stacks;
 | 
			
		||||
      Call_Params call_params;
 | 
			
		||||
 | 
			
		||||
      std::vector<std::vector<Boxed_Value>> call_params;
 | 
			
		||||
      int call_depth = 0;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@@ -401,7 +436,7 @@ namespace chaiscript
 | 
			
		||||
      public:
 | 
			
		||||
        typedef std::map<std::string, chaiscript::Type_Info> Type_Name_Map;
 | 
			
		||||
        typedef std::vector<std::pair<std::string, Boxed_Value>> Scope;
 | 
			
		||||
        typedef std::vector<Scope> StackData;
 | 
			
		||||
        typedef Stack_Holder::StackData StackData;
 | 
			
		||||
 | 
			
		||||
        struct State
 | 
			
		||||
        {
 | 
			
		||||
@@ -585,8 +620,8 @@ namespace chaiscript
 | 
			
		||||
        /// Adds a new scope to the stack
 | 
			
		||||
        static void new_scope(Stack_Holder &t_holder)
 | 
			
		||||
        {
 | 
			
		||||
          get_stack_data(t_holder).emplace_back();
 | 
			
		||||
          t_holder.call_params.emplace_back();
 | 
			
		||||
          t_holder.push_stack_data();
 | 
			
		||||
          t_holder.push_call_params();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// Pops the current scope from the stack
 | 
			
		||||
@@ -605,7 +640,7 @@ namespace chaiscript
 | 
			
		||||
        static void new_stack(Stack_Holder &t_holder)
 | 
			
		||||
        {
 | 
			
		||||
          // add a new Stack with 1 element
 | 
			
		||||
          t_holder.stacks.emplace_back(1);
 | 
			
		||||
          t_holder.push_stack();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        static void pop_stack(Stack_Holder &t_holder)
 | 
			
		||||
@@ -817,7 +852,7 @@ namespace chaiscript
 | 
			
		||||
        {
 | 
			
		||||
          auto &stack = get_stack_data();
 | 
			
		||||
          auto &scope = stack.front();
 | 
			
		||||
          scope = std::vector<std::pair<std::string, Boxed_Value>>(t_locals.begin(), t_locals.end());
 | 
			
		||||
          scope.assign(t_locals.begin(), t_locals.end());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										157
									
								
								include/chaiscript/dispatchkit/short_alloc.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								include/chaiscript/dispatchkit/short_alloc.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,157 @@
 | 
			
		||||
#ifndef SHORT_ALLOC_H
 | 
			
		||||
#define SHORT_ALLOC_H
 | 
			
		||||
 | 
			
		||||
// The MIT License (MIT)
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (c) 2015 Howard Hinnant
 | 
			
		||||
// 
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
// of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
// in the Software without restriction, including without limitation the rights
 | 
			
		||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
// copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
// furnished to do so, subject to the following conditions:
 | 
			
		||||
// 
 | 
			
		||||
// The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
// copies or substantial portions of the Software.
 | 
			
		||||
// 
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
// SOFTWARE.
 | 
			
		||||
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
#include <cassert>
 | 
			
		||||
 | 
			
		||||
template <std::size_t N, std::size_t alignment = alignof(std::max_align_t)>
 | 
			
		||||
class arena
 | 
			
		||||
{
 | 
			
		||||
    alignas(alignment) char buf_[N];
 | 
			
		||||
    char* ptr_;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    ~arena() {ptr_ = nullptr;}
 | 
			
		||||
    arena() noexcept : ptr_(buf_) {}
 | 
			
		||||
    arena(const arena&) = delete;
 | 
			
		||||
    arena& operator=(const arena&) = delete;
 | 
			
		||||
 | 
			
		||||
    template <std::size_t ReqAlign> char* allocate(std::size_t n);
 | 
			
		||||
    void deallocate(char* p, std::size_t n) noexcept;
 | 
			
		||||
 | 
			
		||||
    static constexpr std::size_t size() noexcept {return N;}
 | 
			
		||||
    std::size_t used() const noexcept {return static_cast<std::size_t>(ptr_ - buf_);}
 | 
			
		||||
    void reset() noexcept {ptr_ = buf_;}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    static
 | 
			
		||||
    std::size_t 
 | 
			
		||||
    align_up(std::size_t n) noexcept
 | 
			
		||||
        {return (n + (alignment-1)) & ~(alignment-1);}
 | 
			
		||||
 | 
			
		||||
    bool
 | 
			
		||||
    pointer_in_buffer(char* p) noexcept
 | 
			
		||||
        {return buf_ <= p && p <= buf_ + N;}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <std::size_t N, std::size_t alignment>
 | 
			
		||||
template <std::size_t ReqAlign>
 | 
			
		||||
char*
 | 
			
		||||
arena<N, alignment>::allocate(std::size_t n)
 | 
			
		||||
{
 | 
			
		||||
    static_assert(ReqAlign <= alignment, "alignment is too small for this arena");
 | 
			
		||||
    assert(pointer_in_buffer(ptr_) && "short_alloc has outlived arena");
 | 
			
		||||
    auto const aligned_n = align_up(n);
 | 
			
		||||
    if (static_cast<decltype(aligned_n)>(buf_ + N - ptr_) >= aligned_n)
 | 
			
		||||
    {
 | 
			
		||||
        char* r = ptr_;
 | 
			
		||||
        ptr_ += aligned_n;
 | 
			
		||||
        return r;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static_assert(alignment <= alignof(std::max_align_t), "you've chosen an "
 | 
			
		||||
                  "alignment that is larger than alignof(std::max_align_t), and "
 | 
			
		||||
                  "cannot be guaranteed by normal operator new");
 | 
			
		||||
    return static_cast<char*>(::operator new(n));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <std::size_t N, std::size_t alignment>
 | 
			
		||||
void
 | 
			
		||||
arena<N, alignment>::deallocate(char* p, std::size_t n) noexcept
 | 
			
		||||
{
 | 
			
		||||
    assert(pointer_in_buffer(ptr_) && "short_alloc has outlived arena");
 | 
			
		||||
    if (pointer_in_buffer(p))
 | 
			
		||||
    {
 | 
			
		||||
        n = align_up(n);
 | 
			
		||||
        if (p + n == ptr_)
 | 
			
		||||
            ptr_ = p;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
        ::operator delete(p);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class T, std::size_t N, std::size_t Align = alignof(std::max_align_t)>
 | 
			
		||||
class short_alloc
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    using value_type = T;
 | 
			
		||||
    static auto constexpr alignment = Align;
 | 
			
		||||
    static auto constexpr size = N;
 | 
			
		||||
    using arena_type = arena<size, alignment>;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    arena_type& a_;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    short_alloc(const short_alloc&) = default;
 | 
			
		||||
    short_alloc& operator=(const short_alloc&) = delete;
 | 
			
		||||
 | 
			
		||||
    short_alloc(arena_type& a) noexcept : a_(a)
 | 
			
		||||
    {
 | 
			
		||||
        static_assert(size % alignment == 0,
 | 
			
		||||
                      "size N needs to be a multiple of alignment Align");
 | 
			
		||||
    }
 | 
			
		||||
    template <class U>
 | 
			
		||||
        short_alloc(const short_alloc<U, N, alignment>& a) noexcept
 | 
			
		||||
            : a_(a.a_) {}
 | 
			
		||||
 | 
			
		||||
    template <class _Up> struct rebind {using other = short_alloc<_Up, N, alignment>;};
 | 
			
		||||
 | 
			
		||||
    T* allocate(std::size_t n)
 | 
			
		||||
    {
 | 
			
		||||
        return reinterpret_cast<T*>(a_.template allocate<alignof(T)>(n*sizeof(T)));
 | 
			
		||||
    }
 | 
			
		||||
    void deallocate(T* p, std::size_t n) noexcept
 | 
			
		||||
    {
 | 
			
		||||
        a_.deallocate(reinterpret_cast<char*>(p), n*sizeof(T));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <class T1, std::size_t N1, std::size_t A1, 
 | 
			
		||||
              class U, std::size_t M, std::size_t A2>
 | 
			
		||||
    friend
 | 
			
		||||
    bool
 | 
			
		||||
    operator==(const short_alloc<T1, N1, A1>& x, const short_alloc<U, M, A2>& y) noexcept;
 | 
			
		||||
 | 
			
		||||
    template <class U, std::size_t M, std::size_t A> friend class short_alloc;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, std::size_t N, std::size_t A1, class U, std::size_t M, std::size_t A2>
 | 
			
		||||
inline
 | 
			
		||||
bool
 | 
			
		||||
operator==(const short_alloc<T, N, A1>& x, const short_alloc<U, M, A2>& y) noexcept
 | 
			
		||||
{
 | 
			
		||||
    return N == M && A1 == A2 && &x.a_ == &y.a_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class T, std::size_t N, std::size_t A1, class U, std::size_t M, std::size_t A2>
 | 
			
		||||
inline
 | 
			
		||||
bool
 | 
			
		||||
operator!=(const short_alloc<T, N, A1>& x, const short_alloc<U, M, A2>& y) noexcept
 | 
			
		||||
{
 | 
			
		||||
    return !(x == y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif  // SHORT_ALLOC_HPP
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user