DriveHQ Start Menu
Cloud Drive Mapping
Folder Sync
Cloud Backup
True Drop Box
FTP/SFTP Hosting
Group Account
DriveHQ Start Menu
Online File Server
My Storage
|
Manage Shares
|
Publishes
|
Drop Boxes
|
Group Account
WebDAV Drive Mapping
Cloud Drive Home
|
WebDAV Guide
|
Drive Mapping Tool
|
Drive Mapping URL
Complete Data Backup
Backup Guide
|
Online Backup Tool
|
Cloud-to-Cloud Backup
FTP, Email & Web Service
FTP Home
|
FTP Hosting FAQ
|
Email Hosting
|
EmailManager
|
Web Hosting
Help & Resources
About
|
Enterprise Service
|
Partnership
|
Comparisons
|
Support
Quick Links
Security and Privacy
Download Software
Service Manual
Use Cases
Group Account
Online Help
Blog
Contact
Cloud Surveillance
Sign Up
Login
Features
Business Features
Online File Server
FTP Hosting
Cloud Drive Mapping
Cloud File Backup
Email Backup & Hosting
Cloud File Sharing
Folder Synchronization
Group Management
True Drop Box
Full-text Search
AD Integration/SSO
Mobile Access
IP Camera & DVR Solution
More...
Personal Features
Personal Cloud Drive
Backup All Devices
Mobile APPs
Personal Web Hosting
Sub-Account (for Kids)
Home/PC/Kids Monitoring
More...
Software
DriveHQ Drive Mapping Tool
DriveHQ FileManager
DriveHQ Online Backup
DriveHQ Mobile Apps
Pricing
Business Plans & Pricing
Personal Plans & Pricing
Price Comparison with Others
Feature Comparison with Others
Install Mobile App
Sign up
Creating account...
Invalid character in username! Only 0-9, a-z, A-Z, _, -, . allowed.
Username is required!
Invalid email address!
E-mail is required!
Password is required!
Password is invalid!
Password and confirmation do not match.
Confirm password is required!
I accept
Membership Agreement
Please read the Membership Agreement and check "I accept"!
Free Quick Sign-up
Sign-up Page
Log in
Signing in...
Username or e-mail address is required!
Password is required!
Keep me logged in
Quick Login
Forgot Password
Up
Upload
Download
Share
Publish
New Folder
New File
Copy
Cut
Delete
Paste
Rate
Upgrade
Rotate
Effect
Edit
Slide
History
// 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_POOL_HPP #define BOOST_POOL_HPP #include
// for workarounds // std::less, std::less_equal, std::greater #include
// new[], delete[], std::nothrow #include
// std::size_t, std::ptrdiff_t #include
// std::malloc, std::free #include
// std::invalid_argument #include
// std::max #include
#include
// boost::details::pool::ct_lcm #include
// boost::details::pool::lcm #include
// boost::simple_segregated_storage #include
#ifdef BOOST_NO_STDC_NAMESPACE namespace std { using ::malloc; using ::free; } #endif // There are a few places in this file where the expression "this->m" is used. // This expression is used to force instantiation-time name lookup, which I am // informed is required for strict Standard compliance. It's only necessary // if "m" is a member of a base class that is dependent on a template // parameter. // Thanks to Jens Maurer for pointing this out! namespace boost { struct default_user_allocator_new_delete { typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; static char * malloc(const size_type bytes) { return new (std::nothrow) char[bytes]; } static void free(char * const block) { delete [] block; } }; struct default_user_allocator_malloc_free { typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; static char * malloc(const size_type bytes) { return reinterpret_cast
(std::malloc(bytes)); } static void free(char * const block) { std::free(block); } }; namespace details { // PODptr is a class that pretends to be a "pointer" to different class types // that don't really exist. It provides member functions to access the "data" // of the "object" it points to. Since these "class" types are of variable // size, and contains some information at the *end* of its memory (for // alignment reasons), PODptr must contain the size of this "class" as well as // the pointer to this "object". template
class PODptr { public: typedef SizeType size_type; private: char * ptr; size_type sz; char * ptr_next_size() const { return (ptr + sz - sizeof(size_type)); } char * ptr_next_ptr() const { return (ptr_next_size() - pool::ct_lcm
::value); } public: PODptr(char * const nptr, const size_type nsize) :ptr(nptr), sz(nsize) { } PODptr() :ptr(0), sz(0) { } bool valid() const { return (begin() != 0); } void invalidate() { begin() = 0; } char * & begin() { return ptr; } char * begin() const { return ptr; } char * end() const { return ptr_next_ptr(); } size_type total_size() const { return sz; } size_type element_size() const { return (sz - sizeof(size_type) - pool::ct_lcm
::value); } size_type & next_size() const { return *(reinterpret_cast
(ptr_next_size())); } char * & next_ptr() const { return *(reinterpret_cast
(ptr_next_ptr())); } PODptr next() const { return PODptr
(next_ptr(), next_size()); } void next(const PODptr & arg) const { next_ptr() = arg.begin(); next_size() = arg.total_size(); } }; } // namespace details template
class pool: protected simple_segregated_storage< typename UserAllocator::size_type> { public: typedef UserAllocator user_allocator; typedef typename UserAllocator::size_type size_type; typedef typename UserAllocator::difference_type difference_type; private: BOOST_STATIC_CONSTANT(unsigned, min_alloc_size = (::boost::details::pool::ct_lcm
::value) ); // Returns 0 if out-of-memory // Called if malloc/ordered_malloc needs to resize the free list void * malloc_need_resize(); void * ordered_malloc_need_resize(); protected: details::PODptr
list; simple_segregated_storage
& store() { return *this; } const simple_segregated_storage
& store() const { return *this; } const size_type requested_size; size_type next_size; size_type start_size; // finds which POD in the list 'chunk' was allocated from details::PODptr
find_POD(void * const chunk) const; // is_from() tests a chunk to determine if it belongs in a block static bool is_from(void * const chunk, char * const i, const size_type sizeof_i) { // We use std::less_equal and std::less to test 'chunk' // against the array bounds because standard operators // may return unspecified results. // This is to ensure portability. The operators < <= > >= are only // defined for pointers to objects that are 1) in the same array, or // 2) subobjects of the same object [5.9/2]. // The functor objects guarantee a total order for any pointer [20.3.3/8] //WAS: // return (std::less_equal
()(static_cast
(i), chunk) // && std::less
()(chunk, // static_cast
(i + sizeof_i))); std::less_equal
lt_eq; std::less
lt; return (lt_eq(i, chunk) && lt(chunk, i + sizeof_i)); } size_type alloc_size() const { const unsigned min_size = min_alloc_size; return details::pool::lcm
(requested_size, min_size); } // for the sake of code readability :) static void * & nextof(void * const ptr) { return *(static_cast
(ptr)); } public: // The second parameter here is an extension! // pre: npartition_size != 0 && nnext_size != 0 explicit pool(const size_type nrequested_size, const size_type nnext_size = 32) :list(0, 0), requested_size(nrequested_size), next_size(nnext_size), start_size(nnext_size) { } ~pool() { purge_memory(); } // Releases memory blocks that don't have chunks allocated // pre: lists are ordered // Returns true if memory was actually deallocated bool release_memory(); // Releases *all* memory blocks, even if chunks are still allocated // Returns true if memory was actually deallocated bool purge_memory(); // These functions are extensions! size_type get_next_size() const { return next_size; } void set_next_size(const size_type nnext_size) { next_size = start_size = nnext_size; } size_type get_requested_size() const { return requested_size; } // Both malloc and ordered_malloc do a quick inlined check first for any // free chunks. Only if we need to get another memory block do we call // the non-inlined *_need_resize() functions. // Returns 0 if out-of-memory void * malloc() { // Look for a non-empty storage if (!store().empty()) return store().malloc(); return malloc_need_resize(); } void * ordered_malloc() { // Look for a non-empty storage if (!store().empty()) return store().malloc(); return ordered_malloc_need_resize(); } // Returns 0 if out-of-memory // Allocate a contiguous section of n chunks void * ordered_malloc(size_type n); // pre: 'chunk' must have been previously // returned by *this.malloc(). void free(void * const chunk) { store().free(chunk); } // pre: 'chunk' must have been previously // returned by *this.malloc(). void ordered_free(void * const chunk) { store().ordered_free(chunk); } // pre: 'chunk' must have been previously // returned by *this.malloc(n). void free(void * const chunks, const size_type n) { const size_type partition_size = alloc_size(); const size_type total_req_size = n * requested_size; const size_type num_chunks = total_req_size / partition_size + ((total_req_size % partition_size) ? true : false); store().free_n(chunks, num_chunks, partition_size); } // pre: 'chunk' must have been previously // returned by *this.malloc(n). void ordered_free(void * const chunks, const size_type n) { const size_type partition_size = alloc_size(); const size_type total_req_size = n * requested_size; const size_type num_chunks = total_req_size / partition_size + ((total_req_size % partition_size) ? true : false); store().ordered_free_n(chunks, num_chunks, partition_size); } // is_from() tests a chunk to determine if it was allocated from *this bool is_from(void * const chunk) const { return (find_POD(chunk).valid()); } }; template
bool pool
::release_memory() { // This is the return value: it will be set to true when we actually call // UserAllocator::free(..) bool ret = false; // This is a current & previous iterator pair over the memory block list details::PODptr
ptr = list; details::PODptr
prev; // This is a current & previous iterator pair over the free memory chunk list // Note that "prev_free" in this case does NOT point to the previous memory // chunk in the free list, but rather the last free memory chunk before the // current block. void * free_p = this->first; void * prev_free_p = 0; const size_type partition_size = alloc_size(); // Search through all the all the allocated memory blocks while (ptr.valid()) { // At this point: // ptr points to a valid memory block // free_p points to either: // 0 if there are no more free chunks // the first free chunk in this or some next memory block // prev_free_p points to either: // the last free chunk in some previous memory block // 0 if there is no such free chunk // prev is either: // the PODptr whose next() is ptr // !valid() if there is no such PODptr // If there are no more free memory chunks, then every remaining // block is allocated out to its fullest capacity, and we can't // release any more memory if (free_p == 0) break; // We have to check all the chunks. If they are *all* free (i.e., present // in the free list), then we can free the block. bool all_chunks_free = true; // Iterate 'i' through all chunks in the memory block // if free starts in the memory block, be careful to keep it there void * saved_free = free_p; for (char * i = ptr.begin(); i != ptr.end(); i += partition_size) { // If this chunk is not free if (i != free_p) { // We won't be able to free this block all_chunks_free = false; // free_p might have travelled outside ptr free_p = saved_free; // Abort searching the chunks; we won't be able to free this // block because a chunk is not free. break; } // We do not increment prev_free_p because we are in the same block free_p = nextof(free_p); } // post: if the memory block has any chunks, free_p points to one of them // otherwise, our assertions above are still valid const details::PODptr
next = ptr.next(); if (!all_chunks_free) { if (is_from(free_p, ptr.begin(), ptr.element_size())) { std::less
lt; void * const end = ptr.end(); do { prev_free_p = free_p; free_p = nextof(free_p); } while (free_p && lt(free_p, end)); } // This invariant is now restored: // free_p points to the first free chunk in some next memory block, or // 0 if there is no such chunk. // prev_free_p points to the last free chunk in this memory block. // We are just about to advance ptr. Maintain the invariant: // prev is the PODptr whose next() is ptr, or !valid() // if there is no such PODptr prev = ptr; } else { // All chunks from this block are free // Remove block from list if (prev.valid()) prev.next(next); else list = next; // Remove all entries in the free list from this block if (prev_free_p != 0) nextof(prev_free_p) = free_p; else this->first = free_p; // And release memory UserAllocator::free(ptr.begin()); ret = true; } // Increment ptr ptr = next; } next_size = start_size; return ret; } template
bool pool
::purge_memory() { details::PODptr
iter = list; if (!iter.valid()) return false; do { // hold "next" pointer const details::PODptr
next = iter.next(); // delete the storage UserAllocator::free(iter.begin()); // increment iter iter = next; } while (iter.valid()); list.invalidate(); this->first = 0; next_size = start_size; return true; } template
void * pool
::malloc_need_resize() { // No memory in any of our storages; make a new storage, const size_type partition_size = alloc_size(); const size_type POD_size = next_size * partition_size + details::pool::ct_lcm
::value + sizeof(size_type); char * const ptr = UserAllocator::malloc(POD_size); if (ptr == 0) return 0; const details::PODptr
node(ptr, POD_size); next_size <<= 1; // initialize it, store().add_block(node.begin(), node.element_size(), partition_size); // insert it into the list, node.next(list); list = node; // and return a chunk from it. return store().malloc(); } template
void * pool
::ordered_malloc_need_resize() { // No memory in any of our storages; make a new storage, const size_type partition_size = alloc_size(); const size_type POD_size = next_size * partition_size + details::pool::ct_lcm
::value + sizeof(size_type); char * const ptr = UserAllocator::malloc(POD_size); if (ptr == 0) return 0; const details::PODptr
node(ptr, POD_size); next_size <<= 1; // initialize it, // (we can use "add_block" here because we know that // the free list is empty, so we don't have to use // the slower ordered version) store().add_block(node.begin(), node.element_size(), partition_size); // insert it into the list, // handle border case if (!list.valid() || std::greater
()(list.begin(), node.begin())) { node.next(list); list = node; } else { details::PODptr
prev = list; while (true) { // if we're about to hit the end or // if we've found where "node" goes if (prev.next_ptr() == 0 || std::greater
()(prev.next_ptr(), node.begin())) break; prev = prev.next(); } node.next(prev.next()); prev.next(node); } // and return a chunk from it. return store().malloc(); } template
void * pool
::ordered_malloc(const size_type n) { const size_type partition_size = alloc_size(); const size_type total_req_size = n * requested_size; const size_type num_chunks = total_req_size / partition_size + ((total_req_size % partition_size) ? true : false); void * ret = store().malloc_n(num_chunks, partition_size); if (ret != 0) return ret; // Not enougn memory in our storages; make a new storage, BOOST_USING_STD_MAX(); next_size = max BOOST_PREVENT_MACRO_SUBSTITUTION(next_size, num_chunks); const size_type POD_size = next_size * partition_size + details::pool::ct_lcm
::value + sizeof(size_type); char * const ptr = UserAllocator::malloc(POD_size); if (ptr == 0) return 0; const details::PODptr
node(ptr, POD_size); // Split up block so we can use what wasn't requested // (we can use "add_block" here because we know that // the free list is empty, so we don't have to use // the slower ordered version) if (next_size > num_chunks) store().add_block(node.begin() + num_chunks * partition_size, node.element_size() - num_chunks * partition_size, partition_size); next_size <<= 1; // insert it into the list, // handle border case if (!list.valid() || std::greater
()(list.begin(), node.begin())) { node.next(list); list = node; } else { details::PODptr
prev = list; while (true) { // if we're about to hit the end or // if we've found where "node" goes if (prev.next_ptr() == 0 || std::greater
()(prev.next_ptr(), node.begin())) break; prev = prev.next(); } node.next(prev.next()); prev.next(node); } // and return it. return node.begin(); } template
details::PODptr
::size_type> pool
::find_POD(void * const chunk) const { // We have to find which storage this chunk is from. details::PODptr
iter = list; while (iter.valid()) { if (is_from(chunk, iter.begin(), iter.element_size())) return iter; iter = iter.next(); } return iter; } } // namespace boost #endif
pool.hpp
Page URL
File URL
Prev
2/6
Next
Download
( 17 KB )
Note: The DriveHQ service banners will NOT be displayed if the file owner is a paid member.
Comments
Total ratings:
0
Average rating:
Not Rated
Would you like to comment?
Join DriveHQ
for a free account, or
Logon
if you are already a member.