summaryrefslogtreecommitdiffstats
path: root/cpp/sca/kernel
diff options
context:
space:
mode:
authorjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2009-11-01 05:24:54 +0000
committerjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2009-11-01 05:24:54 +0000
commit9f187b46ae761e8275362d6c1533e9fe79028c7b (patch)
treee2625f63e0c84f172c877e1fe2cbe75adf678208 /cpp/sca/kernel
parent24021bd09a0d5c9664565a244c24e0bdef0908b8 (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 '')
-rw-r--r--cpp/sca/kernel/Makefile.am6
-rw-r--r--cpp/sca/kernel/element.hpp6
-rw-r--r--cpp/sca/kernel/function.hpp22
-rw-r--r--cpp/sca/kernel/gc.hpp135
-rw-r--r--cpp/sca/kernel/kernel-test.cpp12
-rw-r--r--cpp/sca/kernel/list.hpp29
-rw-r--r--cpp/sca/kernel/value.hpp108
-rw-r--r--cpp/sca/kernel/xml.hpp38
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));