⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 simple_segregated_storage.hpp

📁 CGAL is a collaborative effort of several sites in Europe and Israel. The goal is to make the most i
💻 HPP
字号:
// Copyright (C) 2000, 2001 Stephen Cleary//// Distributed under the Boost Software License, Version 1.0. (See// accompanying file LICENSE_1_0.txt or copy at// http://www.boost.org/LICENSE_1_0.txt)//// See http://www.boost.org for updates, documentation, and revision history.#ifndef BOOST_SIMPLE_SEGREGATED_STORAGE_HPP#define BOOST_SIMPLE_SEGREGATED_STORAGE_HPP// std::greater#include <functional>#include <boost/pool/poolfwd.hpp>namespace boost {template <typename SizeType>class simple_segregated_storage{  public:    typedef SizeType size_type;  private:    simple_segregated_storage(const simple_segregated_storage &);    void operator=(const simple_segregated_storage &);    // pre: (n > 0), (start != 0), (nextof(start) != 0)    // post: (start != 0)    static void * try_malloc_n(void * & start, size_type n,        size_type partition_size);  protected:    void * first;    // Traverses the free list referred to by "first",    //  and returns the iterator previous to where    //  "ptr" would go if it was in the free list.    // Returns 0 if "ptr" would go at the beginning    //  of the free list (i.e., before "first")    void * find_prev(void * ptr);    // for the sake of code readability :)    static void * & nextof(void * const ptr)    { return *(static_cast<void **>(ptr)); }  public:    // Post: empty()    simple_segregated_storage()    :first(0) { }    // pre: npartition_sz >= sizeof(void *)    //      npartition_sz = sizeof(void *) * i, for some integer i    //      nsz >= npartition_sz    //      block is properly aligned for an array of object of    //        size npartition_sz and array of void *    // The requirements above guarantee that any pointer to a chunk    //  (which is a pointer to an element in an array of npartition_sz)    //  may be cast to void **.    static void * segregate(void * block,        size_type nsz, size_type npartition_sz,        void * end = 0);    // Same preconditions as 'segregate'    // Post: !empty()    void add_block(void * const block,        const size_type nsz, const size_type npartition_sz)    {      // Segregate this block and merge its free list into the      //  free list referred to by "first"      first = segregate(block, nsz, npartition_sz, first);    }    // Same preconditions as 'segregate'    // Post: !empty()    void add_ordered_block(void * const block,        const size_type nsz, const size_type npartition_sz)    {      // This (slower) version of add_block segregates the      //  block and merges its free list into our free list      //  in the proper order      // Find where "block" would go in the free list      void * const loc = find_prev(block);      // Place either at beginning or in middle/end      if (loc == 0)        add_block(block, nsz, npartition_sz);      else        nextof(loc) = segregate(block, nsz, npartition_sz, nextof(loc));    }    // default destructor    bool empty() const { return (first == 0); }    // pre: !empty()    void * malloc()    {      void * const ret = first;      // Increment the "first" pointer to point to the next chunk      first = nextof(first);      return ret;    }    // pre: chunk was previously returned from a malloc() referring to the    //  same free list    // post: !empty()    void free(void * const chunk)    {      nextof(chunk) = first;      first = chunk;    }    // pre: chunk was previously returned from a malloc() referring to the    //  same free list    // post: !empty()    void ordered_free(void * const chunk)    {      // This (slower) implementation of 'free' places the memory      //  back in the list in its proper order.      // Find where "chunk" goes in the free list      void * const loc = find_prev(chunk);      // Place either at beginning or in middle/end      if (loc == 0)        free(chunk);      else      {        nextof(chunk) = nextof(loc);        nextof(loc) = chunk;      }    }    // Note: if you're allocating/deallocating n a lot, you should    //  be using an ordered pool.    void * malloc_n(size_type n, size_type partition_size);    // pre: chunks was previously allocated from *this with the same    //   values for n and partition_size    // post: !empty()    // Note: if you're allocating/deallocating n a lot, you should    //  be using an ordered pool.    void free_n(void * const chunks, const size_type n,        const size_type partition_size)    {      add_block(chunks, n * partition_size, partition_size);    }    // pre: chunks was previously allocated from *this with the same    //   values for n and partition_size    // post: !empty()    void ordered_free_n(void * const chunks, const size_type n,        const size_type partition_size)    {      add_ordered_block(chunks, n * partition_size, partition_size);    }};template <typename SizeType>void * simple_segregated_storage<SizeType>::find_prev(void * const ptr){  // Handle border case  if (first == 0 || std::greater<void *>()(first, ptr))    return 0;  void * iter = first;  while (true)  {    // if we're about to hit the end or    //  if we've found where "ptr" goes    if (nextof(iter) == 0 || std::greater<void *>()(nextof(iter), ptr))      return iter;    iter = nextof(iter);  }}template <typename SizeType>void * simple_segregated_storage<SizeType>::segregate(    void * const block,    const size_type sz,    const size_type partition_sz,    void * const end){  // Get pointer to last valid chunk, preventing overflow on size calculations  //  The division followed by the multiplication just makes sure that  //    old == block + partition_sz * i, for some integer i, even if the  //    block size (sz) is not a multiple of the partition size.  char * old = static_cast<char *>(block)      + ((sz - partition_sz) / partition_sz) * partition_sz;  // Set it to point to the end  nextof(old) = end;  // Handle border case where sz == partition_sz (i.e., we're handling an array  //  of 1 element)  if (old == block)    return block;  // Iterate backwards, building a singly-linked list of pointers  for (char * iter = old - partition_sz; iter != block;      old = iter, iter -= partition_sz)    nextof(iter) = old;  // Point the first pointer, too  nextof(block) = old;  return block;}// The following function attempts to find n contiguous chunks//  of size partition_size in the free list, starting at start.// If it succeds, it returns the last chunk in that contiguous//  sequence, so that the sequence is known by [start, {retval}]// If it fails, it does do either because it's at the end of the//  free list or hits a non-contiguous chunk.  In either case,//  it will return 0, and set start to the last considered//  chunk.  You are at the end of the free list if//  nextof(start) == 0.  Otherwise, start points to the last//  chunk in the contiguous sequence, and nextof(start) points//  to the first chunk in the next contiguous sequence (assuming//  an ordered free list)template <typename SizeType>void * simple_segregated_storage<SizeType>::try_malloc_n(    void * & start, size_type n, const size_type partition_size){  void * iter = nextof(start);  while (--n != 0)  {    void * next = nextof(iter);    if (next != static_cast<char *>(iter) + partition_size)    {      // next == 0 (end-of-list) or non-contiguous chunk found      start = iter;      return 0;    }    iter = next;  }  return iter;}template <typename SizeType>void * simple_segregated_storage<SizeType>::malloc_n(const size_type n,    const size_type partition_size){  void * start = &first;  void * iter;  do  {    if (nextof(start) == 0)      return 0;    iter = try_malloc_n(start, n, partition_size);  } while (iter == 0);  void * const ret = nextof(start);  nextof(start) = nextof(iter);  return ret;}} // namespace boost#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -