diff options
Diffstat (limited to 'sca-cpp/trunk/kernel')
-rw-r--r-- | sca-cpp/trunk/kernel/dynlib.hpp | 11 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/fstream.hpp | 22 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/gc.hpp | 101 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/hash-test.cpp | 1 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/kernel-test.cpp | 1 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/lambda-test.cpp | 1 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/mem-test.cpp | 1 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/monad.hpp | 128 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/parallel-test.cpp | 43 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/parallel.hpp | 19 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/perf.hpp | 6 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/string-test.cpp | 1 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/xml-test.cpp | 1 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/xml.hpp | 17 |
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; |