diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ChangeLog | 9 | ||||
-rw-r--r-- | src/utils/Makefile.in | 3 | ||||
-rw-r--r-- | src/utils/sexpr.H | 4 | ||||
-rw-r--r-- | src/utils/sexpr.cc | 6 | ||||
-rw-r--r-- | src/utils/storage.H | 75 |
5 files changed, 78 insertions, 19 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 90543b37..f24a8bd8 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,12 @@ +2010-08-28 Gabriel Dos Reis <gdr@cs.tamu.edu> + + * 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. + 2010-08-26 Gabriel Dos Reis <gdr@cs.tamu.edu> * utils/Makefile.in: Install libOpenAxiom.a 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<Quote> quotes; UniqueAllocator<Function> funs; UniqueAllocator<Pair> pairs; - Memory::Arena<List> lists; - Memory::Arena<Vector> vectors; + Memory::Factory<List> lists; + Memory::Factory<Vector> 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<const Syntax*>& 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<const Syntax*>& 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 <stddef.h> #include <string.h> +#include <new> #include <cmath> #include <string> @@ -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<typename T> 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<Storage**>(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<typename T> + struct Factory : Arena<T> { + 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 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<typename T> + Factory<T>::~Factory() { + for (Storage* 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 -- // ----------------- |