diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2009-11-01 05:24:54 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2009-11-01 05:24:54 +0000 |
commit | 9f187b46ae761e8275362d6c1533e9fe79028c7b (patch) | |
tree | e2625f63e0c84f172c877e1fe2cbe75adf678208 /cpp/sca/kernel | |
parent | 24021bd09a0d5c9664565a244c24e0bdef0908b8 (diff) |
Improved memory management using APR memory pools, changed frame allocation in eval library to support forward references and fixed memory leak in XML parsing code. Also simplified a bit the printing of lists to make them easier to read.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@831639 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/sca/kernel')
-rw-r--r-- | cpp/sca/kernel/Makefile.am | 6 | ||||
-rw-r--r-- | cpp/sca/kernel/element.hpp | 6 | ||||
-rw-r--r-- | cpp/sca/kernel/function.hpp | 22 | ||||
-rw-r--r-- | cpp/sca/kernel/gc.hpp | 135 | ||||
-rw-r--r-- | cpp/sca/kernel/kernel-test.cpp | 12 | ||||
-rw-r--r-- | cpp/sca/kernel/list.hpp | 29 | ||||
-rw-r--r-- | cpp/sca/kernel/value.hpp | 108 | ||||
-rw-r--r-- | cpp/sca/kernel/xml.hpp | 38 |
8 files changed, 303 insertions, 53 deletions
diff --git a/cpp/sca/kernel/Makefile.am b/cpp/sca/kernel/Makefile.am index d3caa16b3b..0bbfa195c7 100644 --- a/cpp/sca/kernel/Makefile.am +++ b/cpp/sca/kernel/Makefile.am @@ -19,13 +19,13 @@ noinst_PROGRAMS = kernel-test xsd-test nobase_include_HEADERS = *.hpp -INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} +INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE} kernel_test_SOURCES = kernel-test.cpp -kernel_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 +kernel_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 xsd_test_SOURCES = xsd-test.cpp -xsd_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 +xsd_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 TESTS = kernel-test diff --git a/cpp/sca/kernel/element.hpp b/cpp/sca/kernel/element.hpp index af221f849b..d93e90742b 100644 --- a/cpp/sca/kernel/element.hpp +++ b/cpp/sca/kernel/element.hpp @@ -219,19 +219,19 @@ struct selectorLambda { const list<value> select; selectorLambda(const list<value>& s) : select(s) { } - const bool evalApply(const list<value>& s, const list<value> v) const { + const bool evalExpr(const list<value>& s, const list<value> v) const { if (isNil(s)) return true; if (isNil(v)) return false; if (car(s) != car(v)) return false; - return evalApply(cdr(s), cdr(v)); + return evalExpr(cdr(s), cdr(v)); } const bool operator()(const value& v) const { if (!isList(v)) return false; - return evalApply(select, v); + return evalExpr(select, v); } }; diff --git a/cpp/sca/kernel/function.hpp b/cpp/sca/kernel/function.hpp index 9492879e5e..c99ee5dbad 100644 --- a/cpp/sca/kernel/function.hpp +++ b/cpp/sca/kernel/function.hpp @@ -64,8 +64,6 @@ bool printLambdaCounters() { template<typename R, typename... P> class Callable { public: - unsigned int refCount; - Callable() : refCount(0) { } @@ -76,14 +74,6 @@ public: virtual ~Callable() { } - unsigned int acquire() { - return __sync_add_and_fetch(&refCount, 1); - } - - unsigned int release() { - return __sync_sub_and_fetch(&refCount, 1); - } - template<typename F> class Proxy: public Callable { public: Proxy(const F& f) : function(f) { @@ -112,6 +102,18 @@ public: const F function; }; +private: + friend class gc_counting_ptr<Callable>; + + unsigned int refCount; + + unsigned int acquire() { + return __sync_add_and_fetch(&refCount, 1); + } + + unsigned int release() { + return __sync_sub_and_fetch(&refCount, 1); + } }; template<typename S> class lambda; diff --git a/cpp/sca/kernel/gc.hpp b/cpp/sca/kernel/gc.hpp index 0d292f6194..7739e714c2 100644 --- a/cpp/sca/kernel/gc.hpp +++ b/cpp/sca/kernel/gc.hpp @@ -26,6 +26,8 @@ * Garbage collected pointer. */ +#include <apr_general.h> +#include <apr_pools.h> #include <iostream> namespace tuscany @@ -265,5 +267,138 @@ template<typename T> std::ostream& operator<<(std::ostream& out, const gc_counti return out << p.ptr; } +/** + * Apache Portable Runtime library context + */ +class APRContext { +public: + APRContext() { + apr_initialize(); + } + ~APRContext() { + apr_terminate(); + } +}; + +APRContext aprContext; + +/** + * Garbage collected memory pool, using an APR pool. + */ +class gc_pool { +public: + gc_pool() : aprPool(new APRPool) { + } + + operator apr_pool_t*() const { + return aprPool->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 __sync_add_and_fetch(&refCount, 1); + } + + unsigned int release() { + return __sync_sub_and_fetch(&refCount, 1); + } + }; + + const gc_counting_ptr<APRPool> aprPool; +}; + +/** + * Garbage collected pointer to pooled memory. + */ +template<typename T> class gc_pool_ptr { +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); + } + + 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_pool_ptr<X>&); + +private: + T* ptr; +}; + +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. + */ +template<typename T> apr_status_t gc_pool_cleanupCallback(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) { + + // Allocate memory from the pool + void* m = apr_palloc(mp, sizeof(T)); + + // Register a cleanup callback + apr_pool_cleanup_register(mp, m, gc_pool_cleanupCallback<T>, apr_pool_cleanup_null) ; + + // Run the requested type's constructor over the allocated memory + return new (m) T(); +} + } #endif /* tuscany_gc_hpp */ diff --git a/cpp/sca/kernel/kernel-test.cpp b/cpp/sca/kernel/kernel-test.cpp index 9f977a64f9..0234f6eb3e 100644 --- a/cpp/sca/kernel/kernel-test.cpp +++ b/cpp/sca/kernel/kernel-test.cpp @@ -152,7 +152,7 @@ bool testOut() { std::ostringstream os2; os2 << mklist(1, 2, 3); - assert(os2.str() == "(1, 2, 3)"); + assert(os2.str() == "(1 2 3)"); return true; } @@ -334,6 +334,14 @@ bool testValue() { const list<value> v = mklist<value>(mklist<value>("x", "X"), mklist<value>("a", "A"), mklist<value>("y", "Y")); assert(cadr((list<list<value> >)value(v)) == mklist<value>("a", "A")); + + const value pv(gc_ptr<value>(new value(1))); + assert(*(gc_ptr<value>)pv == value(1)); + + const list<value> lpv = mklist<value>(gc_ptr<value>(new value(1)), gc_ptr<value>(new value(2))); + assert(*(gc_ptr<value>)car(lpv) == value(1)); + *(gc_ptr<value>)cadr(lpv) = value(3); + assert(*(gc_ptr<value>)cadr(lpv) == value(3)); return true; } @@ -521,7 +529,7 @@ bool testReadXML() { return true; } -std::ostringstream* xmlWriter(std::ostringstream* os, const std::string& s) { +std::ostringstream* xmlWriter(const std::string& s, std::ostringstream* os) { (*os) << s; return os; } diff --git a/cpp/sca/kernel/list.hpp b/cpp/sca/kernel/list.hpp index 62c5d91150..deb4414d98 100644 --- a/cpp/sca/kernel/list.hpp +++ b/cpp/sca/kernel/list.hpp @@ -144,7 +144,7 @@ template<typename T> std::ostream& operator<<(std::ostream& out, const list<T>& ml = cdr(ml); if (isNil(ml)) break; - out << ", "; + out << " "; } return out << ")"; } @@ -164,6 +164,17 @@ template<typename T> const list<T> cons(const T& car, const list<T>& cdr) { } /** + * Cons variations for use with the reduce and reduceRight functions. + */ +template<typename T> const list<T> lcons(const list<T>& cdr, const T& car) { + return cons<T>(car, cdr); +} + +template<typename T> const list<T> rcons(const T& car, const list<T>& cdr) { + return cons<T>(car, cdr); +} + +/** * Construct a list from a single value. */ template<typename T> const list<T> cons(const T& car) { @@ -350,6 +361,22 @@ template<typename T, typename R> const R reduce(const lambda<R(R, T)>& f, const return reduceAccumulate<T, R> (f)(initial, p); } +template<typename T, typename R> struct reduceRightAccumulate { + const lambda<R(T, R)> f; + reduceRightAccumulate(const lambda<R(T, R)>& f) : + f(f) { + } + R operator()(const list<T>& p, const R& acc) const { + if(isNil(p)) + return acc; + return (*this)(cdr(p), f(car(p), acc)); + } +}; + +template<typename T, typename R> const R reduceRight(const lambda<R(T, R)>& f, const R& initial, const list<T>& p) { + return reduceRightAccumulate<T, R> (f)(p, initial); +} + /** * Run a filter lambda function on a list. */ diff --git a/cpp/sca/kernel/value.hpp b/cpp/sca/kernel/value.hpp index d57264ff43..618bd7b622 100644 --- a/cpp/sca/kernel/value.hpp +++ b/cpp/sca/kernel/value.hpp @@ -60,7 +60,7 @@ class value { public: enum ValueType { - Undefined, Symbol, String, List, Number, Boolean, Character, Lambda + Undefined, Symbol, String, List, Number, Bool, Char, Lambda, Ptr, PoolPtr }; value() : @@ -84,10 +84,14 @@ public: str() = v.str(); case value::Number: num() = v.num(); - case value::Boolean: + case value::Bool: boo() = v.boo(); - case value::Character: + case value::Char: chr() = v.chr(); + case value::Ptr: + ptr() = v.ptr(); + case value::PoolPtr: + poolptr() = v.poolptr(); default: break; } @@ -108,10 +112,14 @@ public: str() = v.str(); case value::Number: num() = v.num(); - case value::Boolean: + case value::Bool: boo() = v.boo(); - case value::Character: + case value::Char: chr() = v.chr(); + case value::Ptr: + ptr() = v.ptr(); + case value::PoolPtr: + poolptr() = v.poolptr(); default: break; } @@ -165,13 +173,25 @@ public: } value(const bool boo) : - type(value::Boolean), data(vdata(result(boo))) { + type(value::Bool), data(vdata(result(boo))) { countValues++; countVValues++; } value(const char chr) : - type(value::Character), data(vdata(result(chr))) { + type(value::Char), data(vdata(result(chr))) { + countValues++; + countVValues++; + } + + value(const gc_ptr<value> ptr) : + type(value::Ptr), data(vdata(result(ptr))) { + countValues++; + countVValues++; + } + + value(const gc_pool_ptr<value> ptr) : + type(value::PoolPtr), data(vdata(result(ptr))) { countValues++; countVValues++; } @@ -198,10 +218,14 @@ public: return str()() == v.str()(); case value::Number: return num()() == v.num()(); - case value::Boolean: + case value::Bool: return boo()() == v.boo()(); - case value::Character: + case value::Char: return chr()() == v.chr()(); + case value::Ptr: + return ptr()() == v.ptr()(); + case value::PoolPtr: + return poolptr()() == v.poolptr()(); default: return false; } @@ -215,6 +239,8 @@ public: switch(type) { case value::List: case value::Lambda: + case value::Ptr: + case value::PoolPtr: return ""; case value::Symbol: case value::String: @@ -224,13 +250,13 @@ public: sos << num()(); return sos.str(); } - case value::Boolean: { + case value::Bool: { if(boo()()) return "true"; else return "false"; } - case value::Character: { + case value::Char: { std::ostringstream sos; sos << chr()(); return sos.str(); @@ -256,6 +282,14 @@ public: return chr()(); } + operator const gc_ptr<value>() const { + return ptr()(); + } + + operator const gc_pool_ptr<value>() const { + return poolptr()(); + } + operator const list<value>() const { return lst()(); } @@ -294,6 +328,14 @@ private: return vdata<char()> (); } + lambda<gc_ptr<value>()>& ptr() const { + return vdata<gc_ptr<value>()> (); + } + + lambda<gc_pool_ptr<value>()>& poolptr() const { + return vdata<gc_pool_ptr<value>()> (); + } + lambda<std::string()>& str() const { return vdata<std::string()> (); } @@ -328,18 +370,30 @@ std::ostream& operator<<(std::ostream& out, const value& v) { case value::Lambda: return out << "lambda::" << v.func(); case value::Symbol: - return out << "symbol::" << v.str()(); + return out << v.str()(); case value::String: - return out << "string::" << '\"' << v.str()() << '\"'; + return out << '\"' << v.str()() << '\"'; case value::Number: - return out << "number::" << v.num()(); - case value::Boolean: + return out << v.num()(); + case value::Bool: if(v.boo()()) - return out << "bool::" << "true"; + return out << "true"; else - return out << "bool::" << "false"; - case value::Character: - return out << "char::" << v.chr()(); + return out << "false"; + case value::Char: + return out << v.chr()(); + case value::Ptr: { + const gc_ptr<value> p = v.ptr()(); + if (p == gc_ptr<value>(NULL)) + return out << "pointer::null"; + return out << "pointer::" << *p; + } + case value::PoolPtr: { + const gc_pool_ptr<value> p = v.poolptr()(); + if (p == gc_pool_ptr<value>(NULL)) + return out << "pointer::null"; + return out << "pointer::" << *p; + } default: return out << "undefined"; } @@ -369,12 +423,20 @@ const bool isNumber(const value& value) { return value.type == value::Number; } -const bool isBoolean(const value& value) { - return value.type == value::Boolean; +const bool isBool(const value& value) { + return value.type == value::Bool; +} + +const bool isChar(const value& value) { + return value.type == value::Char; +} + +const bool isPtr(const value& value) { + return value.type == value::Ptr; } -const bool isCharacter(const value& value) { - return value.type == value::Character; +const bool isPoolPtr(const value& value) { + return value.type == value::PoolPtr; } const bool isTaggedList(const value& exp, value tag) { diff --git a/cpp/sca/kernel/xml.hpp b/cpp/sca/kernel/xml.hpp index afc3f5cc38..b7611b8477 100644 --- a/cpp/sca/kernel/xml.hpp +++ b/cpp/sca/kernel/xml.hpp @@ -40,6 +40,22 @@ namespace tuscany { /** + * Initializes the libxml2 library. + */ +class XMLParser { +public: + XMLParser() { + xmlInitParser(); + } + + ~XMLParser() { + xmlCleanupParser(); + } +}; + +XMLParser xmlParser; + +/** * Encapsulates a libxml2 xmlTextReader and its state. */ class XMLReader { @@ -54,6 +70,7 @@ public: } ~XMLReader() { + xmlTextReaderClose(xml); xmlFreeTextReader(xml); } @@ -298,9 +315,9 @@ const failable<bool, std::string> write(const list<value>& l, const xmlTextWrite */ template<typename R> class XMLWriteContext { public: - XMLWriteContext(const lambda<R(R, std::string)>& reduce, const R& accum) : reduce(reduce), accum(accum) { + XMLWriteContext(const lambda<R(std::string, R)>& reduce, const R& accum) : reduce(reduce), accum(accum) { } - const lambda<R(R, std::string)> reduce; + const lambda<R(std::string, R)> reduce; R accum; }; @@ -309,36 +326,35 @@ public: */ template<typename R> int writeCallback(void *context, const char* buffer, int len) { XMLWriteContext<R>& cx = *static_cast<XMLWriteContext<R>*>(context); - cx.accum = cx.reduce(cx.accum, std::string(buffer, len)); + cx.accum = cx.reduce(std::string(buffer, len), cx.accum); return len; } /** * Convert a list of values to an XML document. */ -template<typename R> const failable<R, std::string> writeXML(const lambda<R(R, std::string)>& reduce, const R& initial, const list<value>& l) { +template<typename R> const failable<R, std::string> writeXML(const lambda<R(std::string, R)>& reduce, const R& initial, const list<value>& l) { XMLWriteContext<R> cx(reduce, initial); xmlOutputBufferPtr out = xmlOutputBufferCreateIO(writeCallback<R>, NULL, &cx, NULL); + if (out == NULL) + return std::string("xmlOutputBufferCreateIO failed"); xmlTextWriterPtr xml = xmlNewTextWriter(out); if (xml == NULL) return std::string("xmlNewTextWriter failed"); const failable<bool, std::string> w = write(l, xml); - if (!hasValue(w)) + xmlFreeTextWriter(xml); + if (!hasValue(w)) { return std::string(w); - + } return cx.accum; } /** * Convert a list of values to a list of strings representing an XML document. */ -const list<std::string> writeXMLList(const list<std::string>& listSoFar, const std::string& s) { - return cons(s, listSoFar); -} - const failable<list<std::string>, std::string> writeXML(const list<value>& l) { - const failable<list<std::string>, std::string> ls = writeXML<list<std::string> >(writeXMLList, list<std::string>(), l); + const failable<list<std::string>, std::string> ls = writeXML<list<std::string> >(rcons<std::string>, list<std::string>(), l); if (!hasValue(ls)) return ls; return reverse(list<std::string>(ls)); |