summaryrefslogtreecommitdiffstats
path: root/sca-cpp/trunk/kernel/gc.hpp
diff options
context:
space:
mode:
authorjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2010-01-02 10:27:26 +0000
committerjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2010-01-02 10:27:26 +0000
commit95fa76f5f3208d913320c13a05171ecdcd7134c2 (patch)
tree872e101cd2fb1505baf313940e48c6b615fd6725 /sca-cpp/trunk/kernel/gc.hpp
parent1d04916fda43146fb62488c20ba03b7b3006c8e9 (diff)
Performance improvements when running both in multi-threaded and pre-forked HTTPD. Changed memory management to use Apache APR pools instead of ref counting pointers as it's much faster and easier to integrate with the Python and Ruby interpreters. Changed to use simple pool-based string and stream implementations instead of the STL ones, which cause a lots of mutex locks in a multi-threaded environment. Added build options to compile with threading and profiling.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@895165 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sca-cpp/trunk/kernel/gc.hpp')
-rw-r--r--sca-cpp/trunk/kernel/gc.hpp405
1 files changed, 121 insertions, 284 deletions
diff --git a/sca-cpp/trunk/kernel/gc.hpp b/sca-cpp/trunk/kernel/gc.hpp
index c9a1a35756..3d20245c69 100644
--- a/sca-cpp/trunk/kernel/gc.hpp
+++ b/sca-cpp/trunk/kernel/gc.hpp
@@ -23,399 +23,236 @@
#define tuscany_gc_hpp
/**
- * Garbage collected pointer.
+ * Garbage collected memory management, using APR memory pools.
*/
+#include <stdlib.h>
#include <apr_general.h>
#include <apr_pools.h>
-#include <iostream>
+#include <assert.h>
+#include <new>
+#include "debug.hpp"
namespace tuscany
{
/**
- * Macros used to add or subtract values to reference counters.
- * In a multithreaded environment, use the GCC __sync_add_and_fetch
- * and __sync_sub_and_fetch built in functions.
+ * Pointer to a value.
*/
-#ifdef _REENTRANT
-
-#define gc_add_and_fetch(t, v) __sync_add_and_fetch(&(t), v)
-#define gc_sub_and_fetch(t, v) __sync_sub_and_fetch(&(t), v)
-
-#else
-
-#define gc_add_and_fetch(t, v) ((t) = (t) + (v))
-#define gc_sub_and_fetch(t, v) ((t) = (t) - (v))
-
-#endif
-
template<typename T> class gc_ptr {
public:
- gc_ptr(T* p = 0) throw() : countingRef(p == 0? 0 : new CountingRef(p)) {
+ gc_ptr(T* ptr = NULL) throw() : ptr(ptr) {
}
~gc_ptr() throw() {
- release();
}
- gc_ptr(const gc_ptr& r) throw() : countingRef(r.countingRef) {
- acquire(r.countingRef);
+ gc_ptr(const gc_ptr& r) throw() : ptr(r.ptr) {
}
gc_ptr& operator=(const gc_ptr& r) throw() {
if(this == &r)
return *this;
- acquire(r.countingRef);
- release();
- countingRef = r.countingRef;
+ ptr = r.ptr;
return *this;
}
const bool operator==(const gc_ptr& r) const throw() {
if (this == &r)
return true;
- if (countingRef == NULL)
- return r.countingRef == NULL;
- if (r.countingRef == NULL)
- return false;
- return countingRef-> ptr == r.countingRef->ptr;
+ return ptr == r.ptr;
}
const bool operator!=(const gc_ptr& r) const throw() {
- return !this->operator ==(r);
+ return !this->operator==(r);
}
T& operator*() const throw() {
- return *countingRef->ptr;
+ return *ptr;
}
T* operator->() const throw() {
- return countingRef->ptr;
+ return ptr;
}
operator T*() const throw() {
- return countingRef->ptr;
- }
-
- template<typename X> friend std::ostream& operator<<(std::ostream&, const gc_ptr<X>&);
-
-private:
- struct CountingRef {
- T* ptr;
- unsigned count;
-
- CountingRef(T* p) throw() :
- ptr(p), count(1) {
- }
- }* countingRef;
-
- void acquire(CountingRef* ref) throw() {
- if(ref)
- gc_add_and_fetch(ref->count, (unsigned int)1);
+ return ptr;
}
- void release() throw() {
- if(countingRef) {
- unsigned rc = gc_sub_and_fetch(countingRef->count, (unsigned int)1);
- if(rc == 0) {
- delete countingRef->ptr;
- delete countingRef;
- }
- }
- }
+ T* ptr;
};
-template<typename T> std::ostream& operator<<(std::ostream& out, const gc_ptr<T>& p) {
- return out << p.countingRef->ptr;
-}
-
/**
- * Garbage collected pointer to an array.
+ * Garbage collected APR memory pool.
*/
-template<typename T> class gc_aptr {
+class gc_pool {
public:
- gc_aptr(T* p = 0) throw() : countingRef(p == 0? 0 : new CountingRef(p)) {
+ gc_pool() : p(NULL) {
}
- ~gc_aptr() throw() {
- release();
+ gc_pool(apr_pool_t* p) : p(p) {
}
- gc_aptr(const gc_aptr& r) throw() : countingRef(r.countingRef) {
- acquire(r.countingRef);
+ gc_pool(const gc_pool& pool) : p(pool.p) {
}
- gc_aptr& operator=(const gc_aptr& r) throw() {
- if(this == &r)
+ gc_pool& operator=(const gc_pool& pool) {
+ if (this == &pool)
return *this;
- acquire(r.countingRef);
- release();
- countingRef = r.countingRef;
+ p = pool.p;
return *this;
}
- const bool operator==(const gc_aptr& r) const throw() {
- if (this == &r)
- return true;
- if (countingRef == NULL)
- return r.countingRef == NULL;
- if (r.countingRef == NULL)
- return false;
- return countingRef-> ptr == r.countingRef->ptr;
- }
-
- const bool operator!=(const gc_aptr& r) const throw() {
- return !this->operator ==(r);
- }
-
- T& operator*() const throw() {
- return *countingRef->ptr;
- }
-
- T* operator->() const throw() {
- return countingRef->ptr;
- }
-
- operator T*() const throw() {
- return countingRef->ptr;
+ operator apr_pool_t*() const {
+ return p;
}
- template<typename X> friend std::ostream& operator<<(std::ostream&, const gc_aptr<X>&);
-
private:
- struct CountingRef {
- T* ptr;
- unsigned count;
-
- CountingRef(T* p) throw() :
- ptr(p), count(1) {
- }
- }* countingRef;
-
- void acquire(CountingRef* ref) throw() {
- if(ref)
- gc_add_and_fetch(ref->count, (unsigned int)1);
- }
+ friend const bool destroy(gc_pool& pool);
+ friend class gc_global_pool_t;
+ friend class gc_scoped_pool;
- void release() throw() {
- if(countingRef) {
- unsigned rc = gc_sub_and_fetch(countingRef->count, (unsigned int)1);
- if(rc == 0) {
- delete[] countingRef->ptr;
- delete countingRef;
- }
- }
- }
+ apr_pool_t* p;
};
-template<typename T> std::ostream& operator<<(std::ostream& out, const gc_aptr<T>& p) {
- return out << p.countingRef->ptr;
-}
-
/**
- * Garbage collected pointer to a reference counting object.
+ * Destroy a memory pool.
*/
-template<typename T> class gc_counting_ptr {
-public:
- gc_counting_ptr(T* p = 0) throw() : ptr(p) {
- acquire(p);
- }
-
- ~gc_counting_ptr() throw() {
- release();
- }
-
- gc_counting_ptr(const gc_counting_ptr& r) throw() : ptr(r.ptr) {
- acquire(ptr);
- }
-
- gc_counting_ptr& operator=(const gc_counting_ptr& r) throw() {
- if(this == &r)
- return *this;
- acquire(r.ptr);
- release();
- ptr = r.ptr;
- return *this;
- }
-
- const bool operator==(const gc_counting_ptr& r) const throw() {
- if (this == &r)
- return true;
- return ptr == r.ptr;
- }
-
- const bool operator!=(const gc_counting_ptr& r) const throw() {
- return !this->operator ==(r);
- }
-
- T& operator*() const throw() {
- return *ptr;
- }
-
- T* operator->() const throw() {
- return ptr;
- }
-
- operator T*() const throw() {
- return ptr;
- }
-
- template<typename X> friend std::ostream& operator<<(std::ostream&, const gc_counting_ptr<X>&);
-
-private:
- T* ptr;
-
- void acquire(T* p) throw() {
- if(p)
- p->acquire();
- }
-
- void release() throw() {
- if(ptr) {
- if(ptr->release() == 0) {
- delete ptr;
- }
- }
- }
-};
-
-template<typename T> std::ostream& operator<<(std::ostream& out, const gc_counting_ptr<T>& p) {
- return out << p.ptr;
+const bool destroy(gc_pool& pool) {
+ apr_pool_destroy(pool.p);
+ return true;
}
/**
- * Apache Portable Runtime library context
+ * Default global memory pool.
*/
-class APRContext {
+class gc_apr_context_t {
public:
- APRContext() {
+ gc_apr_context_t() {
apr_initialize();
}
- ~APRContext() {
- apr_terminate();
+ ~gc_apr_context_t() {
+ //apr_terminate();
}
};
-APRContext aprContext;
+gc_apr_context_t gc_apr_context;
-/**
- * Garbage collected memory pool, using an APR pool.
- */
-class gc_pool {
+class gc_global_pool_t : public gc_pool {
public:
- gc_pool() : aprPool(new APRPool) {
+ gc_global_pool_t() {
+ apr_pool_create(&p, NULL);
}
- operator apr_pool_t*() const {
- return aprPool->p;
+ ~gc_global_pool_t() {
+ //apr_pool_destroy(p);
}
+};
-private:
- class APRPool {
- friend class gc_pool;
- friend class gc_counting_ptr<APRPool>;
-
- unsigned int refCount;
- apr_pool_t* p;
-
- APRPool() : refCount(0) {
- apr_pool_create(&p, NULL);
- }
-
- ~APRPool() {
- apr_pool_destroy(p);
- }
-
- unsigned int acquire() {
- return gc_add_and_fetch(refCount, (unsigned int)1);
- }
+gc_global_pool_t gc_global_pool;
- unsigned int release() {
- return gc_sub_and_fetch(refCount, (unsigned int)1);
- }
- };
+/**
+ * Maintain a stack of memory pools.
+ */
+#ifdef _REENTRANT
+__thread
+#endif
+apr_pool_t* gc_pool_stack = NULL;
- const gc_counting_ptr<APRPool> aprPool;
-};
+/**
+ * Return the current memory pool.
+ */
+apr_pool_t* gc_current_pool() {
+ apr_pool_t* p = gc_pool_stack;
+ if (p != NULL)
+ return p;
+ apr_pool_t* g = gc_global_pool;
+ gc_pool_stack = g;
+ return g;
+}
/**
- * Garbage collected pointer to pooled memory.
+ * A memory pool scope, used to setup a scope in which a particular pool
+ * will be used for all allocations.
*/
-template<typename T> class gc_pool_ptr {
+class gc_scoped_pool : public gc_pool {
public:
- gc_pool_ptr(T* ptr = 0) throw() : ptr(ptr) {
- }
-
- ~gc_pool_ptr() throw() {
- }
-
- gc_pool_ptr(const gc_pool_ptr& r) throw() : ptr(r.ptr) {
- }
-
- gc_pool_ptr& operator=(const gc_pool_ptr& r) throw() {
- if(this == &r)
- return *this;
- ptr = r.ptr;
- return *this;
- }
- const bool operator==(const gc_pool_ptr& r) const throw() {
- if (this == &r)
- return true;
- return ptr == r.ptr;
- }
-
- const bool operator!=(const gc_pool_ptr& r) const throw() {
- return !this->operator ==(r);
+ gc_scoped_pool() : gc_pool(NULL), prev(gc_current_pool()), owned(true) {
+ apr_pool_create(&p, NULL);
+ gc_pool_stack = p;
}
- T& operator*() const throw() {
- return *ptr;
+ gc_scoped_pool(apr_pool_t* pool) : gc_pool(pool), prev(gc_current_pool()), owned(false) {
+ gc_pool_stack = p;
}
- T* operator->() const throw() {
- return ptr;
+ ~gc_scoped_pool() {
+ if (owned)
+ apr_pool_destroy(p);
+ if (prev != NULL)
+ gc_pool_stack = prev;
}
- operator T*() const throw() {
- return ptr;
+private:
+ gc_scoped_pool(const unused gc_scoped_pool& pool) : gc_pool(pool.p), prev(NULL), owned(false) {
}
- template<typename X> friend std::ostream& operator<<(std::ostream&, const gc_pool_ptr<X>&);
-
-private:
- T* ptr;
+ apr_pool_t* prev;
+ bool owned;
};
-template<typename T> std::ostream& operator<<(std::ostream& out, const gc_pool_ptr<T>& p) {
- return out << p.ptr;
-}
-
/**
- * Cleanup function, called by the APR pool to cleanup registered resources.
- * Calls the allocated object's destructor.
+ * Allocates a pointer to an object allocated from a memory pool and
+ * register a cleanup callback for it.
*/
-template<typename T> apr_status_t gc_pool_cleanupCallback(void* v) {
+template<typename T> apr_status_t gc_pool_cleanup(void* v) {
T* t = static_cast<T*>(v);
t->~T();
return APR_SUCCESS;
}
-/**
- * Returns a pointer to an object allocated from a memory pool.
- */
-template<typename T> gc_pool_ptr<T> gc_pool_new(const gc_pool& mp) {
+template<typename T> T* gc_new(apr_pool_t* p) {
+ void* m = apr_palloc(p, sizeof(T));
+ apr_pool_cleanup_register(p, m, gc_pool_cleanup<T>, apr_pool_cleanup_null) ;
+ return static_cast<T*>(m);
+}
+
+template<typename T> T* gc_new() {
+ return gc_new<T>(gc_current_pool());
+}
+
+template<typename T> apr_status_t gc_pool_acleanup(void* v) {
+ int* m = static_cast<int*>(v);
+ int n = *m;
+ T* t = static_cast<T*>(m + 1);
+ for (int i = 0; i < n; i++, t++)
+ t->~T();
+ return APR_SUCCESS;
+}
- // Allocate memory from the pool
- void* m = apr_palloc(mp, sizeof(T));
+template<typename T> T* gc_anew(apr_pool_t* p, int n) {
+ int* m = static_cast<int*>(apr_palloc(p, sizeof(int) + sizeof(T[n])));
+ *m = n;
+ apr_pool_cleanup_register(p, m, gc_pool_acleanup<T>, apr_pool_cleanup_null) ;
+ return static_cast<T*>(m + 1);
+}
- // Register a cleanup callback
- apr_pool_cleanup_register(mp, m, gc_pool_cleanupCallback<T>, apr_pool_cleanup_null) ;
+template<typename T> T* gc_anew(int n) {
+ return gc_anew<T>(gc_current_pool(), n);
+}
- // Run the requested type's constructor over the allocated memory
- return new (m) T();
+/**
+ * Allocate an array of chars.
+ */
+char* gc_cnew(apr_pool_t* p, int n) {
+ return static_cast<char*>(apr_palloc(p, n));
+}
+
+char* gc_cnew(int n) {
+ return gc_cnew(gc_current_pool(), n);
}
}
+
#endif /* tuscany_gc_hpp */