From 574ccee478b9da9457cdf0e476b8df6eb584b580 Mon Sep 17 00:00:00 2001 From: jsdelfino Date: Mon, 16 Jul 2012 06:48:11 +0000 Subject: Minor memory management, performance, and tracing improvements. git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1361917 13f79535-47bb-0310-9956-ffa450edef68 --- sca-cpp/trunk/components/cache/datacache.cpp | 8 +- sca-cpp/trunk/components/cache/memcache-test.cpp | 2 + sca-cpp/trunk/components/cache/memcache.cpp | 2 +- sca-cpp/trunk/components/cache/memcache.hpp | 34 +++--- sca-cpp/trunk/components/cache/memocache.cpp | 2 +- sca-cpp/trunk/components/cache/partitioner.cpp | 10 +- sca-cpp/trunk/components/chat/chat-sender.cpp | 4 +- sca-cpp/trunk/components/chat/chat-sender2.cpp | 4 +- .../trunk/components/chat/chat-sendreceiver.cpp | 4 +- sca-cpp/trunk/components/chat/xmpp.hpp | 16 ++- sca-cpp/trunk/components/constdb/constdb.cpp | 2 +- sca-cpp/trunk/components/constdb/tinycdb.hpp | 13 ++- sca-cpp/trunk/components/filedb/filedb.cpp | 4 +- sca-cpp/trunk/components/filedb/filedb.hpp | 12 +- sca-cpp/trunk/components/kvdb/client-test.cpp | 4 +- sca-cpp/trunk/components/kvdb/kvdb.cpp | 2 +- sca-cpp/trunk/components/kvdb/leveldb.hpp | 11 ++ sca-cpp/trunk/components/log/log.cpp | 4 +- sca-cpp/trunk/components/log/logger.cpp | 4 +- sca-cpp/trunk/components/log/scribe-cat.cpp | 4 +- sca-cpp/trunk/components/log/scribe.hpp | 12 +- sca-cpp/trunk/components/queue/qpid.hpp | 9 ++ sca-cpp/trunk/components/queue/queue-listener.cpp | 4 +- sca-cpp/trunk/components/queue/queue-sender.cpp | 2 +- sca-cpp/trunk/components/sqldb/pgsql.hpp | 13 ++- sca-cpp/trunk/components/sqldb/sqldb.cpp | 4 +- sca-cpp/trunk/components/webservice/axis2.hpp | 9 ++ sca-cpp/trunk/etc/httpd-ipcrm | 3 +- sca-cpp/trunk/hosting/server/client-test.cpp | 39 +++++++ sca-cpp/trunk/kernel/dynlib.hpp | 11 +- sca-cpp/trunk/kernel/fstream.hpp | 22 +++- sca-cpp/trunk/kernel/gc.hpp | 101 +++++++++++----- sca-cpp/trunk/kernel/hash-test.cpp | 1 + sca-cpp/trunk/kernel/kernel-test.cpp | 1 + sca-cpp/trunk/kernel/lambda-test.cpp | 1 + sca-cpp/trunk/kernel/mem-test.cpp | 1 + sca-cpp/trunk/kernel/monad.hpp | 128 ++++++++++++++++++--- sca-cpp/trunk/kernel/parallel-test.cpp | 43 ++++--- sca-cpp/trunk/kernel/parallel.hpp | 19 ++- sca-cpp/trunk/kernel/perf.hpp | 6 +- sca-cpp/trunk/kernel/string-test.cpp | 1 + sca-cpp/trunk/kernel/xml-test.cpp | 1 + sca-cpp/trunk/kernel/xml.hpp | 17 ++- sca-cpp/trunk/modules/atom/atom-test.cpp | 1 + sca-cpp/trunk/modules/js/eval.hpp | 15 ++- sca-cpp/trunk/modules/js/js-test.cpp | 1 + sca-cpp/trunk/modules/json/json-test.cpp | 38 ++++++ sca-cpp/trunk/modules/python/eval.hpp | 75 ++++++++---- sca-cpp/trunk/modules/python/python-test.cpp | 37 +++++- sca-cpp/trunk/modules/rss/rss-test.cpp | 1 + sca-cpp/trunk/modules/scdl/scdl-test.cpp | 1 + sca-cpp/trunk/modules/scheme/scheme-test.cpp | 1 + sca-cpp/trunk/samples/store-cpp/fruits-catalog.cpp | 2 +- sca-cpp/trunk/samples/store-cpp/shopping-cart.cpp | 10 +- 54 files changed, 601 insertions(+), 175 deletions(-) create mode 100644 sca-cpp/trunk/hosting/server/client-test.cpp (limited to 'sca-cpp') diff --git a/sca-cpp/trunk/components/cache/datacache.cpp b/sca-cpp/trunk/components/cache/datacache.cpp index c26e6eb868..c259ec33c6 100644 --- a/sca-cpp/trunk/components/cache/datacache.cpp +++ b/sca-cpp/trunk/components/cache/datacache.cpp @@ -44,7 +44,7 @@ namespace datacache { /** * Get an item from the cache. */ -const failable get(const value& key, const lambda&)> rcache1, const lambda&)> wcache1, const lambda&)> rcache2, unused const lambda&)> wcache2) { +const failable get(const value& key, const lambda&)>& rcache1, const lambda&)>& wcache1, const lambda&)>& rcache2, unused const lambda&)>& wcache2) { // Lookup level1 cache const value val1 = rcache1(mklist("get", key)); @@ -68,7 +68,7 @@ const failable get(const value& key, const lambda /** * Post an item to the cache. */ -const failable post(const value& key, const value& val, unused const lambda&)> rcache1, const lambda&)> wcache1, unused const lambda&)> rcache2, const lambda&)> wcache2) { +const failable post(const value& key, const value& val, unused const lambda&)>& rcache1, const lambda&)>& wcache1, unused const lambda&)>& rcache2, const lambda&)>& wcache2) { const value id = append(key, mklist(mkuuid())); // Update level1 cache @@ -83,7 +83,7 @@ const failable post(const value& key, const value& val, unused const lamb /** * Put an item into the cache. */ -const failable put(const value& key, const value& val, unused const lambda&)> rcache1, const lambda&)> wcache1, unused const lambda&)> rcache2, const lambda&)> wcache2) { +const failable put(const value& key, const value& val, unused const lambda&)>& rcache1, const lambda&)>& wcache1, unused const lambda&)>& rcache2, const lambda&)>& wcache2) { // Update level1 cache wcache1(mklist("put", key, val)); @@ -97,7 +97,7 @@ const failable put(const value& key, const value& val, unused const lambd /** * Delete an item from the cache. */ -const failable del(const value& key, unused const lambda&)> rcache1, const lambda&)> wcache1, unused const lambda&)> rcache2, const lambda&)> wcache2) { +const failable del(const value& key, unused const lambda&)>& rcache1, const lambda&)>& wcache1, unused const lambda&)>& rcache2, const lambda&)>& wcache2) { // Delete from level1 cache wcache1(mklist("delete", key)); diff --git a/sca-cpp/trunk/components/cache/memcache-test.cpp b/sca-cpp/trunk/components/cache/memcache-test.cpp index 49848dd2a7..85fc339f1a 100644 --- a/sca-cpp/trunk/components/cache/memcache-test.cpp +++ b/sca-cpp/trunk/components/cache/memcache-test.cpp @@ -52,6 +52,7 @@ struct getLoop { getLoop(const value& k, MemCached& ch) : k(k), ch(ch) { } const bool operator()() const { + gc_scoped_pool p; assert(get(k, ch) == value(string("CCC"))); return true; } @@ -71,6 +72,7 @@ bool testGetPerf() { } int main() { + tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::memcache::testMemCached(); diff --git a/sca-cpp/trunk/components/cache/memcache.cpp b/sca-cpp/trunk/components/cache/memcache.cpp index af710696b3..738a6ddd5a 100644 --- a/sca-cpp/trunk/components/cache/memcache.cpp +++ b/sca-cpp/trunk/components/cache/memcache.cpp @@ -103,7 +103,7 @@ private: const list servers(const list& params) { if (isNil(params)) return list(); - const value s = ((lambda)>)car(params))(list()); + const value s = ((lambda&)>)car(params))(list()); return cons(s, servers(cdr(params))); } diff --git a/sca-cpp/trunk/components/cache/memcache.hpp b/sca-cpp/trunk/components/cache/memcache.hpp index fe77c26671..f18405b2ec 100644 --- a/sca-cpp/trunk/components/cache/memcache.hpp +++ b/sca-cpp/trunk/components/cache/memcache.hpp @@ -49,38 +49,41 @@ namespace memcache { class MemCached { public: MemCached() : owner(false) { - debug("memcache::memcached"); } - MemCached(const string host, const int port) : owner(true) { + MemCached(const string host, const int port) : p(), owner(true) { debug(host, "memcache::memcached::host"); debug(port, "memcache::memcached::port"); - apr_pool_create(&pool, NULL); - apr_memcache_create(pool, 1, 0, &mc); + apr_memcache_create(pool(p), 1, 0, &mc); addServer(host, port); } - MemCached(const list& servers) : owner(true) { + MemCached(const list& servers) : p(), owner(true) { debug(servers, "memcache::memcached::servers"); - apr_pool_create(&pool, NULL); - apr_memcache_create(pool, (apr_uint16_t)length(servers), 0, &mc); + apr_memcache_create(pool(p), (apr_uint16_t)length(servers), 0, &mc); addServers(servers); } - MemCached(const MemCached& c) : owner(false), pool(c.pool), mc(c.mc) { + MemCached(const MemCached& c) : p(c.p), owner(false), mc(c.mc) { debug("memcache::memcached::copy"); } + const MemCached& operator=(const MemCached& c) { + debug("memcache::memcached::operator="); + if(this == &c) + return *this; + p = c.p; + owner = false; + mc = c.mc; + return *this; + } + ~MemCached() { - debug("memcache::~memcached"); - if (!owner) - return; - apr_pool_destroy(pool); } private: + gc_child_pool p; bool owner; - apr_pool_t* pool; apr_memcache_t* mc; friend const failable post(const value& key, const value& val, const MemCached& cache); @@ -93,7 +96,7 @@ private: */ const failable addServer(const string& host, const int port) { apr_memcache_server_t *server; - const apr_status_t sc = apr_memcache_server_create(pool, c_str(host), (apr_port_t)port, 1, 1, 1, 600, &server); + const apr_status_t sc = apr_memcache_server_create(pool(p), c_str(host), (apr_port_t)port, 1, 1, 1, 600, &server); if (sc != APR_SUCCESS) { ostringstream os; os << "Couldn't connect to memcached server: " << host << ":" << port; @@ -176,7 +179,8 @@ const failable get(const value& key, const MemCached& cache) { const string ks(scheme::writeValue(key)); char *data; apr_size_t size; - const apr_status_t rc = apr_memcache_getp(cache.mc, cache.pool, nospaces(c_str(ks)), &data, &size, NULL); + gc_local_pool lp; + const apr_status_t rc = apr_memcache_getp(cache.mc, pool(lp), nospaces(c_str(ks)), &data, &size, NULL); if (rc != APR_SUCCESS) { ostringstream os; os << "Couldn't get memcached entry: " << key; diff --git a/sca-cpp/trunk/components/cache/memocache.cpp b/sca-cpp/trunk/components/cache/memocache.cpp index 054638e275..e7e52cdc59 100644 --- a/sca-cpp/trunk/components/cache/memocache.cpp +++ b/sca-cpp/trunk/components/cache/memocache.cpp @@ -42,7 +42,7 @@ namespace memocache { /** * Memoize the value of a function application in a cache. */ -const failable memoize(const list& params, const lambda&)> relay, const lambda&)> cache) { +const failable memoize(const list& params, const lambda&)>& relay, const lambda&)>& cache) { debug(params, "memocache::memoize::params"); // Lookup memoized value from cache diff --git a/sca-cpp/trunk/components/cache/partitioner.cpp b/sca-cpp/trunk/components/cache/partitioner.cpp index ea12699977..e3f04ba112 100644 --- a/sca-cpp/trunk/components/cache/partitioner.cpp +++ b/sca-cpp/trunk/components/cache/partitioner.cpp @@ -40,7 +40,7 @@ namespace partitioner { /** * Return the target partition for a key. */ -const failable&)> > partition(const value& key, const lambda&)> selector, const list& partitions) { +const failable&)> > partition(const value& key, const lambda&)>& selector, const list& partitions) { // Call the selector component to convert the given key to a partition number const value p = selector(mklist("get", key, partitions)); @@ -55,7 +55,7 @@ const failable&)> > partition(const value& key, c /** * Get an item from a partition. */ -const failable get(const value& key, const lambda&)> selector, const list& partitions) { +const failable get(const value& key, const lambda&)>& selector, const list& partitions) { // Select partition const failable&)> > p = partition(key, selector, partitions); @@ -76,7 +76,7 @@ const failable get(const value& key, const lambda /** * Post an item to a partition. */ -const failable post(const value& key, const value& val, const lambda&)> selector, const list& partitions) { +const failable post(const value& key, const value& val, const lambda&)>& selector, const list& partitions) { const value id = append(key, mklist(mkuuid())); // Select partition @@ -93,7 +93,7 @@ const failable post(const value& key, const value& val, const lambda put(const value& key, const value& val, const lambda&)> selector, const list& partitions) { +const failable put(const value& key, const value& val, const lambda&)>& selector, const list& partitions) { // Select partition const failable&)> > p = partition(key, selector, partitions); @@ -109,7 +109,7 @@ const failable put(const value& key, const value& val, const lambda del(const value& key, const lambda&)> selector, const list& partitions) { +const failable del(const value& key, const lambda&)>& selector, const list& partitions) { // Select partition const failable&)> > p = partition(key, selector, partitions); diff --git a/sca-cpp/trunk/components/chat/chat-sender.cpp b/sca-cpp/trunk/components/chat/chat-sender.cpp index 0672292a06..a4cabef8de 100644 --- a/sca-cpp/trunk/components/chat/chat-sender.cpp +++ b/sca-cpp/trunk/components/chat/chat-sender.cpp @@ -118,8 +118,8 @@ private: const failable start(const list& params) { // Extract the the XMPP JID and password const list props = params; - const value jid = ((lambda)>)car(props))(list()); - const value pass = ((lambda)>)cadr(props))(list()); + const value jid = ((lambda&)>)car(props))(list()); + const value pass = ((lambda&)>)cadr(props))(list()); // Create an XMPP client session XMPPClient xc(jid, pass, false); diff --git a/sca-cpp/trunk/components/chat/chat-sender2.cpp b/sca-cpp/trunk/components/chat/chat-sender2.cpp index b230d130c1..0e00728022 100644 --- a/sca-cpp/trunk/components/chat/chat-sender2.cpp +++ b/sca-cpp/trunk/components/chat/chat-sender2.cpp @@ -41,7 +41,7 @@ namespace sender { /** * Post an item to an XMPP JID. */ -const failable post(const lambda&)> jid, const lambda&)> pass, const lambda&)> to, const lambda&)> msg, const list& params) { +const failable post(const lambda&)>& jid, const lambda&)>& pass, const lambda&)>& to, const lambda&)>& msg, const list& params) { const value vjid = jid(mklist("get", params)); const value vpass = pass(mklist("get", params)); @@ -69,7 +69,7 @@ const failable post(const lambda&)> jid, const la */ class chatSender { public: - chatSender(const lambda&)> jid, const lambda&)> pass, const lambda&)> to, const lambda&)> msg) : jid(jid), pass(pass), to(to), msg(msg) { + chatSender(const lambda&)>& jid, const lambda&)>& pass, const lambda&)>& to, const lambda&)>& msg) : jid(jid), pass(pass), to(to), msg(msg) { } const value operator()(const list& params) const { diff --git a/sca-cpp/trunk/components/chat/chat-sendreceiver.cpp b/sca-cpp/trunk/components/chat/chat-sendreceiver.cpp index aac8d69f6c..bfbd32b9ae 100644 --- a/sca-cpp/trunk/components/chat/chat-sendreceiver.cpp +++ b/sca-cpp/trunk/components/chat/chat-sendreceiver.cpp @@ -131,8 +131,8 @@ const failable start(const list& params) { const bool hasRelay = !isNil(cddr(params)); const value rel = hasRelay? car(params) : value(lambda&)>()); const list props = hasRelay? cdr(params) : params; - const value jid = ((lambda)>)car(props))(list()); - const value pass = ((lambda)>)cadr(props))(list()); + const value jid = ((lambda&)>)car(props))(list()); + const value pass = ((lambda&)>)cadr(props))(list()); // Create an XMPP client session XMPPClient xc(jid, pass, false); diff --git a/sca-cpp/trunk/components/chat/xmpp.hpp b/sca-cpp/trunk/components/chat/xmpp.hpp index e5f423c270..aa006029fa 100644 --- a/sca-cpp/trunk/components/chat/xmpp.hpp +++ b/sca-cpp/trunk/components/chat/xmpp.hpp @@ -76,6 +76,20 @@ public: debug("chat::xmppclient::copy"); } + const XMPPClient& operator=(const XMPPClient& xc) { + debug("chat::xmppclient::operator="); + if(this == &xc) + return *this; + owner = false; + ctx = xc.ctx; + conn = xc.conn; + listener = xc.listener; + connecting = xc.connecting; + connected = xc.connected; + disconnecting = xc.disconnecting; + return *this; + } + ~XMPPClient() { debug("chat::~xmppclient"); extern const failable disconnect(XMPPClient& xc); @@ -98,7 +112,7 @@ private: friend const failable disconnect(XMPPClient& xc); friend const failable listen(const lambda(const value&, const value&, XMPPClient&)>& listener, XMPPClient& xc); - const bool owner; + bool owner; xmpp_ctx_t* ctx; xmpp_conn_t* conn; lambda(const value&, const value&, XMPPClient&)> listener; diff --git a/sca-cpp/trunk/components/constdb/constdb.cpp b/sca-cpp/trunk/components/constdb/constdb.cpp index c3b9d63284..6d1cb15baf 100644 --- a/sca-cpp/trunk/components/constdb/constdb.cpp +++ b/sca-cpp/trunk/components/constdb/constdb.cpp @@ -102,7 +102,7 @@ private: */ const failable start(unused const list& params) { // Connect to the configured database and table - const value dbname = ((lambda)>)car(params))(list()); + const value dbname = ((lambda&)>)car(params))(list()); tinycdb::TinyCDB& cdb = *(new (gc_new()) tinycdb::TinyCDB(dbname)); // Return the component implementation lambda function diff --git a/sca-cpp/trunk/components/constdb/tinycdb.hpp b/sca-cpp/trunk/components/constdb/tinycdb.hpp index c7d4cf520b..68be0a09dc 100644 --- a/sca-cpp/trunk/components/constdb/tinycdb.hpp +++ b/sca-cpp/trunk/components/constdb/tinycdb.hpp @@ -107,7 +107,6 @@ const string absdbname(const string& name) { class TinyCDB { public: TinyCDB() : owner(false), fd(-1) { - debug("tinycdb::tinycdb"); st.st_ino = 0; } @@ -121,8 +120,18 @@ public: st.st_ino = c.st.st_ino; } + const TinyCDB& operator=(const TinyCDB& c) { + debug("tinycdb::tinycdb::operator="); + if(this == &c) + return *this; + owner = false; + name = c.name; + fd = c.fd; + st.st_ino = c.st.st_ino; + return *this; + } + ~TinyCDB() { - debug("tinycdb::~tinycdb"); if (!owner) return; if (fd == -1) diff --git a/sca-cpp/trunk/components/filedb/filedb.cpp b/sca-cpp/trunk/components/filedb/filedb.cpp index 21b509a3b7..8644a78574 100644 --- a/sca-cpp/trunk/components/filedb/filedb.cpp +++ b/sca-cpp/trunk/components/filedb/filedb.cpp @@ -102,8 +102,8 @@ private: */ const failable start(const list& params) { // Connect to the configured database and table - const value dbname = ((lambda)>)car(params))(list()); - const value format = ((lambda)>)cadr(params))(list()); + const value dbname = ((lambda&)>)car(params))(list()); + const value format = ((lambda&)>)cadr(params))(list()); filedb::FileDB& db = *(new (gc_new()) filedb::FileDB(absdbname(dbname), format)); diff --git a/sca-cpp/trunk/components/filedb/filedb.hpp b/sca-cpp/trunk/components/filedb/filedb.hpp index a7151eade1..9c3017d0d8 100644 --- a/sca-cpp/trunk/components/filedb/filedb.hpp +++ b/sca-cpp/trunk/components/filedb/filedb.hpp @@ -57,7 +57,6 @@ const string absdbname(const string& name) { class FileDB { public: FileDB() : owner(false) { - debug("filedb::filedb"); } FileDB(const string& name, const string& format) : owner(true), name(absdbname(name)), format(format) { @@ -69,8 +68,17 @@ public: debug("filedb::filedb::copy"); } + const FileDB& operator=(const FileDB& c) { + debug("filedb::filedb::operator="); + if(this == &c) + return *this; + owner = false; + name = c.name; + format = c.format; + return *this; + } + ~FileDB() { - debug("filedb::~filedb"); } private: diff --git a/sca-cpp/trunk/components/kvdb/client-test.cpp b/sca-cpp/trunk/components/kvdb/client-test.cpp index fc31a99e69..5f0ef21d00 100644 --- a/sca-cpp/trunk/components/kvdb/client-test.cpp +++ b/sca-cpp/trunk/components/kvdb/client-test.cpp @@ -93,8 +93,8 @@ bool testNoSqlDb() { struct getLoop { const string path; const value entry; - http::CURLSession cs; - getLoop(const string& path, const value& entry, http::CURLSession cs) : path(path), entry(entry), cs(cs) { + http::CURLSession& cs; + getLoop(const string& path, const value& entry, http::CURLSession& cs) : path(path), entry(entry), cs(cs) { } const bool operator()() const { const failable val = http::get(uri + path, cs); diff --git a/sca-cpp/trunk/components/kvdb/kvdb.cpp b/sca-cpp/trunk/components/kvdb/kvdb.cpp index 24a2fb5a16..0df8f13882 100644 --- a/sca-cpp/trunk/components/kvdb/kvdb.cpp +++ b/sca-cpp/trunk/components/kvdb/kvdb.cpp @@ -102,7 +102,7 @@ private: */ const failable start(unused const list& params) { // Connect to the configured database and table - const value dbname = ((lambda)>)car(params))(list()); + const value dbname = ((lambda&)>)car(params))(list()); leveldb::LevelDB& cdb = *(new (gc_new()) leveldb::LevelDB(dbname)); // Return the component implementation lambda function diff --git a/sca-cpp/trunk/components/kvdb/leveldb.hpp b/sca-cpp/trunk/components/kvdb/leveldb.hpp index 8105f86ec4..05a89a76f7 100644 --- a/sca-cpp/trunk/components/kvdb/leveldb.hpp +++ b/sca-cpp/trunk/components/kvdb/leveldb.hpp @@ -121,6 +121,17 @@ public: st.st_ino = c.st.st_ino; } + const LevelDB& operator=(const LevelDB& c) { + debug("leveldb::leveldb::operator="); + if(this == &c) + return *this; + owner = false; + name = c.name; + fd = c.fd; + st.st_ino = c.st.st_ino; + return *this; + } + ~LevelDB() { debug("leveldb::~leveldb"); if (!owner) diff --git a/sca-cpp/trunk/components/log/log.cpp b/sca-cpp/trunk/components/log/log.cpp index 2e7742cfd7..f7f7086192 100644 --- a/sca-cpp/trunk/components/log/log.cpp +++ b/sca-cpp/trunk/components/log/log.cpp @@ -75,8 +75,8 @@ const failable start(const list& params) { scribe::Scribe& sc = *(new (gc_new()) scribe::Scribe("localhost", 1464)); // Extract the configured category - const value host = ((lambda)>)car(params))(list()); - const value category = ((lambda)>)cadr(params))(list()); + const value host = ((lambda&)>)car(params))(list()); + const value category = ((lambda&)>)cadr(params))(list()); debug(host, "log::start::host"); debug(category, "log::start::category"); diff --git a/sca-cpp/trunk/components/log/logger.cpp b/sca-cpp/trunk/components/log/logger.cpp index d7a54507fb..d7969036ab 100644 --- a/sca-cpp/trunk/components/log/logger.cpp +++ b/sca-cpp/trunk/components/log/logger.cpp @@ -73,8 +73,8 @@ const failable start(const list& params) { // Extract the configured relay service and category const value rel = car(params); - const value host = ((lambda)>)cadr(params))(list()); - const value category = ((lambda)>)caddr(params))(list()); + const value host = ((lambda&)>)cadr(params))(list()); + const value category = ((lambda&)>)caddr(params))(list()); debug(host, "logger::start::host"); debug(category, "logger::start::category"); diff --git a/sca-cpp/trunk/components/log/scribe-cat.cpp b/sca-cpp/trunk/components/log/scribe-cat.cpp index fbfdaca533..254e2167ae 100644 --- a/sca-cpp/trunk/components/log/scribe-cat.cpp +++ b/sca-cpp/trunk/components/log/scribe-cat.cpp @@ -38,12 +38,12 @@ namespace scribecat { int cat(const string& host, const string& category, const string& type) { // Connect to Scribe - scribe::Scribe& sc = *(new (gc_new()) scribe::Scribe("localhost", 1464)); + scribe::Scribe& sc = *(new (gc_new()) scribe::Scribe(host, 1464)); // Read lines from stdin and log them char buf[8193]; for (;;) { - gc_scoped_pool(); + gc_scoped_pool p; // Write line prefix ostringstream os; diff --git a/sca-cpp/trunk/components/log/scribe.hpp b/sca-cpp/trunk/components/log/scribe.hpp index 5ae8a50776..0f0570be64 100644 --- a/sca-cpp/trunk/components/log/scribe.hpp +++ b/sca-cpp/trunk/components/log/scribe.hpp @@ -66,7 +66,6 @@ namespace scribe { class Scribe { public: Scribe() : owner(false) { - debug("scribe::scribe"); } Scribe(const string host, const int port) : owner(true) { @@ -80,9 +79,18 @@ public: client = c.client; transport = c.transport; } + + const Scribe& operator=(const Scribe& c) { + debug("scribe::scribe::operator="); + if(this == &c) + return *this; + owner = false; + client = c.client; + transport = c.transport; + return *this; + } ~Scribe() { - debug("scribe::~scribe"); if (!owner) return; try { diff --git a/sca-cpp/trunk/components/queue/qpid.hpp b/sca-cpp/trunk/components/queue/qpid.hpp index 63f27d2519..ef53c529e8 100644 --- a/sca-cpp/trunk/components/queue/qpid.hpp +++ b/sca-cpp/trunk/components/queue/qpid.hpp @@ -65,6 +65,15 @@ public: debug("queue::qpidonnection::copy"); } + const QpidConnection& operator=(const QpidConnection& qc) { + debug("queue::qpidonnection::operator="); + if(this == &c) + return *this; + owner = false; + c = qc.c; + return *this; + } + ~QpidConnection() { debug("queue::~qpidonnection"); if (!owner) diff --git a/sca-cpp/trunk/components/queue/queue-listener.cpp b/sca-cpp/trunk/components/queue/queue-listener.cpp index 3c30e7feca..483d0de65a 100644 --- a/sca-cpp/trunk/components/queue/queue-listener.cpp +++ b/sca-cpp/trunk/components/queue/queue-listener.cpp @@ -123,9 +123,9 @@ private: const failable start(const list& params) { // Extract the relay reference and the AMQP key and queue name const value rel = car(params); - const value pk = ((lambda)>)cadr(params))(list()); + const value pk = ((lambda&)>)cadr(params))(list()); const value key = isList(pk)? (list)pk : mklist(pk); - const value qname = ((lambda)>)caddr(params))(list()); + const value qname = ((lambda&)>)caddr(params))(list()); // Create an AMQP session QpidConnection qc(false); diff --git a/sca-cpp/trunk/components/queue/queue-sender.cpp b/sca-cpp/trunk/components/queue/queue-sender.cpp index ff2ede1057..202a0e4435 100644 --- a/sca-cpp/trunk/components/queue/queue-sender.cpp +++ b/sca-cpp/trunk/components/queue/queue-sender.cpp @@ -48,7 +48,7 @@ const failable post(const list& params) { QpidSession qs(qc); // Post the item - const value pk = ((lambda)>)caddr(params))(list()); + const value pk = ((lambda&)>)caddr(params))(list()); const value key = isList(pk)? append(pk, (list)car(params)) : cons(pk, (list)car(params)); debug(key, "queue::post::key"); debug(cadr(params), "queue::post::value"); diff --git a/sca-cpp/trunk/components/sqldb/pgsql.hpp b/sca-cpp/trunk/components/sqldb/pgsql.hpp index d38af54c97..581cd943e6 100644 --- a/sca-cpp/trunk/components/sqldb/pgsql.hpp +++ b/sca-cpp/trunk/components/sqldb/pgsql.hpp @@ -91,6 +91,17 @@ public: debug("pgsql::pgsql::copy"); } + const PGSql& operator=(const PGSql& c) { + debug("pgsql::pgsql::operator="); + if(this == &c) + return *this; + owner = false; + conn = c.conn; + conninfo = c.conninfo; + table = c.table; + return *this; + } + ~PGSql() { debug("pgsql::~pgsql"); if (!owner) @@ -104,7 +115,7 @@ private: bool owner; PGconn *conn; string conninfo; - const string table; + string table; string kname; string vname; diff --git a/sca-cpp/trunk/components/sqldb/sqldb.cpp b/sca-cpp/trunk/components/sqldb/sqldb.cpp index bbf118385e..9925897693 100644 --- a/sca-cpp/trunk/components/sqldb/sqldb.cpp +++ b/sca-cpp/trunk/components/sqldb/sqldb.cpp @@ -120,8 +120,8 @@ private: */ const failable start(unused const list& params) { // Connect to the configured database and table - const value conninfo = ((lambda)>)car(params))(list()); - const value table = ((lambda)>)cadr(params))(list()); + const value conninfo = ((lambda&)>)car(params))(list()); + const value table = ((lambda&)>)cadr(params))(list()); const perthread_ptr pg(lambda()>(newPGSql(conninfo, table))); // Return the component implementation lambda function diff --git a/sca-cpp/trunk/components/webservice/axis2.hpp b/sca-cpp/trunk/components/webservice/axis2.hpp index 7630b54295..9bad109ff0 100644 --- a/sca-cpp/trunk/components/webservice/axis2.hpp +++ b/sca-cpp/trunk/components/webservice/axis2.hpp @@ -65,6 +65,15 @@ public: debug("webservice::axis2context::copy"); } + const Axis2Context& operator=(const Axis2Context& ax) { + debug("webservice::axis2context::operator="); + if(this == &ax) + return *this; + env = ax.env; + owner = false; + return *this; + } + Axis2Context(const axutil_env_t* env) : env(const_cast(env)), owner(false) { debug("webservice::axis2context::env"); } diff --git a/sca-cpp/trunk/etc/httpd-ipcrm b/sca-cpp/trunk/etc/httpd-ipcrm index b457e7385f..860b724296 100755 --- a/sca-cpp/trunk/etc/httpd-ipcrm +++ b/sca-cpp/trunk/etc/httpd-ipcrm @@ -19,5 +19,6 @@ # Remove ipcs created by httpd -ipcs -s | grep 0x | awk '{ print $2 }' | xargs -i -t ipcrm -s {} +id=`id -un` +ipcs -s | grep "$id" | grep "0x" | awk '{ print $2 }' | xargs -i -t ipcrm -s {} diff --git a/sca-cpp/trunk/hosting/server/client-test.cpp b/sca-cpp/trunk/hosting/server/client-test.cpp new file mode 100644 index 0000000000..c0a01b5237 --- /dev/null +++ b/sca-cpp/trunk/hosting/server/client-test.cpp @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* $Rev$ $Date$ */ + +/** + * Test HTTP client functions. + */ + +#include "stream.hpp" +#include "string.hpp" +#include "client-test.hpp" + +int main(const int argc, const char** argv) { + tuscany::cout << "Testing..." << tuscany::endl; + tuscany::server::testURI = argc > 1? argv[1] : "https://jane:jane@www.example.com:8453"; + + tuscany::server::testServer(); + + tuscany::cout << "OK" << tuscany::endl; + + return 0; +} 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 friend const failable > dynlambda(const string& name, const lib& l); - const string name; + string name; failable 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 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 const bool debugLog(const V& v, const string& msg) { * Log a debug message and two values. */ template 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,21 +149,13 @@ 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. */ @@ -171,16 +163,6 @@ apr_pool_t* pool(const gc_pool& pool) { return pool.apr_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. */ @@ -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 +#include #include "function.hpp" #include "string.hpp" #include "stream.hpp" @@ -277,39 +279,135 @@ template const lambda(cons return mksuccess; } +/** + * 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 const failable 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(false, f, c); } template const failable 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(false, f, c); + return mkfailure(f, c, log); } template const failable mkfailure(const char* f, const int c = -1, const bool log = true) { - return mkfailure(string(f), c, log); + return mkfailure(string(f), c, log); } template const failable 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 tlsic() { + gc_ptr i = new (gc_new()) int(); + *i = 0; + return i; +} +const perthread_ptr 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 tlsic() { - gc_ptr i = new (gc_new()) int(); - *i = 0; - return i; -} -const perthread_ptr 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 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 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 > createkey() { + return new (gc_new >()) gc_ptr(); } - bool deletekey(unused int k) { + bool deletekey(unused gc_ptr > k) { return true; } bool set(const gc_ptr& v) { - val = v; + *key = v; return true; } gc_ptr 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 val; + gc_ptr >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& 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; diff --git a/sca-cpp/trunk/modules/atom/atom-test.cpp b/sca-cpp/trunk/modules/atom/atom-test.cpp index e00c75a62f..479ed64f29 100644 --- a/sca-cpp/trunk/modules/atom/atom-test.cpp +++ b/sca-cpp/trunk/modules/atom/atom-test.cpp @@ -273,6 +273,7 @@ bool testFeed() { } int main() { + tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::atom::testEntry(); diff --git a/sca-cpp/trunk/modules/js/eval.hpp b/sca-cpp/trunk/modules/js/eval.hpp index 21fa274d2c..f8f4cbe598 100644 --- a/sca-cpp/trunk/modules/js/eval.hpp +++ b/sca-cpp/trunk/modules/js/eval.hpp @@ -65,7 +65,7 @@ public: JSRuntime() { // Create JS runtime debug("js::jsruntime"); - rt = JS_NewRuntime(32L * 1024L * 1024L); + rt = JS_NewRuntime(1L * 512L * 1024L); if(rt == NULL) cleanup(); } @@ -114,14 +114,19 @@ public: debug("js::jscontext"); if (jsContext != NULL) { cx = jsContext; + JS_BeginRequest(cx); return; } + debug("js::jsnewcontext"); cx = JS_NewContext(jsRuntime, 8192); if(cx == NULL) return; + JS_BeginRequest(cx); + JS_SetOptions(cx, JSOPTION_VAROBJFIX | JSOPTION_JIT | JSOPTION_METHODJIT); JS_SetVersion(cx, JSVERSION_LATEST); JS_SetErrorReporter(cx, reportError); + //JS_SetGCZeal(cx, 2); // Create global JS object global = JS_NewCompartmentAndGlobalObject(cx, &jsGlobalClass, NULL); @@ -140,8 +145,6 @@ public: ~JSContext() { debug("js::~jscontext"); - if (cx != NULL) - JS_MaybeGC(cx); cleanup(); } @@ -156,8 +159,12 @@ public: private: bool cleanup() { if(cx != NULL) { - if (cx != jsContext) + JS_MaybeGC(cx); + JS_EndRequest(cx); + if (cx != jsContext) { + debug("js::jsdestroycontext"); JS_DestroyContext(cx); + } cx = NULL; } return true; diff --git a/sca-cpp/trunk/modules/js/js-test.cpp b/sca-cpp/trunk/modules/js/js-test.cpp index 9cbf000ac3..a7e5597610 100644 --- a/sca-cpp/trunk/modules/js/js-test.cpp +++ b/sca-cpp/trunk/modules/js/js-test.cpp @@ -42,6 +42,7 @@ bool testJSEval() { } int main() { + tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::js::testJSEval(); diff --git a/sca-cpp/trunk/modules/json/json-test.cpp b/sca-cpp/trunk/modules/json/json-test.cpp index 61aac4ee02..945b6c072c 100644 --- a/sca-cpp/trunk/modules/json/json-test.cpp +++ b/sca-cpp/trunk/modules/json/json-test.cpp @@ -27,6 +27,7 @@ #include "stream.hpp" #include "string.hpp" #include "json.hpp" +#include "perf.hpp" namespace tuscany { namespace json { @@ -74,6 +75,7 @@ const string jsarray("{\n" "}"); bool testJSON() { + gc_scoped_pool pool; const js::JSContext cx; { @@ -217,6 +219,7 @@ const string jsechores("{\n" "}"); bool testJSONRPC() { + gc_scoped_pool pool; js::JSContext cx; { const string lm("{\"id\": 1, \"method\": \"test\", \"params\": []}"); @@ -283,14 +286,49 @@ bool testJSONRPC() { return true; } +struct testReadWrite { + testReadWrite() { + } + const bool operator()() const { + gc_scoped_pool pool; + js::JSContext cx; + + const list ad = mklist(mklist(attribute, "city", string("san francisco")), mklist(attribute, "state", string("ca"))); + const list ac = mklist(mklist(element, "id", string("1234")), mklist(attribute, "balance", 1000)); + const list cr = mklist(mklist (attribute, "name", string("jdoe")), cons(element, cons("address", ad)), cons(element, cons("account", ac))); + const list c = mklist(cons(element, cons("customer", cr))); + + ostringstream os; + writeJSON(jsonWriter, &os, c, cx); + assert(str(os) == jscustomer); + + istringstream is(jscustomer); + const list il = streamList(is); + const list r = content(readJSON(il, cx)); + assert(r == c); + return true; + } +}; + +bool testJSONPerf() { + gc_scoped_pool pool; + + const lambda rwl = lambda(testReadWrite()); + cout << "JSON read + write test " << time(rwl, 5, 200) << " ms" << endl; + + return true; +} + } } int main() { + tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::json::testJSON(); tuscany::json::testJSONRPC(); + tuscany::json::testJSONPerf(); tuscany::cout << "OK" << tuscany::endl; diff --git a/sca-cpp/trunk/modules/python/eval.hpp b/sca-cpp/trunk/modules/python/eval.hpp index da5d226789..5c0be7d261 100644 --- a/sca-cpp/trunk/modules/python/eval.hpp +++ b/sca-cpp/trunk/modules/python/eval.hpp @@ -26,6 +26,8 @@ * Python script evaluation logic. */ #if PYTHON_VERSION == 27 +#undef _POSIX_C_SOURCE +#undef _XOPEN_SOURCE #include #include #include @@ -71,15 +73,12 @@ public: PythonRuntime() { debug("python::pythonruntime"); + // Save current process id #ifdef WANT_THREADS pthread_mutex_init(&mutex, NULL); - -#ifdef IS_DARWIN - // Save current process id pthread_mutex_init(&pidmutex, NULL); - pid = processId(); -#endif #endif + pid = processId(); // Initialize the Python interpreter #ifdef IS_DARWIN @@ -134,11 +133,9 @@ public: private: #ifdef WANT_THREADS pthread_mutex_t mutex; -#ifdef IS_DARWIN pthread_mutex_t pidmutex; - unsigned long pid; -#endif #endif + unsigned long pid; friend class PythonThreadIn; friend class PythonThreadOut; @@ -177,8 +174,8 @@ const string lastError(PythonRuntime* py) { PyObject* trace = NULL; PyErr_Fetch(&type, &val, &trace); if (type != NULL && val != NULL) { - PyObject* stype = PyObject_Str(type); - PyObject* sval = PyObject_Str(val); + PyObject* stype = PyObject_Repr(type); + PyObject* sval = PyObject_Repr(val); string msg = string() + PyString_AsString(stype) + " : " + PyString_AsString(sval) + lastErrorTrace(trace); pyDecRef(stype, py); pyDecRef(sval, py); @@ -220,11 +217,10 @@ private: class PythonThreadIn { public: PythonThreadIn(PythonRuntime* py) : py(py) { -#ifdef WANT_THREADS -#ifdef IS_DARWIN // Reinitialize Python thread support after a fork const unsigned long pid = processId(); +#ifdef WANT_THREADS if (pid != py->pid) { pthread_mutex_lock(&py->pidmutex); if (pid != py->pid) { @@ -236,16 +232,26 @@ public: } pthread_mutex_unlock(&py->pidmutex); } -#endif // Acquire the Python GIL //debug("python::gil::ensure"); gstate = PyGILState_Ensure(); //debug("python::gil::ensured"); +#else + if (pid != py->pid) { + debug("python::afterfork"); + PyOS_AfterFork(); + debug("python::afterforked"); + py->pid = pid; + } #endif } ~PythonThreadIn() { + // Run Python cyclic reference garbage collector + //const size_t c = PyGC_Collect(); + //debug(c, "python::gc::collect::c"); + #ifdef WANT_THREADS // Release the Python GIL //debug("python::gil::release"); @@ -520,7 +526,6 @@ PyObject* valueToPyObject(const value& v, PythonRuntime* py) { /** * Convert a python tuple to a list of values. */ - const list pyTupleToValuesHelper(PyObject* o, const size_t i, const size_t size, PythonRuntime* py) { if (i == size) return list(); @@ -546,6 +551,15 @@ struct pyCallable { pyCallable(const pyCallable& c) : func(c.func), py(c.py), owner(false) { } + const pyCallable& operator=(const pyCallable& c) { + if(this == &c) + return *this; + func = c.func; + py = c.py; + owner = false; + return *this; + } + ~pyCallable() { if (!owner) return; @@ -554,8 +568,7 @@ struct pyCallable { const value operator()(const list& args) const { PythonThreadIn pyin(py); - { - // Temp + if (debug_islogging()) { PyObject* rfunc = PyObject_Repr(func); char* s = NULL; Py_ssize_t l = 0; @@ -564,8 +577,7 @@ struct pyCallable { pyDecRef(rfunc, py); } PyObject* pyargs = valuesToPyTuple(args, py); - { - // Temp + if (debug_islogging()) { PyObject* rargs = PyObject_Repr(pyargs); char* s = NULL; Py_ssize_t l = 0; @@ -573,9 +585,11 @@ struct pyCallable { debug(string(s, l), "python::operator()::args"); pyDecRef(rargs, py); } + PyObject* result = PyObject_CallObject(func, pyargs); - const value v = pyObjectToValue(result, py); pyDecRef(pyargs, py); + + const value v = pyObjectToValue(result, py); pyDecRef(result, py); return v; } @@ -605,6 +619,8 @@ const value pyObjectToValue(PyObject *o, PythonRuntime* py) { return value((double)PyFloat_AsDouble(o)); if (PyTuple_Check(o)) return pyTupleToValues(o, py); + if (PyObject_TypeCheck(o, &pyLambda_type)) + return *(((pyLambda*)o)->func); if (PyCallable_Check(o)) return lambda&)>(pyCallable(o, py)); return value(); @@ -646,10 +662,14 @@ const failable evalScript(const value& expr, PyObject* script, PythonRunt // Call the function PyObject* result = PyObject_CallObject(func, args); + if (result == NULL) { + const string msg = lastError(&py); + pyDecRef(func, &py); + pyDecRef(args, &py); + return mkfailure(string("Function call failed: ") + car(expr) + " : " + msg); + } pyDecRef(func, &py); pyDecRef(args, &py); - if (result == NULL) - return mkfailure(string("Function call failed: ") + car(expr) + " : " + lastError(&py)); // Convert python result to a value const value v = pyObjectToValue(result, &py); @@ -680,10 +700,19 @@ const failable readScript(const string& name, const string& path, ist return mkfailure(string("Couldn't compile script: ") + path + " : " + lastError(&py)); PyObject* mod = PyImport_ExecCodeModuleEx(const_cast(c_str(name)), code, const_cast(c_str(path))); if (mod == NULL) { + const string msg = lastError(&py); pyDecRef(code, &py); - return mkfailure(string("Couldn't import module: ") + path + " : " + lastError(&py)); + return mkfailure(string("Couldn't import module: ") + path + " : " + msg); } - return mod; + pyDecRef(code, &py); + pyDecRef(mod, &py); + + // Lookup the loaded module + PyObject *lmod = PyDict_GetItemString(mods, const_cast(c_str(name))); + if (lmod != NULL) + return lmod; + + return mkfailure(string("Couldn't lookup module: ") + path); } /** diff --git a/sca-cpp/trunk/modules/python/python-test.cpp b/sca-cpp/trunk/modules/python/python-test.cpp index bc275f27c7..29a66cc2e7 100644 --- a/sca-cpp/trunk/modules/python/python-test.cpp +++ b/sca-cpp/trunk/modules/python/python-test.cpp @@ -42,7 +42,7 @@ bool testEvalExpr() { PythonRuntime py; istringstream is(testPythonAdd); - failable script = readScript("script", "script.py", is, py); + failable script = readScript("script1", "script1.py", is, py); assert(hasContent(script)); const value exp = mklist("add", 2, 3); @@ -54,6 +54,29 @@ bool testEvalExpr() { return true; } +const string testPythonMap = + "def addmap(x, y):\n" + " return tuple(map(lambda i: i + y, x))\n"; + +bool testEvalList() { + gc_scoped_pool pool; + PythonRuntime py; + + istringstream is(testPythonMap); + failable script = readScript("script2", "script2.py", is, py); + assert(hasContent(script)); + + const value exp = mklist("addmap", mklist(1, 2, 3), 1); + const failable r = evalScript(exp, content(script), py); + assert(hasContent(r)); + assert(car(content(r)) == value(2)); + assert(cadr(content(r)) == value(3)); + assert(caddr(content(r)) == value(4)); + + releaseScript(content(script), py); + return true; +} + const value mult(const list& args) { const double x = car(args); const double y = cadr(args); @@ -104,7 +127,7 @@ struct testEvalReadAdd { } const bool operator()() const { istringstream is(testPythonAdd); - failable script = readScript("script", "script.py", is, py); + failable script = readScript("script3", "script3.py", is, py); assert(hasContent(script)); const value exp = mklist("add", 2, 3); @@ -139,7 +162,7 @@ bool testEvalPerf() { cout << "Python read + eval test " << time(erl, 5, 10000) << " ms" << endl; istringstream is(testPythonAdd); - failable script = readScript("script", "script.py", is, py); + failable script = readScript("script4", "script4.py", is, py); assert(hasContent(script)); const lambda el = lambda(testEvalAdd(content(script), py)); @@ -158,7 +181,7 @@ struct testReadEvalAddLoop { const bool operator()() const { for (int i = 0; i < 100; i++) { istringstream is(testPythonAdd); - failable script = readScript("script", "script.py", is, py); + failable script = readScript("script6", "script6.py", is, py); assert(hasContent(script)); const value exp = mklist("add", 2, 3); @@ -247,7 +270,7 @@ bool testThreads() { cout << "Python eval + read thread test " << time(elr, 1, 1) / 10000.0 << " ms" << endl; istringstream is(testPythonAdd); - failable script = readScript("script", "script.py", is, py); + failable script = readScript("script7", "script7.py", is, py); assert(hasContent(script)); const lambda el = lambda(testEvalThreads(w, max, content(script), py)); @@ -263,9 +286,13 @@ bool testThreads() { } int main() { + tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::python::testEvalExpr(); + tuscany::python::testEvalList(); + tuscany::python::testEvalLambda(); + tuscany::python::testEvalLambda(); tuscany::python::testEvalLambda(); tuscany::python::testEvalPerf(); #ifdef WANT_THREADS diff --git a/sca-cpp/trunk/modules/rss/rss-test.cpp b/sca-cpp/trunk/modules/rss/rss-test.cpp index b30792bfe1..be1dcac574 100644 --- a/sca-cpp/trunk/modules/rss/rss-test.cpp +++ b/sca-cpp/trunk/modules/rss/rss-test.cpp @@ -240,6 +240,7 @@ bool testFeed() { } int main() { + tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::rss::testEntry(); diff --git a/sca-cpp/trunk/modules/scdl/scdl-test.cpp b/sca-cpp/trunk/modules/scdl/scdl-test.cpp index 94baf930a9..4c10f515df 100644 --- a/sca-cpp/trunk/modules/scdl/scdl-test.cpp +++ b/sca-cpp/trunk/modules/scdl/scdl-test.cpp @@ -110,6 +110,7 @@ bool testProperties() { } int main() { + tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::scdl::testComposite(); diff --git a/sca-cpp/trunk/modules/scheme/scheme-test.cpp b/sca-cpp/trunk/modules/scheme/scheme-test.cpp index dd97bc358d..5b69b8e588 100644 --- a/sca-cpp/trunk/modules/scheme/scheme-test.cpp +++ b/sca-cpp/trunk/modules/scheme/scheme-test.cpp @@ -225,6 +225,7 @@ bool testEvalGC() { } int main() { + tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::scheme::testEnv(); diff --git a/sca-cpp/trunk/samples/store-cpp/fruits-catalog.cpp b/sca-cpp/trunk/samples/store-cpp/fruits-catalog.cpp index ce5ebfec6f..9907650316 100644 --- a/sca-cpp/trunk/samples/store-cpp/fruits-catalog.cpp +++ b/sca-cpp/trunk/samples/store-cpp/fruits-catalog.cpp @@ -50,7 +50,7 @@ const list mkfruit(const string& name, const string& code, const string& mklist("name", name) + mklist("currencyCode", code) + mklist("currencySymbol", symbol) + mklist("price", price); } -const failable items(const lambda&)> converter, const lambda&)> currencyCode) { +const failable items(const lambda&)>& converter, const lambda&)>& currencyCode) { const string currency(currencyCode(list())); const string symbol(converter(mklist("symbol", currency))); const lambda conv(convert(converter, currency)); diff --git a/sca-cpp/trunk/samples/store-cpp/shopping-cart.cpp b/sca-cpp/trunk/samples/store-cpp/shopping-cart.cpp index 4b5dc8db6b..2771d7cd9c 100644 --- a/sca-cpp/trunk/samples/store-cpp/shopping-cart.cpp +++ b/sca-cpp/trunk/samples/store-cpp/shopping-cart.cpp @@ -38,7 +38,7 @@ const string cartId("1234"); * Get the shopping cart from the cache. Return an empty * cart if not found. */ -const list getcart(const value& id, const lambda&)> cache) { +const list getcart(const value& id, const lambda&)>& cache) { const value cart = cache(mklist("get", mklist(id))); cerr << "cart value: " << cart << "\n"; const failable fcart = cart; @@ -53,7 +53,7 @@ const list getcart(const value& id, const lambda& /** * Post a new item to the cart. Create a new cart if necessary. */ -const failable post(unused const list& collection, const value& item, const lambda&)> cache) { +const failable post(unused const list& collection, const value& item, const lambda&)>& cache) { const value id(mkuuid()); const list newItem(mklist("entry", cadr(car(item)), mklist("id", id), cadddr(car(item)))); const list cart(cons(newItem, getcart(cartId, cache))); @@ -75,7 +75,7 @@ const value find(const value& id, const list& cart) { /** * Return items from the cart. */ -const failable get(const list& id, const lambda&)> cache) { +const failable get(const list& id, const lambda&)>& cache) { if (isNil(id)) return value(mklist(append(mklist("feed", mklist("title", string("Your Cart")), mklist("id", cartId)), getcart(cartId, cache)))); return find(car(id), getcart(cartId, cache)); @@ -84,7 +84,7 @@ const failable get(const list& id, const lambda del(const list& id, unused const lambda&)> cache) { +const failable del(const list& id, unused const lambda&)>& cache) { if (isNil(id)) return cache(mklist("delete", mklist(cartId))); return value(true); @@ -109,7 +109,7 @@ const double sum(const list& items) { /** * Return the total price of the items in the cart. */ -const failable total(const lambda&)> cache) { +const failable total(const lambda&)>& cache) { const list cart(getcart(cartId, cache)); return value(sum(cart)); } -- cgit v1.2.3