summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2010-01-02 22:13:15 +0000
committerjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2010-01-02 22:13:15 +0000
commit996d5f6c4e21d3d8688674f20e6f4318e3ace607 (patch)
treebe6a3d80f2cab11cd39d0f55bd4bc55793a2e735
parentdda9255a5c9336cd3078f85f02e88120563ad304 (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
-rw-r--r--sca-cpp/trunk/kernel/debug.hpp5
-rw-r--r--sca-cpp/trunk/kernel/dynlib.hpp50
-rw-r--r--sca-cpp/trunk/kernel/fstream.hpp25
-rw-r--r--sca-cpp/trunk/kernel/gc.hpp90
-rw-r--r--sca-cpp/trunk/kernel/kernel-test.cpp7
-rw-r--r--sca-cpp/trunk/kernel/list.hpp2
-rw-r--r--sca-cpp/trunk/kernel/monad.hpp14
-rw-r--r--sca-cpp/trunk/kernel/sstream.hpp6
-rw-r--r--sca-cpp/trunk/kernel/stream.hpp54
-rw-r--r--sca-cpp/trunk/kernel/string.hpp3
-rw-r--r--sca-cpp/trunk/kernel/value.hpp2
-rw-r--r--sca-cpp/trunk/kernel/xml.hpp8
-rw-r--r--sca-cpp/trunk/modules/http/curl.hpp43
-rw-r--r--sca-cpp/trunk/modules/json/json.hpp13
-rw-r--r--sca-cpp/trunk/modules/server/mod-cpp.hpp9
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));
}
}