diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2010-01-02 22:13:15 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2010-01-02 22:13:15 +0000 |
commit | 996d5f6c4e21d3d8688674f20e6f4318e3ace607 (patch) | |
tree | be6a3d80f2cab11cd39d0f55bd4bc55793a2e735 /sca-cpp/trunk | |
parent | dda9255a5c9336cd3078f85f02e88120563ad304 (diff) |
Cleaned up lifecycle handling of objects that hold library and file resources. Fixed pool stack initialization concurrency issue. Re-enabled watch strings to help watch compound values in debugger.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@895305 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sca-cpp/trunk')
-rw-r--r-- | sca-cpp/trunk/kernel/debug.hpp | 5 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/dynlib.hpp | 50 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/fstream.hpp | 25 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/gc.hpp | 90 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/kernel-test.cpp | 7 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/list.hpp | 2 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/monad.hpp | 14 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/sstream.hpp | 6 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/stream.hpp | 54 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/string.hpp | 3 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/value.hpp | 2 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/xml.hpp | 8 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/http/curl.hpp | 43 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/json/json.hpp | 13 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/server/mod-cpp.hpp | 9 |
15 files changed, 186 insertions, 145 deletions
diff --git a/sca-cpp/trunk/kernel/debug.hpp b/sca-cpp/trunk/kernel/debug.hpp index c51ee6c974..f9baf73c3c 100644 --- a/sca-cpp/trunk/kernel/debug.hpp +++ b/sca-cpp/trunk/kernel/debug.hpp @@ -31,7 +31,10 @@ namespace tuscany #ifdef _DEBUG -//#define _DEBUG_WATCH +/** + * Add string watch members to important classes to help watch them in a debugger. + */ +#define _DEBUG_WATCH /** * Increment / decrement a debug counter. diff --git a/sca-cpp/trunk/kernel/dynlib.hpp b/sca-cpp/trunk/kernel/dynlib.hpp index a000653455..9f55dc4a49 100644 --- a/sca-cpp/trunk/kernel/dynlib.hpp +++ b/sca-cpp/trunk/kernel/dynlib.hpp @@ -48,52 +48,40 @@ const string dynlibExt(".so"); */ class lib { public: - lib() : dl(NULL) { + lib() : h(NULL), owner(false) { } - lib(const string& name) : dl(new (gc_new<DynLib>()) DynLib(name)) { + lib(const string& name) : name(name), h(dlopen(c_str(name), RTLD_NOW)), owner(true) { + if (h == NULL) + h = mkfailure<void*>(string("Could not load library: ") + name + ": " + dlerror()); + } + + lib(const lib& l) : name(l.name), h(l.h), owner(false) { } ~lib() { + if (!owner) + return; + if (!hasContent(h) || content(h) == NULL) + return; + dlclose(content(h)); } private: - class DynLib { - public: - DynLib(const string& name) : name(name), h(dlopen(c_str(name), RTLD_NOW)) { - } - - ~DynLib() { - if (h == NULL) - return; - dlclose(h); - } - - const string name; - void* h; - }; - - gc_ptr<DynLib> dl; - - friend const failable<lib> dynlib(const string& name); template<typename S> friend const failable<lambda<S> > dynlambda(const string& name, const lib& l); -}; -/** - * Load a dynamic library. - */ -const failable<lib> dynlib(const string& name) { - const lib l(name); - if (l.dl->h == NULL) - return mkfailure<lib>(string("Could not load library: ") + name + ": " + dlerror()); - return l; -} + const string name; + failable<void*> h; + bool owner; +}; /** * Find a lambda function in a dynamic library. */ template<typename S> const failable<lambda<S> > dynlambda(const string& name, const lib& l) { - const void* s = dlsym(l.dl->h, c_str(name)); + if (!hasContent(l.h)) + return mkfailure<lambda<S> >(reason(l.h)); + const void* s = dlsym(content(l.h), c_str(name)); if (s == NULL) return mkfailure<lambda<S> >(string("Could not load symbol: ") + name); return lambda<S>((S*)s); diff --git a/sca-cpp/trunk/kernel/fstream.hpp b/sca-cpp/trunk/kernel/fstream.hpp index 3d6b1edade..b158e66084 100644 --- a/sca-cpp/trunk/kernel/fstream.hpp +++ b/sca-cpp/trunk/kernel/fstream.hpp @@ -38,17 +38,17 @@ namespace tuscany { */ class ofstream : public ostream { public: - ofstream(const string& path) : file(fopen(c_str(path), "wb")), owned(true) { + ofstream(const string& path) : file(fopen(c_str(path), "wb")), owner(true) { } - ofstream(FILE* file) : file(file), owned(false) { + ofstream(FILE* file) : file(file), owner(false) { } - ofstream(const ofstream& os) : file(os.file), owned(false) { + ofstream(const ofstream& os) : file(os.file), owner(false) { } ~ofstream() { - if (!owned) + if (!owner) return; if (file == NULL) return; @@ -63,6 +63,11 @@ public: return *this; } + ofstream& write(const string& s) { + fwrite(c_str(s), 1, length(s), file); + return *this; + } + ofstream& flush() { fflush(file); return *this; @@ -70,7 +75,7 @@ public: private: FILE* file; - bool owned; + bool owner; }; /* @@ -78,17 +83,17 @@ private: */ class ifstream : public istream { public: - ifstream(const string& path) : file(fopen(c_str(path), "rb")), owned(true) { + ifstream(const string& path) : file(fopen(c_str(path), "rb")), owner(true) { } - ifstream(FILE* file) : file(file), owned(false) { + ifstream(FILE* file) : file(file), owner(false) { } - ifstream(const ifstream& is) : file(is.file), owned(false) { + ifstream(const ifstream& is) : file(is.file), owner(false) { } ~ifstream() { - if (!owned) + if (!owner) return; if (file == NULL) return; @@ -121,7 +126,7 @@ public: private: FILE* file; - bool owned; + bool owner; }; /** diff --git a/sca-cpp/trunk/kernel/gc.hpp b/sca-cpp/trunk/kernel/gc.hpp index cc347a6da4..bfb304615d 100644 --- a/sca-cpp/trunk/kernel/gc.hpp +++ b/sca-cpp/trunk/kernel/gc.hpp @@ -103,12 +103,8 @@ public: return *this; } - operator apr_pool_t*() const { - return p; - } - private: - friend const bool destroy(gc_pool& pool); + friend apr_pool_t* pool(const gc_pool& pool); friend class gc_global_pool_t; friend class gc_scoped_pool; @@ -116,40 +112,29 @@ private: }; /** + * Return APR pool used by a gc_pool. + */ +apr_pool_t* pool(const gc_pool& pool) { + return pool.p; +} + +/** * Destroy a memory pool. */ -const bool destroy(gc_pool& pool) { - apr_pool_destroy(pool.p); +const bool destroy(const gc_pool& p) { + apr_pool_destroy(pool(p)); return true; } /** - * Default global memory pool. + * Initialize APR. */ class gc_apr_context_t { public: gc_apr_context_t() { apr_initialize(); } - ~gc_apr_context_t() { - //apr_terminate(); - } -}; - -gc_apr_context_t gc_apr_context; - -class gc_global_pool_t : public gc_pool { -public: - gc_global_pool_t() { - apr_pool_create(&p, NULL); - } - - ~gc_global_pool_t() { - //apr_pool_destroy(p); - } -}; - -gc_global_pool_t gc_global_pool; +} gc_apr_context; /** * Maintain a stack of memory pools. @@ -166,9 +151,29 @@ 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; + + // Create a parent pool for the current thread + apr_pool_create(&p, NULL); + gc_pool_stack = p; + return p; +} + +/** + * Push a pool onto the stack. + */ +apr_pool_t* gc_push_pool(apr_pool_t* pool) { + apr_pool_t* p = gc_pool_stack; + gc_pool_stack = pool; + return p; +} + +/** + * Pop a pool from the stack. + */ +apr_pool_t* gc_pop_pool(apr_pool_t* pool) { + apr_pool_t* p = gc_pool_stack; + gc_pool_stack = pool; + return p; } /** @@ -178,28 +183,27 @@ apr_pool_t* gc_current_pool() { class gc_scoped_pool : public gc_pool { public: - gc_scoped_pool() : gc_pool(NULL), prev(gc_current_pool()), owned(true) { + gc_scoped_pool() : gc_pool(NULL), prev(gc_current_pool()), owner(true) { apr_pool_create(&p, NULL); - gc_pool_stack = p; + gc_push_pool(p); } - gc_scoped_pool(apr_pool_t* pool) : gc_pool(pool), prev(gc_current_pool()), owned(false) { - gc_pool_stack = p; + gc_scoped_pool(apr_pool_t* pool) : gc_pool(pool), prev(gc_current_pool()), owner(false) { + gc_push_pool(p); } ~gc_scoped_pool() { - if (owned) + if (owner) apr_pool_destroy(p); - if (prev != NULL) - gc_pool_stack = prev; + gc_pop_pool(prev); } private: - gc_scoped_pool(const unused gc_scoped_pool& pool) : gc_pool(pool.p), prev(NULL), owned(false) { + gc_scoped_pool(const unused gc_scoped_pool& pool) : gc_pool(pool.p), prev(NULL), owner(false) { } apr_pool_t* prev; - bool owned; + bool owner; }; /** @@ -218,6 +222,10 @@ template<typename T> T* gc_new(apr_pool_t* p) { return static_cast<T*>(m); } +template<typename T> T* gc_new(const gc_pool& p) { + return gc_new<T>(pool(p)); +} + template<typename T> T* gc_new() { return gc_new<T>(gc_current_pool()); } @@ -238,6 +246,10 @@ template<typename T> T* gc_anew(apr_pool_t* p, int n) { return (T*)(m + 1); } +template<typename T> T* gc_anew(const gc_pool& p, int n) { + return gc_anew<T>(pool(p), n); +} + template<typename T> T* gc_anew(int n) { return gc_anew<T>(gc_current_pool(), n); } diff --git a/sca-cpp/trunk/kernel/kernel-test.cpp b/sca-cpp/trunk/kernel/kernel-test.cpp index c4f76c13c9..44ffe06b7b 100644 --- a/sca-cpp/trunk/kernel/kernel-test.cpp +++ b/sca-cpp/trunk/kernel/kernel-test.cpp @@ -540,14 +540,13 @@ bool testStateMonad() { } bool testDynLib() { - const failable<lib> dl(dynlib(string(".libs/libdynlib-test") + dynlibExt)); - assert(hasContent(dl)); - const failable<lambda<int(const int)>> sq(dynlambda<int(const int)>("csquare", content(dl))); + const lib dl(string(".libs/libdynlib-test") + dynlibExt); + const failable<lambda<int(const int)> > sq(dynlambda<int(const int)>("csquare", dl)); assert(hasContent(sq)); lambda<int(const int)> l(content(sq)); assert(l(2) == 4); - const failable<lambda<lambda<int(const int)>()>> sql(dynlambda<lambda<int(const int)>()>("csquarel", content(dl))); + const failable<lambda<lambda<int(const int)>()> > sql(dynlambda<lambda<int(const int)>()>("csquarel", dl)); assert(hasContent(sql)); lambda<lambda<int(const int)>()> ll(content(sql)); assert(ll()(3) == 9); diff --git a/sca-cpp/trunk/kernel/list.hpp b/sca-cpp/trunk/kernel/list.hpp index 653f49dfe5..6a725d0382 100644 --- a/sca-cpp/trunk/kernel/list.hpp +++ b/sca-cpp/trunk/kernel/list.hpp @@ -198,7 +198,7 @@ private: template<typename T> const string watchList(const list<T>& p) { if(isNil(p)) return "()"; - ostringstream<string::npos> os; + odebugstream os; os << "(" << car(p) << " ...)"; return str(os); } diff --git a/sca-cpp/trunk/kernel/monad.hpp b/sca-cpp/trunk/kernel/monad.hpp index d2057cf367..15029b20ec 100644 --- a/sca-cpp/trunk/kernel/monad.hpp +++ b/sca-cpp/trunk/kernel/monad.hpp @@ -213,6 +213,15 @@ public: failable(const failable<V, F>& m) : hasv(m.hasv), v(m.v), f(m.f) { } + const failable<V, F>& operator=(const failable<V, F>& m) { + if (&m == this) + return *this; + hasv = m.hasv; + v = m.v; + f = m.f; + return *this; + } + const bool operator!=(const failable<V, F>& m) const { return !this->operator==(m); } @@ -229,11 +238,6 @@ private: failable(const bool hasv, const F& f) : hasv(hasv), f(f) { } - // Prevent mutation - const failable<V, F>& operator=(const failable<V, F>& m) { - return *this; - } - template<typename A, typename B> friend const bool hasContent(const failable<A, B>& m); template<typename A, typename B> friend const A content(const failable<A, B>& m); template<typename A, typename B> friend const B reason(const failable<A, B>& m); diff --git a/sca-cpp/trunk/kernel/sstream.hpp b/sca-cpp/trunk/kernel/sstream.hpp index 5fcdb0c22b..f5006606dd 100644 --- a/sca-cpp/trunk/kernel/sstream.hpp +++ b/sca-cpp/trunk/kernel/sstream.hpp @@ -71,6 +71,12 @@ public: return *this; } + ostringstream& write(const string& s) { + buf = cons(s, buf); + len += s.len; + return *this; + } + ostringstream& flush() { return *this; } diff --git a/sca-cpp/trunk/kernel/stream.hpp b/sca-cpp/trunk/kernel/stream.hpp index a3e532c4ce..f3efb13479 100644 --- a/sca-cpp/trunk/kernel/stream.hpp +++ b/sca-cpp/trunk/kernel/stream.hpp @@ -39,6 +39,7 @@ namespace tuscany { class ostream { public: virtual ostream& vprintf(const char* fmt, ...) = 0; + virtual ostream& write(const string& s) = 0; virtual ostream& flush() = 0; }; @@ -68,10 +69,18 @@ ostream& operator<<(ostream& os, const int v) { return os.vprintf("%d", v); } +ostream& operator<<(ostream& os, const unsigned int v) { + return os.vprintf("%u", v); +} + ostream& operator<<(ostream& os, const long int v) { return os.vprintf("%ld", v); } +ostream& operator<<(ostream& os, const long unsigned int v) { + return os.vprintf("%lu", v); +} + ostream& operator<<(ostream& os, const double v) { return os.vprintf("%g", v); } @@ -81,7 +90,7 @@ ostream& operator<<(ostream& os, const void* v) { } ostream& operator<<(ostream& os, const string& v) { - return os.vprintf("%s", c_str(v)); + return os.write(v); } class stream_endl { @@ -143,6 +152,49 @@ template<typename T> ostream& operator<<(ostream& out, const gc_ptr<T>& p) { return out << p.ptr; } +#ifdef _DEBUG + +/** + * Debug stream implementation with no dependencies on anything else. + */ +class odebugstream : public ostream { +public: + odebugstream() { + } + + odebugstream& vprintf(const char* fmt, ...) { + va_list args; + va_start (args, fmt); + string s; + s.len = vsnprintf(NULL, 0, fmt, args); + s.buf = gc_cnew(s.len + 1); + vsnprintf(s.buf, s.len + 1, fmt, args); + buf = buf + s; + va_end (args); + return *this; + } + + odebugstream& write(const string& s) { + buf = buf + s; + return *this; + } + + odebugstream& flush() { + return *this; + } + +private: + friend const string str(odebugstream& os); + + string buf; +}; + +const string str(odebugstream& os) { + return os.buf; +} + +#endif + } #endif /* tuscany_stream_hpp */ diff --git a/sca-cpp/trunk/kernel/string.hpp b/sca-cpp/trunk/kernel/string.hpp index f065bcc9a4..9a3af49fc7 100644 --- a/sca-cpp/trunk/kernel/string.hpp +++ b/sca-cpp/trunk/kernel/string.hpp @@ -172,6 +172,9 @@ public: } private: +#ifdef _DEBUG + friend class odebugstream; +#endif friend class ostringstream; friend const string operator+(const string& a, const string& b); friend const string operator+(const string& a, const char* b); diff --git a/sca-cpp/trunk/kernel/value.hpp b/sca-cpp/trunk/kernel/value.hpp index d2c5f12e95..df85f51cff 100644 --- a/sca-cpp/trunk/kernel/value.hpp +++ b/sca-cpp/trunk/kernel/value.hpp @@ -509,7 +509,7 @@ private: const string watchValue(const value& v) { if (v.type == value::List) return watchList<value>(v); - ostringstream<string::npos> os; + odebugstream os; os << v; return str(os); } diff --git a/sca-cpp/trunk/kernel/xml.hpp b/sca-cpp/trunk/kernel/xml.hpp index 84cfc30475..9e903ea34d 100644 --- a/sca-cpp/trunk/kernel/xml.hpp +++ b/sca-cpp/trunk/kernel/xml.hpp @@ -47,13 +47,7 @@ public: XMLParser() { xmlInitParser(); } - - ~XMLParser() { - xmlCleanupParser(); - } -}; - -XMLParser xmlParser; +} xmlParser; /** * Encapsulates a libxml2 xmlTextReader and its state. diff --git a/sca-cpp/trunk/modules/http/curl.hpp b/sca-cpp/trunk/modules/http/curl.hpp index 3478a590fd..d836eaa2f0 100644 --- a/sca-cpp/trunk/modules/http/curl.hpp +++ b/sca-cpp/trunk/modules/http/curl.hpp @@ -43,50 +43,37 @@ namespace tuscany { namespace http { /** - * CURL library context, one per process. + * CURL library runtime, one per process. */ -class CURLContext { +class CURLRuntime { public: - CURLContext() { + CURLRuntime() { curl_global_init(CURL_GLOBAL_ALL); } - ~CURLContext() { - curl_global_cleanup(); - } -}; - -CURLContext curlContext; +} curlRuntime; /** * Represents a CURL session handle. */ class CURLSession { public: - CURLSession() : ch(new (gc_new<CURLHandle>()) CURLHandle()) { + CURLSession() : h(curl_easy_init()), owner(true) { } - ~CURLSession() { + CURLSession(const CURLSession& c) : h(c.h), owner(false) { } - CURLSession(const CURLSession& c) : ch(c.ch) { + ~CURLSession() { + if (!owner) + return; + if (h == NULL) + return; + curl_easy_cleanup(h); } private: - class CURLHandle { - public: - CURLHandle() : h(curl_easy_init()) { - } - ~CURLHandle() { - curl_easy_cleanup(h); - h = NULL; - } - private: - CURL* h; - - friend CURL* handle(const CURLSession& c); - }; - - const gc_ptr<CURLHandle> ch; + CURL* h; + bool owner; friend CURL* handle(const CURLSession& c); }; @@ -95,7 +82,7 @@ private: * Returns the CURL handle used by a CURL session. */ CURL* handle(const CURLSession& c) { - return c.ch->h; + return c.h; } /** diff --git a/sca-cpp/trunk/modules/json/json.hpp b/sca-cpp/trunk/modules/json/json.hpp index 9124c5143c..e2f036541a 100644 --- a/sca-cpp/trunk/modules/json/json.hpp +++ b/sca-cpp/trunk/modules/json/json.hpp @@ -46,7 +46,7 @@ void reportError(unused JSContext *cx, const char *message, JSErrorReport *repor } /** - * Encapsulates a JavaScript runtime. Can be shared by multiple threads in + * Encapsulates a JavaScript runtime. Shared by multiple threads in * a process. */ class JSONRuntime { @@ -58,9 +58,6 @@ public: cleanup(); } - ~JSONRuntime() { - } - operator JSRuntime*() const { return rt; } @@ -75,17 +72,11 @@ private: } JSRuntime* rt; -}; - -/** - * Global JavaScript runtime instance. - */ -JSONRuntime jsRuntime; +} jsRuntime; JSClass jsGlobalClass = { "global", JSCLASS_GLOBAL_FLAGS, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, JSCLASS_NO_OPTIONAL_MEMBERS}; - /** * Represents a JavaScript context. Create one per thread. */ diff --git a/sca-cpp/trunk/modules/server/mod-cpp.hpp b/sca-cpp/trunk/modules/server/mod-cpp.hpp index 2cf2e540d6..17d44e1428 100644 --- a/sca-cpp/trunk/modules/server/mod-cpp.hpp +++ b/sca-cpp/trunk/modules/server/mod-cpp.hpp @@ -65,14 +65,11 @@ struct evalImplementation { * Read a C++ component implementation. */ const failable<lambda<value(const list<value>&)> > readImplementation(const string& path, const list<value>& px) { - const failable<lib> ilib(dynlib(path + dynlibExt)); - if (!hasContent(ilib)) - return mkfailure<lambda<value(const list<value>&)> >(reason(ilib)); - - const failable<lambda<value(const list<value>&)> > impl(dynlambda<value(const list<value>&)>("eval", content(ilib))); + const lib ilib(*(new (gc_new<lib>()) lib(path + dynlibExt))); + const failable<lambda<value(const list<value>&)> > impl(dynlambda<value(const list<value>&)>("eval", ilib)); if (!hasContent(impl)) return impl; - return lambda<value(const list<value>&)>(evalImplementation(content(ilib), content(impl), px)); + return lambda<value(const list<value>&)>(evalImplementation(ilib, content(impl), px)); } } |