diff options
Diffstat (limited to 'src/utils')
-rw-r--r-- | src/utils/Makefile.in | 6 | ||||
-rw-r--r-- | src/utils/storage.H | 330 | ||||
-rw-r--r-- | src/utils/storage.cc | 27 |
3 files changed, 19 insertions, 344 deletions
diff --git a/src/utils/Makefile.in b/src/utils/Makefile.in index e9734fd2..a3021748 100644 --- a/src/utils/Makefile.in +++ b/src/utils/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2011, Gabriel Dos Reis. +# Copyright (C) 2013, Gabriel Dos Reis. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -36,14 +36,14 @@ hammer_SOURCES = hammer.cc hammer_OBJECTS = $(hammer_SOURCES:.cc=.lo) hammer_LDADD = -L. -lOpenAxiom -libOpenAxiom_HEADERS = storage.H hash-table.H string-pool.H sexpr.H vm.H +libOpenAxiom_HEADERS = hash-table.H string-pool.H sexpr.H vm.H libOpenAxiom_SOURCES = \ storage.cc string-pool.cc sexpr.cc command.cc \ filesystem.cc vm.cc libOpenAxiom_OBJECTS = $(libOpenAxiom_SOURCES:.cc=.lo) -oa_public_headers = storage hash-table string-pool sexpr vm +oa_public_headers = hash-table string-pool sexpr vm ## Where we store public header files oa_target_headerdir = $(oa_target_includedir)/open-axiom diff --git a/src/utils/storage.H b/src/utils/storage.H deleted file mode 100644 index 72b9eb1e..00000000 --- a/src/utils/storage.H +++ /dev/null @@ -1,330 +0,0 @@ -// Copyright (C) 2010-2011, Gabriel Dos Reis. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// - Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// - Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in -// the documentation and/or other materials provided with the -// distribution. -// -// - Neither the name of The Numerical Algorithms Group Ltd. nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// --% Author: Gabriel Dos Reis -// --% Description: -// --% Memory management facility. Acquire raw memory directly -// --% from the host OS. Provide random access read to -// --% files through file mapping. - -#ifndef OPENAXIOM_STORAGE_INCLUDED -#define OPENAXIOM_STORAGE_INCLUDED - -#include <stddef.h> -#include <new> -#include <cmath> -#include <string> - -#include <open-axiom/config> - -namespace OpenAxiom { - // ----------------- - // -- SystemError -- - // ----------------- - // Objects of (type derived from) this type are used to report - // error orignating from the OpenAxiom core system. - struct SystemError { - explicit SystemError(const std::string&); - virtual ~SystemError(); - // Return the text of the diagnostic message. - virtual const std::string& message() const; - protected: - const std::string text; - }; - - // Report a file system error - void filesystem_error(const std::string&); - - namespace Memory { - // Datatype for the unit of storage. - typedef unsigned char Byte; - - // Datatype for pointers to data. - typedef void* Pointer; - - // Precision of the host OS storage page unit in byte count - size_t page_size(); - - // Acquire raw memory from the host OS. - Pointer os_acquire_raw_memory(size_t); - - // Release raw storage to the hosting OS. The first operand must - // be a pointer value previously returned by `os_acquire_raw_memory'. - // Otherwise, the result is undefined. - void os_release_raw_memory(Pointer, size_t); - - // Acquire `n' pages of memory storage from the host OS. - inline Pointer - acquire_raw_pages(size_t n) { - return os_acquire_raw_memory(n * page_size()); - } - - // Release `n' pages of storage starting the location `p'. - inline void - release_raw_pages(Pointer p, size_t n) { - os_release_raw_memory(p, n * page_size()); - } - - // ------------- - // -- Storage -- - // ------------- - // This class provides low-level abstractions intented for use - // to implement higher level storage abstractions. - struct Storage { - // Objects of this abstract datatype hold storage objects. - struct Handle; - - // Return the storage pointed to by the operand. It - // must be a pointer value previously returned by `acquire'. - // Otherwise, the result is undefined. - static void release(Handle*); - - // Return the start address of storage area. Clients would - // want to add padding bytes necessary to accomodate alignment - // requirements. - // Note: this should not be confused with the address of - // the handle object. - static Pointer begin(Handle*); - - // Courtesy conversion function from pointer to byte address. - static Byte* byte_address(Pointer h) { - return static_cast<Byte*>(h); - } - - // Round up `n' to a multiple of `a', a power of 2. - static size_t - round_up(size_t n, size_t a) { - return (n + a - 1) & ~(a - 1); - } - }; - - // ------------------------- - // -- SinglyLinkedStorage -- - // ------------------------- - // This class implements a simple single-linked list of storage - // objects. Each storage object in the link is created with - // a specific starting alignment requirements. - struct SinglyLinkedStorage : Storage { - // Return the previous handle in the link chain. - static Handle*& previous(Handle*); - }; - - // ------------------------- - // -- DoublyLinkedStorage -- - // ------------------------- - // Like SinglyLinkedStorage, except that the chain of storage - // object supports bidirectional travervsal. - struct DoublyLinkedStorage : Storage { - // Same as Storage::acquire, except that begin(h) returns an - // address that satisfies the alignment requirement `a'. - static Handle* acquire(size_t n, size_t a); - - // Return the previous handle in the link chain. - static Handle*& previous(Handle*); - - // Return the next handle in the link chain. - static Handle*& next(Handle*); - }; - - // ------------------ - // -- BlockStorage -- - // ------------------ - // This class implements a simple single-linked list of block storage. - // Each block maintains information about the next allocatable - // address within that block. - struct BlockStorage : SinglyLinkedStorage { - // Same as SinglyLinkedStorage::acquire(); initialize internal - // bookkeepking machinery. - static Handle* acquire(size_t n, size_t a); - - // Return the next allocatable address within the given block. - static Pointer next_address(Handle*); - - // Return the amount of allocatable byte in the given block. - static size_t room(Handle*); - - // Set `n' bytes aside with the given storage block. - static Pointer book(Handle*, size_t); - }; - - // ----------- - // -- Arena -- - // ----------- - // Extensible storage holding objects of a given type. - // The totality of all objects held in such a storage does not - // necessarily constitute a contiguous block. However, - // it is guaranteed that objects allocated in a single call - // to `allocate()' occupy a contiguous block of storage. - template<typename T> - struct Arena : protected BlockStorage { - // Acquire storage capable of holding `n' objects of type `T'. - explicit Arena(size_t); - // Release all storage acquired by this object, upon end of life. - ~Arena(); - // allocate storage for `n' more objects of type `T'. - T* allocate(size_t); - // Number of objects of type `T' allocated in this storage. - size_t population() const; - - protected: - // Address of the first object of type `T' in a storage. - static T* first_object(Handle* h) { - return static_cast<T*>(BlockStorage::begin(h)); - } - - // Address of one-past-the-end object of type `T' in this storage. - static T* last_object(Handle* h) { - return static_cast<T*>(BlockStorage::next_address(h)); - } - - // Number of objects allocated in a storage. - static size_t object_count(Handle* h) { - return last_object(h) - first_object(h); - } - - BlockStorage::Handle* store; // active storage to allocate from - }; - - template<typename T> - size_t - Arena<T>::population() const { - size_t n = 0; - for (Handle* h = store; h != 0; h = previous(h)) - n += object_count(h); - return n; - } - - template<typename T> - T* - Arena<T>::allocate(size_t n) { - const size_t sz = n * sizeof(T); - if (BlockStorage::room(store) < sz) { - // Not enough room left. Make sure we allocate storage - // at least as big as the current. - Handle* h = acquire(std::max(n, object_count(store)), - openaxiom_alignment(T)); - previous(h) = store; - store = h; - } - return static_cast<T*>(BlockStorage::book(store, sz)); - } - - template<typename T> - Arena<T>::Arena(size_t n) - : store(BlockStorage::acquire(n * sizeof (T), - openaxiom_alignment (T))) - { } - - template<typename T> - Arena<T>::~Arena() { - // Release storage in the reverse order of their - // their allocation. - while (store != 0) { - Handle* current = store; - store = BlockStorage::previous(store); - BlockStorage::release(current); - } - } - - // ------------- - // -- Factory -- - // ------------- - template<typename T> - struct Factory : Arena<T> { - typedef typename Arena<T>::Handle Handle; - - Factory() : Arena<T>(nominal_population()) { } - ~Factory(); - - // Allocate storage and value-construct an object of type `T'. - T* make() { - return new(this->allocate(1)) T(); - } - - // Allocate storage and construct an object of type `T'. - template<typename U> - T* make(const U& u) { - return new(this->allocate(1)) T(u); - } - - // Allocate storage and construct an object of type `T'. - template<typename U, typename V> - T* make(const U& u, const V& v) { - return new(this->allocate(1)) T(u, v); - } - - // Allocate storage and construct an object of type `T'. - template<typename U, typename V, typename W> - T* make(const U& u, const V& v, const W& w) { - return new(this->allocate(1)) T(u, v, w); - } - - private: - // Return 1 or the number of objects that can fit in a page unit. - static size_t nominal_population() { - const size_t psz = page_size(); - if (sizeof (T) > psz) - return 1; - return psz / sizeof(T); - } - }; - - // Destroy objects in the reverse order of their construction. - template<typename T> - Factory<T>::~Factory() { - for (Handle* s = this->store; s != 0; s = Arena<T>::previous(s)) { - T* last = Arena<T>::last_object(s); - for (--last; last >= Arena<T>::first_object(s); --last) - last->~T(); - } - } - - // ----------------- - // -- FileMapping -- - // ----------------- - struct FileMapping { - explicit FileMapping(std::string); - ~FileMapping(); - const char* begin() const { return static_cast<const char*>(start); } - const char* end() const { return begin() + extent; } - std::size_t size() const { return extent; } - protected: - Pointer start; // address at the mapped storage - size_t extent; // length (in bytes) of the storage - private: - FileMapping(const FileMapping&); // not implemented - FileMapping& operator=(const FileMapping&); // idem - }; - - } -} - -#endif // OPENAXIOM_STORAGE_INCLUDED diff --git a/src/utils/storage.cc b/src/utils/storage.cc index 4f5fc67c..54d14761 100644 --- a/src/utils/storage.cc +++ b/src/utils/storage.cc @@ -31,8 +31,7 @@ // --%: Gabriel Dos Reis. -#include <open-axiom/config> - +#include <open-axiom/storage> #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> #endif @@ -55,8 +54,6 @@ #include <errno.h> #include <stdlib.h> #include <string.h> -#include <new> // for placement new. -#include <open-axiom/storage> namespace OpenAxiom { // ---------------- @@ -111,7 +108,7 @@ namespace OpenAxiom { Pointer os_acquire_raw_memory(size_t nbytes) { Pointer p = os_allocate_read_write_raw_memory(nbytes); - if (p == 0) + if (p == nullptr) throw SystemError("cannot acquire more memory"); return memset(p, nbytes, 0); } @@ -206,8 +203,8 @@ namespace OpenAxiom { TwoWayLinkHeader* h = acquire_storage_with_header<TwoWayLinkHeader>(overhead + n); h->start = byte_address (h) + overhead; - h->previous = 0; - h->next = 0; + h->previous = nullptr; + h->next = nullptr; return h; } @@ -232,7 +229,7 @@ namespace OpenAxiom { h->available = byte_address(h) + overhead; // That is also where the actual object storage starts. h->start = h->available; - h->previous = 0; + h->previous = nullptr; return h; } @@ -293,14 +290,22 @@ namespace OpenAxiom { #endif // OPENAXIOM_MS_WINDOWS_HOST } + FileMapping::FileMapping(FileMapping&& f) + : start(f.start), extent(f.extent) { + f.start = nullptr; + f.extent = 0; + } + FileMapping::~FileMapping() { + if (start != nullptr) { #if defined(OPENAXIOM_MS_WINDOWS_HOST) - UnmapViewOfFile(start); + UnmapViewOfFile(start); #elif defined(HAVE_SYS_MMAN_H) - munmap(start, extent); + munmap(start, extent); #else # error "Don't know how to unmap a file on this platform" -#endif +#endif + } } } } |