summaryrefslogtreecommitdiffstats
path: root/sca-cpp/trunk/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'sca-cpp/trunk/kernel')
-rw-r--r--sca-cpp/trunk/kernel/dynlib.hpp11
-rw-r--r--sca-cpp/trunk/kernel/fstream.hpp22
-rw-r--r--sca-cpp/trunk/kernel/gc.hpp101
-rw-r--r--sca-cpp/trunk/kernel/hash-test.cpp1
-rw-r--r--sca-cpp/trunk/kernel/kernel-test.cpp1
-rw-r--r--sca-cpp/trunk/kernel/lambda-test.cpp1
-rw-r--r--sca-cpp/trunk/kernel/mem-test.cpp1
-rw-r--r--sca-cpp/trunk/kernel/monad.hpp128
-rw-r--r--sca-cpp/trunk/kernel/parallel-test.cpp43
-rw-r--r--sca-cpp/trunk/kernel/parallel.hpp19
-rw-r--r--sca-cpp/trunk/kernel/perf.hpp6
-rw-r--r--sca-cpp/trunk/kernel/string-test.cpp1
-rw-r--r--sca-cpp/trunk/kernel/xml-test.cpp1
-rw-r--r--sca-cpp/trunk/kernel/xml.hpp17
14 files changed, 274 insertions, 79 deletions
diff --git a/sca-cpp/trunk/kernel/dynlib.hpp b/sca-cpp/trunk/kernel/dynlib.hpp
index 484de3d666..69359b4dae 100644
--- a/sca-cpp/trunk/kernel/dynlib.hpp
+++ b/sca-cpp/trunk/kernel/dynlib.hpp
@@ -59,6 +59,15 @@ public:
lib(const lib& l) : name(l.name), h(l.h), owner(false) {
}
+ const lib& operator=(const lib& l) {
+ if(this == &l)
+ return *this;
+ name = l.name;
+ h = l.h;
+ owner = false;
+ return *this;
+ }
+
~lib() {
if (!owner)
return;
@@ -70,7 +79,7 @@ public:
private:
template<typename S> friend const failable<lambda<S> > dynlambda(const string& name, const lib& l);
- const string name;
+ string name;
failable<void*> h;
bool owner;
};
diff --git a/sca-cpp/trunk/kernel/fstream.hpp b/sca-cpp/trunk/kernel/fstream.hpp
index 5ea9df2d62..4f7f5152aa 100644
--- a/sca-cpp/trunk/kernel/fstream.hpp
+++ b/sca-cpp/trunk/kernel/fstream.hpp
@@ -78,6 +78,14 @@ public:
ofstream(const ofstream& os) : file(os.file), owner(false) {
}
+ const ofstream& operator=(const ofstream& os) {
+ if(this == &os)
+ return *this;
+ file = os.file;
+ owner = false;
+ return *this;
+ }
+
~ofstream() {
if (!owner)
return;
@@ -127,6 +135,14 @@ public:
ifstream(const ifstream& is) : file(is.file), owner(false) {
}
+ const ifstream& operator=(const ifstream& is) {
+ if(this == &is)
+ return *this;
+ file = is.file;
+ owner = false;
+ return *this;
+ }
+
~ifstream() {
if (!owner)
return;
@@ -351,7 +367,7 @@ const bool debug_isLogging() {
* Log a debug message.
*/
const bool debugLog(const string& msg) {
- gc_scoped_pool();
+ gc_scoped_pool p;
cdebug << msg << endl;
return true;
}
@@ -360,7 +376,7 @@ const bool debugLog(const string& msg) {
* Log a debug message and a value.
*/
template<typename V> const bool debugLog(const V& v, const string& msg) {
- gc_scoped_pool();
+ gc_scoped_pool p;
cdebug << msg << ": " << v << endl;
return true;
}
@@ -369,7 +385,7 @@ template<typename V> const bool debugLog(const V& v, const string& msg) {
* Log a debug message and two values.
*/
template<typename V, typename W> const bool debugLog(const V& v, const W& w, const string& msg) {
- gc_scoped_pool();
+ gc_scoped_pool p;
cdebug << msg << ": " << v << " : " << w << endl;
return true;
}
diff --git a/sca-cpp/trunk/kernel/gc.hpp b/sca-cpp/trunk/kernel/gc.hpp
index 260688f4ff..32ad8160cc 100644
--- a/sca-cpp/trunk/kernel/gc.hpp
+++ b/sca-cpp/trunk/kernel/gc.hpp
@@ -149,22 +149,14 @@ public:
private:
friend apr_pool_t* pool(const gc_pool& pool);
friend class gc_global_pool_t;
+ friend class gc_child_pool;
+ friend class gc_local_pool;
friend class gc_scoped_pool;
apr_pool_t* apr_pool;
};
/**
- * Make a new APR pool.
- */
-apr_pool_t* mkpool() {
- apr_pool_t* p = NULL;
- apr_pool_create(&p, NULL);
- assertOrFail(p != NULL);
- return p;
-}
-
-/**
* Return the APR pool used by a gc_pool.
*/
apr_pool_t* pool(const gc_pool& pool) {
@@ -172,16 +164,6 @@ apr_pool_t* pool(const gc_pool& pool) {
}
/**
- * Destroy a memory pool.
- */
-const bool destroy(const gc_pool& p) {
- if (pool(p) == NULL)
- return false;
- apr_pool_destroy(pool(p));
- return true;
-}
-
-/**
* Maintain a stack of memory pools.
*/
#ifdef WANT_THREADS
@@ -244,19 +226,77 @@ apr_pool_t* gc_current_pool() {
}
/**
- * A memory pool scope, used to setup a scope in which a particular pool
- * will be used for all allocations.
+ * A child memory pool, which will be destroyed when its parent pool is destroyed.
+ */
+class gc_child_pool : public gc_pool {
+public:
+
+ gc_child_pool() : gc_pool(NULL), owner(true) {
+ apr_pool_create(&apr_pool, gc_current_pool());
+ assertOrFail(apr_pool != NULL);
+ }
+
+ gc_child_pool(const gc_child_pool& p) : gc_pool(p.apr_pool), owner(false) {
+ }
+
+ const gc_child_pool& operator=(const gc_child_pool& p) {
+ if(this == &p)
+ return *this;
+ apr_pool = p.apr_pool;
+ owner = false;
+ return *this;
+ }
+
+
+private:
+ bool owner;
+};
+
+/**
+ * A local pool scope, which will be destroyed when exiting the current scope.
+ */
+class gc_local_pool : public gc_pool {
+public:
+
+ gc_local_pool() : gc_pool(NULL), owner(true) {
+ apr_pool_create(&apr_pool, gc_current_pool());
+ assertOrFail(apr_pool != NULL);
+ }
+
+ ~gc_local_pool() {
+ if (owner)
+ apr_pool_destroy(apr_pool);
+ }
+
+ gc_local_pool(const gc_local_pool& p) : gc_pool(p.apr_pool), owner(false) {
+ }
+
+ const gc_local_pool& operator=(const gc_local_pool& p) {
+ if(this == &p)
+ return *this;
+ apr_pool = p.apr_pool;
+ owner = false;
+ return *this;
+ }
+
+private:
+ bool owner;
+};
+
+/**
+ * A memory pool scope, used to setup a scope in which a particular pool will be
+ * used for all allocations. Will be destroyed when existing the current scope.
*/
class gc_scoped_pool : public gc_pool {
public:
gc_scoped_pool() : gc_pool(NULL), prev(gc_current_pool()), owner(true) {
- apr_pool_create(&apr_pool, NULL);
+ apr_pool_create(&apr_pool, prev);
assertOrFail(apr_pool != NULL);
gc_push_pool(apr_pool);
}
- gc_scoped_pool(apr_pool_t* pool) : gc_pool(pool), prev(gc_current_pool()), owner(false) {
+ gc_scoped_pool(apr_pool_t* p) : gc_pool(p), prev(gc_current_pool()), owner(false) {
gc_push_pool(apr_pool);
}
@@ -266,10 +306,19 @@ public:
gc_pop_pool(prev);
}
-private:
- gc_scoped_pool(const gc_scoped_pool& pool) : gc_pool(pool.apr_pool), prev(NULL), owner(false) {
+ gc_scoped_pool(const gc_scoped_pool& p) : gc_pool(p.apr_pool), prev(p.prev), owner(false) {
}
+ const gc_scoped_pool& operator=(const gc_scoped_pool& p) {
+ if(this == &p)
+ return *this;
+ apr_pool = p.apr_pool;
+ prev = p.prev;
+ owner = false;
+ return *this;
+ }
+
+private:
apr_pool_t* prev;
bool owner;
};
diff --git a/sca-cpp/trunk/kernel/hash-test.cpp b/sca-cpp/trunk/kernel/hash-test.cpp
index b794e38920..4e6a3654e5 100644
--- a/sca-cpp/trunk/kernel/hash-test.cpp
+++ b/sca-cpp/trunk/kernel/hash-test.cpp
@@ -121,6 +121,7 @@ bool testHashPerf() {
}
int main() {
+ tuscany::gc_scoped_pool p;
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::testCrc32hash();
diff --git a/sca-cpp/trunk/kernel/kernel-test.cpp b/sca-cpp/trunk/kernel/kernel-test.cpp
index 7bde4fb526..4d2ca2ba81 100644
--- a/sca-cpp/trunk/kernel/kernel-test.cpp
+++ b/sca-cpp/trunk/kernel/kernel-test.cpp
@@ -575,6 +575,7 @@ bool testDynLib() {
}
int main() {
+ tuscany::gc_scoped_pool p;
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::testLambda();
diff --git a/sca-cpp/trunk/kernel/lambda-test.cpp b/sca-cpp/trunk/kernel/lambda-test.cpp
index e17cf57e67..05a16c2eb8 100644
--- a/sca-cpp/trunk/kernel/lambda-test.cpp
+++ b/sca-cpp/trunk/kernel/lambda-test.cpp
@@ -87,6 +87,7 @@ bool testCppPerf() {
}
int main() {
+ tuscany::gc_scoped_pool p;
tuscany::cout << "Testing..." << tuscany::endl;
#ifdef HAS_CXX0X_LAMBDAS
diff --git a/sca-cpp/trunk/kernel/mem-test.cpp b/sca-cpp/trunk/kernel/mem-test.cpp
index e9a2f85ec6..668dabe749 100644
--- a/sca-cpp/trunk/kernel/mem-test.cpp
+++ b/sca-cpp/trunk/kernel/mem-test.cpp
@@ -151,6 +151,7 @@ bool testStdAllocPerf() {
}
int main() {
+ tuscany::gc_scoped_pool p;
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::testPoolAllocPerf();
diff --git a/sca-cpp/trunk/kernel/monad.hpp b/sca-cpp/trunk/kernel/monad.hpp
index 657a809c1c..b67e92ad79 100644
--- a/sca-cpp/trunk/kernel/monad.hpp
+++ b/sca-cpp/trunk/kernel/monad.hpp
@@ -26,6 +26,8 @@
* Simple monad implementations.
*/
+#include <execinfo.h>
+#include <cxxabi.h>
#include "function.hpp"
#include "string.hpp"
#include "stream.hpp"
@@ -278,38 +280,134 @@ template<typename V, typename F, typename C> const lambda<failable<V, F, C>(cons
}
/**
+ * Demangle a C++ function name.
+ */
+const string demangleFrame(const char* fun) {
+ int status;
+ char* name = abi::__cxa_demangle(fun, 0, 0, &status);
+ if (name == NULL)
+ return fun;
+ const string s = name;
+ free(name);
+ return s;
+}
+
+/**
+ * Format a backtrace frame.
+ */
+const char* formatFrameFile(const char* file) {
+ const char* s = strrchr(file, '/');
+ return s == NULL? file : s + 1;
+}
+
+const string formatFrame(const char* symbol) {
+#ifdef __clang__
+ // Mac OS X CLang/LLVM stack frame format
+ // 0 kernel-test 0x000000010d440179 _ZN7tuscany9mkfailureINS_5valueENS_6stringEiEEKNS_8failableIT_T0_T1_EERKS5_RKS6_b + 265
+ char nb[3];
+ char file[256];
+ char addr[32];
+ char fun[256];
+ char offset[16];
+ if (sscanf(symbol, "%2s %255s %31s %255s %*[+] %15s", nb, file, addr, fun, offset) == 5) {
+ char buf[1024];
+ if (debug_islogging())
+ sprintf(buf, "%.255s %.31s %.511s + %.15s", formatFrameFile(file), addr, c_str(demangleFrame(fun)), offset);
+ else
+ sprintf(buf, "%.255s %.31s", formatFrameFile(file), addr);
+ return buf;
+ }
+#else
+ // Linux GCC stack frame format
+ // ./kernel-test(_ZN7tuscany9mkfailureINS_5valueENS_6stringEiEEKNS_8failableIT_T0_T1_EERKS5_RKS6_b+0x23d) [0xb7197afd]
+ char file[256];
+ char fun[256];
+ char offset[16];
+ char addr[32];
+ if (sscanf(symbol, "%[^(]%*[(]%[^+]%*[+]%[^)]%*[)] %*[[]%[^]]%*[]]", file, fun, offset, addr) == 4) {
+ char buf[1024];
+ if (debug_islogging())
+ sprintf(buf, "%.255s %.31s %.511s + %.15s", formatFrameFile(file), addr, c_str(demangleFrame(fun)), offset);
+ else
+ sprintf(buf, "%.255s %.31s", formatFrameFile(file), addr);
+ return buf;
+ }
+ if (sscanf(symbol, "%[^(]%*[(]%*[^)]%*[)] %*[[]%[^]]%*[]]", file, addr) == 2) {
+ char buf[512];
+ sprintf(buf, "%.255s %.31s", formatFrameFile(file), addr);
+ return buf;
+ }
+ if (sscanf(symbol, "%[^(]%*[(]%*[)] %*[[]%[^]]%*[]]", file, addr) == 2) {
+ char buf[512];
+ sprintf(buf, "%.255s %.31s", formatFrameFile(file), addr);
+ return buf;
+ }
+#endif
+ return symbol;
+}
+
+/**
+ * Log backtrace frames.
+ */
+const bool logFrames(char** symbols, const int frames, const bool log) {
+ if (frames == 0)
+ return true;
+#ifdef WANT_MAINTAINER_LOG
+ if (!log)
+ debug(formatFrame(*symbols), "failable::backtrace");
+#endif
+ if (log)
+ cfailure << "failable::backtrace: " << formatFrame(*symbols) << endl;
+ return logFrames(symbols + 1, frames - 1, log);
+}
+
+/**
+ * Log a backtrace.
+ */
+const bool logBacktrace(void** callstack, const int frames, const bool log) {
+ char** symbols = backtrace_symbols(callstack, frames);
+ logFrames(symbols, frames, log);
+ free(symbols);
+ return true;
+}
+
+/**
* Returns a failable monad with a failure in it.
*/
template<typename V, typename F, typename C> const failable<V, F, C> mkfailure(const F& f, const C& c, const bool log = true) {
#ifdef WANT_MAINTAINER_LOG
- if (!log)
+ if (!log) {
+ // Log the failure
debug(f, "failable::mkfailure");
+
+ // Log the call stack
+ void* callstack[16];
+ const int frames = backtrace(callstack, 16);
+ logBacktrace(callstack, frames, log);
+ }
#endif
if (log) {
ostringstream os;
os << f;
- if (length(str(os)) != 0)
- cfailure << "failable::mkfailure" << ": " << f << " : " << c << endl;
+ if (length(str(os)) != 0) {
+ // Log the failure
+ cfailure << "failable::mkfailure: " << f << " : " << c << endl;
+
+ // Print the call stack
+ void* callstack[16];
+ const int frames = backtrace(callstack, 16);
+ logBacktrace(callstack, frames, log);
+ }
}
return failable<V, F, C>(false, f, c);
}
template<typename V, typename F> const failable<V, F> mkfailure(const F& f, const int c = -1, const bool log = true) {
-#ifdef WANT_MAINTAINER_LOG
- if (!log)
- debug(f, c, "failable::mkfailure");
-#endif
- if (log) {
- ostringstream os;
- os << f;
- if (length(str(os)) != 0)
- cfailure << "failable::mkfailure: " << str(os) << " : " << c << endl;
- }
- return failable<V, F>(false, f, c);
+ return mkfailure<V, F, int>(f, c, log);
}
template<typename V> const failable<V> mkfailure(const char* f, const int c = -1, const bool log = true) {
- return mkfailure<V, string>(string(f), c, log);
+ return mkfailure<V, string, int>(string(f), c, log);
}
template<typename V> const failable<V> mkfailure() {
diff --git a/sca-cpp/trunk/kernel/parallel-test.cpp b/sca-cpp/trunk/kernel/parallel-test.cpp
index 59cfd81978..28e484d42b 100644
--- a/sca-cpp/trunk/kernel/parallel-test.cpp
+++ b/sca-cpp/trunk/kernel/parallel-test.cpp
@@ -33,8 +33,6 @@
namespace tuscany {
-#ifdef WANT_THREADS
-
int inci = 0;
struct incPerf {
@@ -46,6 +44,24 @@ struct incPerf {
}
};
+const gc_ptr<int> tlsic() {
+ gc_ptr<int> i = new (gc_new<int>()) int();
+ *i = 0;
+ return i;
+}
+const perthread_ptr<int> tlsi(tlsic);
+
+struct tlsPerf {
+ tlsPerf() {
+ }
+ const bool operator()() const {
+ *tlsi = *tlsi + 1;
+ return true;
+ }
+};
+
+#ifdef WANT_THREADS
+
int addi = 0;
struct addAndFetchPerf {
@@ -71,21 +87,7 @@ struct mutexPerf {
}
};
-const gc_ptr<int> tlsic() {
- gc_ptr<int> i = new (gc_new<int>()) int();
- *i = 0;
- return i;
-}
-const perthread_ptr<int> tlsi(tlsic);
-
-struct tlsPerf {
- tlsPerf() {
- }
- const bool operator()() const {
- *tlsi = *tlsi + 1;
- return true;
- }
-};
+#endif
bool testAtomicPerf() {
const int count = 100000;
@@ -94,6 +96,7 @@ bool testAtomicPerf() {
cout << "Non-atomic inc test " << time(l, 1000, count) << " ms" << endl;
assert(inci == count + 1000);
}
+#ifdef WANT_THREADS
{
const lambda<bool()> l = addAndFetchPerf();
cout << "Atomic inc test " << time(l, 1000, count) << " ms" << endl;
@@ -107,6 +110,7 @@ bool testAtomicPerf() {
assert(muxi == count + 1000);
pthread_mutex_destroy(&mutex);
}
+#endif
{
const lambda<bool()> l = tlsPerf();
cout << "Thread local inc test " << time(l, 1000, count) << " ms" << endl;
@@ -115,6 +119,8 @@ bool testAtomicPerf() {
return true;
}
+#ifdef WANT_THREADS
+
const int mtsquare(const int x) {
for(int i = 0; i < 10000000; i++)
;
@@ -239,10 +245,11 @@ bool testWorker() {
}
int main() {
+ tuscany::gc_scoped_pool p;
tuscany::cout << "Testing..." << tuscany::endl;
-#ifdef WANT_THREADS
tuscany::testAtomicPerf();
+#ifdef WANT_THREADS
tuscany::testWorker();
#else
tuscany::cout << "Skipped multi-thread tests" << tuscany::endl;
diff --git a/sca-cpp/trunk/kernel/parallel.hpp b/sca-cpp/trunk/kernel/parallel.hpp
index 57754a33e6..3be4d3bc8e 100644
--- a/sca-cpp/trunk/kernel/parallel.hpp
+++ b/sca-cpp/trunk/kernel/parallel.hpp
@@ -429,24 +429,24 @@ private:
}
#else
- int createkey() {
- return 0;
+ gc_ptr<gc_ptr<T> > createkey() {
+ return new (gc_new<gc_ptr<T> >()) gc_ptr<T>();
}
- bool deletekey(unused int k) {
+ bool deletekey(unused gc_ptr<gc_ptr<T> > k) {
return true;
}
bool set(const gc_ptr<T>& v) {
- val = v;
+ *key = v;
return true;
}
gc_ptr<T> get() const {
- if (val != NULL || !managed)
- return val;
- val = cl();
- return val;
+ if (*key != NULL || !managed)
+ return *key;
+ *key = cl();
+ return *key;
}
#endif
@@ -454,8 +454,7 @@ private:
#ifdef WANT_THREADS
pthread_key_t key;
#else
- int key;
- gc_ptr<T> val;
+ gc_ptr<gc_ptr<T> >key;
#endif
bool owner;
diff --git a/sca-cpp/trunk/kernel/perf.hpp b/sca-cpp/trunk/kernel/perf.hpp
index 82d0ddad03..04aad06664 100644
--- a/sca-cpp/trunk/kernel/perf.hpp
+++ b/sca-cpp/trunk/kernel/perf.hpp
@@ -42,10 +42,8 @@ struct timeLambda {
timeLambda(const lambda<bool()>& f) : f(f) {
}
bool operator()(const long count) const {
- if (count == 0)
- return true;
- f();
- (*this)(count - 1);
+ for (long i = 0; i < count; i++)
+ f();
return true;
}
};
diff --git a/sca-cpp/trunk/kernel/string-test.cpp b/sca-cpp/trunk/kernel/string-test.cpp
index e691d93dfb..b6f016b294 100644
--- a/sca-cpp/trunk/kernel/string-test.cpp
+++ b/sca-cpp/trunk/kernel/string-test.cpp
@@ -185,6 +185,7 @@ bool testStringPerf() {
}
int main() {
+ tuscany::gc_scoped_pool p;
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::testCopies();
diff --git a/sca-cpp/trunk/kernel/xml-test.cpp b/sca-cpp/trunk/kernel/xml-test.cpp
index c505cae9cf..0523cc74a6 100644
--- a/sca-cpp/trunk/kernel/xml-test.cpp
+++ b/sca-cpp/trunk/kernel/xml-test.cpp
@@ -221,6 +221,7 @@ bool testValues() {
}
int main() {
+ tuscany::gc_scoped_pool p;
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::testReadXML();
diff --git a/sca-cpp/trunk/kernel/xml.hpp b/sca-cpp/trunk/kernel/xml.hpp
index 14549e5dfc..d00a2905fb 100644
--- a/sca-cpp/trunk/kernel/xml.hpp
+++ b/sca-cpp/trunk/kernel/xml.hpp
@@ -78,6 +78,19 @@ public:
debug("xml::XMLReader::copy");
}
+ const XMLReader& operator=(const XMLReader& r) {
+ debug("xml::XMLReader::operator=");
+ if(this == &r)
+ return *this;
+ xml = r.xml;
+ owner = false;
+ tokenType = r.tokenType;
+ isEmptyElement = r.isEmptyElement;
+ hasValue = r.hasValue;
+ hasAttributes = r.hasAttributes;
+ return *this;
+ }
+
~XMLReader() {
if (!owner)
return;
@@ -112,8 +125,8 @@ public:
}
private:
- const xmlTextReaderPtr xml;
- const bool owner;
+ xmlTextReaderPtr xml;
+ bool owner;
int tokenType;
bool isEmptyElement;
bool hasValue;