From 871c6f7c1422155b3263455e291e6eaace27af87 Mon Sep 17 00:00:00 2001 From: dos-reis Date: Sun, 29 Aug 2010 04:25:45 +0000 Subject: * utils/Makefile.in ($(oa_target_oalib)): Create contaning directory if necessary. * utils/storage.H (Memory::Factory): New. Allocate, construct, and destroy objects. * utils/sexpr.H (Sexpr::Allocator): Use Memory::Factory. * utils/sexpr.cc: Adjust implementation. --- src/utils/Makefile.in | 3 +++ src/utils/sexpr.H | 4 +-- src/utils/sexpr.cc | 6 ++--- src/utils/storage.H | 75 +++++++++++++++++++++++++++++++++++++++++---------- 4 files changed, 69 insertions(+), 19 deletions(-) (limited to 'src/utils') diff --git a/src/utils/Makefile.in b/src/utils/Makefile.in index db30091e..2e963e67 100644 --- a/src/utils/Makefile.in +++ b/src/utils/Makefile.in @@ -64,6 +64,9 @@ stamp: $(oa_target_oalib) hammer$(EXEEXT) $(STAMP) stamp $(oa_target_oalib): libOpenAxiom.$(LIBEXT) + if [ ! -d $(axiom_target_libdir) ]; then \ + mkdir -p $(axiom_target_libdir); \ + fi cp $< $@ stamp-headers: $(libOpenAxiom_HEADERS) Makefile diff --git a/src/utils/sexpr.H b/src/utils/sexpr.H index 3059dce5..f7c9f766 100644 --- a/src/utils/sexpr.H +++ b/src/utils/sexpr.H @@ -348,8 +348,8 @@ namespace OpenAxiom { UniqueAllocator quotes; UniqueAllocator funs; UniqueAllocator pairs; - Memory::Arena lists; - Memory::Arena vectors; + Memory::Factory lists; + Memory::Factory vectors; List empty_list; Vector empty_vector; }; diff --git a/src/utils/sexpr.cc b/src/utils/sexpr.cc index 248c0649..4910f053 100644 --- a/src/utils/sexpr.cc +++ b/src/utils/sexpr.cc @@ -395,7 +395,7 @@ namespace OpenAxiom { // --------------- // -- Allocator -- // --------------- - Allocator::Allocator() : lists(4 * 1024), vectors(1024) { } + Allocator::Allocator() { } // This destructor is defined here so that it provides // a single instantiation point for destructors of all @@ -446,14 +446,14 @@ namespace OpenAxiom { Allocator::make_list(const std::vector& elts) { if (elts.empty()) return &empty_list; - return new(lists.allocate(1)) List(elts); + return lists.make(elts); } const Vector* Allocator::make_vector(const std::vector& elts) { if (elts.empty()) return &empty_vector; - return new(vectors.allocate(1)) Vector(elts); + return vectors.make(elts); } // ------------ diff --git a/src/utils/storage.H b/src/utils/storage.H index 03b03604..ad8eaa09 100644 --- a/src/utils/storage.H +++ b/src/utils/storage.H @@ -40,6 +40,7 @@ #include #include +#include #include #include @@ -184,15 +185,12 @@ namespace OpenAxiom { // 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 memory. - // Objects are destroyed when the arena is destroyed. So, - // allocators of this type implement a form of sticky object - // allocator. + // to `allocate()' occupy a contiguous block of storage. template struct Arena { // Acquire storage capable of holding `n' objects of type `T'. explicit Arena(size_t); - // Destroy allocated objects when done. + // 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); @@ -216,14 +214,14 @@ namespace OpenAxiom { return last_object(s) - first_object(s); } - private: - Storage* store; // active storage to allocate from - // The `previous' link in the chain of storage. static Storage*& previous(Storage* s) { return *static_cast(s->at_offset(0)); } + Storage* store; // active storage to allocate from + + private: // Acquire storage large enough to hold `n' objects of type `T'. static Storage* acquire(size_t); }; @@ -257,12 +255,6 @@ namespace OpenAxiom { // Destroy objects in the reverse order of their // their allocation. while (store != 0) { - // The first allocated object is right after the `previous' - // link in the storage chain. - T* first = first_object(store); - T* last = last_object(store); - for (--last; first >= last; --last) - last->~T(); Storage* current = store; store = previous(store); Storage::release(current); @@ -284,6 +276,61 @@ namespace OpenAxiom { return s; } + // ------------- + // -- Factory -- + // ------------- + template + struct Factory : Arena { + Factory() : Arena(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 + T* make(const U& u) { + return new(this->allocate(1)) T(u); + } + + // Allocate storage and construct an object of type `T'. + template + 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 + 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 overhead = + Storage::round_up(sizeof(Storage), + openaxiom_alignment(Storage*)) + + Storage::round_up(sizeof(Storage*), openaxiom_alignment(T)); + const size_t psz = page_size(); + if (overhead + sizeof (T) > psz) + return 1; + return (psz - overhead) / sizeof(T); + } + }; + + // Destroy objects in the reverse order of their construction. + template + Factory::~Factory() { + for (Storage* s = this->store; s != 0; s = Arena::previous(s)) { + T* last = Arena::last_object(s); + for (--last; last >= Arena::first_object(s); --last) + last->~T(); + } + } + // ----------------- // -- FileMapping -- // ----------------- -- cgit v1.2.3