diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2012-12-11 03:51:03 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2012-12-11 03:51:03 +0000 |
commit | ae0b7c0063db6236be2d7cf01ddbf2159f77c98c (patch) | |
tree | 2f64d65d018634b8728623e2ca99514541fab8aa /sca-cpp/trunk/kernel | |
parent | 1f3796522a078dda5906395ba471d151ad694b6b (diff) |
Port kernel to C++11 and refactor some of the core modules. Convert functors to lambdas, and add C++ const, noexcept and inline annotations to get more efficient generated code.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1419985 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sca-cpp/trunk/kernel')
27 files changed, 1769 insertions, 2175 deletions
diff --git a/sca-cpp/trunk/kernel/Makefile.am b/sca-cpp/trunk/kernel/Makefile.am index e6a7fdb2b3..47c65a1889 100644 --- a/sca-cpp/trunk/kernel/Makefile.am +++ b/sca-cpp/trunk/kernel/Makefile.am @@ -37,14 +37,8 @@ mem_test_SOURCES = mem-test.cpp parallel_test_SOURCES = parallel-test.cpp -xml_test_SOURCES = xml-test.cpp -xml_test_LDFLAGS = -lxml2 - -xsd_test_SOURCES = xsd-test.cpp -xsd_test_LDFLAGS = -lxml2 - hash_test_SOURCES = hash-test.cpp -noinst_PROGRAMS = string-test kernel-test lambda-test hash-test mem-test parallel-test xml-test xsd-test -TESTS = string-test kernel-test lambda-test hash-test mem-test parallel-test xml-test +noinst_PROGRAMS = string-test kernel-test lambda-test hash-test mem-test parallel-test +TESTS = string-test kernel-test lambda-test hash-test mem-test parallel-test diff --git a/sca-cpp/trunk/kernel/config.hpp b/sca-cpp/trunk/kernel/config.hpp index 944b9629e7..e6af54552b 100644 --- a/sca-cpp/trunk/kernel/config.hpp +++ b/sca-cpp/trunk/kernel/config.hpp @@ -93,12 +93,12 @@ namespace tuscany #ifdef WANT_MAINTAINER_COUNTERS -bool debug_inc(long int& c) { +const bool debug_inc(long int& c) { c++; return true; } -bool debug_dec(long int& c) { +const bool debug_dec(long int& c) { c--; return true; } diff --git a/sca-cpp/trunk/kernel/dynlib-test.cpp b/sca-cpp/trunk/kernel/dynlib-test.cpp index 419fa29db5..c7f0e6238d 100644 --- a/sca-cpp/trunk/kernel/dynlib-test.cpp +++ b/sca-cpp/trunk/kernel/dynlib-test.cpp @@ -28,7 +28,7 @@ namespace tuscany { namespace test { - const int cppsquare(int x) { + const int cppsquare(const int x) { return x * x; } @@ -41,8 +41,8 @@ extern "C" { return tuscany::test::cppsquare(x); } - const tuscany::lambda<int(const int)> csquarel() { - return tuscany::lambda<int(const int)>(tuscany::test::cppsquare); + const tuscany::lambda<const int(const int)> csquarel() { + return tuscany::lambda<const int(const int)>(tuscany::test::cppsquare); } } diff --git a/sca-cpp/trunk/kernel/dynlib.hpp b/sca-cpp/trunk/kernel/dynlib.hpp index 69359b4dae..ea6b50bacb 100644 --- a/sca-cpp/trunk/kernel/dynlib.hpp +++ b/sca-cpp/trunk/kernel/dynlib.hpp @@ -48,27 +48,18 @@ const string dynlibExt(".so"); */ class lib { public: - lib() : h(NULL), owner(false) { + inline lib() : h(NULL), owner(false) { } - 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()); + inline lib(const string& name) : name(name), h(open(name)), owner(true) { } - lib(const lib& l) : name(l.name), h(l.h), owner(false) { + inline 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& operator=(const lib& l) = delete; - ~lib() { + inline ~lib() { if (!owner) return; if (!hasContent(h) || content(h) == NULL) @@ -77,17 +68,22 @@ public: } private: + const failable<void*> open(const string& name) { + void * h = dlopen(c_str(name), RTLD_NOW); + return h != NULL? failable<void*>(h) : mkfailure<void*>(string("Could not load library: ") + name + ": " + dlerror()); + } + template<typename S> friend const failable<lambda<S> > dynlambda(const string& name, const lib& l); - string name; - failable<void*> h; - bool owner; + const string name; + const failable<void*> h; + const bool owner; }; /** * Find a lambda function in a dynamic library. */ -template<typename S> const failable<lambda<S> > dynlambda(const string& name, const lib& l) { +template<typename S> inline const failable<lambda<S> > dynlambda(const string& name, const lib& l) { if (!hasContent(l.h)) return mkfailure<lambda<S>>(l.h); const void* s = dlsym(content(l.h), c_str(name)); diff --git a/sca-cpp/trunk/kernel/element.hpp b/sca-cpp/trunk/kernel/element.hpp index 27b5af8691..9ae1e632cb 100644 --- a/sca-cpp/trunk/kernel/element.hpp +++ b/sca-cpp/trunk/kernel/element.hpp @@ -42,7 +42,7 @@ const string atsign("@"); /** * Returns true if a value is an element. */ -bool isElement(const value& v) { +inline const bool isElement(const value& v) { if (!isList(v) || isNil(v) || element != car<value>(v)) return false; return true; @@ -51,7 +51,7 @@ bool isElement(const value& v) { /** * Returns true if a value is an attribute. */ -bool isAttribute(const value& v) { +inline const bool isAttribute(const value& v) { if (!isList(v) || isNil(v) || attribute != car<value>(v)) return false; return true; @@ -60,42 +60,42 @@ bool isAttribute(const value& v) { /** * Returns the name of an attribute. */ -const value attributeName(const list<value>& l) { +inline const value attributeName(const list<value>& l) { return cadr(l); } /** * Returns the value of an attribute. */ -const value attributeValue(const list<value>& l) { +inline const value attributeValue(const list<value>& l) { return caddr(l); } /** * Returns the name of an element. */ -const value elementName(const list<value>& l) { +inline const value elementName(const list<value>& l) { return cadr(l); } /** * Returns true if an element has children. */ -const bool elementHasChildren(const list<value>& l) { +inline const bool elementHasChildren(const list<value>& l) { return !isNil(cddr(l)); } /** * Returns the children of an element. */ -const list<value> elementChildren(const list<value>& l) { +inline const list<value> elementChildren(const list<value>& l) { return cddr(l); } /** * Returns true if an element has a value. */ -const bool elementHasValue(const list<value>& l) { +inline const bool elementHasValue(const list<value>& l) { const list<value> r = reverse(l); if (isSymbol(car(r))) return false; @@ -107,26 +107,26 @@ const bool elementHasValue(const list<value>& l) { /** * Returns the value of an element. */ -const value elementValue(const list<value>& l) { +inline const value elementValue(const list<value>& l) { return car(reverse(l)); } /** * Convert an element to a value. */ -const bool elementToValueIsList(const value& v) { +inline const bool elementToValueIsList(const value& v) { if (!isList(v)) return false; const list<value> l = v; return (isNil(l) || !isSymbol(car(l))); } -const value elementToValue(const value& t) { +inline const value elementToValue(const value& t) { const list<value> elementsToValues(const list<value>& e); // Convert an attribute if (isTaggedList(t, attribute)) - return mklist<value>(c_str(atsign + attributeName(t)), attributeValue(t)); + return mklist<value>(c_str(atsign + (string)attributeName(t)), attributeValue(t)); // Convert an element if (isTaggedList(t, element)) { @@ -155,7 +155,7 @@ const value elementToValue(const value& t) { /** * Convert a list of elements to a list of values. */ -const bool elementToValueIsSymbol(const value& v) { +inline const bool elementToValueIsSymbol(const value& v) { if (!isList(v)) return false; const list<value> l = v; @@ -166,7 +166,7 @@ const bool elementToValueIsSymbol(const value& v) { return true; } -const list<value> elementToValueGroupValues(const value& v, const list<value>& l) { +inline const list<value> elementToValueGroupValues(const value& v, const list<value>& l) { if (isNil(l) || !elementToValueIsSymbol(v) || !elementToValueIsSymbol(car(l))) return cons(v, l); if (car<value>(car(l)) != car<value>(v)) @@ -180,7 +180,7 @@ const list<value> elementToValueGroupValues(const value& v, const list<value>& l } -const list<value> elementsToValues(const list<value>& e) { +inline const list<value> elementsToValues(const list<value>& e) { if (isNil(e)) return e; return elementToValueGroupValues(elementToValue(car(e)), elementsToValues(cdr(e))); @@ -189,13 +189,13 @@ const list<value> elementsToValues(const list<value>& e) { /** * Convert a value to an element. */ -const value valueToElement(const value& t) { +inline const value valueToElement(const value& t) { const list<value> valuesToElements(const list<value>& l); // Convert a name value pair if (isList(t) && !isNil((list<value>)t) && isSymbol(car<value>(t))) { const value n = car<value>(t); - const value v = isNil(cdr<value>(t))? value() : cadr<value>(t); + const value v = isNil(cdr<value>(t))? nilValue : cadr<value>(t); // Convert a single value to an attribute or an element if (!isList(v)) { @@ -221,7 +221,7 @@ const value valueToElement(const value& t) { /** * Convert a list of values to a list of elements. */ -const list<value> valuesToElements(const list<value>& l) { +inline const list<value> valuesToElements(const list<value>& l) { if (isNil(l)) return l; return cons<value>(valueToElement(car(l)), valuesToElements(cdr(l))); @@ -231,72 +231,51 @@ const list<value> valuesToElements(const list<value>& l) { * Returns a selector lambda function which can be used to filter * elements against the given element pattern. */ -struct selectorLambda { - const list<value> select; - selectorLambda(const list<value>& s) : select(s) { - } - const bool evalSelect(const list<value>& s, const list<value> v) const { - if (isNil(s)) - return true; - if (isNil(v)) - return false; - if (car(s) != car(v)) - return false; - return evalSelect(cdr(s), cdr(v)); - } - const bool operator()(const value& v) const { +inline const lambda<const bool(const value&)> selector(const list<value>& select) { + return [select](const value& v) -> const bool { + const lambda<const bool(const list<value>&, const list<value>&)> evalSelect = [&evalSelect](const list<value>& s, const list<value>& v) -> const bool { + if (isNil(s)) + return true; + if (isNil(v)) + return false; + if (car(s) != car(v)) + return false; + return evalSelect(cdr(s), cdr(v)); + }; if (!isList(v)) return false; return evalSelect(select, v); - } -}; - -const lambda<bool(const value&)> selector(const list<value> s) { - return selectorLambda(s); + }; } /** * Returns the value of the attribute with the given name. */ -struct filterAttribute { - const value name; - filterAttribute(const value& n) : name(n) { - } - const bool operator()(const value& v) const { - return isAttribute(v) && attributeName((list<value>)v) == name; - } -}; - -const value attributeValue(const value& name, const value& l) { - const list<value> f = filter<value>(filterAttribute(name), list<value>(l)); +inline const value attributeValue(const value& name, const value& l) { + const list<value> f = filter<value>([name](const value& v) { + return isAttribute(v) && attributeName((list<value>)v) == name; + }, list<value>(l)); if (isNil(f)) - return value(); + return nilValue; return caddr<value>(car(f)); } /** * Returns child elements with the given name. */ -struct filterElement { - const value name; - filterElement(const value& n) : name(n) { - } - const bool operator()(const value& v) const { - return isElement(v) && elementName((list<value>)v) == name; - } -}; - -const value elementChildren(const value& name, const value& l) { - return filter<value>(filterElement(name), list<value>(l)); +inline const value elementChildren(const value& name, const value& l) { + return filter<value>([name](const value& v) { + return isElement(v) && elementName((list<value>)v) == name; + }, list<value>(l)); } /** * Return the child element with the given name. */ -const value elementChild(const value& name, const value& l) { +inline const value elementChild(const value& name, const value& l) { const list<value> f = elementChildren(name, l); if (isNil(f)) - return value(); + return nilValue; return car(f); } diff --git a/sca-cpp/trunk/kernel/fstream.hpp b/sca-cpp/trunk/kernel/fstream.hpp index 4f7f5152aa..1ed1487707 100644 --- a/sca-cpp/trunk/kernel/fstream.hpp +++ b/sca-cpp/trunk/kernel/fstream.hpp @@ -69,24 +69,18 @@ namespace tuscany { */ class ofstream : public ostream { public: - ofstream(const string& path) : file(fopen(c_str(path), "wb")), owner(true) { + inline ofstream(const string& path) : file(fopen(c_str(path), "wb")), owner(true) { } - ofstream(FILE* file) : file(file), owner(false) { + inline ofstream(FILE* const file) : file(file), owner(false) { } - ofstream(const ofstream& os) : file(os.file), owner(false) { + inline 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& operator=(const ofstream& os) = delete; - ~ofstream() { + inline ~ofstream() { if (!owner) return; if (file == NULL) @@ -94,11 +88,11 @@ public: fclose(file); } - const bool fail() { + inline const bool fail() { return file == NULL; } - ofstream& vprintf(const char* fmt, ...) { + inline ofstream& vprintf(const char* const fmt, ...) { va_list args; va_start (args, fmt); vfprintf (file, fmt, args); @@ -106,19 +100,24 @@ public: return *this; } - ofstream& write(const string& s) { + inline ofstream& write(const string& s) { fwrite(c_str(s), 1, length(s), file); return *this; } - ofstream& flush() { + inline ofstream& write(const char c) { + fwrite(&c, 1, 1, file); + return *this; + } + + inline ofstream& flush() { fflush(file); return *this; } private: - FILE* file; - bool owner; + FILE* const file; + const bool owner; }; /* @@ -126,24 +125,18 @@ private: */ class ifstream : public istream { public: - ifstream(const string& path) : file(fopen(c_str(path), "rb")), owner(true) { + inline ifstream(const string& path) : file(fopen(c_str(path), "rb")), owner(true) { } - ifstream(FILE* file) : file(file), owner(false) { + inline ifstream(FILE* const file) : file(file), owner(false) { } - ifstream(const ifstream& is) : file(is.file), owner(false) { + inline 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& operator=(const ifstream& is) = delete; - ~ifstream() { + inline ~ifstream() { if (!owner) return; if (file == NULL) @@ -151,23 +144,23 @@ public: fclose(file); } - const size_t read(void* buf, size_t size) { + inline const size_t read(void* const buf, const size_t size) { return fread(buf, 1, size, file); } - const bool eof() { + inline const bool eof() { return feof(file); } - const bool fail() { + inline const bool fail() { return file == NULL; } - const int get() { + inline const int get() { return fgetc(file); } - const int peek() { + inline const int peek() { int c = fgetc(file); if (c == -1) return c; @@ -176,8 +169,8 @@ public: } private: - FILE* file; - bool owner; + FILE* const file; + const bool owner; }; /** @@ -198,24 +191,24 @@ ifstream cin(stdin); */ class loghstream : public ostream { public: - loghstream(const int level) : level(level), len(0) { + inline loghstream(const int level) : level(level), len(0) { } - ~loghstream() { + inline ~loghstream() { } - ostream& vprintf(const char* fmt, ...) { + inline ostream& vprintf(const char* const fmt, ...) { va_list args; - va_start (args, fmt); + va_start(args, fmt); const int l = vsnprintf(buf + len, (sizeof(buf) - 1) - len, fmt, args); - va_end (args); + va_end(args); len += l; if (len > (int)(sizeof(buf) - 1)) len = sizeof(buf) - 1; return *this; } - ostream& write(const string& s) { + inline ostream& write(const string& s) { if (s != "\n") return this->vprintf("%s", c_str(s)); buf[len] = '\0'; @@ -224,14 +217,23 @@ public: return *this; } - ostream& flush() { + inline ostream& write(const char c) { + if (c != '\n') + return this->vprintf("%c", c); + buf[len] = '\0'; + ap_log_error(NULL, 0, -1, level, 0, ap_server_conf, "%s", buf); + len = 0; + return *this; + } + + inline ostream& flush() { return *this; } private: const int level; int len; - char buf[2049]; + char buf[513]; }; /** @@ -259,11 +261,11 @@ loghstream cdebug(APLOG_DEBUG); /** * Format the current time. */ -const string logTime() { +inline const string logTime() { struct timeval tv; gettimeofday(&tv, NULL); const time_t t = tv.tv_sec; - const tm* lt = localtime(&t); + const tm* const lt = localtime(&t); char ft[32]; strftime(ft, 20, "%a %b %d %H:%M:%S", lt); sprintf(ft + 19, ".%06lu ", (unsigned long)tv.tv_usec); @@ -276,16 +278,16 @@ const string logTime() { */ class logfstream : public ostream { public: - logfstream(FILE* file, const string& type) : file(file), type(type), head(false) { + inline logfstream(FILE* const file, const string& type) : file(file), type(type), head(false) { } - logfstream(const logfstream& os) : file(os.file), type(os.type), head(os.head) { + inline logfstream(const logfstream& os) : file(os.file), type(os.type), head(os.head) { } - ~logfstream() { + inline ~logfstream() { } - ostream& vprintf(const char* fmt, ...) { + inline ostream& vprintf(const char* const fmt, ...) { whead(); va_list args; va_start (args, fmt); @@ -294,7 +296,7 @@ public: return *this; } - ostream& write(const string& s) { + inline ostream& write(const string& s) { whead(); fwrite(c_str(s), 1, length(s), file); if (s == "\n") @@ -302,17 +304,25 @@ public: return *this; } - ostream& flush() { + inline ostream& write(const char c) { + whead(); + fwrite(&c, 1, 1, file); + if (c == '\n') + head = false; + return *this; + } + + inline ostream& flush() { fflush(file); return *this; } private: - FILE* file; + FILE* const file; const string type; bool head; - const unsigned long tid() const { + inline const unsigned long tid() const { #ifdef WANT_THREADS return (unsigned long)pthread_self(); #else @@ -320,7 +330,7 @@ private: #endif } - ostream& whead() { + inline ostream& whead() { if (head) return *this; head = true; @@ -348,7 +358,7 @@ logfstream cdebug(stderr, "debug"); bool debug_isLoggingSet = false; bool debug_isLoggingEnv = false; -const bool debug_isLogging() { +inline const bool debug_isLogging() { if (debug_isLoggingSet) return debug_isLoggingEnv; debug_isLoggingEnv = getenv("TUSCANY_DEBUG_LOG") != NULL; @@ -366,8 +376,8 @@ const bool debug_isLogging() { /** * Log a debug message. */ -const bool debugLog(const string& msg) { - gc_scoped_pool p; +inline const bool debugLog(const string& msg) { + const gc_scoped_pool p; cdebug << msg << endl; return true; } @@ -375,8 +385,8 @@ const bool debugLog(const string& msg) { /** * Log a debug message and a value. */ -template<typename V> const bool debugLog(const V& v, const string& msg) { - gc_scoped_pool p; +template<typename V> inline const bool debugLog(const V& v, const string& msg) { + const gc_scoped_pool p; cdebug << msg << ": " << v << endl; return true; } @@ -384,8 +394,8 @@ template<typename V> const bool debugLog(const V& v, const string& msg) { /** * Log a debug message and two values. */ -template<typename V, typename W> const bool debugLog(const V& v, const W& w, const string& msg) { - gc_scoped_pool p; +template<typename V, typename W> inline const bool debugLog(const V& v, const W& w, const string& msg) { + const gc_scoped_pool p; cdebug << msg << ": " << v << " : " << w << endl; return true; } diff --git a/sca-cpp/trunk/kernel/function.hpp b/sca-cpp/trunk/kernel/function.hpp index 60117dab98..0a88cf51d9 100644 --- a/sca-cpp/trunk/kernel/function.hpp +++ b/sca-cpp/trunk/kernel/function.hpp @@ -23,7 +23,9 @@ #define tuscany_function_hpp /** - * Lambda function type. + * Lambda function type that enforces pass by ref and constant parameters, + * allocates memory only as needed and using an APR memory pool, is about + * 2 times faster than std::function and between 1/4 and 1/6 of its size. */ #include <utility> @@ -46,16 +48,16 @@ long int countELambdas = 0; long int countCLambdas = 0; long int countFLambdas = 0; -bool resetLambdaCounters() { +inline const bool resetLambdaCounters() { countLambdas = countELambdas = countCLambdas = countFLambdas = countProxies = countFProxies = countCProxies = 0; return true; } -bool checkLambdaCounters() { +inline const bool checkLambdaCounters() { return countLambdas == 0; } -bool printLambdaCounters() { +inline const bool printLambdaCounters() { cout << "countLambdas " << countLambdas << endl; cout << "countELambdas " << countELambdas << endl; cout << "countFLambdas " << countFLambdas << endl; @@ -80,38 +82,32 @@ bool printLambdaCounters() { template<typename R, typename... P> class Callable { public: - Callable() { + inline Callable() noexcept { } - virtual const size_t size() const = 0; - - virtual const R operator()(P... p) const = 0; + virtual const R operator()(const P&&... p) const noexcept = 0; - virtual ~Callable() { + inline virtual ~Callable() noexcept { } - template<typename F> class Proxy: public Callable { + template<typename F> class Proxy: public Callable<R, P...> { public: - Proxy(const F& f) : function(f) { + inline Proxy(const F& f) noexcept : function(f) { debug_inc(countProxies); debug_inc(countFProxies); } - Proxy(const Proxy& p) : function(p.function) { + inline Proxy(const Proxy& p) noexcept : function(p.function) { debug_inc(countProxies); debug_inc(countCProxies); } - ~Proxy() { + inline ~Proxy() noexcept { debug_dec(countProxies); } - virtual const R operator() (P... p) const { - return function(std::forward<P>(p)...); - } - - virtual const size_t size() const { - return sizeof(function); + virtual const R operator() (const P&&... p) const noexcept { + return function(std::forward<const P&&>(p)...); } private: @@ -123,67 +119,68 @@ template<typename S> class lambda; template<typename R, typename... P> class lambda<R(P...)> { public: - lambda() : callable(0) { + inline lambda() noexcept : callable(NULL) { debug_inc(countLambdas); debug_inc(countELambdas); } - template<typename F> lambda(const F f) { + template<typename F> inline lambda(const F f) noexcept : callable(mkproxy<F>(f)) { debug_inc(countLambdas); debug_inc(countFLambdas); + } - typedef typename CallableType::template Proxy<F> ProxyType; - callable = gc_ptr<CallableType>(new (gc_new<ProxyType>()) ProxyType(f)); + template<typename F> inline lambda(const gc_mutable_ref<F>& r) noexcept : callable(mkproxy<F>(*(F*)r)) { + debug_inc(countLambdas); + debug_inc(countFLambdas); } - lambda(const lambda& l) { + inline lambda(const lambda& l) noexcept : callable(l.callable) { debug_inc(countLambdas); debug_inc(countCLambdas); - callable = l.callable; } - const lambda& operator=(const lambda& l) { - if (this == &l) - return *this; - callable = l.callable; - return *this; - } + lambda& operator=(const lambda& l) = delete; - ~lambda() { + inline ~lambda() noexcept { debug_dec(countLambdas); } - const bool operator==(const lambda& l) const { + inline const bool operator==(const lambda& l) const noexcept { if (this == &l) return true; - return callable == l.callable; + return false; } - const bool operator!=(const lambda& l) const { + inline const bool operator!=(const lambda& l) const noexcept { return !this->operator==(l); } - const R operator()(P... p) const { - return (*callable)(std::forward<P>(p)...); + inline const R operator()(const P&... p) const noexcept { + return (*callable)(std::forward<const P&&>(p)...); } template<typename S> friend ostream& operator<<(ostream&, const lambda<S>&); - template<typename S> friend const bool isNil(const lambda<S>& l); + template<typename S> friend const bool isNil(const lambda<S>& l) noexcept; private: typedef Callable<R,P...> CallableType; - gc_ptr<CallableType> callable; + const gc_ptr<CallableType> callable; + + template<typename F> inline gc_ptr<CallableType> mkproxy(const F& f) noexcept { + typedef typename CallableType::template Proxy<F> ProxyType; + return gc_ptr<CallableType>(new (gc_new<ProxyType>()) ProxyType(f)); + } }; -template<typename S> ostream& operator<<(ostream& out, const lambda<S>& l) { +template<typename S> inline ostream& operator<<(ostream& out, const lambda<S>& l) { return out << "lambda::" << l.callable; } /** * Return true if a lambda is nil. */ -template<typename S> const bool isNil(const lambda<S>& l) { - return ((void*)l.callable) == 0; +template<typename S> inline const bool isNil(const lambda<S>& l) noexcept { + return (const void*)l.callable == NULL; } /** @@ -191,11 +188,11 @@ template<typename S> const bool isNil(const lambda<S>& l) { */ template<typename R, typename T, typename... P> class curried { public: - curried(const lambda<R(T, P...)>& f, const T& v): v(v), f(f) { + inline curried(const lambda<R(T, P...)>& f, const T& v) noexcept: v(v), f(f) { } - const R operator()(P... p) const { - return f(v, std::forward<P>(p)...); + inline const R operator()(const P&... p) const noexcept { + return f(v, std::forward<const P&>(p)...); } private: @@ -203,36 +200,29 @@ private: const lambda<R(T, P...)>f; }; -template<typename R, typename T, typename... P> const lambda<R(P...)> curry(const lambda<R(T, P...)>& f, const T& t) { +template<typename R, typename T, typename... P> inline const lambda<const R(P...)> curry(const lambda<R(T, P...)>& f, const T& t) noexcept { return curried<R, T, P...>(f, t); } -template<typename R, typename T, typename U, typename... P> const lambda<R(P...)> curry(const lambda<R(T, U, P...)>& f, const T& t, const U& u) { +template<typename R, typename T, typename U, typename... P> inline const lambda<R(P...)> curry(const lambda<R(T, U, P...)>& f, const T& t, const U& u) noexcept { return curry(curry(f, t), u); } -template<typename R, typename T, typename U, typename V, typename... P> const lambda<R(P...)> curry(const lambda<R(T, U, V, P...)>& f, const T& t, const U& u, const V& v) { +template<typename R, typename T, typename U, typename V, typename... P> inline const lambda<R(P...)> curry(const lambda<R(T, U, V, P...)>& f, const T& t, const U& u, const V& v) noexcept { return curry(curry(curry(f, t), u), v); } /** * A lambda function that returns the given value. */ -template<typename T> class returnResult { -public: - returnResult(const T& v) : - v(v) { - } - const T operator()() const { - return v; - } -private: - const T v; -}; - -template<typename T> const lambda<T()> result(const T& v) { - return returnResult<T> (v); +template<typename T> inline const lambda<const T()> result(const T& v) { + return [v]()->T { return v; }; } +/** + * Commonly used lambda types. + */ +typedef lambda<const bool()> blambda; + } #endif /* tuscany_function_hpp */ diff --git a/sca-cpp/trunk/kernel/gc.hpp b/sca-cpp/trunk/kernel/gc.hpp index 32ad8160cc..7853c551dc 100644 --- a/sca-cpp/trunk/kernel/gc.hpp +++ b/sca-cpp/trunk/kernel/gc.hpp @@ -49,7 +49,7 @@ namespace tuscany /** * Force a core dump on assertion violation. */ -bool assertOrFail(const bool expr) { +inline const bool assertOrFail(const bool expr) { if (!expr) abort(); return true; @@ -64,63 +64,135 @@ bool assertOrFail(const bool expr) { /** * Pointer to a value. */ +#ifdef WANT_RAW_PTR + +template<typename T> using gc_ptr = T*; + +#else + template<typename T> class gc_ptr { public: - gc_ptr(T* ptr = NULL) throw() : ptr(ptr) { + inline gc_ptr(T* const ptr = NULL) noexcept : ptr(ptr) { + } + + inline ~gc_ptr() noexcept { + } + + inline gc_ptr(const gc_ptr& r) noexcept : ptr(r.ptr) { + } + + gc_ptr& operator=(const gc_ptr& r) = delete; + + inline const bool operator==(const gc_ptr& r) const noexcept { + if (this == &r) + return true; + return ptr == r.ptr; + } + + inline const bool operator==(const T* const p) const noexcept { + return ptr == p; + } + + inline const bool operator!=(const gc_ptr& r) const noexcept { + return !this->operator==(r); + } + + inline const bool operator!=(const T* const p) const noexcept { + return !this->operator==(p); + } + + inline T& operator*() const noexcept { + return *ptr; + } + + inline T* const operator->() const noexcept { + return ptr; + } + + inline operator T* const () const noexcept { + return ptr; + } + +private: + T* const ptr; +}; + +#endif + +/** + * Mutable pointer to an immutable value. + */ +#ifdef WANT_RAW_PTR + +template<typename T> using gc_mutable_ptr = T*; + +#else + +template<typename T> class gc_mutable_ptr { +public: + inline gc_mutable_ptr(T* const ptr = NULL) noexcept : ptr(ptr) { } - ~gc_ptr() throw() { + inline ~gc_mutable_ptr() noexcept { } - gc_ptr(const gc_ptr& r) throw() : ptr(r.ptr) { + inline gc_mutable_ptr(const gc_mutable_ptr& r) noexcept : ptr(r.ptr) { } - gc_ptr& operator=(const gc_ptr& r) throw() { - if(this == &r) + inline gc_mutable_ptr& operator=(T* const p) noexcept { + ptr = p; + return *this; + } + + inline gc_mutable_ptr& operator=(const gc_mutable_ptr& r) noexcept { + if (this == &r) return *this; ptr = r.ptr; return *this; } - const bool operator==(const gc_ptr& r) const throw() { + inline const bool operator==(const gc_mutable_ptr& r) const noexcept { if (this == &r) return true; return ptr == r.ptr; } - const bool operator==(T* p) const throw() { + inline const bool operator==(T* const p) const noexcept { return ptr == p; } - const bool operator!=(const gc_ptr& r) const throw() { + inline const bool operator!=(const gc_mutable_ptr& r) const noexcept { return !this->operator==(r); } - const bool operator!=(T* p) const throw() { + inline const bool operator!=(T* const p) const noexcept { return !this->operator==(p); } - T& operator*() const throw() { + inline T& operator*() const noexcept { return *ptr; } - T* operator->() const throw() { + inline T* const operator->() const noexcept { return ptr; } - operator T*() const throw() { + inline operator T* const () const noexcept { return ptr; } +private: T* ptr; }; +#endif + /** * Initialize APR. */ class gc_apr_context_t { public: - gc_apr_context_t() { + inline gc_apr_context_t() { apr_initialize(); } } gc_apr_context; @@ -130,36 +202,31 @@ public: */ class gc_pool { public: - gc_pool() : apr_pool(NULL) { + inline gc_pool() noexcept : apr_pool(NULL) { } - gc_pool(apr_pool_t* p) : apr_pool(p) { + inline gc_pool(apr_pool_t* const p) noexcept : apr_pool(p) { } - gc_pool(const gc_pool& pool) : apr_pool(pool.apr_pool) { + inline gc_pool(const gc_pool& pool) noexcept : apr_pool(pool.apr_pool) { } - gc_pool& operator=(const gc_pool& pool) { - if (this == &pool) - return *this; - apr_pool = pool.apr_pool; - return *this; - } + gc_pool& operator=(const gc_pool& pool) = delete; private: - friend apr_pool_t* pool(const gc_pool& pool); + friend apr_pool_t* pool(const gc_pool& pool) noexcept; 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; + apr_pool_t* const apr_pool; }; /** * Return the APR pool used by a gc_pool. */ -apr_pool_t* pool(const gc_pool& pool) { +inline apr_pool_t* pool(const gc_pool& pool) noexcept { return pool.apr_pool; } @@ -168,35 +235,51 @@ apr_pool_t* pool(const gc_pool& pool) { */ #ifdef WANT_THREADS +#ifdef __clang__ + class gc_pool_stack_t { public: - gc_pool_stack_t() { - int rc = pthread_key_create(&key, NULL); - assertOrFail(rc == 0); + inline gc_pool_stack_t() noexcept : key(mkkey()) { } - operator apr_pool_t*() const { - return static_cast<apr_pool_t*>(pthread_getspecific(key)); + inline operator apr_pool_t*() const noexcept { + return (apr_pool_t*)pthread_getspecific(key); } - const gc_pool_stack_t& operator=(apr_pool_t* p) { + inline const gc_pool_stack_t& operator=(apr_pool_t* p) noexcept { pthread_setspecific(key, p); return *this; } private: pthread_key_t key; + + pthread_key_t mkkey() { + pthread_key_t k; + int rc = pthread_key_create(&k, NULL); + assertOrFail(rc == 0); + return k; + } + } gc_pool_stack; #else + +__thread apr_pool_t* gc_pool_stack = NULL; + +#endif + +#else + apr_pool_t* gc_pool_stack = NULL; + #endif /** * Push a pool onto the stack. */ -apr_pool_t* gc_push_pool(apr_pool_t* pool) { - apr_pool_t* p = gc_pool_stack; +inline apr_pool_t* const gc_push_pool(apr_pool_t* pool) noexcept { + apr_pool_t* const p = gc_pool_stack; gc_pool_stack = pool; return p; } @@ -204,8 +287,8 @@ apr_pool_t* gc_push_pool(apr_pool_t* pool) { /** * Pop a pool from the stack. */ -apr_pool_t* gc_pop_pool(apr_pool_t* pool) { - apr_pool_t* p = gc_pool_stack; +inline apr_pool_t* const gc_pop_pool(apr_pool_t* pool) noexcept { + apr_pool_t* const p = gc_pool_stack; gc_pool_stack = pool; return p; } @@ -213,16 +296,17 @@ apr_pool_t* gc_pop_pool(apr_pool_t* pool) { /** * Return the current memory pool. */ -apr_pool_t* gc_current_pool() { - apr_pool_t* p = gc_pool_stack; +inline apr_pool_t* const gc_current_pool() noexcept { + apr_pool_t* const p = gc_pool_stack; if (p != NULL) return p; // Create a parent pool for the current thread - apr_pool_create(&p, NULL); - assertOrFail(p != NULL); - gc_push_pool(p); - return p; + apr_pool_t* pp; + apr_pool_create(&pp, NULL); + assertOrFail(pp != NULL); + gc_push_pool(pp); + return pp; } /** @@ -231,25 +315,23 @@ apr_pool_t* gc_current_pool() { 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); + inline gc_child_pool() noexcept : gc_pool(mkpool()), owner(true) { } - 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; + inline gc_child_pool(const gc_child_pool& p) noexcept : gc_pool(p.apr_pool), owner(false) { } + gc_child_pool& operator=(const gc_child_pool& p) = delete; private: - bool owner; + const bool owner; + + apr_pool_t* const mkpool() { + apr_pool_t* p; + apr_pool_create(&p, gc_current_pool()); + assertOrFail(p != NULL); + return p; + } }; /** @@ -258,29 +340,28 @@ private: 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); + inline gc_local_pool() noexcept : gc_pool(mkpool()), owner(true) { } - ~gc_local_pool() { + inline ~gc_local_pool() noexcept { if (owner) apr_pool_destroy(apr_pool); } - gc_local_pool(const gc_local_pool& p) : gc_pool(p.apr_pool), owner(false) { + inline gc_local_pool(const gc_local_pool& p) noexcept : 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; - } + gc_local_pool& operator=(const gc_local_pool& p) = delete; private: - bool owner; + const bool owner; + + apr_pool_t* const mkpool() { + apr_pool_t* p; + apr_pool_create(&p, gc_current_pool()); + assertOrFail(p != NULL); + return p; + } }; /** @@ -290,66 +371,64 @@ private: 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, prev); - assertOrFail(apr_pool != NULL); + inline gc_scoped_pool() noexcept : gc_pool(mkpool()), prev(gc_current_pool()), owner(true) { gc_push_pool(apr_pool); } - gc_scoped_pool(apr_pool_t* p) : gc_pool(p), prev(gc_current_pool()), owner(false) { + inline gc_scoped_pool(apr_pool_t* p) noexcept : gc_pool(p), prev(gc_current_pool()), owner(false) { gc_push_pool(apr_pool); } - ~gc_scoped_pool() { + inline ~gc_scoped_pool() noexcept { if (owner) apr_pool_destroy(apr_pool); gc_pop_pool(prev); } - gc_scoped_pool(const gc_scoped_pool& p) : gc_pool(p.apr_pool), prev(p.prev), owner(false) { + inline gc_scoped_pool(const gc_scoped_pool& p) noexcept : 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; - } + gc_scoped_pool& operator=(const gc_scoped_pool& p) = delete; private: - apr_pool_t* prev; - bool owner; + apr_pool_t* const prev; + const bool owner; + + apr_pool_t* const mkpool() { + apr_pool_t* p; + apr_pool_create(&p, gc_current_pool()); + assertOrFail(p != NULL); + return p; + } }; /** * Allocates a pointer to an object allocated from a memory pool and * register a cleanup callback for it. */ -template<typename T> apr_status_t gc_pool_cleanup(void* v) { +template<typename T> inline apr_status_t gc_pool_cleanup(void* v) { T* t = (T*)v; t->~T(); return APR_SUCCESS; } -template<typename T> T* gc_new(apr_pool_t* p) { +template<typename T> inline T* const gc_new(apr_pool_t* const p) noexcept { void* gc_new_ptr = apr_palloc(p, sizeof(T)); assertOrFail(gc_new_ptr != NULL); apr_pool_cleanup_register(p, gc_new_ptr, gc_pool_cleanup<T>, apr_pool_cleanup_null) ; return (T*)(gc_new_ptr); } -template<typename T> T* gc_new(const gc_pool& p) { +template<typename T> inline T* const gc_new(const gc_pool& p) noexcept { return gc_new<T>(pool(p)); } -template<typename T> T* gc_new() { +template<typename T> inline T* const gc_new() noexcept { return gc_new<T>(gc_current_pool()); } -template<typename T> apr_status_t gc_pool_acleanup(void* v) { - size_t* m = static_cast<size_t*>(v); +template<typename T> inline apr_status_t gc_pool_acleanup(void* v) { + size_t* m = (size_t*)v; size_t n = *m; T* t = (T*)(m + 1); for (size_t i = 0; i < n; i++, t++) @@ -357,40 +436,101 @@ template<typename T> apr_status_t gc_pool_acleanup(void* v) { return APR_SUCCESS; } -template<typename T> T* gc_anew(apr_pool_t* p, size_t n) { - size_t* gc_anew_ptr = static_cast<size_t*>(apr_palloc(p, sizeof(size_t) + sizeof(T) * n)); +template<typename T> inline T* const gc_anew(apr_pool_t* const p, const size_t n) noexcept { + size_t* const gc_anew_ptr = (size_t*)apr_palloc(p, sizeof(size_t) + sizeof(T) * n); assertOrFail(gc_anew_ptr != NULL); *gc_anew_ptr = n; apr_pool_cleanup_register(p, gc_anew_ptr, gc_pool_acleanup<T>, apr_pool_cleanup_null) ; return (T*)(gc_anew_ptr + 1); } -template<typename T> T* gc_anew(const gc_pool& p, size_t n) { +template<typename T> inline T* const gc_anew(const gc_pool& p, const size_t n) noexcept { return gc_anew<T>(pool(p), n); } -template<typename T> T* gc_anew(size_t n) { +template<typename T> inline T* const gc_anew(const size_t n) noexcept { return gc_anew<T>(gc_current_pool(), n); } /** * Allocate an array of chars. */ -char* gc_cnew(apr_pool_t* p, size_t n) { - char* gc_cnew_ptr = static_cast<char*>(apr_palloc(p, n)); +inline char* const gc_cnew(apr_pool_t* const p, const size_t n) noexcept { + char* const gc_cnew_ptr = (char*)apr_palloc(p, n); assertOrFail(gc_cnew_ptr != NULL); return gc_cnew_ptr; } -char* gc_cnew(size_t n) { +inline char* const gc_cnew(const size_t n) noexcept { return gc_cnew(gc_current_pool(), n); } /** + * Mutable reference to an immutable value. + */ +template<typename T> class gc_mutable_ref { +public: + inline gc_mutable_ref() noexcept : ptr(new (gc_new<T>()) T()) { + } + + inline ~gc_mutable_ref() noexcept { + } + + inline gc_mutable_ref(const gc_mutable_ref& r) noexcept : ptr(r.ptr) { + } + + inline gc_mutable_ref(const T& v) noexcept : ptr(new (gc_new<T>()) T(v)) { + } + + inline gc_mutable_ref& operator=(const gc_mutable_ref& r) noexcept { + if (this == &r) + return *this; + ptr = r.ptr; + return *this; + } + + inline gc_mutable_ref& operator=(const T& v) noexcept { + ptr = new (gc_new<T>()) T(v); + return *this; + } + + inline const bool operator==(const gc_mutable_ref& r) const noexcept { + if (this == &r) + return true; + if (ptr == r.ptr) + return true; + return *ptr == *r.ptr; + } + + inline const bool operator==(const T& v) const noexcept { + return *ptr == v; + } + + inline const bool operator!=(const gc_mutable_ref& r) const noexcept { + return !this->operator==(r); + } + + inline const bool operator!=(const T& v) const noexcept { + return !this->operator==(v); + } + + inline operator T&() const noexcept { + return *ptr; + } + + inline operator T* const () const noexcept { + return ptr; + } + +private: + T* ptr; +}; + +/** * Pool based equivalent of the standard malloc function. */ -void* gc_pool_malloc(size_t n) { - size_t* ptr = static_cast<size_t*>(apr_palloc(gc_current_pool(), sizeof(size_t) + n)); +inline void* gc_pool_malloc(size_t n) { + size_t* ptr = (size_t*)apr_palloc(gc_current_pool(), sizeof(size_t) + n); assertOrFail(ptr != NULL); *ptr = n; return ptr + 1; @@ -399,9 +539,9 @@ void* gc_pool_malloc(size_t n) { /** * Pool based equivalent of the standard realloc function. */ -void* gc_pool_realloc(void* ptr, size_t n) { - size_t size = *(static_cast<size_t*>(ptr) - 1); - size_t* rptr = static_cast<size_t*>(apr_palloc(gc_current_pool(), sizeof(size_t) + n)); +inline void* gc_pool_realloc(void* ptr, size_t n) { + size_t size = *(((size_t*)ptr) - 1); + size_t* rptr = (size_t*)apr_palloc(gc_current_pool(), sizeof(size_t) + n); assertOrFail(rptr != NULL); *rptr = n; memcpy(rptr + 1, ptr, size < n? size : n); @@ -411,15 +551,15 @@ void* gc_pool_realloc(void* ptr, size_t n) { /** * Pool based equivalent of the standard free function. */ -void gc_pool_free(unused void* ptr) { +inline void gc_pool_free(unused void* ptr) { // Memory allocated from a pool is freed when the pool is freed } /** * Pool based equivalent of the standard strdup function. */ -char* gc_pool_strdup(const char* str) { - char* dptr = static_cast<char*>(gc_pool_malloc(strlen(str) + 1)); +inline char* gc_pool_strdup(const char* str) { + char* dptr = (char*)gc_pool_malloc(strlen(str) + 1); assertOrFail(dptr != NULL); strcpy(dptr, str); return dptr; @@ -434,9 +574,9 @@ char* gc_pool_strdup(const char* str) { /** * Mmap based equivalent of the standard malloc function. */ -void* gc_mmap_malloc(size_t n, unused const void* caller) { +inline void* gc_mmap_malloc(size_t n, unused const void* caller) { //printf("gc_mmap_malloc %d", n); - size_t* ptr = static_cast<size_t*>(mmap(NULL, sizeof(size_t) + n, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)); + size_t* ptr = (size_t*)mmap(NULL, sizeof(size_t) + n, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); assertOrFail(ptr != NULL); *ptr = n; //printf(" %p\n", ptr + 1); @@ -446,12 +586,12 @@ void* gc_mmap_malloc(size_t n, unused const void* caller) { /** * Mmap based equivalent of the standard realloc function. */ -void* gc_mmap_realloc(void* ptr, size_t n, const void* caller) { +inline void* gc_mmap_realloc(void* ptr, size_t n, const void* caller) { if (ptr == NULL) return gc_mmap_malloc(n, caller);; //printf("gc_mmap_realloc %p %d", ptr, n); - size_t size = *(static_cast<size_t*>(ptr) - 1); - size_t* rptr = static_cast<size_t*>(mremap(static_cast<size_t*>(ptr) - 1, sizeof(size_t) + size, sizeof(size_t) + n, MREMAP_MAYMOVE, NULL)); + size_t size = *(((size_t*)ptr) - 1); + size_t* rptr = (size_t*)mremap(((size_t*)ptr) - 1, sizeof(size_t) + size, sizeof(size_t) + n, MREMAP_MAYMOVE, NULL); assertOrFail(rptr != NULL); *rptr = n; //printf(" %p\n", rptr + 1); @@ -461,18 +601,18 @@ void* gc_mmap_realloc(void* ptr, size_t n, const void* caller) { /** * Mmap based equivalent of the standard free function. */ -void gc_mmap_free(void* ptr, unused const void* caller) { +inline void gc_mmap_free(void* ptr, unused const void* caller) { //printf("gc_mmap_free %p\n", ptr); if (ptr == NULL) return; - size_t size = *(static_cast<size_t*>(ptr) - 1); - munmap(static_cast<size_t*>(ptr) - 1, sizeof(size_t) + size); + size_t size = *(((size_t*)ptr) - 1); + munmap(((size_t*)ptr) - 1, sizeof(size_t) + size); } /** * Mmap based equivalent of the standard memalign function. */ -void* gc_mmap_memalign(unused size_t alignment, size_t n, unused const void* caller) { +inline void* gc_mmap_memalign(unused size_t alignment, size_t n, unused const void* caller) { //printf("gc_mmap_memalign %d %d\n", alignment, n); return gc_mmap_malloc(n, caller); } @@ -480,7 +620,7 @@ void* gc_mmap_memalign(unused size_t alignment, size_t n, unused const void* cal /** * Install the mmap based memory allocation functions. */ -void gc_mmap_init_hook(void) { +inline void gc_mmap_init_hook(void) { __malloc_hook = gc_mmap_malloc; __realloc_hook = gc_mmap_realloc; __free_hook = gc_mmap_free; diff --git a/sca-cpp/trunk/kernel/hash-test.cpp b/sca-cpp/trunk/kernel/hash-test.cpp index 4e6a3654e5..a012cd5ee7 100644 --- a/sca-cpp/trunk/kernel/hash-test.cpp +++ b/sca-cpp/trunk/kernel/hash-test.cpp @@ -30,89 +30,64 @@ namespace tuscany { -bool testCrc32hash() { +const bool testCrc32hash() { const string key("This is a test key"); - unsigned int h = crc32hash(c_str(key), length(key)); + const unsigned int h = crc32hash(c_str(key), length(key)); assert(h != 0); return true; } -bool testTimes33hash() { +const bool testTimes33hash() { const string key("This is a test key"); - unsigned int h = times33hash(c_str(key), length(key)); + const unsigned int h = times33hash(c_str(key), length(key)); assert(h != 0); return true; } -bool testMurmurhash() { +const bool testMurmurhash() { const string key("This is a test key"); - unsigned int h = murmurhash(c_str(key), length(key)); + const unsigned int h = murmurhash(c_str(key), length(key)); assert(h != 0); return true; } -bool testPortablemurmurhash() { +const bool testPortablemurmurhash() { const string key("This is a test key"); - unsigned int h = portablemurmurhash(c_str(key), length(key)); + const unsigned int h = portablemurmurhash(c_str(key), length(key)); assert(h != 0); return true; } -struct crc32hashTest { - const string key; - crc32hashTest(const string& key) : key(key) { - } - bool operator()() const { - unsigned int h = crc32hash(c_str(key), length(key)); +const bool testHashPerf() { + const string key("This is a test key"); + const int count = 100000; + + const blambda crc32 = [key]() -> const bool { + const unsigned int h = crc32hash(c_str(key), length(key)); assert(h != 0); return true; - } -}; - -struct times33hashTest { - const string key; - times33hashTest(const string& key) : key(key) { - } - bool operator()() const { - unsigned int h = times33hash(c_str(key), length(key)); + }; + cout << "crc32hash test " << time(crc32, 5, count) << " ms" << endl; + + const blambda times33 = [key]() -> const bool { + const unsigned int h = times33hash(c_str(key), length(key)); assert(h != 0); return true; - } -}; - -struct murmurhashTest { - const string key; - murmurhashTest(const string& key) : key(key) { - } - bool operator()() const { - unsigned int h = murmurhash(c_str(key), length(key)); + }; + cout << "times33hash test " << time(times33, 5, count) << " ms" << endl; + + const blambda murmur = [key]() -> const bool { + const unsigned int h = murmurhash(c_str(key), length(key)); assert(h != 0); return true; - } -}; - -struct portablemurmurhashTest { - const string key; - portablemurmurhashTest(const string& key) : key(key) { - } - bool operator()() const { - unsigned int h = portablemurmurhash(c_str(key), length(key)); + }; + cout << "murmurhash test " << time(murmur, 5, count) << " ms" << endl; + + const blambda portablemurmur = [key]() -> const bool { + const unsigned int h = portablemurmurhash(c_str(key), length(key)); assert(h != 0); return true; - } -}; - -bool testHashPerf() { - const string key("This is a test key"); - const int count = 100000; - - const lambda<bool()> crc32 = crc32hashTest(key); - cout << "crc32hash test " << time(crc32, 5, count) << " ms" << endl; - const lambda<bool()> times33 = times33hashTest(key); - cout << "times33hash test " << time(times33, 5, count) << " ms" << endl; - const lambda<bool()> murmur = murmurhashTest(key); - cout << "murmurhash test " << time(murmur, 5, count) << " ms" << endl; - const lambda<bool()> portablemurmur = portablemurmurhashTest(key); + }; cout << "portable murmurhash test " << time(portablemurmur, 5, count) << " ms" << endl; return true; @@ -121,7 +96,7 @@ bool testHashPerf() { } int main() { - tuscany::gc_scoped_pool p; + const tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::testCrc32hash(); diff --git a/sca-cpp/trunk/kernel/hash.hpp b/sca-cpp/trunk/kernel/hash.hpp index 993511e3c2..9e80c977fe 100644 --- a/sca-cpp/trunk/kernel/hash.hpp +++ b/sca-cpp/trunk/kernel/hash.hpp @@ -43,7 +43,7 @@ namespace tuscany * tree at contrib/ltree/crc32.[ch] and from FreeBSD at * src/usr.bin/cksum/crc32.c. */ -const unsigned int crc32hash(const char* data, const size_t len) { +inline const unsigned int crc32hash(const char* const data, const size_t len) { return (unsigned int)apr_memcache_hash_default(NULL, data, len); } @@ -89,7 +89,7 @@ const unsigned int crc32hash(const char* data, const size_t len) { * * -- Ralf S. Engelschall <rse@engelschall.com> */ -const unsigned int times33hash(const char* data, const size_t len) { +inline const unsigned int times33hash(const char* const data, const size_t len) { apr_ssize_t l = len; return apr_hashfunc_default(data, &l); } @@ -107,7 +107,7 @@ const unsigned int times33hash(const char* data, const size_t len) { * Passes Bob Jenkin's frog.c torture-test. No collisions possible for 4 byte * keys, no small 1 to 7 bit differentials. */ -const unsigned int murmurhash(const char* key, const size_t klen) { +inline const unsigned int murmurhash(const char* const key, const size_t klen) { unsigned int len = (unsigned int)klen; const unsigned int seed = 0; @@ -153,7 +153,7 @@ const unsigned int murmurhash(const char* key, const size_t klen) { * An endian and alignment neutral, but half the speed, version of * the murmur hash. */ -const unsigned int portablemurmurhash(const char* key, const size_t klen) { +inline const unsigned int portablemurmurhash(const char* const key, const size_t klen) { unsigned int len = (unsigned int)klen; const unsigned int seed = 0; @@ -199,7 +199,7 @@ const unsigned int portablemurmurhash(const char* key, const size_t klen) { return h; } -const unsigned int hashselect(const unsigned int hash, const unsigned int max) { +inline const unsigned int hashselect(const unsigned int hash, const unsigned int max) { return hash % max; } diff --git a/sca-cpp/trunk/kernel/kernel-test.cpp b/sca-cpp/trunk/kernel/kernel-test.cpp index 4d2ca2ba81..0e2a14246a 100644 --- a/sca-cpp/trunk/kernel/kernel-test.cpp +++ b/sca-cpp/trunk/kernel/kernel-test.cpp @@ -23,6 +23,7 @@ * Test kernel functions. */ +#include <functional> #include <assert.h> #include "string.hpp" #include "sstream.hpp" @@ -36,58 +37,324 @@ namespace tuscany { -struct inc { - int i; - inc(int i) : +const bool ptrPerf() { + int x = 1; + for (int i = 0; i < 10000; i++) { + int* const y = &x; + int z = *y + *y; + z = z + 1; + } + return true; +} + +const bool gcptrPerf() { + int x = 1; + for (int i = 0; i < 10000; i++) { + const gc_ptr<int> y = &x; + int z = *y + *y; + z = z + 1; + } + return true; +} + +const bool testPtrPerf() { + { + const gc_scoped_pool gcp; + const blambda pp = ptrPerf; + cout << "Pointer test " << (time(pp, 5, 10000) / 10000) << " ms" << endl; + } + { + const gc_scoped_pool gcp; + const blambda gpp = gcptrPerf; + cout << "GC Pointer test " << (time(gpp, 5, 10000) / 10000) << " ms" << endl; + } + return true; +} + +class incFunctor { +public: + incFunctor(const int i) : i(i) { } const int operator()(const int x) const { return x + i; } +private: + const int i; }; const int square(const int x) { return x * x; } -int mapLambda(lambda<int(const int)> f, int v) { +const int mapLambda(lambda<const int(const int)> f, int v) { return f(v); } -bool testLambda() { - const lambda<int(const int)> sq(square); +const lambda<const int(const int)> mksquare() { + return square; +} + +const bool testSizes() { + const gc_ptr<int> p(NULL); + cout << "sizeof gc_ptr " << sizeof(p) << endl; + const lambda<const int(const int)> sq(square); + cout << "sizeof C function lambda " << sizeof(sq) << endl; + const lambda<const int(const int)> incl(incFunctor(10)); + cout << "sizeof functor lambda " << sizeof(incl) << endl; + const std::function<int(const int)> sqf(square); + cout << "sizeof C function std::function " << sizeof(sqf) << endl; + const std::function<int(const int)> incf(incFunctor(10)); + cout << "sizeof functor std::function " << sizeof(incf) << endl; + const string s("abcd"); + cout << "sizeof string " << sizeof(s) << endl; + const string v(s); + cout << "sizeof val " << sizeof(v) << endl; + const list<int> li = cons<int>(2, mklist<int>(3, 4)); + cout << "sizeof list<int> " << sizeof(li) << endl; + const list<string> ls = cons<string>("a", mklist<string>("b", "c")); + cout << "sizeof list<string> " << sizeof(ls) << endl; + const list<value> lv = cons<value>("a", mklist<value>("b", "c")); + cout << "sizeof list<value> " << sizeof(lv) << endl; + return true; +} + +const bool testLambda() { + const lambda<const int(const int)> sq(square); assert(sq(2) == 4); + + const lambda<const lambda<const int(const int)>()> mksq(mksquare); + assert(mksq()(2) == 4); + assert(mapLambda(sq, 2) == 4); assert(mapLambda(square, 2) == 4); - const lambda<int(const int)> incf(inc(10)); + const lambda<const int(const int)> incf(incFunctor(10)); assert(incf(1) == 11); assert(mapLambda(incf, 1) == 11); - assert(mapLambda(inc(10), 1) == 11); + assert(mapLambda(incFunctor(10), 1) == 11); + + const int base = 10; + auto incl11 = [base](const int i) { return base + i; }; + const lambda<const int(const int)> incl(incl11); + assert(incl(1) == 11); + assert(mapLambda(incl, 1) == 11); + assert(mapLambda(incl11, 1) == 11); + + const lambda<const int(const int)> il(incf); + assert(il(1) == 11); + const lambda<const int(const int)> sl(square); + assert(sl(2) == 4); + return true; +} + +int constructCopiable = 0; +int copyCopiable = 0; + +class Copiable { +public: + Copiable() { + assert(false); + } + + Copiable(const string& s) : s(s) { + constructCopiable++; + } + + Copiable(const Copiable& c) : s(c.s) { + copyCopiable++; + } + + Copiable& operator=(const Copiable& c) = delete; + + ~Copiable() { + } + + void doit() const { + } + +private: + const string s; +}; + +bool testLambdaRef(const Copiable& c) { + [&c] { c.doit(); }(); + return true; +} + +bool testLambdaCopy(const Copiable& c) { + [c] { c.doit(); }(); + return true; +} + +const bool testCopiable() { + const Copiable ac = Copiable("assigned"); + ac.doit(); + assert(constructCopiable = 1); + assert(copyCopiable = 1); + + const Copiable ac2 = []{ return Copiable("returned"); }(); + ac2.doit(); + assert(constructCopiable = 2); + assert(copyCopiable = 2); + + const Copiable rc = Copiable("captured by ref"); + testLambdaRef(rc); + assert(constructCopiable = 3); + assert(copyCopiable = 3); + + const Copiable cc = Copiable("captured by value"); + testLambdaCopy(cc); + assert(constructCopiable = 4); + assert(copyCopiable = 5); - lambda<int(const int)> l; - l = incf; - assert(l(1) == 11); - l = square; - assert(l(2) == 4); return true; } -bool testLambdaGC() { +const bool testMutable() { + { + gc_mutable_ref<string> s = string("aaa"); + s = "bbb"; + assert(s == "bbb"); + } + { + gc_mutable_ref<string> s; + assert(s == ""); + s = "bbb"; + assert(s == "bbb"); + } + { + gc_mutable_ref<value> v; + assert(isNil((value)v)); + v = 1; + assert(v == 1); + } + return true; +} + +const bool testLambdaGC() { resetLambdaCounters(); { - gc_scoped_pool gc; + const gc_scoped_pool gcp; testLambda(); } assert(checkLambdaCounters()); return true; } -int countElements = 0; +class sint { +public: + sint(const int i) : i(i) { + } + const int i; + char b[4]; +}; -struct Element { - int i; +const int mult(const sint& a, const sint& b) { + return a.i * b.i; +} + +const bool testCurry() { + const lambda<const int(const sint)> mult2 = curry((lambda<const int(const sint, const sint)>)mult, sint(2)); + assert(6 == mult2(sint(3))); + return true; +} + +const bool curryPerf() { + const sint a(2); + const sint b(3); + const lambda<const int(const sint)> mult2 = curry((lambda<const int(const sint, const sint)>)mult, a); + for(int i = 0; i < 1000; i++) + mult2(b); + return true; +} + +class multFunctor { +public: + multFunctor(const sint& a) : a(a) { + } + const int operator()(const sint& b) const { + return a.i * b.i; + } +private: + const sint a; +}; + +const bool testFunctor() { + const lambda<const int(const sint)> mult2 = multFunctor(sint(2)); + assert(6 == mult2(sint(3))); + return true; +} + +const bool functorPerf() { + const sint a(2); + const sint b(3); + const lambda<const int(const sint)> mult2 = lambda<const int(const sint)>(multFunctor(a)); + for(int i = 0; i < 1000; i++) + mult2(b); + return true; +} + +const bool test11Lambda() { + const sint a(2); + assert(6 == [a](const sint& b) { return a.i * b.i; } (sint(3))); + return true; +} + +const lambda<const sint(const sint)> multlambda11(const sint& a) { + return [a](const sint& b) { return a.i * b.i; }; +} + +const bool lambda11Perf() { + const sint a(2); + const sint b(3); + const lambda<const sint(const sint)> mult2 = multlambda11(a); + for(int i = 0; i < 1000; i++) + mult2(b); + return true; +} + +const std::function<sint(const sint&)> multfunction11(const sint& a) { + return [a](const sint& b) { return a.i * b.i; }; +} + +const bool function11Perf() { + const sint a(2); + const sint b(3); + const std::function<sint(const sint&)> mult2 = multfunction11(a); + for(int i = 0; i < 1000; i++) + mult2(b); + return true; +} + +const bool testFuncPerf() { + { + const gc_scoped_pool gcp; + const blambda cp = curryPerf; + cout << "Curry test " << (time(cp, 5, 1000) / 1000) << " ms" << endl; + } + { + const gc_scoped_pool gcp; + const blambda fp = functorPerf; + cout << "Functor test " << (time(fp, 5, 1000) / 1000) << " ms" << endl; + } + { + const gc_scoped_pool gcp; + const blambda lp = lambda11Perf; + cout << "Lambda11 test " << (time(lp, 5, 1000) / 1000) << " ms" << endl; + } + { + const gc_scoped_pool gcp; + const blambda lp = function11Perf; + cout << "Function11 test " << (time(lp, 5, 1000) / 1000) << " ms" << endl; + } + return true; +} +int countElements = 0; + +class Element { +public: Element() : i(0) { countElements++; } @@ -107,13 +374,16 @@ struct Element { const bool operator==(const Element& o) const { return o.i == i; } + + int i; }; + ostream& operator<<(ostream& out, const Element& v) { out << v.i ; return out; } -bool testCons() { +const bool testCons() { assert(car(cons(2, mklist(3))) == 2); assert(car(cdr(cons(2, mklist(3)))) == 3); assert(isNil(cdr(cdr(cons(2, mklist(3)))))); @@ -122,12 +392,12 @@ bool testCons() { return true; } -bool testListGC() { +const bool testListGC() { resetLambdaCounters(); resetListCounters(); countElements = 0; { - gc_scoped_pool gc; + const gc_scoped_pool gcp; testCons(); } assert(checkLambdaCounters()); @@ -136,7 +406,41 @@ bool testListGC() { return true; } -bool testOut() { +template<typename T> const list<T> listPerf(const T& v, const long int i) { + if (i == 0) + return list<T>(); + return cons<T>(v, listPerf<T>(v, i -1)); +} + +const bool testListPerf() { + { + const gc_scoped_pool gcp; + const blambda lp = []() -> const bool { + listPerf<int>(0, 1000); + return true; + }; + cout << "List<int> test " << (time(lp, 5, 1000) / 1000) << " ms" << endl; + } + { + const gc_scoped_pool gcp; + const blambda lp = []() -> const bool { + listPerf<string>(string("x"), 1000); + return true; + }; + cout << "List<string> test " << (time(lp, 5, 1000) / 1000) << " ms" << endl; + } + { + const gc_scoped_pool gcp; + const blambda lp = []() -> const bool { + listPerf<string>(value("x"), 1000); + return true; + }; + cout << "List<value> test " << (time(lp, 5, 1000) / 1000) << " ms" << endl; + } + return true; +} + +const bool testOut() { ostringstream os1; os1 << list<int> (); assert(str(os1) == "()"); @@ -147,7 +451,7 @@ bool testOut() { return true; } -bool testEquals() { +const bool testEquals() { assert(list<int>() == list<int>()); assert(mklist(1, 2) == mklist(1, 2)); assert(list<int>() != mklist(1, 2)); @@ -156,14 +460,14 @@ bool testEquals() { return true; } -bool testLength() { +const bool testLength() { assert(0 == length(list<int>())); assert(1 == length(mklist(1))); assert(2 == length(cons(1, mklist(2)))); return true; } -bool testAppend() { +const bool testAppend() { assert(car(append(mklist(1), mklist(2))) == 1); assert(car(cdr(append(mklist(1), mklist(2)))) == 2); assert(car(cdr(cdr(append(mklist(1), mklist(2, 3))))) == 3); @@ -173,21 +477,23 @@ bool testAppend() { return true; } -struct Complex { - int x; - int y; - Complex() { +class Complex { +public: + Complex() : x(0), y(0) { } - Complex(int x, int y) : - x(x), y(y) { + Complex(const int x, const int y) : x(x), y(y) { } + + const int x; + const int y; }; + ostream& operator<<(ostream& out, const Complex& v) { out << "[" << v.x << ":" << v.y << "]"; return out; } -bool testComplex() { +const bool testComplex() { const list<Complex> p = mklist(Complex(1, 2), Complex(3, 4)); assert(car(p).x == 1); assert(car(cdr(p)).x == 3); @@ -195,7 +501,7 @@ bool testComplex() { return true; } -bool testMap() { +const bool testMap() { assert(isNil(map<int, int>(square, list<int>()))); const list<int> m = map<int, int>(square, mklist(2, 3)); @@ -209,26 +515,26 @@ const int add(const int x, const int y) { return x + y; } -bool testReduce() { - const lambda<int(const int, const int)> r(add); +const bool testReduce() { + const lambda<const int(const int, const int)> r(add); assert(reduce(r, 0, mklist(1, 2, 3)) == 6); return true; } -bool isPositive(const int x) { +const bool isPositive(const int x) { if(x >= 0) return true; else return false; } -bool testFilter() { +const bool testFilter() { assert(car(filter<int>(isPositive, mklist(1, -1, 2, -2))) == 1); assert(cadr(filter<int>(isPositive, mklist(1, -1, 2, -2))) == 2); return true; } -bool testMember() { +const bool testMember() { assert(isNil(member(4, mklist(1, 2, 3)))); assert(car(member(1, mklist(1, 2, 3))) == 1); assert(car(member(2, mklist(1, 2, 3))) == 2); @@ -236,14 +542,14 @@ bool testMember() { return true; } -bool testReverse() { +const bool testReverse() { assert(isNil(reverse(list<int>()))); assert(car(reverse(mklist(1, 2, 3))) == 3); assert(cadr(reverse(mklist(1, 2, 3))) == 2); return true; } -bool testListRef() { +const bool testListRef() { assert(listRef(mklist(1), 0) == 1); assert(listRef(mklist(1, 2, 3), 0) == 1); assert(listRef(mklist(1, 2, 3), 1) == 2); @@ -251,7 +557,7 @@ bool testListRef() { return true; } -bool testAssoc() { +const bool testAssoc() { const list<list<string> > l = mklist(mklist<string>("x", "X"), mklist<string>("a", "A"), mklist<string>("y", "Y"), mklist<string>("a", "AA")); assert(assoc<string>("a", l) == mklist<string>("a", "A")); assert(isNil(assoc<string>("z", l))); @@ -261,10 +567,13 @@ bool testAssoc() { const list<value> v = mklist<value>(mklist<value>("x", "X"), mklist<value>("a", "A"), mklist<value>("y", "Y"), mklist<value>("a", "AA")); assert(assoc<value>("a", v) == mklist<value>("a", "A")); + + const list<value> v2 = mklist<value>(mklist<value>("x", "X"), "a", mklist<value>("a", "A"), mklist<value>("y", "Y"), mklist<value>("a", "AA")); + assert(assoc<value>("a", v2) == mklist<value>("a", "A")); return true; } -bool testZip() { +const bool testZip() { const list<string> k = mklist<string>("x", "a", "y", "a"); const list<string> v = mklist<string>("X", "A", "Y", "AA"); const list<list<string> > z = mklist(k, v); @@ -274,7 +583,7 @@ bool testZip() { return true; } -bool testTokenize() { +const bool testTokenize() { assert(tokenize("/", "") == list<string>()); assert(tokenize("/", "aaa") == mklist<string>("aaa")); assert(tokenize("/", "aaa/bbb/ccc/ddd") == mklist<string>("aaa", "bbb", "ccc", "ddd")); @@ -292,11 +601,11 @@ bool testTokenize() { return true; } -double testSeqMap(double x) { +const double testSeqMap(const double x) { return x; } -double testSeqReduce(unused double v, double accum) { +double testSeqReduce(unused const double v, const double accum) { return accum + 1.0; } @@ -316,16 +625,16 @@ bool testSeq() { return true; } -value valueSquare(list<value> x) { +const value valueSquare(const list<value>& x) { return (int)car(x) * (int)car(x); } -bool testValue() { - assert(value(true) == value(true)); +const bool testValue() { + assert(value(true) == trueValue); assert(value(1) == value(1)); assert(value("abcd") == value("abcd")); - lambda<value(const list<value>&)> vl(valueSquare); - assert(value(vl) == value(vl)); + lvvlambda vl(valueSquare); + //assert(value(vl) == value(vl)); assert(value(mklist<value>(1, 2)) == value(mklist<value>(1, 2))); const list<value> v = mklist<value>(mklist<value>("x", "X"), mklist<value>("a", "A"), mklist<value>("y", "Y")); @@ -339,12 +648,12 @@ bool testValue() { return true; } -bool testValueGC() { +const bool testValueGC() { resetLambdaCounters(); resetListCounters(); resetValueCounters(); { - gc_scoped_pool gc; + const gc_scoped_pool gcp; testValue(); } assert(checkValueCounters()); @@ -353,8 +662,8 @@ bool testValueGC() { return true; } -bool testTree() { - const list<value> t = mktree<value>("a", list<value>(), list<value>()); +const bool testTree() { + const list<value> t = mktree<value>("a", nilListValue, nilListValue); const list<value> ct = constree<value>("d", constree<value>("f", constree<value>("c", constree<value>("e", constree<value>("b", t))))); const list<value> mt = mktree(mklist<value>("d", "f", "c", "e", "b", "a")); assert(mt == ct); @@ -371,8 +680,8 @@ const list<value> lta(const string& x) { return mklist<value>(c_str(x), c_str(x + x)); } -bool testTreeAssoc() { - const list<value> t = mktree<value>(lta("a"), list<value>(), list<value>()); +const bool testTreeAssoc() { + const list<value> t = mktree<value>(lta("a"), nilListValue, nilListValue); const list<value> at = constree<value>(lta("d"), constree<value>(lta("f"), constree<value>(lta("c"), constree<value>(lta("e"), constree<value>(lta("b"), t))))); const list<value> l = flatten<value>(at); assert(length(l) == 6); @@ -387,58 +696,46 @@ bool testTreeAssoc() { return true; } -double fib_aux(double n, double a, double b) { +const double fib_aux(const double n, const double a, const double b) { if(n == 0.0) return a; return fib_aux(n - 1.0, b, a + b); } -double fib(double n) { +const double fib(const double n) { return fib_aux(n, 0.0, 1.0); } -struct fibMapPerf { - const bool operator()() const { - list<double> s = seq(0.0, 999.0); - list<double> r = map<double, double>(fib, s); - assert(1000 == length(r)); - return true; - } -}; - -struct nestedFibMapPerf { - const lambda<double(const double)> fib; - nestedFibMapPerf(const lambda<double(const double)>& fib) : fib(fib) { - } - const bool operator()() const { - list<double> s = seq(0.0, 999.0); - list<double> r = map<double, double>(fib, s); - assert(1000 == length(r)); - return true; - } -}; +const bool fibMapPerf() { + const list<double> s = seq(0.0, 999.0); + const list<double> r = map<double, double>(fib, s); + assert(1000 == length(r)); + return true; +} -bool testCppPerf() { +const bool testCppPerf() { { - const lambda<bool()> fml = fibMapPerf(); + const gc_scoped_pool gcp; + const blambda fml = fibMapPerf; cout << "Fibonacci map test " << (time(fml, 1, 1) / 1000) << " ms" << endl; } { - struct nested { - static double fib(double n) { - struct nested { - static double fib_aux(double n, double a, double b) { - if(n == 0.0) - return a; - return fib_aux(n - 1.0, b, a + b); - } - }; - return nested::fib_aux(n, 0.0, 1.0); - } + const lambda<const double(const double n)> fib = [](const double n) -> const double { + const lambda<const double(const double, const double, const double)> fib_aux = [&fib_aux](double n, double a, double b) -> const double { + if(n == 0.0) + return a; + return fib_aux(n - 1.0, b, a + b); + }; + return fib_aux(n, 0.0, 1.0); }; - const lambda<bool()> nfml = nestedFibMapPerf(lambda<double(const double)>(nested::fib)); + const blambda nfml = [fib]() -> const bool { + const list<double> s = seq(0.0, 999.0); + const list<double> r = map<double, double>(fib, s); + assert(1000 == length(r)); + return true; + }; cout << "Nested Fibonacci map test " << (time(nfml, 1, 1) / 1000) << " ms" << endl; } return true; @@ -456,7 +753,7 @@ const id<int> idH(const int v) { return idF(v) >> idG; } -bool testIdMonad() { +const bool testIdMonad() { const id<int> m(2); assert(m >> idF == idF(2)); assert(m >> unit<int>() == m); @@ -476,7 +773,7 @@ const maybe<int> maybeH(const int v) { return maybeF(v) >> maybeG; } -bool testMaybeMonad() { +const bool testMaybeMonad() { const maybe<int> m(2); assert(m >> maybeF == maybeF(2)); assert((m >> just<int>()) == m); @@ -498,7 +795,7 @@ const failable<int> failableH(const int v) { return failableF(v) >> failableG; } -bool testFailableMonad() { +const bool testFailableMonad() { const failable<int> m(2); assert(m >> failableF == failableF(2)); assert((m >> success<int, string, int>()) == m); @@ -515,23 +812,16 @@ bool testFailableMonad() { assert(rcode(vooops) == 500); const value v = value(vooops); - assert(car<value>(v) == value()); + assert(car<value>(v) == nilValue); assert(cadr<value>(v) == string("test")); assert(caddr<value>(v) == value((double)500)); return true; } -struct tickInc { - const double v; - tickInc(const double v) : v(v) { - } - const scp<int, double> operator()(int s) const { - return scp<int, double>(s + 1, v); - } -}; - const state<int, double> tick(const double v) { - return transformer<int, double>(tickInc(v)); + return transformer<int, double>([v](const int s) { + return scp<int, double>(s + 1, v); + }); } const state<int, double> stateF(const double v) { @@ -546,8 +836,8 @@ const state<int, double> stateH(const double v) { return stateF(v) >> stateG; } -bool testStateMonad() { - const lambda<state<int, double>(const double)> r(result<int, double>); +const bool testStateMonad() { + const lambda<const state<int, double>(const double)> r(result<int, double>); state<int, double> m = result<int, double>(2.0); assert((m >> stateF)(0) == stateF(2.0)(0)); @@ -558,30 +848,40 @@ bool testStateMonad() { return true; } -bool testDynLib() { +const bool testDynLib() { const lib dl(string("./libdynlib-test") + dynlibExt); - const failable<lambda<int(const int)> > sq(dynlambda<int(const int)>("csquare", dl)); + const failable<lambda<const int(const int)> > sq(dynlambda<const int(const int)>("csquare", dl)); assert(hasContent(sq)); - lambda<int(const int)> l(content(sq)); + lambda<const int(const int)> l(content(sq)); assert(l(2) == 4); - const failable<lambda<lambda<int(const int)>()> > sql(dynlambda<lambda<int(const int)>()>("csquarel", dl)); + const failable<lambda<const lambda<const int(const int)>()> > sql(dynlambda<const lambda<const int(const int)>()>("csquarel", dl)); assert(hasContent(sql)); - lambda<lambda<int(const int)>()> ll(content(sql)); + lambda<const lambda<const int(const int)>()> ll(content(sql)); assert(ll()(3) == 9); return true; } + } int main() { - tuscany::gc_scoped_pool p; + const tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; + tuscany::testSizes(); + tuscany::testCopiable(); + tuscany::testMutable(); + tuscany::testPtrPerf(); tuscany::testLambda(); tuscany::testLambdaGC(); + tuscany::testCurry(); + tuscany::testFunctor(); + tuscany::test11Lambda(); + tuscany::testFuncPerf(); tuscany::testCons(); tuscany::testListGC(); + tuscany::testListPerf(); tuscany::testOut(); tuscany::testEquals(); tuscany::testLength(); diff --git a/sca-cpp/trunk/kernel/lambda-test.cpp b/sca-cpp/trunk/kernel/lambda-test.cpp index 05a16c2eb8..81f17a57b0 100644 --- a/sca-cpp/trunk/kernel/lambda-test.cpp +++ b/sca-cpp/trunk/kernel/lambda-test.cpp @@ -34,7 +34,7 @@ namespace tuscany { #ifdef HAS_CXX0X_LAMBDAS const lambda<const int(const int)> inc(const int i) { - return [=](const int x)->const int { + return [i](const int x)->const int { return x + i; }; } @@ -43,27 +43,26 @@ const int square(const int x) { return x * x; } -int mapLambda(const lambda<const int(const int)> f, int v) { +const int mapLambda(const lambda<const int(const int)> f, int v) { return f(v); } -bool testLambda() { +const bool testLambda() { const lambda<const int(const int)> sq = square; assert(sq(2) == 4); assert(mapLambda(square, 2) == 4); assert(mapLambda(sq, 2) == 4); assert(mapLambda([](const int x)->const int { return x * x; }, 2) == 4); - const lambda<int(int)> incf = inc(10); + const lambda<const int(const int)> incf = inc(10); assert(incf(1) == 11); assert(mapLambda(incf, 1) == 11); assert(mapLambda(inc(10), 1) == 11); - lambda<const int(const int)> l; - l = incf; - assert(l(1) == 11); - l = square; - assert(l(2) == 4); + const lambda<const int(const int)> il(incf); + assert(il(1) == 11); + const lambda<const int(const int)> sl(square); + assert(sl(2) == 4); return true; } @@ -72,13 +71,13 @@ const double fib_aux(const double n, const double a, const double b) { } const bool fibMapPerf() { - list<double> s = seq(0.0, 4999.0); - list<double> r = map<double, double>([](const double n)->const double { return fib_aux(n, 0.0, 1.0); }, s); + const list<double> s = seq(0.0, 4999.0); + const list<double> r = map<double, double>([](const double n)->const double { return fib_aux(n, 0.0, 1.0); }, s); assert(5000 == length(r)); return true; } -bool testCppPerf() { +const bool testCppPerf() { cout << "Fibonacci map test " << (time([]()->const bool { return fibMapPerf(); }, 1, 1) / 5000) << " ms" << endl; return true; } @@ -87,7 +86,7 @@ bool testCppPerf() { } int main() { - tuscany::gc_scoped_pool p; + const tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; #ifdef HAS_CXX0X_LAMBDAS diff --git a/sca-cpp/trunk/kernel/list.hpp b/sca-cpp/trunk/kernel/list.hpp index d3736de62c..16a0649fe9 100644 --- a/sca-cpp/trunk/kernel/list.hpp +++ b/sca-cpp/trunk/kernel/list.hpp @@ -43,16 +43,16 @@ long countILists = 0; long countCLists = 0; long countELists = 0; -bool resetListCounters() { +inline const bool resetListCounters() { countLists = countILists = countCLists = countELists = 0; return true; } -bool checkListCounters() { +inline const bool checkListCounters() { return countLists == 0; } -bool printListCounters() { +inline const bool printListCounters() { cout << "countLists " << countLists << endl; cout << "countELists " << countELists << endl; cout << "countILists " << countILists << endl; @@ -91,19 +91,19 @@ bool printListCounters() { template<typename T> class list { public: - list() { + inline list() : car() { debug_inc(countLists); debug_inc(countELists); debug_watchList(); } - list(const T car, const lambda<list<T>()>& cdr) : car(car), cdr(cdr) { + inline list(const T& car, const lambda<list<T>()>& cdr) : car(car), cdr(cdr) { debug_inc(countLists); debug_inc(countILists); debug_watchList(); } - list(const list& p) : car(p.car), cdr(p.cdr) { + inline list(const list& p) : car(p.car), cdr(p.cdr) { debug_inc(countLists); debug_inc(countCLists); #ifdef WANT_MAINTAINER_WATCH @@ -111,22 +111,13 @@ public: #endif } - const list<T>& operator=(const list<T>& p) { - if(this == &p) - return *this; - car = p.car; - cdr = p.cdr; -#ifdef WANT_MAINTAINER_WATCH - watch = p.watch; -#endif - return *this; - } + list<T>& operator=(const list<T>& p) = delete; - ~list() { + inline ~list() { debug_dec(countLists); } - const bool operator==(const list<T>& p) const { + inline const bool operator==(const list<T>& p) const { if(this == &p) return true; if(isNil(cdr)) @@ -140,7 +131,7 @@ public: return cdr() == p.cdr(); } - const bool operator<(const list<T>& p) const { + inline const bool operator<(const list<T>& p) const { if(this == &p) return false; if (isNil(cdr)) @@ -154,7 +145,7 @@ public: return cdr() < p.cdr(); } - const bool operator>(const list<T>& p) const { + inline const bool operator>(const list<T>& p) const { if(this == &p) return false; if (isNil(cdr)) @@ -168,11 +159,11 @@ public: return cdr() > p.cdr(); } - const bool operator!=(const list<T>& p) const { + inline const bool operator!=(const list<T>& p) const { return !this->operator==(p); } - operator const list<list<T> >() const { + inline operator const list<list<T> >() const { return (list<list<T> >)T(*this); } @@ -185,9 +176,10 @@ private: template<typename X> friend const bool isNil(const list<X>& p); template<typename X> friend const X car(const list<X>& p); template<typename X> friend const list<X> cdr(const list<X>& p); + template<typename X> friend const bool setlist(list<X>& target, const list<X>& l); - T car; - lambda<list<T>()> cdr; + const T car; + const lambda<list<T>()> cdr; }; #ifdef WANT_MAINTAINER_WATCH @@ -196,7 +188,7 @@ private: * Debug utility used to write the contents of a list to a string, easier * to watch than the list itself in a debugger. */ -template<typename T> const string watchList(const list<T>& p) { +template<typename T> inline const string watchList(const list<T>& p) { if(isNil(p)) return "()"; odebugstream os; @@ -209,21 +201,21 @@ template<typename T> const string watchList(const list<T>& p) { /** * Returns true if the given list is nil. */ -template<typename T> const bool isNil(const list<T>& p) { +template<typename T> inline const bool isNil(const list<T>& p) { return isNil(p.cdr); } /** * Write a list to an output stream. */ -template<typename T> ostream& writeHelper(ostream& out, const list<T>& l) { +template<typename T> inline ostream& writeHelper(ostream& out, const list<T>& l) { if (isNil(l)) return out; out << " " << car(l); return writeHelper(out, cdr(l)); } -template<typename T> ostream& operator<<(ostream& out, const list<T>& l) { +template<typename T> inline ostream& operator<<(ostream& out, const list<T>& l) { if(isNil(l)) return out << "()"; out << "(" << car(l); @@ -234,74 +226,74 @@ template<typename T> ostream& operator<<(ostream& out, const list<T>& l) { /** * Construct a (lazy) list from a value and a lambda function that returns the cdr. */ -template<typename T> const list<T> cons(const T& car, const lambda<list<T>()>& cdr) { +template<typename T> inline const list<T> cons(const T& car, const lambda<const list<T>()>& cdr) { return list<T> (car, cdr); } /** * Construct a list from a value and a cdr list. */ -template<typename T> const list<T> cons(const T& car, const list<T>& cdr) { +template<typename T> inline const list<T> cons(const T& car, const list<T>& cdr) { return list<T> (car, result(cdr)); } /** * Cons variations for use with the reduce and reduceRight functions. */ -template<typename T> const list<T> lcons(const list<T>& cdr, const T& car) { +template<typename T> inline const list<T> lcons(const list<T>& cdr, const T& car) { return cons<T>(car, cdr); } -template<typename T> const list<T> rcons(const T& car, const list<T>& cdr) { +template<typename T> inline const list<T> rcons(const T& car, const list<T>& cdr) { return cons<T>(car, cdr); } /** * Construct a list of one value. */ -template<typename T> const list<T> mklist(const T& car) { +template<typename T> inline const list<T> mklist(const T& car) { return list<T> (car, result(list<T> ())); } /** * Construct a list of two values. */ -template<typename T> const list<T> mklist(const T& a, const T& b) { +template<typename T> inline const list<T> mklist(const T& a, const T& b) { return cons(a, mklist(b)); } /** * Construct a list of three values. */ -template<typename T> const list<T> mklist(const T& a, const T& b, const T& c) { +template<typename T> inline const list<T> mklist(const T& a, const T& b, const T& c) { return cons(a, cons(b, mklist(c))); } /** * Construct a list of four values. */ -template<typename T> const list<T> mklist(const T& a, const T& b, const T& c, const T& d) { +template<typename T> inline const list<T> mklist(const T& a, const T& b, const T& c, const T& d) { return cons(a, cons(b, cons(c, mklist(d)))); } /** * Construct a list of five values. */ -template<typename T> const list<T> mklist(const T& a, const T& b, const T& c, const T& d, const T& e) { +template<typename T> inline const list<T> mklist(const T& a, const T& b, const T& c, const T& d, const T& e) { return cons(a, cons(b, cons(c, cons(d, mklist(e))))); } /** * Construct a list of six values. */ -template<typename T> const list<T> mklist(const T& a, const T& b, const T& c, const T& d, const T& e, const T& f) { +template<typename T> inline const list<T> mklist(const T& a, const T& b, const T& c, const T& d, const T& e, const T& f) { return cons(a, cons(b, cons(c, cons(d, cons(e, mklist(f)))))); } /** * Returns the car of a list. */ -template<typename T> const T car(const list<T>& p) { +template<typename T> inline const T car(const list<T>& p) { // Abort if trying to access the car of a nil list assertOrFail(!isNil(p.cdr)); return p.car; @@ -310,159 +302,144 @@ template<typename T> const T car(const list<T>& p) { /** * Returns the cdr of a list. */ -template<typename T> const list<T> cdr(const list<T>& p) { +template<typename T> inline const list<T> cdr(const list<T>& p) { return p.cdr(); } /** * Returns the car of the cdr (the 2nd element) of a list. */ -template<typename T> const T cadr(const list<T>& p) { +template<typename T> inline const T cadr(const list<T>& p) { return car(cdr(p)); } /** * Returns the 3rd element of a list. */ -template<typename T> const T caddr(const list<T>& p) { +template<typename T> inline const T caddr(const list<T>& p) { return car(cdr(cdr(p))); } /** * Returns the 4th element of a list. */ -template<typename T> const T cadddr(const list<T>& p) { +template<typename T> inline const T cadddr(const list<T>& p) { return car(cdr(cdr(cdr(p)))); } /** * Returns the 5th element of a list. */ -template<typename T> const T caddddr(const list<T>& p) { +template<typename T> inline const T caddddr(const list<T>& p) { return car(cdr(cdr(cdr(cdr(p))))); } /** * Returns the 6th element of a list. */ -template<typename T> const T cadddddr(const list<T>& p) { +template<typename T> inline const T cadddddr(const list<T>& p) { return car(cdr(cdr(cdr(cdr(cdr(p)))))); } /** * Returns the 7th element of a list. */ -template<typename T> const T caddddddr(const list<T>& p) { +template<typename T> inline const T caddddddr(const list<T>& p) { return car(cdr(cdr(cdr(cdr(cdr(cdr(p))))))); } /** * Returns the 8th element of a list. */ -template<typename T> const T cadddddddr(const list<T>& p) { +template<typename T> inline const T cadddddddr(const list<T>& p) { return car(cdr(cdr(cdr(cdr(cdr(cdr(cdr(p)))))))); } /** * Returns a list of elements from the 3rd to the end of a list. */ -template<typename T> const list<T> cddr(const list<T>& p) { +template<typename T> inline const list<T> cddr(const list<T>& p) { return cdr(cdr(p)); } /** * Returns a list of elements from the 4th to the end of a list. */ -template<typename T> const list<T> cdddr(const list<T>& p) { +template<typename T> inline const list<T> cdddr(const list<T>& p) { return cdr(cdr(cdr(p))); } /** * Returns a list of elements from the 5th to the end of a list. */ -template<typename T> const list<T> cddddr(const list<T>& p) { +template<typename T> inline const list<T> cddddr(const list<T>& p) { return cdr(cdr(cdr(cdr(p)))); } /** * Returns a list of elements from the 6th to the end of a list. */ -template<typename T> const list<T> cdddddr(const list<T>& p) { +template<typename T> inline const list<T> cdddddr(const list<T>& p) { return cdr(cdr(cdr(cdr(cdr(p))))); } /** * Returns a list of elements from the 7th to the end of a list. */ -template<typename T> const list<T> cddddddr(const list<T>& p) { +template<typename T> inline const list<T> cddddddr(const list<T>& p) { return cdr(cdr(cdr(cdr(cdr(cdr(p)))))); } /** * Returns a list of elements from the 8th to the end of a list. */ -template<typename T> const list<T> cdddddddr(const list<T>& p) { +template<typename T> inline const list<T> cdddddddr(const list<T>& p) { return cdr(cdr(cdr(cdr(cdr(cdr(cdr(p))))))); } /** * Returns the length of a list. */ -template<typename T> struct lengthRef { - const size_t operator()(const size_t c, const list<T>& p) { +template<typename T> inline const size_t length(const list<T>& p) { + const lambda<size_t(const size_t, const list<T>&)> lengthRef = [&lengthRef](const size_t c, const list<T>& p) -> const size_t { if(isNil(p)) return c; - return (*this)(c + 1, cdr(p)); - } -}; - -template<typename T> const size_t length(const list<T>& p) { - return lengthRef<T> ()(0, p); + return lengthRef(c + 1, cdr(p)); + }; + return lengthRef(0, p); } /** * Appends a list and a lambda function returning a list. */ -template<typename T> struct appendCdr { - const list<T> a; - const lambda<list<T>()> fb; - appendCdr(const list<T>& a, const lambda<list<T>()>& fb) : - a(a), fb(fb) { - } - const list<T> operator()() const { - return append(a, fb); - } -}; - -template<typename T> const list<T> append(const list<T>&a, const lambda<list<T>()>& fb) { +template<typename T> inline const list<T> append(const list<T>&a, const lambda<const list<T>()>& fb) { if(isNil(a)) return fb(); - - return cons<T>(car(a), appendCdr<T> (cdr(a), fb)); + return cons<T>(car(a), [a, fb]() { return append(cdr(a), fb); }); } /** * Appends two lists. */ -template<typename T> const list<T> append(const list<T>&a, const list<T>& b) { +template<typename T> inline const list<T> append(const list<T>&a, const list<T>& b) { return append(a, result(b)); } /** * Append a value to a list. */ -template<typename T> const list<T> operator+(const list<T>& l, const T& v) { +template<typename T> inline const list<T> operator+(const list<T>& l, const T& v) { return append(l, mklist(v)); } -template<typename T, typename V> const list<T> operator+(const list<T>& l, const V& v) { +template<typename T, typename V> const list<T> inline operator+(const list<T>& l, const V& v) { return append(l, mklist<T>(v)); } /** * Map a lambda function on a list. */ -template<typename T, typename R> const list<R> map(const lambda<R(const T)>& f, const list<T>& p) { +template<typename T, typename R> inline const list<R> map(const lambda<const R(const T)>& f, const list<T>& p) { if(isNil(p)) return list<R> (); return cons(f(car(p)), map(f, cdr(p))); @@ -471,46 +448,32 @@ template<typename T, typename R> const list<R> map(const lambda<R(const T)>& f, /** * Run a reduce lambda function on a list. */ -template<typename T, typename R> struct reduceAccumulate { - const lambda<R(const R&, const T&)> f; - reduceAccumulate(const lambda<R(const R, const T)>& f) : - f(f) { - } - R operator()(const R& acc, const list<T>& p) const { +template<typename T, typename R> inline const R reduce(const lambda<const R(const R, const T)>& f, const R& initial, const list<T>& p) { + const lambda<const R(const R&, const list<T>&p)> reduceAccumulate = [f, &reduceAccumulate](const R& acc, const list<T>& p) -> R { if(isNil(p)) return acc; - return (*this)(f(acc, car(p)), cdr(p)); - } -}; - -template<typename T, typename R> const R reduce(const lambda<R(const R, const T)>& f, const R& initial, const list<T>& p) { - return reduceAccumulate<T, R> (f)(initial, p); + return reduceAccumulate(f(acc, car(p)), cdr(p)); + }; + return reduceAccumulate(initial, p); } -template<typename T, typename R> struct reduceRightAccumulate { - const lambda<R(const T&, const R&)> f; - reduceRightAccumulate(const lambda<R(const T, const R)>& f) : - f(f) { - } - R operator()(const list<T>& p, const R& acc) const { +template<typename T, typename R> inline const R reduceRight(const lambda<const R(const T, const R)>& f, const R& initial, const list<T>& p) { + const lambda<const R(const list<T>&p, const R&)> reduceRightAccumulate = [f, &reduceRightAccumulate](const list<T>& p, const R& acc) -> R { if(isNil(p)) return acc; - return (*this)(cdr(p), f(car(p), acc)); - } -}; - -template<typename T, typename R> const R reduceRight(const lambda<R(const T, const R)>& f, const R& initial, const list<T>& p) { - return reduceRightAccumulate<T, R> (f)(p, initial); + return reduceRightAccumulate(cdr(p), f(car(p), acc)); + }; + return reduceRightAccumulate(p, initial); } /** * Run a filter lambda function on a list. */ -template<typename T> const list<T> filter(const lambda<bool(const T)>& f, const list<T>& p) { +template<typename T> inline const list<T> filter(const lambda<const bool(const T)>& f, const list<T>& p) { if(isNil(p)) return list<T> (); if(f(car(p))) { - const lambda<list<T>(const lambda<bool(const T)>, const list<T>)> ff(filter<T>); + const lambda<const list<T>(const lambda<const bool(const T)>, const list<T>)> ff(filter<T>); return cons(car(p), curry(ff, f, cdr(p))); } return filter(f, cdr(p)); @@ -519,7 +482,7 @@ template<typename T> const list<T> filter(const lambda<bool(const T)>& f, const /** * Returns a list pointing to a member of a list. */ -template<typename T> const list<T> member(const T& t, const list<T>& p) { +template<typename T> inline const list<T> member(const T& t, const list<T>& p) { if(isNil(p)) return list<T> (); if(t == car(p)) @@ -530,44 +493,31 @@ template<typename T> const list<T> member(const T& t, const list<T>& p) { /** * Reverse a list. */ -template<typename T> const list<T> reverseIter(const list<T>& acc, const list<T>& p) { +template<typename T> inline const list<T> reverseIter(const list<T>& acc, const list<T>& p) { if(isNil(p)) return acc; return reverseIter(cons(car(p), acc), cdr(p)); } -template<typename T> const list<T> reverse(const list<T>& p) { +template<typename T> inline const list<T> reverse(const list<T>& p) { return reverseIter(list<T> (), p); } -template<typename T> const list<T> seq(const T& start, const T& end); - -template<typename T> struct seqGenerate { - const T start; - const T end; - seqGenerate(const T& start, const T&end) : - start(start), end(end) { - } - const list<T> operator()() const { - return seq<T> (start, end); - } -}; - /** * Returns a sequence of values between the given bounds. */ -template<typename T> const list<T> seq(const T& start, const T& end) { +template<typename T> inline const list<T> seq(const T& start, const T& end) { if(start == end) return mklist(start); if(start < end) - return cons<T>(start, seqGenerate<T> (start + 1, end)); - return cons<T>(start, seqGenerate<T> (start - 1, end)); + return cons<T>(start, [start, end] { return seq<T> (start + 1, end); }); + return cons<T>(start, [start, end] { return seq<T> (start - 1, end); }); } /** * Returns the i-th element of a list. */ -template<typename T> const T listRef(const list<T>& l, const size_t i) { +template<typename T> inline const T listRef(const list<T>& l, const size_t i) { if (i == 0) return car(l); return listRef(cdr(l), i - 1); @@ -576,7 +526,7 @@ template<typename T> const T listRef(const list<T>& l, const size_t i) { /** * Returns the first pair matching a key from a list of key value pairs. */ -template<typename T> const list<T> assoc(const T& k, const list<list<T> >& p) { +template<typename T> inline const list<T> assoc(const T& k, const list<list<T> >& p) { if(isNil(p)) return list<T> (); if(k == car(car(p))) @@ -587,7 +537,7 @@ template<typename T> const list<T> assoc(const T& k, const list<list<T> >& p) { /** * Returns a list of lists containing elements from two input lists. */ -template<typename T> const list<list<T> > zip(const list<T>& a, const list<T>& b) { +template<typename T> inline const list<list<T> > zip(const list<T>& a, const list<T>& b) { if (isNil(a) || isNil(b)) return list<list<T> >(); return cons<list<T> >(mklist<T>(car(a), car(b)), zip(cdr(a), cdr(b))); @@ -596,19 +546,19 @@ template<typename T> const list<list<T> > zip(const list<T>& a, const list<T>& b /** * Converts a list of key value pairs to a list containing the list of keys and the list of values. */ -template<typename T> const list<T> unzipKeys(const list<list<T> >& l) { +template<typename T> inline const list<T> unzipKeys(const list<list<T> >& l) { if (isNil(l)) return list<T>(); return cons(car(car(l)), unzipKeys(cdr(l))); } -template<typename T> const list<T> unzipValues(const list<list<T> >& l) { +template<typename T> inline const list<T> unzipValues(const list<list<T> >& l) { if (isNil(l)) return list<T>(); return cons(cadr(car(l)), unzipValues(cdr(l))); } -template<typename T> const list<list<T> > unzip(const list<list<T> >& l) { +template<typename T> inline const list<list<T> > unzip(const list<list<T> >& l) { return mklist<list<T> >(unzipKeys(l), unzipValues(l)); } diff --git a/sca-cpp/trunk/kernel/mem-test.cpp b/sca-cpp/trunk/kernel/mem-test.cpp index 668dabe749..2072da9f68 100644 --- a/sca-cpp/trunk/kernel/mem-test.cpp +++ b/sca-cpp/trunk/kernel/mem-test.cpp @@ -43,7 +43,7 @@ public: maxElements = countElements; } - Element(int i) : i(i) { + Element(const int i) : i(i) { countElements++; if (countElements > maxElements) maxElements = countElements; @@ -66,7 +66,7 @@ public: private: friend ostream& operator<<(ostream& out, const Element& v); - int i; + const int i; char c[20]; }; @@ -75,14 +75,14 @@ ostream& operator<<(ostream& out, const Element& v) { return out; } -bool poolAlloc(Element** p, const int count) { +const bool poolAlloc(Element** const p, const int count) { if (count == 0) return true; p[count - 1] = new (gc_new<Element>()) Element(); return poolAlloc(p, count - 1); }; -bool poolFree(Element** p, const int count) { +bool poolFree(Element** const p, const int count) { if (count == 0) return true; // Do nothing to free the element, but cycle through them just @@ -90,21 +90,14 @@ bool poolFree(Element** p, const int count) { return poolFree(p, count - 1); }; -struct poolAllocPerf { - const int n; - Element** p; - poolAllocPerf(const int n) : n(n), p(new Element*[n]) { - } - const bool operator()() const { - gc_scoped_pool gc; - poolAlloc(p, n); - return true; - } -}; - -bool testPoolAllocPerf() { +const bool testPoolAllocPerf() { const int count = 10000; - const lambda<bool()> pl = poolAllocPerf(count); + Element** const elements = new Element*[count]; + const blambda pl = [elements, count]() -> const bool { + const gc_scoped_pool gc; + poolAlloc(elements, count); + return true; + }; maxElements = 0; cout << "Memory pool alloc test " << (time(pl, 1, 1) / count) << " ms" << endl; assert(countElements == 0); @@ -112,35 +105,28 @@ bool testPoolAllocPerf() { return true; } -bool stdAlloc(Element** p, const int count) { +const bool stdAlloc(Element** const p, const int count) { if (count == 0) return true; p[count - 1] = new Element(); return stdAlloc(p, count - 1); }; -bool stdFree(Element** p, const int count) { +const bool stdFree(Element** const p, const int count) { if (count == 0) return true; delete p[count -1]; return stdFree(p, count - 1); }; -struct stdAllocPerf { - const int n; - Element** p; - stdAllocPerf(const int n) : n(n), p(new Element*[n]) { - } - const bool operator()() const { - stdAlloc(p, n); - stdFree(p, n); - return true; - } -}; - -bool testStdAllocPerf() { +const bool testStdAllocPerf() { const int count = 10000; - const lambda<bool()> sl = stdAllocPerf(count); + Element** const elements = new Element*[count]; + const blambda sl = [elements, count]() -> const bool { + stdAlloc(elements, count); + stdFree(elements, count); + return true; + }; maxElements = 0; cout << "Memory standard alloc test " << (time(sl, 1, 1) / count) << " ms" << endl; assert(countElements == 0); @@ -151,7 +137,7 @@ bool testStdAllocPerf() { } int main() { - tuscany::gc_scoped_pool p; + const 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 b67e92ad79..de79780e7a 100644 --- a/sca-cpp/trunk/kernel/monad.hpp +++ b/sca-cpp/trunk/kernel/monad.hpp @@ -26,8 +26,11 @@ * Simple monad implementations. */ +#ifdef WANT_MAINTAINER_BACKTRACE #include <execinfo.h> #include <cxxabi.h> +#endif + #include "function.hpp" #include "string.hpp" #include "stream.hpp" @@ -43,21 +46,16 @@ namespace tuscany */ template<typename V> class id { public: - id(const V& v) : v(v) { + inline id(const V& v) : v(v) { } - const id<V>& operator=(const id<V>& m) { - if(this == &m) - return *this; - v = m.v; - return *this; - } + id<V>& operator=(const id<V>& m) = delete; - const bool operator!=(const id<V>& m) const { + inline const bool operator!=(const id<V>& m) const { return !this->operator==(m); } - const bool operator==(const id<V>& m) const { + inline const bool operator==(const id<V>& m) const { if (&m == this) return true; return v == m.v; @@ -72,7 +70,7 @@ private: /** * Write an identity monad to a stream. */ -template<typename V> ostream& operator<<(ostream& out, const id<V>& m) { +template<typename V> inline ostream& operator<<(ostream& out, const id<V>& m) { out << content(m); return out; } @@ -80,29 +78,29 @@ template<typename V> ostream& operator<<(ostream& out, const id<V>& m) { /** * Returns the content of an identity monad. */ -template<typename V> const V content(const id<V>& m) { +template<typename V> inline const V content(const id<V>& m) { return m.v; } /** * Return an identity monad from a value. */ -template<typename V> const id<V> mkunit(const V& v) { +template<typename V> inline const id<V> mkunit(const V& v) { return id<V>(v); } -template<typename V> const lambda<id<V>(const V)> unit() { +template<typename V> inline const lambda<const id<V>(const V)> unit() { return mkunit<V>; } /** * Bind a function to an identity monad. Pass the value in the monad to the function. */ -template<typename R, typename V> const id<R> operator>>(const id<V>& m, const lambda<id<R>(const V)>& f) { +template<typename R, typename V> inline const id<R> operator>>(const id<V>& m, const lambda<const id<R>(const V)>& f) { return f(content(m)); } -template<typename R, typename V> const id<R> operator>>(const id<V>& m, const id<R> (* const f)(const V)) { +template<typename R, typename V> inline const id<R> operator>>(const id<V>& m, const id<R> (* const f)(const V)) { return f(content(m)); } @@ -112,26 +110,22 @@ template<typename R, typename V> const id<R> operator>>(const id<V>& m, const id */ template<typename V> class maybe { public: - maybe(const V& v) : hasv(true), v(v) { + inline maybe(const V& v) : hasv(true), v(v) { } - maybe() : hasv(false) { + inline maybe() : hasv(false), v() { } - const maybe<V>& operator=(const maybe<V>& m) { - if(this == &m) - return *this; - hasv = m.hasv; - if (hasv) - v = m.v; - return *this; + inline maybe(const maybe<V>& m) : hasv(m.hasv), v(m.v) { } - const bool operator!=(const maybe<V>& m) const { + maybe<V>& operator=(const maybe<V>& m) = delete; + + inline const bool operator!=(const maybe<V>& m) const { return !this->operator==(m); } - const bool operator==(const maybe<V>& m) const { + inline const bool operator==(const maybe<V>& m) const { if (this == &m) return true; if (!hasv) @@ -141,7 +135,7 @@ public: private: const bool hasv; - V v; + const V v; template<typename X> friend const bool hasContent(const maybe<X>& m); template<typename X> friend const X content(const maybe<X>& m); @@ -150,7 +144,7 @@ private: /** * Write a maybe monad to a stream. */ -template<typename V> ostream& operator<<(ostream& out, const maybe<V>& m) { +template<typename V> inline ostream& operator<<(ostream& out, const maybe<V>& m) { if (!hasContent(m)) { out << "nothing"; return out; @@ -162,25 +156,25 @@ template<typename V> ostream& operator<<(ostream& out, const maybe<V>& m) { /** * Return a maybe monad with a value in it. */ -template<typename V> const maybe<V> mkjust(const V& v) { +template<typename V> inline const maybe<V> mkjust(const V& v) { return maybe<V>(v); } -template<typename V> const lambda<maybe<V>(const V)> just() { +template<typename V> inline const lambda<const maybe<V>(const V)> just() { return mkjust<V>; } /** * Returns true if a maybe monad contains a content. */ -template<typename V> const bool hasContent(const maybe<V>& m) { +template<typename V> inline const bool hasContent(const maybe<V>& m) { return m.hasv; } /** * Returns the content of a maybe monad. */ -template<typename V> const V content(const maybe<V>& m) { +template<typename V> inline const V content(const maybe<V>& m) { return m.v; } @@ -188,13 +182,13 @@ template<typename V> const V content(const maybe<V>& m) { * Bind a function to a maybe monad. Passes the value in the monad to the function * if present, or does nothing if there's no value. */ -template<typename R, typename V> const maybe<R> operator>>(const maybe<V>& m, const lambda<maybe<R>(const V)>& f) { +template<typename R, typename V> inline const maybe<R> operator>>(const maybe<V>& m, const lambda<const maybe<R>(const V)>& f) { if (!hasContent(m)) return m; return f(content(m)); } -template<typename R, typename V> const maybe<R> operator>>(const maybe<V>& m, const maybe<R> (* const f)(const V)) { +template<typename R, typename V> inline const maybe<R> operator>>(const maybe<V>& m, const maybe<R> (* const f)(const V)) { if (!hasContent(m)) return m; return f(content(m)); @@ -207,30 +201,22 @@ template<typename R, typename V> const maybe<R> operator>>(const maybe<V>& m, co */ template<typename V, typename F = string, typename C = int> class failable { public: - failable() : hasv(false), c(-1) { + inline failable() : hasv(false), v(), c(-1) { } - failable(const V& v) : hasv(true), v(v), c(-1) { + inline failable(const V& v) : hasv(true), v(v), c(-1) { } - failable(const failable<V, F, C>& m) : hasv(m.hasv), v(m.v), f(m.f), c(m.c) { + inline failable(const failable<V, F, C>& m) : hasv(m.hasv), v(m.v), f(m.f), c(m.c) { } - const failable<V, F, C>& operator=(const failable<V, F, C>& m) { - if (&m == this) - return *this; - hasv = m.hasv; - v = m.v; - f = m.f; - c = m.c; - return *this; - } + failable<V, F, C>& operator=(const failable<V, F, C>& m) = delete; - const bool operator!=(const failable<V, F, C>& m) const { + inline const bool operator!=(const failable<V, F, C>& m) const { return !this->operator==(m); } - const bool operator==(const failable<V, F, C>& m) const { + inline const bool operator==(const failable<V, F, C>& m) const { if (this == &m) return true; if (!hasv) @@ -239,7 +225,7 @@ public: } private: - failable(const bool hasv, const F& f, const C& c) : hasv(hasv), f(f), c(c) { + inline failable(const bool hasv, const F& f, const C& c) : hasv(hasv), v(), f(f), c(c) { } template<typename A, typename B, typename R> friend const bool hasContent(const failable<A, B, R>& m); @@ -250,16 +236,16 @@ private: template<typename A, typename B> friend const failable<A, B> mkfailure(const B& f, const int c, const bool log); template<typename A> friend const failable<A> mkfailure(); - bool hasv; - V v; - F f; - C c; + const bool hasv; + const V v; + const F f; + const C c; }; /** * Write a failable monad to a stream. */ -template<typename V, typename F, typename C> ostream& operator<<(ostream& out, const failable<V, F, C>& m) { +template<typename V, typename F, typename C> inline ostream& operator<<(ostream& out, const failable<V, F, C>& m) { if (!hasContent(m)) { out << reason(m) << " : " << rcode(m); return out; @@ -271,20 +257,22 @@ template<typename V, typename F, typename C> ostream& operator<<(ostream& out, c /** * Returns a failable monad with a success value in it. */ -template<typename V, typename F, typename C> const failable<V, F, C> mksuccess(const V& v) { +template<typename V, typename F, typename C> inline const failable<V, F, C> mksuccess(const V& v) { return failable<V, F, C>(v); } -template<typename V, typename F, typename C> const lambda<failable<V, F, C>(const V)> success() { +template<typename V, typename F, typename C> inline const lambda<const failable<V, F, C>(const V)> success() { return mksuccess<V, F, C>; } +#ifdef WANT_MAINTAINER_BACKTRACE + /** * Demangle a C++ function name. */ -const string demangleFrame(const char* fun) { +inline const string demangleFrame(const char* fun) { int status; - char* name = abi::__cxa_demangle(fun, 0, 0, &status); + char* const name = abi::__cxa_demangle(fun, 0, 0, &status); if (name == NULL) return fun; const string s = name; @@ -295,12 +283,12 @@ const string demangleFrame(const char* fun) { /** * Format a backtrace frame. */ -const char* formatFrameFile(const char* file) { - const char* s = strrchr(file, '/'); +inline const char* const formatFrameFile(const char* const file) { + const char* const s = strrchr(file, '/'); return s == NULL? file : s + 1; } -const string formatFrame(const char* symbol) { +inline const string formatFrame(const char* const 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 @@ -349,7 +337,7 @@ const string formatFrame(const char* symbol) { /** * Log backtrace frames. */ -const bool logFrames(char** symbols, const int frames, const bool log) { +inline const bool logFrames(char** const symbols, const int frames, const bool log) { if (frames == 0) return true; #ifdef WANT_MAINTAINER_LOG @@ -364,26 +352,30 @@ const bool logFrames(char** symbols, const int frames, const bool log) { /** * Log a backtrace. */ -const bool logBacktrace(void** callstack, const int frames, const bool log) { +inline const bool logBacktrace(void** const callstack, const int frames, const bool log) { char** symbols = backtrace_symbols(callstack, frames); logFrames(symbols, frames, log); free(symbols); return true; } +#endif + /** * Returns a failable monad with a failure in it. */ -template<typename V, typename F, typename C> const failable<V, F, C> mkfailure(const F& f, const C& c, const bool log = true) { +template<typename V, typename F, typename C> inline const failable<V, F, C> mkfailure(const F& f, const C& c, const bool log = true) { #ifdef WANT_MAINTAINER_LOG if (!log) { // Log the failure debug(f, "failable::mkfailure"); +#ifdef WANT_MAINTAINER_BACKTRACE // Log the call stack void* callstack[16]; const int frames = backtrace(callstack, 16); logBacktrace(callstack, frames, log); +#endif } #endif if (log) { @@ -393,63 +385,65 @@ template<typename V, typename F, typename C> const failable<V, F, C> mkfailure(c // Log the failure cfailure << "failable::mkfailure: " << f << " : " << c << endl; +#ifdef WANT_MAINTAINER_BACKTRACE // Print the call stack void* callstack[16]; const int frames = backtrace(callstack, 16); logBacktrace(callstack, frames, log); +#endif } } return failable<V, F, C>(false, f, c); } -template<typename V, typename F> const failable<V, F> mkfailure(const F& f, const int c = -1, const bool log = true) { +template<typename V, typename F> inline const failable<V, F> mkfailure(const F& f, const int c = -1, const bool log = true) { return mkfailure<V, F, int>(f, c, log); } -template<typename V> const failable<V> mkfailure(const char* f, const int c = -1, const bool log = true) { +template<typename V> inline const failable<V> mkfailure(const char* f, const int c = -1, const bool log = true) { return mkfailure<V, string, int>(string(f), c, log); } -template<typename V> const failable<V> mkfailure() { +template<typename V> inline const failable<V> mkfailure() { return failable<V, string>(false, string(), -1); } -template<typename V, typename F, typename C> const lambda<failable<V, F, C>(const V)> failure() { +template<typename V, typename F, typename C> inline const lambda<const failable<V, F, C>(const V)> failure() { return mkfailure<V, F, C>; } /** * Convert a failable of a given type to a failable of another type. */ -template<typename V, typename F, typename C, typename X> const failable<V, F, C> mkfailure(const failable<X, F, C>& f, const bool log = true) { +template<typename V, typename F, typename C, typename X> inline const failable<V, F, C> mkfailure(const failable<X, F, C>& f, const bool log = false) { return mkfailure<V, F, C>(reason(f), rcode(f), log); } /** * Returns true if the monad contains a content. */ -template<typename V, typename F, typename C> const bool hasContent(const failable<V, F, C>& m) { +template<typename V, typename F, typename C> inline const bool hasContent(const failable<V, F, C>& m) { return m.hasv; } /** * Returns the content of a failable monad. */ -template<typename V, typename F, typename C> const V content(const failable<V, F, C>& m) { +template<typename V, typename F, typename C> inline const V content(const failable<V, F, C>& m) { return m.v; } /** * Returns the reason for failure of a failable monad. */ -template<typename V, typename F, typename C> const F reason(const failable<V, F, C>& m) { +template<typename V, typename F, typename C> inline const F reason(const failable<V, F, C>& m) { return m.f; } /** * Returns the reason code for failure of a failable monad. */ -template<typename V, typename F, typename C> const C rcode(const failable<V, F, C>& m) { +template<typename V, typename F, typename C> inline const C rcode(const failable<V, F, C>& m) { return m.c; } @@ -458,14 +452,14 @@ template<typename V, typename F, typename C> const C rcode(const failable<V, F, * if present, or does nothing if there's no value and a failure instead. */ template<typename R, typename FR, typename XR, typename V, typename FV, typename XV> -const failable<R, FR, XR> operator>>(const failable<V, FV, XV>& m, const lambda<failable<R, FR, XR>(const V)>& f) { +inline const failable<R, FR, XR> operator>>(const failable<V, FV, XV>& m, const lambda<const failable<R, FR, XR>(const V)>& f) { if (!hasContent(m)) return m; return f(content(m)); } template<typename R, typename FR, typename XR, typename V, typename FV, typename XV> -const failable<R, FR, XR> operator>>(const failable<V, FV, XV>& m, const failable<R, FR, XR> (* const f)(const V)) { +inline const failable<R, FR, XR> operator>>(const failable<V, FV, XV>& m, const failable<R, FR, XR> (* const f)(const V)) { if (!hasContent(m)) return m; return f(content(m)); @@ -476,30 +470,27 @@ const failable<R, FR, XR> operator>>(const failable<V, FV, XV>& m, const failabl */ template<typename S, typename V> class scp { public: - scp(const S& s, const V& v) : s(s), v(v) { + inline scp(const S& s, const V& v) : s(s), v(v) { } - operator const S() const { + inline operator const S() const { return s; } - operator const V() const { + inline operator const V() const { return v; } - const scp<S, V>& operator=(const scp<S, V>& p) { - if(this == &p) - return *this; - s = p.s; - v = p.v; - return *this; + inline scp(const scp<S, V>& p) : s(p.s), v(p.v) { } - const bool operator!=(const scp<S, V>& p) const { + scp<S, V>& operator=(const scp<S, V>& p) = delete; + + inline const bool operator!=(const scp<S, V>& p) const { return !this->operator==(p); } - const bool operator==(const scp<S, V>& p) const { + inline const bool operator==(const scp<S, V>& p) const { if (this == &p) return true; return s == p.s && v == p.v; @@ -516,14 +507,14 @@ private: /** * Returns the state of a state-content pair. */ -template<typename S, typename V> const S scpstate(const scp<S, V>& m) { +template<typename S, typename V> inline const S scpstate(const scp<S, V>& m) { return m.s; } /** * Returns the content of a state-content pair. */ -template<typename S, typename V> const S content(const scp<S, V>& m) { +template<typename S, typename V> inline const S content(const scp<S, V>& m) { return m.v; } @@ -532,38 +523,36 @@ template<typename S, typename V> const S content(const scp<S, V>& m) { */ template<typename S, typename V> class state { public: - state(const lambda<scp<S, V>(const S)>& f) : f(f) { + inline state(const lambda<const scp<S, V>(const S)>& f) : f(f) { } - const scp<S, V> operator()(const S& s) const { + inline const scp<S, V> operator()(const S& s) const { return f(s); } - const state<S, V>& operator=(const state<S, V>& m) { - if(this == &m) - return *this; - f = m.f; - return *this; + inline state(const state<S, V>& m) : f(m.f) { } - const bool operator!=(const state<S, V>& m) const { + state<S, V>& operator=(const state<S, V>& m) = delete; + + inline const bool operator!=(const state<S, V>& m) const { return !this->operator==(m); } - const bool operator==(const state<S, V>& m) const { + inline const bool operator==(const state<S, V>& m) const { if (this == &m) return true; return f == m.f; } private: - const lambda<scp<S, V>(const S)> f; + const lambda<const scp<S, V>(const S)> f; }; /** * Write a state monad to a stream. */ -template<typename S, typename V> ostream& operator<<(ostream& out, const state<S, V>& m) { +template<typename S, typename V> inline ostream& operator<<(ostream& out, const state<S, V>& m) { const S s = m; const V v = m; out << '(' << s << ' ' << v << ')'; @@ -573,17 +562,10 @@ template<typename S, typename V> ostream& operator<<(ostream& out, const state<S /** * Return a state monad carrying a result content. */ -template<typename S, typename V> struct returnState { - const V v; - returnState(const V& v) : v(v) { - } - const scp<S, V> operator()(const S& s) const { +template<typename S, typename V> inline const state<S, V> result(const V& v) { + return state<S, V>([v](const S& s) -> const scp<S, V> { return scp<S, V>(s, v); - } -}; - -template<typename S, typename V> const state<S, V> result(const V& v) { - return state<S, V>(returnState<S, V>(v)); + }); } /** @@ -591,7 +573,7 @@ template<typename S, typename V> const state<S, V> result(const V& v) { * A transformer function takes a state and returns an scp pair carrying a content and a * new (transformed) state. */ -template<typename S, typename V> const state<S, V> transformer(const lambda<scp<S, V>(const S)>& f) { +template<typename S, typename V> inline const state<S, V> transformer(const lambda<const scp<S, V>(const S)>& f) { return state<S, V>(f); } @@ -599,28 +581,19 @@ template<typename S, typename V> const state<S, V> transformer(const lambda<scp< * Bind a function to a state monad. The function takes a content and returns a state * monad carrying a return content. */ -template<typename S, typename A, typename B> struct stateBind { - const state<S, A> st; - const lambda<state<S, B>(const A)>f; - - stateBind(const state<S, A>& st, const lambda<state<S, B>(const A)>& f) : st(st), f(f) { - } - - const scp<S, B> operator()(const S& is) const { +template<typename S, typename A, typename B> +inline const state<S, B> operator>>(const state<S, A>& st, const lambda<const state<S, B>(const A)>& f) { + const lambda<const scp<S, B>(const S&)> stateBind = [st, f](const S& is) -> const scp<S, B> { const scp<S, A> iscp = st(is); const state<S, B> m = f((A)iscp); return m((S)iscp); - } -}; - -template<typename S, typename A, typename B> -const state<S, B> operator>>(const state<S, A>& st, const lambda<state<S, B>(const A)>& f) { - return state<S, B>(stateBind<S, A , B>(st, f)); + }; + return state<S, B>(stateBind); } template<typename S, typename A, typename B> -const state<S, B> operator>>(const state<S, A>& st, const state<S, B> (* const f)(const A)) { - return state<S, B>(stateBind<S, A , B>(st, f)); +inline const state<S, B> operator>>(const state<S, A>& st, const state<S, B> (* const f)(const A)) { + return st >> lambda<const state<S, B>(const A)>(f); } } diff --git a/sca-cpp/trunk/kernel/parallel-test.cpp b/sca-cpp/trunk/kernel/parallel-test.cpp index 28e484d42b..895bb91eb8 100644 --- a/sca-cpp/trunk/kernel/parallel-test.cpp +++ b/sca-cpp/trunk/kernel/parallel-test.cpp @@ -35,84 +35,58 @@ namespace tuscany { int inci = 0; -struct incPerf { - incPerf() { - } - const bool operator()() const { - inci = inci + 1; - return true; - } -}; - const gc_ptr<int> tlsic() { - gc_ptr<int> i = new (gc_new<int>()) int(); + const gc_ptr<int> i = new (gc_new<int>()) int(); *i = 0; return i; } const perthread_ptr<int> tlsi(tlsic); -struct tlsPerf { - tlsPerf() { - } - const bool operator()() const { - *tlsi = *tlsi + 1; - return true; - } -}; - #ifdef WANT_THREADS int addi = 0; - -struct addAndFetchPerf { - addAndFetchPerf() { - } - const bool operator()() const { - __sync_add_and_fetch(&addi, 1); - return true; - } -}; - int muxi = 0; -struct mutexPerf { - pthread_mutex_t* mutex; - mutexPerf(pthread_mutex_t* mutex) : mutex(mutex) { - } - const bool operator()() const { - pthread_mutex_lock(mutex); - muxi = muxi + 1; - pthread_mutex_unlock(mutex); - return true; - } -}; - #endif -bool testAtomicPerf() { +const bool testAtomicPerf() { const int count = 100000; { - const lambda<bool()> l = incPerf(); + const blambda l = []() -> const bool { + inci = inci + 1; + return true; + }; cout << "Non-atomic inc test " << time(l, 1000, count) << " ms" << endl; assert(inci == count + 1000); } #ifdef WANT_THREADS { - const lambda<bool()> l = addAndFetchPerf(); + const blambda l = []() -> const bool { + __sync_add_and_fetch(&addi, 1); + return true; + }; cout << "Atomic inc test " << time(l, 1000, count) << " ms" << endl; assert(addi == count + 1000); } { pthread_mutex_t mutex; pthread_mutex_init(&mutex, NULL); - const lambda<bool()> l = mutexPerf(&mutex); + const blambda l = [&mutex]() -> const bool { + pthread_mutex_lock(&mutex); + muxi = muxi + 1; + pthread_mutex_unlock(&mutex); + return true; + }; cout << "Locked inc test " << time(l, 1000, count) << " ms" << endl; assert(muxi == count + 1000); pthread_mutex_destroy(&mutex); } #endif { - const lambda<bool()> l = tlsPerf(); + const blambda l = []() -> const bool { + *tlsi = *tlsi + 1; + return true; + }; cout << "Thread local inc test " << time(l, 1000, count) << " ms" << endl; assert(*tlsi == count + 1000); } @@ -130,7 +104,7 @@ const int mtsquare(const int x) { const list<future<int> > submitSquares(worker& w, const int max, const int i) { if (i == max) return list<future<int> >(); - const lambda<int()> func = curry(lambda<int(const int)> (mtsquare), i); + const lambda<const int()> func = curry(lambda<const int(const int)> (mtsquare), i); return cons(submit(w, func), submitSquares(w, max, i + 1)); } @@ -143,7 +117,7 @@ bool checkSquareResults(const list<future<int> > r, int i) { } const gc_ptr<unsigned long> tlsvc() { - gc_ptr<unsigned long> i = new (gc_new<unsigned long>()) unsigned long(); + const gc_ptr<unsigned long> i = new (gc_new<unsigned long>()) unsigned long(); *i = 0l; return i; } @@ -181,11 +155,11 @@ const bool unblockWorkers(wqueue<bool>& wq, const int n) { const list<future<long int> > submitTLSSets(worker& w, wqueue<bool>& wq, wqueue<bool>& xq, const int max, const int i) { if (i == max) return list<future<long int> >(); - const lambda<long int()> func = curry(lambda<long int(gc_ptr<wqueue<bool>>, gc_ptr<wqueue<bool>>)>(tlsset), (gc_ptr<wqueue<bool>>)&wq, (gc_ptr<wqueue<bool>>)&xq); + const lambda<const long int()> func = curry(lambda<const long int(gc_ptr<wqueue<bool>>, gc_ptr<wqueue<bool>>)>(tlsset), (gc_ptr<wqueue<bool>>)&wq, (gc_ptr<wqueue<bool>>)&xq); return cons(submit(w, func), submitTLSSets(w, wq, xq, max, i + 1)); } -bool checkTLSSets(const list<future<long int> > s) { +const bool checkTLSSets(const list<future<long int> > s) { if (isNil(s)) return true; assert(car(s) == 0); @@ -195,22 +169,22 @@ bool checkTLSSets(const list<future<long int> > s) { const list<future<bool> > submitTLSChecks(worker& w, wqueue<bool>& wq, wqueue<bool>& xq, const int max, const int i) { if (i == max) return list<future<bool> >(); - const lambda<bool()> func = curry(lambda<bool(gc_ptr<wqueue<bool>>, gc_ptr<wqueue<bool>>)>(tlscheck), (gc_ptr<wqueue<bool>>)&wq, (gc_ptr<wqueue<bool>>)&xq); + const blambda func = curry(lambda<const bool(gc_ptr<wqueue<bool>>, gc_ptr<wqueue<bool>>)>(tlscheck), (gc_ptr<wqueue<bool>>)&wq, (gc_ptr<wqueue<bool>>)&xq); return cons(submit(w, func), submitTLSChecks(w, wq, xq, max, i + 1)); } -bool checkTLSResults(const list<future<bool> > r) { +const bool checkTLSResults(const list<future<bool> > r) { if (isNil(r)) return true; assert(car(r) == true); return checkTLSResults(cdr(r)); } -bool testWorker() { +const bool testWorker() { const int max = 100; worker w(max); { - const lambda<int()> func = curry(lambda<int(const int)> (mtsquare), 2); + const lambda<const int()> func = curry(lambda<const int(const int)> (mtsquare), 2); assert(submit(w, func) == 4); } { @@ -245,7 +219,7 @@ bool testWorker() { } int main() { - tuscany::gc_scoped_pool p; + const tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::testAtomicPerf(); diff --git a/sca-cpp/trunk/kernel/parallel.hpp b/sca-cpp/trunk/kernel/parallel.hpp index 3be4d3bc8e..8b01bb819f 100644 --- a/sca-cpp/trunk/kernel/parallel.hpp +++ b/sca-cpp/trunk/kernel/parallel.hpp @@ -39,7 +39,7 @@ namespace tuscany { /** * Returns the current process id. */ -unsigned long processId() { +inline const unsigned long processId() noexcept { return (unsigned long)getpid(); } @@ -48,7 +48,7 @@ unsigned long processId() { /** * Returns the current thread id. */ -unsigned long threadId() { +inline const unsigned long threadId() noexcept{ return (unsigned long)pthread_self(); } @@ -60,20 +60,20 @@ template<typename T> class future { private: template<typename X> class futureValue { public: - futureValue() : hasValue(false) { + inline futureValue() noexcept : hasValue(false) { pthread_mutex_init(&valueMutex, NULL); pthread_cond_init(&valueCond, NULL); } - futureValue(const futureValue& fv) : valueMutex(fv.valueMutex), valueCond(fv.valueCond), hasValue(fv.hasValue), value(fv.value) { + inline futureValue(const futureValue& fv) noexcept : valueMutex(fv.valueMutex), valueCond(fv.valueCond), hasValue(fv.hasValue), value(fv.value) { } - ~futureValue() { + inline ~futureValue() noexcept { //pthread_mutex_destroy(&valueMutex); //pthread_cond_destroy(&valueCond); } - bool set(const T& v) { + inline const bool set(const T& v) noexcept { pthread_mutex_lock(&valueMutex); if(hasValue) { pthread_mutex_unlock(&valueMutex); @@ -86,7 +86,7 @@ private: return true; } - const T get() { + inline const T get() noexcept { pthread_mutex_lock(&valueMutex); while(!hasValue) { pthread_cond_wait(&valueCond, &valueMutex); @@ -100,37 +100,32 @@ private: pthread_mutex_t valueMutex; pthread_cond_t valueCond; bool hasValue; - X value; + gc_mutable_ref<X> value; }; - gc_ptr<futureValue<T> > fvalue; + const gc_ptr<futureValue<T> > fvalue; - template<typename X> friend const X get(const future<X>& f); - template<typename X> friend bool set(const future<X>& f, const X& v); + template<typename X> friend const X get(const future<X>& f) noexcept; + template<typename X> friend bool set(const future<X>& f, const X& v) noexcept; public: - future() : fvalue(new (gc_new<futureValue<T> >()) futureValue<T>()) { + inline future() noexcept : fvalue(new (gc_new<futureValue<T> >()) futureValue<T>()) { } - ~future() { + inline ~future() noexcept { } - future(const future& f) : fvalue(f.fvalue) { + inline future(const future& f) noexcept : fvalue(f.fvalue) { } - const future& operator=(const future& f) { - if (&f == this) - return *this; - fvalue = f.fvalue; - return *this; - } + const future& operator=(const future& f) = delete; - const future& operator=(const T& v) const { + inline const future& operator=(const T& v) const noexcept { fvalue->set(v); return *this; } - operator const T() const { + inline operator const T() const noexcept { return fvalue->get(); } }; @@ -140,16 +135,16 @@ public: */ template<typename T> class wqueue { public: - wqueue(size_t max) : max(max), size(0), tail(0), head(0), values(new (gc_anew<T>(max)) T[max]) { + inline wqueue(size_t max) noexcept : max(max), size(0), tail(0), head(0), values(new (gc_anew<gc_mutable_ref<T> >(max)) gc_mutable_ref<T>[max]) { pthread_mutex_init(&mutex, NULL); pthread_cond_init(&full, NULL); pthread_cond_init(&empty, NULL); } - wqueue(const wqueue& wq) : max(wq.max), size(wq.size), tail(wq.tail), head(wq.head), mutex(wq.mutex), full(wq.full), empty(wq.empty), values(wq.values) { + inline wqueue(const wqueue& wq) noexcept : max(wq.max), size(wq.size), tail(wq.tail), head(wq.head), mutex(wq.mutex), full(wq.full), empty(wq.empty), values(wq.values) { } - ~wqueue() { + inline ~wqueue() { //pthread_mutex_destroy(&mutex); //pthread_cond_destroy(&full); //pthread_cond_destroy(&empty); @@ -163,16 +158,16 @@ private: pthread_mutex_t mutex; pthread_cond_t full; pthread_cond_t empty; - gc_ptr<T> values; + gc_ptr<gc_mutable_ref<T> > values; - template<typename X> friend const size_t enqueue(wqueue<X>& q, const X& v); - template<typename X> friend const X dequeue(wqueue<X>& q); + template<typename X> friend const size_t enqueue(wqueue<X>& q, const X& v) noexcept; + template<typename X> friend const X dequeue(wqueue<X>& q) noexcept; }; /** * Adds an element to the tail of the queue. */ -template<typename T> const size_t enqueue(wqueue<T>&q, const T& v) { +template<typename T> inline const size_t enqueue(wqueue<T>&q, const T& v) noexcept { pthread_mutex_lock(&q.mutex); while(q.size == q.max) pthread_cond_wait(&q.full, &q.mutex); @@ -187,7 +182,7 @@ template<typename T> const size_t enqueue(wqueue<T>&q, const T& v) { /** * Returns the element at the head of the queue. */ -template<typename T> const T dequeue(wqueue<T>& q) { +template<typename T> inline const T dequeue(wqueue<T>& q) noexcept { pthread_mutex_lock(&q.mutex); while(q.size == 0) pthread_cond_wait(&q.empty, &q.mutex); @@ -202,13 +197,13 @@ template<typename T> const T dequeue(wqueue<T>& q) { /** * The worker thread function. */ -void *workerThreadFunc(void *arg) { +inline void* workerThreadFunc(void* arg) noexcept { int ost; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &ost); int ot; pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &ot); - wqueue<lambda<bool()> >* work = reinterpret_cast<wqueue<lambda<bool()> >*>(arg); + wqueue<blambda >* work = reinterpret_cast<wqueue<blambda >*>(arg); while(dequeue(*work)()) ; return NULL; @@ -217,7 +212,7 @@ void *workerThreadFunc(void *arg) { /** * Returns a list of worker threads. */ -const list<pthread_t> workerThreads(wqueue<lambda<bool()> >& wqueue, const size_t count) { +inline const list<pthread_t> workerThreads(wqueue<blambda >& wqueue, const size_t count) noexcept { if (count == 0) return list<pthread_t>(); pthread_t thread; @@ -235,32 +230,32 @@ private: // copies of the queue and thread pool when a worker is copied class sharedWorker { public: - sharedWorker(size_t max) : work(wqueue<lambda<bool()> >(max)), threads(workerThreads(work, max)) { + inline sharedWorker(size_t max) noexcept : work(wqueue<blambda >(max)), threads(workerThreads(work, max)) { } - wqueue<lambda<bool()> > work; + wqueue<blambda > work; const list<pthread_t> threads; }; public: - worker(size_t max) : w(*(new (gc_new<sharedWorker>()) sharedWorker(max))) { + inline worker(size_t max) noexcept : w(*(new (gc_new<sharedWorker>()) sharedWorker(max))) { } - worker(const worker& wk) : w(wk.w) { + inline worker(const worker& wk) noexcept : w(wk.w) { } private: sharedWorker& w; - template<typename X> friend const future<X> submit(worker& w, const lambda<X()>& func); - friend const bool shutdown(worker& w); - friend const bool cancel(worker& w); + template<typename X> friend const future<X> submit(const worker& w, const lambda<const X()>& func) noexcept; + friend const bool shutdown(const worker& w) noexcept; + friend const bool cancel(const worker& w) noexcept; }; /** * Function used to wrap work submitted to a worker. */ -template<typename R> bool submitFunc(const lambda<R()>& func, const future<R>& fut) { +template<typename R> inline const bool submitFunc(const lambda<const R()>& func, const future<R>& fut) noexcept { fut = func(); return true; } @@ -268,9 +263,9 @@ template<typename R> bool submitFunc(const lambda<R()>& func, const future<R>& f /** * Submits work to a worker. */ -template<typename R> const future<R> submit(worker& w, const lambda<R()>& func) { +template<typename R> inline const future<R> submit(const worker& w, const lambda<const R()>& func) noexcept { const future<R> fut; - const lambda<bool()> f = curry(lambda<bool(const lambda<R()>, future<R>)>(submitFunc<R>), func, fut); + const blambda f = curry(lambda<const bool(const lambda<const R()>, future<R>)>(submitFunc<R>), func, fut); enqueue(w.w.work, f); return fut; } @@ -278,7 +273,7 @@ template<typename R> const future<R> submit(worker& w, const lambda<R()>& func) /** * Enqueues shutdown requests. */ -const bool shutdownEnqueue(const list<pthread_t>& threads, wqueue<lambda<bool()> >& work) { +inline const bool shutdownEnqueue(const list<pthread_t>& threads, wqueue<blambda>& work) noexcept { if (isNil(threads)) return true; enqueue(work, result(false)); @@ -288,7 +283,7 @@ const bool shutdownEnqueue(const list<pthread_t>& threads, wqueue<lambda<bool()> /** * Waits for shut down threads to terminate. */ -const bool shutdownJoin(const list<pthread_t>& threads) { +inline const bool shutdownJoin(const list<pthread_t>& threads) noexcept { if (isNil(threads)) return true; pthread_join(car(threads), NULL); @@ -298,7 +293,7 @@ const bool shutdownJoin(const list<pthread_t>& threads) { /** * Shutdown a worker. */ -const bool shutdown(worker& w) { +inline const bool shutdown(const worker& w) noexcept { shutdownEnqueue(w.w.threads, w.w.work); shutdownJoin(w.w.threads); return true; @@ -307,14 +302,14 @@ const bool shutdown(worker& w) { /** * Cancel a worker. */ -const bool cancel(const list<pthread_t>& threads) { +inline const bool cancel(const list<pthread_t>& threads) noexcept { if (isNil(threads)) return true; pthread_cancel(car(threads)); return cancel(cdr(threads)); } -const bool cancel(worker& w) { +inline const bool cancel(const worker& w) noexcept { cancel(w.w.threads); return true; } @@ -324,7 +319,7 @@ const bool cancel(worker& w) { /** * Returns the current thread id. */ -unsigned long threadId() { +inline const unsigned long threadId() noexcept { return 0; } @@ -335,114 +330,106 @@ unsigned long threadId() { */ template<typename T> class perthread_ptr { public: - perthread_ptr() : key(createkey()), owner(true), cl(lambda<gc_ptr<T>()>()), managed(false) { + inline perthread_ptr() noexcept : key(createkey()), owner(true), cl(lambda<const gc_ptr<T>()>()), managed(false) { } - perthread_ptr(const lambda<gc_ptr<T>()>& cl) : key(createkey()), owner(true), cl(cl), managed(true) { + inline perthread_ptr(const lambda<const gc_ptr<T>()>& cl) noexcept : key(createkey()), owner(true), cl(cl), managed(true) { } - ~perthread_ptr() { + inline ~perthread_ptr() noexcept { if (owner) deletekey(key); } - perthread_ptr(const perthread_ptr& c) : key(c.key), owner(false), cl(c.cl), managed(c.managed) { + inline perthread_ptr(const perthread_ptr& c) noexcept : key(c.key), owner(false), cl(c.cl), managed(c.managed) { } - perthread_ptr& operator=(const perthread_ptr& r) throw() { - if(this == &r) - return *this; - key = r.key; - owner = false; - cl = r.cl; - managed = r.managed; - return *this; - } + perthread_ptr& operator=(const perthread_ptr& r) = delete; - const perthread_ptr& operator=(const gc_ptr<T>& v) { + inline const perthread_ptr& operator=(const gc_ptr<T>& v) const noexcept { set(v); return *this; } - const perthread_ptr& operator=(T* v) { + inline const perthread_ptr& operator=(T* const v) const noexcept { set(v); return *this; } - const bool operator==(const gc_ptr<T>& r) const throw() { + inline const bool operator==(const gc_ptr<T>& r) const noexcept { return get() == r; } - const bool operator==(T* p) const throw() { + inline const bool operator==(const T* const p) const noexcept { return get() == p; } - const bool operator!=(const gc_ptr<T>& r) const throw() { + inline const bool operator!=(const gc_ptr<T>& r) const noexcept { return !this->operator==(r); } - const bool operator!=(T* p) const throw() { + inline const bool operator!=(const T* const p) const noexcept { return !this->operator==(p); } - T& operator*() const throw() { + inline T& operator*() const noexcept { return *get(); } - T* operator->() const throw() { + inline T* const operator->() const noexcept { return get(); } - operator gc_ptr<T>() const { + inline operator gc_ptr<T>() const { return get(); } - operator T*() const { + inline operator T* const () const { return get(); } private: #ifdef WANT_THREADS - pthread_key_t createkey() { + inline const pthread_key_t createkey() noexcept { pthread_key_t k; pthread_key_create(&k, NULL); return k; } - bool deletekey(pthread_key_t k) { + inline const bool deletekey(pthread_key_t k) noexcept { pthread_key_delete(k); return true; } - bool set(const gc_ptr<T>& v) { + inline const bool set(const gc_ptr<T>& v) const noexcept { pthread_setspecific(key, (T*)v); return true; } - gc_ptr<T> get() const { - const gc_ptr<T> v = static_cast<T*>(pthread_getspecific(key)); + inline const gc_ptr<T> get() const noexcept { + const gc_ptr<T> v = (T*)(pthread_getspecific(key)); if (v != NULL || !managed) return v; const gc_ptr<T> nv = cl(); - pthread_setspecific(key, nv); + pthread_setspecific(key, (T*)nv); return nv; } #else - gc_ptr<gc_ptr<T> > createkey() { + inline const gc_ptr<gc_ptr<T> > createkey() noexcept { return new (gc_new<gc_ptr<T> >()) gc_ptr<T>(); } - bool deletekey(unused gc_ptr<gc_ptr<T> > k) { + inline const bool deletekey(unused gc_ptr<gc_ptr<T> > k) noexcept { return true; } - bool set(const gc_ptr<T>& v) { + inline const bool set(const gc_ptr<T>& v) const noexcept { *key = v; return true; } - gc_ptr<T> get() const { + inline const gc_ptr<T> get() const noexcept { if (*key != NULL || !managed) return *key; *key = cl(); @@ -452,14 +439,14 @@ private: #endif #ifdef WANT_THREADS - pthread_key_t key; + const pthread_key_t key; #else - gc_ptr<gc_ptr<T> >key; + const gc_ptr<gc_ptr<T> >key; #endif - bool owner; - lambda<const gc_ptr<T>()> cl; - bool managed; + const bool owner; + const lambda<const gc_ptr<T>()> cl; + const bool managed; }; } diff --git a/sca-cpp/trunk/kernel/perf.hpp b/sca-cpp/trunk/kernel/perf.hpp index 04aad06664..07c586ce7c 100644 --- a/sca-cpp/trunk/kernel/perf.hpp +++ b/sca-cpp/trunk/kernel/perf.hpp @@ -37,21 +37,15 @@ namespace tuscany /** * Measure the time required to perform a function in msec. */ -struct timeLambda { - const lambda<bool()> f; - timeLambda(const lambda<bool()>& f) : f(f) { - } - bool operator()(const long count) const { +inline const double time(const blambda& f, const long warmup, const long count) { + struct timeval start; + struct timeval end; + + const lambda<const bool(const long)> tl = [f](const long count) -> const bool { for (long i = 0; i < count; i++) f(); return true; - } -}; - -const double time(const lambda<bool()>& f, const long warmup, const long count) { - const lambda<bool(long)> tl = timeLambda(f); - struct timeval start; - struct timeval end; + }; tl(warmup); gettimeofday(&start, NULL); @@ -62,13 +56,13 @@ const double time(const lambda<bool()>& f, const long warmup, const long count) return (double)t / (double)count; } -const unsigned long timems() { +inline const unsigned long timems() { struct timeval t; gettimeofday(&t, NULL); return (unsigned long)(t.tv_sec * 1000 + t.tv_usec / 1000); } -const unsigned long timens() { +inline const unsigned long timens() { struct timeval t; gettimeofday(&t, NULL); return (unsigned long)(t.tv_sec * 1000000000 + t.tv_usec * 1000); diff --git a/sca-cpp/trunk/kernel/sstream.hpp b/sca-cpp/trunk/kernel/sstream.hpp index 17fd28b48b..dbdc7414a1 100644 --- a/sca-cpp/trunk/kernel/sstream.hpp +++ b/sca-cpp/trunk/kernel/sstream.hpp @@ -38,14 +38,14 @@ namespace tuscany { /** * Instrumentable memcpy. */ -void* stream_memcpy(void* t, const void* s, const size_t n) { +inline void* stream_memcpy(void* t, const void* s, const size_t n) { return memcpy(t, s, n); } /** * Write a list of strings into a buffer. */ -const bool writeList(const list<string>& l, char* buf) { +const bool writeList(const list<string>& l, char* const buf) { if (isNil(l)) return true; const string c = car(l); @@ -59,63 +59,108 @@ const bool writeList(const list<string>& l, char* buf) { */ class ostringstream : public ostream { public: - ostringstream() : len(0) { + inline ostringstream() : len(0), accumbuf(NULL), accumlen(0), buf() { } - ~ostringstream() { + inline ~ostringstream() { } - ostringstream(const ostringstream& os) { - len = os.len; - buf = os.buf; + inline ostringstream(const ostringstream& os) : len(os.len), accumbuf(os.accumbuf), accumlen(os.accumlen), buf(os.buf) { } - ostringstream& vprintf(const char* fmt, ...) { + inline ostringstream& vprintf(const char* const fmt, ...) { va_list args; - string s; va_start (args, fmt); - s.len = vsnprintf(NULL, 0, fmt, args); - s.buf = gc_cnew(s.len + 1); + const size_t l = vsnprintf(NULL, 0, fmt, args); + if (l <= 256) { + char c[256]; + va_start (args, fmt); + vsnprintf(c, l + 1, fmt, args); + va_end (args); + accumulate(c, l); + return *this; + } + spill(); + char* const sbuf = gc_cnew(l + 1); va_start (args, fmt); - vsnprintf(s.buf, s.len + 1, fmt, args); - buf = cons(s, buf); - len += s.len; + vsnprintf(sbuf, l + 1, fmt, args); va_end (args); + buf = cons(string(sbuf, l, false), (const list<string>)buf); + len += l; return *this; } - ostringstream& write(const string& s) { - buf = cons(s, buf); + inline ostringstream& write(const string& s) { + if (s.len <= 256) { + accumulate(s.buf, s.len); + return *this; + } + spill(); + buf = cons(s, (const list<string>)buf); len += s.len; return *this; } - ostringstream& flush() { + inline ostringstream& write(const char c) { + accumulate(&c, 1); + return *this; + } + + inline ostringstream& flush() { + spill(); return *this; } private: - const string str() { - if (isNil(buf)) - return string(); - string s; - s.len = len; - s.buf = gc_cnew(s.len + 1); - writeList(buf, s.buf + len); - s.buf[s.len] = '\0'; - return s; + inline const string str() { + spill(); + if (isNil((const list<string>)buf)) + return emptyString; + char* const sbuf = gc_cnew(len + 1); + writeList(buf, sbuf + len); + sbuf[len] = '\0'; + return string(sbuf, len, false); + } + + inline const bool accumulate(const char* const c, const size_t l) { + if (accumbuf == NULL) + accumbuf = gc_cnew(65); + for(size_t i = 0; i < l; i++) { + accumbuf[accumlen] = c[i]; + accumlen++; + if (accumlen == 64) { + accumbuf[accumlen] = '\0'; + buf = cons(string(accumbuf, accumlen, false), (const list<string>)buf); + accumbuf = i < l? gc_cnew(65) : NULL; + accumlen = 0; + } + } + accumbuf[accumlen] = '\0'; + len += l; + return true; + } + + inline const bool spill() { + if (accumbuf == NULL) + return true; + buf = cons(string(accumbuf, accumlen), (const list<string>)buf); + accumbuf = NULL; + accumlen = 0; + return true; } friend const string str(ostringstream& os); size_t len; - list<string> buf; + char* accumbuf; + size_t accumlen; + gc_mutable_ref<list<string> > buf; }; /** * Return a string representation of a stream. */ -const string str(ostringstream& os) { +inline const string str(ostringstream& os) { return os.str(); } @@ -124,23 +169,16 @@ const string str(ostringstream& os) { */ class istringstream : public istream { public: - istringstream(const string& s) { - cur = 0; - const size_t slen = length(s); - len = slen; - buf = c_str(s); - } - - ~istringstream() { + inline istringstream(const string& s) : len(length(s)), cur(0), buf(c_str(s)) { + } + + inline ~istringstream() { } - istringstream(const istringstream& is) { - len = is.len; - cur = is.cur; - buf = is.buf; + inline istringstream(const istringstream& is) : len(is.len), cur(is.cur), buf(is.buf) { } - const size_t read(void* b, size_t size) { + inline const size_t read(void* const b, const size_t size) { const size_t n = len - cur; if (n == 0) return 0; @@ -154,30 +192,28 @@ public: return n; } - const bool eof() { + inline const bool eof() { return cur == len; } - const bool fail() { + inline const bool fail() { return false; } - const int get() { - if (eof()) + inline const int get() { + if (cur == len) return -1; - const int c = buf[cur]; - cur += 1; - return c; + return buf[cur++]; } - const int peek() { - if (eof()) + inline const int peek() { + if (cur == len) return -1; return buf[cur]; } private: - size_t len; + const size_t len; size_t cur; const char* buf; }; @@ -185,62 +221,52 @@ private: /** * Tokenize a string into a list of strings. */ -const list<string> tokenize(const char* sep, const string& str) { - struct nested { - static const list<string> tokenize(const char* sep, const size_t slen, const string& str, const size_t start) { - if (start >= length(str)) - return list<string>(); - const size_t i = find(str, sep, start); - if (i == length(str)) - return mklist(string(substr(str, start))); - return cons(string(substr(str, start, i - start)), tokenize(sep, slen, str, i + slen)); - } +inline const list<string> tokenize(const char* const sep, const string& str) { + const lambda<const list<string>(const char* const, const size_t, const string&, const size_t)> tokenize = [&tokenize](const char* const sep, const size_t slen, const string& str, const size_t start) -> const list<string> { + if (start >= length(str)) + return list<string>(); + const size_t i = find(str, sep, start); + if (i == length(str)) + return mklist(string(substr(str, start))); + return cons(string(substr(str, start, i - start)), tokenize(sep, slen, str, i + slen)); }; - return nested::tokenize(sep, strlen(sep), str, 0); + return tokenize(sep, strlen(sep), str, 0); } /** * Join a list of strings into a single string. */ -const string join(const char* sep, const list<string>& l) { - struct nested { - static ostringstream& join(const char* sep, const list<string>& l, ostringstream& os) { - if (isNil(l)) - return os; - os << car(l); - if (!isNil(cdr(l))) - os << sep; - return join(sep, cdr(l), os); - } - }; +inline const string join(const char* const sep, const list<string>& l) { ostringstream os; - return str(nested::join(sep, l, os)); + const lambda<ostringstream&(const char* const, const list<string>&, ostringstream&)> join = [&join](const char* const sep, const list<string>& l, ostringstream& os) -> ostringstream& { + if (isNil(l)) + return os; + os << car(l); + if (!isNil(cdr(l))) + os << sep; + return join(sep, cdr(l), os); + }; + return str(join(sep, l, os)); } /** * Returns a lazy list view of an input stream. */ -struct ilistRead{ - istream &is; - ilistRead(istream& is) : is(is) { - } - const list<string> operator()() { +inline const list<string> streamList(istream& is) { + const lambda<const list<string>()> ilistRead = [&is, &ilistRead]() -> const list<string> { char buffer[1024]; const size_t n = read(is, buffer, sizeof(buffer)); if (n ==0) return list<string>(); - return cons(string(buffer, n), (*this)()); - } -}; - -const list<string> streamList(istream& is) { - return ilistRead(is)(); + return cons(string(buffer, n), ilistRead()); + }; + return ilistRead(); } /** * Fragment the first element of a list of strings to fit the given max length. */ -const list<string> fragment(list<string> l, size_t max) { +inline const list<string> fragment(const list<string>& l, const size_t max) { const string s = car(l); if (length(s) <= max) return l; @@ -250,13 +276,26 @@ const list<string> fragment(list<string> l, size_t max) { /** * Write a list of strings to an output stream. */ -ostream& write(const list<string>& l, ostream& os) { +inline ostream& write(const list<string>& l, ostream& os) { if(isNil(l)) return os; os << car(l); return write(cdr(l), os); } +/** + * Convert a list of strings to a string. + */ +inline const string write(const list<string>& l) { + if (isNil(l)) + return emptyString; + if (isNil(cdr(l))) + return car(l); + ostringstream os; + write(l, os); + return str(os); +} + } #endif /* tuscany_sstream_hpp */ diff --git a/sca-cpp/trunk/kernel/stream.hpp b/sca-cpp/trunk/kernel/stream.hpp index 8ccfed948f..e59e6a4ef5 100644 --- a/sca-cpp/trunk/kernel/stream.hpp +++ b/sca-cpp/trunk/kernel/stream.hpp @@ -38,66 +38,67 @@ namespace tuscany { */ class ostream { public: - virtual ostream& vprintf(const char* fmt, ...) = 0; + virtual ostream& vprintf(const char* const fmt, ...) = 0; virtual ostream& write(const string& s) = 0; + virtual ostream& write(const char c) = 0; virtual ostream& flush() = 0; }; /** * Flush a stream. */ -ostream& flush(ostream& os) { +inline ostream& flush(ostream& os) { return os.flush(); } /** * Write simple values to a stream. */ -ostream& operator<<(ostream& os, const char* v) { +inline ostream& operator<<(ostream& os, const char* const v) { return os.vprintf("%s", v); } -ostream& operator<<(ostream& os, const unsigned char* v) { +inline ostream& operator<<(ostream& os, const unsigned char* const v) { return os.vprintf("%s", v); } -ostream& operator<<(ostream& os, const char v) { - return os.vprintf("%c", v); +inline ostream& operator<<(ostream& os, const char v) { + return os.write(v); } -ostream& operator<<(ostream& os, const int v) { +inline ostream& operator<<(ostream& os, const int v) { return os.vprintf("%d", v); } -ostream& operator<<(ostream& os, const unsigned int v) { +inline ostream& operator<<(ostream& os, const unsigned int v) { return os.vprintf("%u", v); } -ostream& operator<<(ostream& os, const long int v) { +inline ostream& operator<<(ostream& os, const long int v) { return os.vprintf("%ld", v); } -ostream& operator<<(ostream& os, const long unsigned int v) { +inline ostream& operator<<(ostream& os, const long unsigned int v) { return os.vprintf("%lu", v); } -ostream& operator<<(ostream& os, const double v) { +inline ostream& operator<<(ostream& os, const double v) { return os.vprintf("%.10g", v); } -ostream& operator<<(ostream& os, const void* v) { +inline ostream& operator<<(ostream& os, const void* const v) { return os.vprintf("%p", v); } -ostream& operator<<(ostream& os, const string& v) { +inline ostream& operator<<(ostream& os, const string& v) { return os.write(v); } class stream_endl { } endl; -ostream& operator<<(ostream& os, unused const stream_endl e) { - os.write("\n"); +inline ostream& operator<<(ostream& os, unused const stream_endl e) { + os.write('\n'); return os.flush(); } @@ -106,7 +107,7 @@ ostream& operator<<(ostream& os, unused const stream_endl e) { */ class istream { public: - virtual const size_t read(void* buf, size_t size) = 0; + virtual const size_t read(void* const buf, const size_t size) = 0; virtual const bool eof() = 0; virtual const bool fail() = 0; virtual const int get() = 0; @@ -116,40 +117,61 @@ public: /** * Read from an input stream. */ -const size_t read(istream& is, void * buf, size_t size) { +inline const size_t read(istream& is, void* const buf, const size_t size) { return is.read(buf, size); } /** * Return true if the end of an input stream has been reached. */ -const bool eof(istream& is) { +inline const bool eof(istream& is) { return is.eof(); } /** * Return true if an input stream can't be accessed. */ -const bool fail(istream& is) { +inline const bool fail(istream& is) { return is.fail(); } /** * Read a character from a stream. */ -const int get(istream& is) { +inline const int get(istream& is) { return is.get(); } /** * Peek a character from a stream. */ -const int peek(istream& is) { +inline const int peek(istream& is) { return is.peek(); } -template<typename T> ostream& operator<<(ostream& out, const gc_ptr<T>& p) { - return out << p.ptr; +#ifndef WANT_RAW_PTR + +/** + * Write a pointer. + */ +template<typename T> inline ostream& operator<<(ostream& out, const gc_ptr<T>& p) { + return out << (T*)p; +} + +/** + * Write a mutable pointer. + */ +template<typename T> inline ostream& operator<<(ostream& out, const gc_mutable_ptr<T>& p) { + return out << (T*)p; +} + +#endif + +/** + * Write a mutable reference. + */ +template<typename T> inline ostream& operator<<(ostream& out, const gc_mutable_ref<T>& r) { + return out << (T)r; } #ifdef WANT_MAINTAINER_LOG @@ -159,35 +181,40 @@ template<typename T> ostream& operator<<(ostream& out, const gc_ptr<T>& p) { */ class odebugstream : public ostream { public: - odebugstream() { + inline odebugstream() : buf() { } - odebugstream& vprintf(const char* fmt, ...) { + inline odebugstream& vprintf(const char* const fmt, ...) { va_list args; string s; va_start (args, fmt); - s.len = vsnprintf(NULL, 0, fmt, args); - s.buf = gc_cnew(s.len + 1); + const size_t slen = vsnprintf(NULL, 0, fmt, args); + char* const sbuf = gc_cnew(slen + 1); va_start (args, fmt); - vsnprintf(s.buf, s.len + 1, fmt, args); - buf = buf + s; + vsnprintf(sbuf, slen + 1, fmt, args); + buf = buf + string(sbuf, slen, false); va_end (args); return *this; } - odebugstream& write(const string& s) { + inline odebugstream& write(const string& s) { buf = buf + s; return *this; } - odebugstream& flush() { + inline odebugstream& write(const char c) { + buf = buf + c; + return *this; + } + + inline odebugstream& flush() { return *this; } private: friend const string str(odebugstream& os); - string buf; + gc_mutable_ref<string> buf; }; const string str(odebugstream& os) { diff --git a/sca-cpp/trunk/kernel/string-test.cpp b/sca-cpp/trunk/kernel/string-test.cpp index b6f016b294..66716c96b5 100644 --- a/sca-cpp/trunk/kernel/string-test.cpp +++ b/sca-cpp/trunk/kernel/string-test.cpp @@ -32,15 +32,15 @@ namespace tuscany { -bool testCopies() { +const bool testCopies() { resetStringCopyCounters(); - string x("abcd"); + const string x("abcd"); assert(checkStringCopyCounters(1)); resetStringCopyCounters(); - string y = string("abcd"); + const string y = string("abcd"); assert(checkStringCopyCounters(1)); resetStringCopyCounters(); - unused string z = y; + unused const string z = y; assert(checkStringCopyCounters(0)); resetStringCopyCounters(); const list<string> pl = list<string>() + "abcd" + "efgh"; @@ -51,7 +51,7 @@ bool testCopies() { return true; } -bool testString() { +const bool testString() { const string s("abcd"); assert(length(s) == 4); assert(!strcmp(c_str(s), "abcd")); @@ -89,12 +89,19 @@ bool testString() { return true; } -bool testStream() { +const bool testStream() { ostringstream os; os << "ab" << "cd"; - cout << str(os) << endl; assert(str(os) == "abcd"); + ostringstream bos; + bos << "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"; + bos << "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"; + cout << str(bos) << endl; + assert(str(bos) == + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"); + ostringstream cs; cs << "\'"; assert(str(cs) == "\'"); @@ -113,69 +120,65 @@ bool testStream() { return true; } -std::string stdAdd(std::string& x, std::string& y) { +const std::string stdAdd(const std::string& x, const std::string& y) { return x + y; } -string add(string& x, string& y) { +const string add(const string& x, const string& y) { return x + y; } char charBuffer[16385]; -struct addStrings{ - const size_t size; - addStrings(const size_t size) : size(size) { - } - bool operator()() const { - const size_t sz = size / 4; - string x(charBuffer, sz); - string y(charBuffer, sz); - assert(length(add(x, y)) == sz * 2); - return true; - } -}; - -struct addStdStrings{ - const size_t size; - addStdStrings(const size_t size) : size(size) { - } - bool operator()() const { - const size_t sz = size / 4; - std::string x(charBuffer, sz); - std::string y(charBuffer, sz); - assert(stdAdd(x, y).length() == (unsigned int)(sz * 2)); - return true; - } -}; - -bool testStringPerf() { +const bool testStringPerf() { memset(charBuffer, 'A', 16384); charBuffer[16384] = '\0'; const int count = 10000; { - const lambda<bool()> a16 = addStrings(16); + const lambda<const blambda(const size_t size)> addStrings = [](const size_t size) -> const blambda { + const blambda l = [size]() -> const bool { + const size_t sz = size / 4; + const string x(charBuffer, sz); + const string y(charBuffer, sz); + assert(length(add(x, y)) == sz * 2); + return true; + }; + return l; + }; + + const blambda a16 = addStrings(16); cout << "string test " << time(a16, 5, count) << " ms" << endl; - const lambda<bool()> a32 =addStrings(32); + const blambda a32 =addStrings(32); cout << "string test " << time(a32, 5, count) << " ms" << endl; - const lambda<bool()> a256 =addStrings(256); + const blambda a256 =addStrings(256); cout << "string test " << time(a256, 5, count) << " ms" << endl; - const lambda<bool()> a1024 =addStrings(1024); + const blambda a1024 =addStrings(1024); cout << "string test " << time(a1024, 5, count) << " ms" << endl; - const lambda<bool()> a4096 =addStrings(4096); + const blambda a4096 =addStrings(4096); cout << "string test " << time(a4096, 5, count) << " ms" << endl; } { - const lambda<bool()> a16 =addStdStrings(16); + const lambda<const blambda(const size_t size)> addStdStrings = [](const size_t size) -> const blambda { + const blambda l = [size]() -> const bool { + const size_t sz = size / 4; + const std::string x(charBuffer, sz); + const std::string y(charBuffer, sz); + assert(stdAdd(x, y).length() == (unsigned int)(sz * 2)); + return true; + }; + return l; + }; + + const blambda a16 =addStdStrings(16); cout << "Std string test " << time(a16, 5, count) << " ms" << endl; - const lambda<bool()> a32 =addStdStrings(32); + const blambda a32 =addStdStrings(32); cout << "Std string test " << time(a32, 5, count) << " ms" << endl; - const lambda<bool()> a256 =addStdStrings(256); + const blambda a256 =addStdStrings(256); cout << "Std string test " << time(a256, 5, count) << " ms" << endl; - const lambda<bool()> a1024 =addStdStrings(1024); + const blambda a1024 =addStdStrings(1024); cout << "Std string test " << time(a1024, 5, count) << " ms" << endl; - const lambda<bool()> a4096 =addStdStrings(4096); + const blambda a4096 =addStdStrings(4096); cout << "Std string test " << time(a4096, 5, count) << " ms" << endl; } @@ -185,7 +188,7 @@ bool testStringPerf() { } int main() { - tuscany::gc_scoped_pool p; + const tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::testCopies(); diff --git a/sca-cpp/trunk/kernel/string.hpp b/sca-cpp/trunk/kernel/string.hpp index e726a61b84..4d27ce84d7 100644 --- a/sca-cpp/trunk/kernel/string.hpp +++ b/sca-cpp/trunk/kernel/string.hpp @@ -41,16 +41,16 @@ namespace tuscany { */ long countStringCopies = 0; -bool resetStringCopyCounters() { +inline const bool resetStringCopyCounters() { countStringCopies = 0; return true; } -bool checkStringCopyCounters(long c) { +inline const bool checkStringCopyCounters(long c) { return countStringCopies == c; } -bool printStringCopyCounters() { +inline const bool printStringCopyCounters() { printf("countStringCopies %ld\n", countStringCopies); return true; } @@ -66,13 +66,19 @@ bool printStringCopyCounters() { /** * Instrumented memcpy. */ -void* string_memcpy(void* t, const void* s, const size_t n) { #ifdef WANT_MAINTAINER_COUNTERS + +inline void* string_memcpy(void* t, const void* s, const size_t n) { countStringCopies += 1; -#endif return memcpy(t, s, n); } +#else + +#define string_memcpy(t, s, n) memcpy(t, s, n) + +#endif + char stringEmptyBuffer[1] = { '\0' }; /** @@ -80,56 +86,27 @@ char stringEmptyBuffer[1] = { '\0' }; */ class string { public: - string() : len(0) { - buf = stringEmptyBuffer; + inline string() noexcept : len(0), buf(stringEmptyBuffer) { } - string(const char* s) { - len = strlen(s); - if (len == 0) { - buf = stringEmptyBuffer; - return; - } - buf = gc_cnew(len + 1); - string_memcpy(buf, s, len + 1); + inline string(const char* const s) noexcept : len(strlen(s)), buf(mksbuf(s, len)) { } - string(const char* s, const size_t n) { - len = n; - if (len == 0) { - buf = stringEmptyBuffer; - return; - } - buf = gc_cnew(len + 1); - string_memcpy(buf, s, len); - buf[len] = '\0'; + inline string(const char* const s, const size_t n) noexcept : len(n), buf(mksbuf(s, n)) { } - string(const size_t n, const char c) { - len = n; - if (len == 0) { - buf = stringEmptyBuffer; - return; - } - buf = gc_cnew(len + 1); - memset(buf, c, n); - buf[len] = '\0'; + inline string(const char* const s, const size_t n, const bool copy) noexcept : len(n), buf(mksbuf(s, n, copy)) { } - string(const string& s) { - len = s.len; - buf = s.buf; + inline string(const size_t n, const char c) noexcept : len(n), buf(mkcbuf(c, n)) { } - const string& operator=(const string& s) { - if (&s == this) - return *this; - len = s.len; - buf = s.buf; - return *this; + inline string(const string& s) noexcept : len(s.len), buf(s.buf) { } - const bool operator==(const string& s) const { + string& operator=(const string& s) = delete; + + inline const bool operator==(const string& s) const noexcept { if (len != s.len) return false; if (buf == s.buf) @@ -137,21 +114,21 @@ public: return memcmp(buf, s.buf, len) == 0; } - const bool operator!=(const string& s) const { + inline const bool operator!=(const string& s) const noexcept { return !(*this == s); } - const bool operator==(const char* s) const { + inline const bool operator==(const char* const s) const noexcept { if (buf == s) return true; return strcmp(buf, s) == 0; } - const bool operator!=(const char* s) const { + inline const bool operator!=(const char* const s) const noexcept { return !(*this == s); } - const bool operator<(const string& s) const { + inline const bool operator<(const string& s) const noexcept { const size_t n = len < s.len? len : s.len; const int c = memcmp(buf, s.buf, n); if (c < 0) @@ -161,9 +138,9 @@ public: return false; } - const bool operator>(const string& s) const { + inline const bool operator>(const string& s) const noexcept { const size_t n = len < s.len? len : s.len; - int c = memcmp(buf, s.buf, n); + const int c = memcmp(buf, s.buf, n); if (c > 0) return true; if (c == 0) @@ -176,91 +153,137 @@ private: 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); - friend const size_t length(const string& s); - friend const char* c_str(const string& s); - friend const size_t find(const string& s1, const char* s2, const size_t start); - friend const string substr(const string& s, const size_t pos, const size_t n); - - size_t len; - char* buf; + friend const string operator+(const string& a, const string& b) noexcept; + friend const string operator+(const string& a, const char* const b) noexcept; + friend const string operator+(const string& a, const char c) noexcept; + friend const size_t length(const string& s) noexcept; + friend const char* const c_str(const string& s) noexcept; + friend const size_t find(const string& s1, const char* const s2, const size_t start) noexcept; + friend const string substr(const string& s, const size_t pos, const size_t n) noexcept; + friend const bool setstring(string& target, const string& s); + + const size_t len; + const char* const buf; + + const char* const mkbuf(const size_t n) { + if (n == 0) + return stringEmptyBuffer; + char* const b = gc_cnew(n + 1); + b[n] = '\0'; + return b; + } + + const char* const mksbuf(const char* const s, const size_t n) { + if (n == 0) + return stringEmptyBuffer; + char* const b = gc_cnew(n + 1); + string_memcpy(b, s, n); + b[n] = '\0'; + return b; + } + + const char* const mksbuf(const char* const s, const size_t n, const bool copy) { + if (!copy) + return s; + if (n == 0) + return stringEmptyBuffer; + char* const b = gc_cnew(n + 1); + string_memcpy(b, s, n); + b[n] = '\0'; + return b; + } + + const char* const mkcbuf(const char c, const size_t n) { + if (n == 0) + return stringEmptyBuffer; + char* const b = gc_cnew(n + 1); + memset(b, c, n); + b[n] = '\0'; + return b; + } }; /** * Adds two strings. */ -const string operator+(const string& a, const string& b) { - string s; - s.len = a.len + b.len; - s.buf = gc_cnew(s.len + 1); - string_memcpy(s.buf, a.buf, a.len); - string_memcpy(s.buf + a.len, b.buf, b.len); - s.buf[s.len] = '\0'; - return s; +inline const string operator+(const string& sa, const string& sb) noexcept { + const size_t n = sa.len + sb.len; + char* const b = gc_cnew(n + 1); + string_memcpy(b, sa.buf, sa.len); + string_memcpy(b + sa.len, sb.buf, sb.len); + b[n] = '\0'; + return string(b, n, false); } -const string operator+(const string& a, const char* b) { - string s; - const size_t blen = strlen(b); - s.len = a.len + blen; - s.buf = gc_cnew(s.len + 1); - string_memcpy(s.buf, a.buf, a.len); - string_memcpy(s.buf + a.len, b, blen); - s.buf[s.len] = '\0'; - return s; +inline const string operator+(const string& sa, const char* const sb) noexcept { + const size_t bn = strlen(sb); + const size_t n = sa.len + bn; + char* const b = gc_cnew(n + 1); + string_memcpy(b, sa.buf, sa.len); + string_memcpy(b + sa.len, sb, bn); + b[n] = '\0'; + return string(b, n, false); +} + +inline const string operator+(const string& sa, const char c) noexcept { + const size_t n = sa.len + 1; + char* const b = gc_cnew(n + 1); + string_memcpy(b, sa.buf, sa.len); + b[n - 1] = c; + b[n] = '\0'; + return string(b, n, false); } /** * Returns the length of a string. */ -const size_t length(const string& s) { +inline const size_t length(const string& s) noexcept { return s.len; } /** * Returns a string as a C zero terminated string. */ -const char* c_str(const string& s) { +inline const char* const c_str(const string& s) noexcept { return s.buf; } /** * Find the first occurrence of string s2 in s1, starting at the given position. */ -const size_t find(const string& s1, const char* s2, const size_t start) { +inline const size_t find(const string& s1, const char* const s2, const size_t start) noexcept { if (start >= s1.len) return s1.len; - const char *f = strstr(s1.buf + start, s2); + const char* const f = strstr(s1.buf + start, s2); if (f == NULL) return s1.len; return f - s1.buf; } -const size_t find(const string& s1, const char* s2) { +inline const size_t find(const string& s1, const char* const s2) noexcept { return find(s1, s2, 0); } /** * Return true if string s1 contains s2. */ -const bool contains(const string& s1, const char* s2) { +inline const bool contains(const string& s1, const char* const s2) noexcept { return find(s1, s2) != length(s1); } /** * Find the first occurence of any character from a string in a string. */ -const size_t find_first_of(const string& s1, const string& s2) { +inline const size_t find_first_of(const string& s1, const string& s2) noexcept { return strcspn(c_str(s1), c_str(s2)); } /** * Find the first occurence of a character in a string. */ -const size_t find(const string& s, const char c) { - const char* cs = c_str(s); - const char* f = strchr(cs, c); +inline const size_t find(const string& s, const char c) noexcept { + const char* const cs = c_str(s); + const char* const f = strchr(cs, c); if (f == NULL) return length(s); return f - cs; @@ -269,9 +292,9 @@ const size_t find(const string& s, const char c) { /** * Find the last occurence of a character in a string. */ -const size_t find_last(const string& s, const char c) { - const char* cs = c_str(s); - const char* f = strrchr(cs, c); +inline const size_t find_last(const string& s, const char c) noexcept { + const char* const cs = c_str(s); + const char* const f = strrchr(cs, c); if (f == NULL) return length(s); return f - cs; @@ -280,7 +303,7 @@ const size_t find_last(const string& s, const char c) { /** * Return a substring of a string. */ -const string substr(const string& s, const size_t pos, const size_t n) { +inline const string substr(const string& s, const size_t pos, const size_t n) noexcept { if (pos >= s.len) return string(); if (pos + n > s.len) @@ -288,17 +311,29 @@ const string substr(const string& s, const size_t pos, const size_t n) { return string(s.buf + pos, n); } -const string substr(const string& s, const size_t pos) { +inline const string substr(const string& s, const size_t pos) noexcept { return substr(s, pos, length(s)); } /** - * Common string constants. + * Set a string. Use with moderation. */ +/* +inline const bool setstring(string& target, const string& s) { + if (&target == &s) + return true; + memcpy((void*)&target.len, (void*)&s.len, sizeof(size_t)); + memcpy((void*)&target.buf, (void*)&s.buf, sizeof(char*)); + return true; +} +*/ -string trueString("true"); -string falseString("false"); -string emptyString(""); +/** + * Common string constants. + */ +const string trueString("true"); +const string falseString("false"); +const string emptyString(""); } diff --git a/sca-cpp/trunk/kernel/tree.hpp b/sca-cpp/trunk/kernel/tree.hpp index 89a131c324..44af09fa64 100644 --- a/sca-cpp/trunk/kernel/tree.hpp +++ b/sca-cpp/trunk/kernel/tree.hpp @@ -38,14 +38,14 @@ namespace tuscany { /** * Make a tree from a leaf and two branches. */ -template<typename T> const list<T> mktree(const T& e, const list<T>& left, const list<T>& right) { +template<typename T> inline const list<T> mktree(const T& e, const list<T>& left, const list<T>& right) { return mklist<T>(e, left, right); } /** * Find a leaf with the given key in a tree. */ -template<typename T> const list<T> assoctree(const T& k, const list<T>& tree) { +template<typename T> inline const list<T> assoctree(const T& k, const list<T>& tree) { if (isNil(tree)) return tree; if (k == car<T>(car(tree))) @@ -58,7 +58,7 @@ template<typename T> const list<T> assoctree(const T& k, const list<T>& tree) { /** * Construct a new tree from a leaf and a tree. */ -template<typename T> const list<T> constree(const T& e, const list<T>& tree) { +template<typename T> inline const list<T> constree(const T& e, const list<T>& tree) { if (isNil(tree)) return mktree(e, list<T>(), list<T>()); if (e == car(tree)) @@ -71,7 +71,7 @@ template<typename T> const list<T> constree(const T& e, const list<T>& tree) { /** * Make a tree from an unordered list of leaves. */ -template<typename T> const list<T> mktree(const list<T>& l) { +template<typename T> inline const list<T> mktree(const list<T>& l) { if (isNil(l)) return l; return constree(car(l), mktree(cdr(l))); @@ -80,7 +80,7 @@ template<typename T> const list<T> mktree(const list<T>& l) { /** * Convert a tree to an ordered list of leaves. */ -template<typename T> const list<T> flatten(const list<T>& tree) { +template<typename T> inline const list<T> flatten(const list<T>& tree) { if (isNil(tree)) return tree; return append<T>(flatten<T>(cadr(tree)), cons<T>(car(tree), flatten<T>(caddr(tree)))); @@ -89,14 +89,14 @@ template<typename T> const list<T> flatten(const list<T>& tree) { /** * Sort a list. */ -template<typename T> const list<T> sort(const list<T>& l) { +template<typename T> inline const list<T> sort(const list<T>& l) { return flatten(mktree(l)); } /** * Make a balanced tree from an ordered list of leaves. */ -template<typename T> const list<T> btreeHelper(const list<T>& elements, const size_t n) { +template<typename T> inline const list<T> btreeHelper(const list<T>& elements, const size_t n) { if (n == 0) return cons<T>(list<T>(), elements); const size_t leftSize = (n - 1) / 2; { @@ -116,7 +116,7 @@ template<typename T> const list<T> btreeHelper(const list<T>& elements, const si } } -template<typename T> const list<T> mkbtree(const list<T>& elements) { +template<typename T> inline const list<T> mkbtree(const list<T>& elements) { return car(btreeHelper<T>(elements, length(elements))); } diff --git a/sca-cpp/trunk/kernel/value.hpp b/sca-cpp/trunk/kernel/value.hpp index 206fe8b32b..60fb29070c 100644 --- a/sca-cpp/trunk/kernel/value.hpp +++ b/sca-cpp/trunk/kernel/value.hpp @@ -50,16 +50,16 @@ long int countEValues = 0; long int countCValues = 0; long int countVValues = 0; -bool resetValueCounters() { +inline const bool resetValueCounters() { countValues = countEValues = countCValues = countVValues = 0; return true; } -bool checkValueCounters() { +inline const bool checkValueCounters() { return countValues == 0; } -bool printValueCounters() { +inline const bool printValueCounters() { cout << "countValues " << countValues << endl; cout << "countEValues " << countEValues << endl; cout << "countCValues " << countCValues << endl; @@ -92,7 +92,28 @@ bool printValueCounters() { #endif +/** + * Common value constants. + */ class value; +extern const value nilValue; +extern const list<value> nilListValue; +extern const list<value> nilPairValue; +extern const value emptyStringValue; +extern const value trueValue; +extern const value falseValue; + +/** + * Common value-based lambda types. + */ +typedef lambda<const value(const list<value>&)> lvvlambda; +typedef lambda<const value(const value&)> vvlambda; +typedef lambda<const bool(const value&)> vblambda; +typedef lambda<const value()> vlambda; + +/** + * Generic value type class. + */ class value { public: @@ -101,346 +122,309 @@ public: Nil, Symbol, String, List, Number, Bool, Lambda, Ptr }; - value() : type(value::Nil) { + typedef union { + const void* mix; + const gc_ptr<list<value> > lst; + const string str; + const lvvlambda func; + const gc_ptr<value> ptr; + const double num; + const bool boo; + } ValueMix; + + inline value() noexcept : type(value::Nil) { debug_inc(countValues); debug_inc(countEValues); debug_watchValue(); } - value(const value& v) { + inline value(const value& v) noexcept : type(v.type) { debug_inc(countValues); debug_inc(countCValues); - type = v.type; - switch(type) { - case value::List: - lst() = v.lst(); - case value::Lambda: - func() = v.func(); - case value::Symbol: - str() = v.str(); - case value::String: - str() = v.str(); - case value::Number: - num() = v.num(); - case value::Bool: - boo() = v.boo(); - case value::Ptr: - ptr() = v.ptr(); - default: - break; - } + memcpy((void*)&mix, (void*)&v.mix, sizeof(ValueMix)); #ifdef WANT_MAINTAINER_WATCH watch = v.watch; #endif } - virtual ~value() { + inline value(const gc_mutable_ref<value>& r) noexcept : type(((value*)r)->type) { + debug_inc(countValues); + debug_inc(countCValues); + memcpy((void*)&mix, (void*)&(((value*)r)->mix), sizeof(ValueMix)); +#ifdef WANT_MAINTAINER_WATCH + watch = v.watch; +#endif + } + + inline virtual ~value() noexcept { debug_dec(countValues); } - value(const lambda<value(const list<value>&)>& func) : type(value::Lambda), data(vdata(func)) { + inline value(const lvvlambda& f) noexcept : type(value::Lambda), func(f) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - value(const string& str) : type(value::String), data(vdata(result(str))) { + inline value(const string& s) noexcept : type(value::String), str(s) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - value(const char* str) : type(value::Symbol), data(vdata(result(string(str)))) { + inline value(const char* s) noexcept : type(value::Symbol), str(s) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - value(const list<value>& lst) : type(value::List), data(vdata(result(lst))) { + inline value(const list<value>& l) noexcept : type(value::List), lst(new (gc_new<list<value> >()) list<value>(l)) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - value(const list<list<value> >& l) : type(value::List), data(vdata(result(listOfValues(l)))) { + inline value(const list<list<value> >& l) noexcept : type(value::List), lst(new (gc_new<list<value> >()) list<value>(listOfValues(l))) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - value(const double num) : type(value::Number), data(vdata(result(num))) { + inline value(const double d) noexcept : type(value::Number), num(d) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - value(const int num) : type(value::Number), data(vdata(result((double)num))) { + inline value(const int i) noexcept : type(value::Number), num((double)i) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - value(const bool boo) : type(value::Bool), data(vdata(result(boo))) { + inline value(const bool b) noexcept : type(value::Bool), boo(b) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - value(const gc_ptr<value> ptr) : type(value::Ptr), data(vdata(result(ptr))) { + inline value(const gc_ptr<value> p) noexcept : type(value::Ptr), ptr(p) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - value(const failable<value>& m) : type(value::List), - data(vdata(result(hasContent(m)? mklist<value>(content(m)) : rcode(m) == 1? mklist<value>(value(), reason(m)) : mklist<value>(value(), reason(m), rcode(m))))) { + inline value(const failable<value>& m) noexcept : type(value::List), + lst(new (gc_new<list<value> >()) list<value>(hasContent(m)? mklist<value>(content(m)) : + rcode(m) == 1? mklist<value>(nilValue, reason(m)) : mklist<value>(nilValue, reason(m), rcode(m)))) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - value(const maybe<value>& m) : type(value::List), - data(vdata(result(hasContent(m)? mklist<value>(content(m)) : list<value>()))) { + inline value(const maybe<value>& m) noexcept : type(value::List), + lst(new (gc_new<list<value> >()) list<value>(hasContent(m)? mklist<value>(content(m)) : nilListValue)) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - const value& operator=(const value& v) { - if(this == &v) - return *this; - type = v.type; - switch(type) { - case value::List: - lst() = v.lst(); - case value::Lambda: - func() = v.func(); - case value::Symbol: - str() = v.str(); - case value::String: - str() = v.str(); - case value::Number: - num() = v.num(); - case value::Bool: - boo() = v.boo(); - case value::Ptr: - ptr() = v.ptr(); - default: - break; - } -#ifdef WANT_MAINTAINER_WATCH - watch = v.watch; -#endif - return *this; - } + value& operator=(const value& v) = delete; - const bool operator!=(const value& v) const { + inline const bool operator!=(const value& v) const noexcept { return !this->operator==(v); } - const bool operator==(const value& v) const { + inline const bool operator==(const value& v) const noexcept { if(this == &v) return true; switch(type) { case value::Nil: return v.type == value::Nil; case value::List: - return v.type == value::List && lst()() == v.lst()(); + return v.type == value::List && *lst == *v.lst; case value::Lambda: - return v.type == value::Lambda && func() == v.func(); + return v.type == value::Lambda && func == v.func; case value::Symbol: case value::String: - return str()() == (string)v; + return (v.type == value::Symbol || v.type == value::String) && str == v.str; case value::Number: - return num()() == (double)v; + return v.type == value::Number && num == v.num; case value::Bool: - return boo()() == (bool)v; + return v.type == value::Bool && boo == v.boo; case value::Ptr: - return v.type == value::Ptr && ptr()() == v.ptr()(); + return v.type == value::Ptr && ptr == v.ptr; default: return false; } } - const bool operator<(const value& v) const { + inline const bool operator<(const value& v) const noexcept { if(this == &v) return false; switch(type) { case value::List: - return v.type == value::List && lst()() < v.lst()(); + return v.type == value::List && *lst < *v.lst; case value::Symbol: case value::String: - return str()() < (string)v; + return (v.type == value::Symbol || v.type == value::String) && str < v.str; case value::Bool: - return boo()() < (bool)v; + return v.type == value::Bool && boo < v.boo; case value::Number: - return num()() < (double)v; + return v.type == value::Number && num < v.num; default: return false; } } - const bool operator>(const value& v) const { + inline const bool operator>(const value& v) const noexcept { if(this == &v) return false; switch(type) { case value::List: - return v.type == value::List && lst()() > v.lst()(); + return v.type == value::List && *lst > *v.lst; case value::Symbol: case value::String: - return str()() > (string)v; + return (v.type == value::Symbol || v.type == value::String) && str > v.str; case value::Bool: - return boo()() > (bool)v; + return v.type == value::Bool && boo > v.boo; case value::Number: - return num()() > (double)v; + return v.type == value::Number && num > v.num; default: return false; } } - const value operator()(const list<value>& args) const { - return func()(args); + inline const value operator()(const list<value>& args) const noexcept { + return func(args); } - operator const string() const { + inline operator const string() const noexcept { switch(type) { case value::Symbol: case value::String: - return str()(); + return str; case value::Number: { ostringstream os; - os << num()(); + os << num; return tuscany::str(os); } case value::Bool: - return boo()()? trueString : falseString; + return boo? trueString : falseString; default: return emptyString; } } - operator const double() const { + inline operator const double() const noexcept { switch(type) { case value::Symbol: case value::String: - return atof(c_str(str()())); + return atof(c_str(str)); case value::Number: - return (double)num()(); + return (double)num; case value::Bool: - return boo()()? 1.0 : 0.0; + return boo? 1.0 : 0.0; default: return 0.0; } } - operator const int() const { + inline operator const int() const noexcept { switch(type) { case value::Symbol: case value::String: - return atoi(c_str(str()())); + return atoi(c_str(str)); case value::Number: - return (int)num()(); + return (int)num; case value::Bool: - return boo()()? 1 : 0; + return boo? 1 : 0; default: return 0; } } - operator const bool() const { + inline operator const bool() const noexcept { switch(type) { case value::Symbol: case value::String: - return str()() == string("true"); + return str == trueString; case value::Number: - return (int)num()() != 0; + return num != 0.0; case value::Bool: - return boo()(); + return boo; default: - return 0; + return false; } } - operator const gc_ptr<value>() const { - return ptr()(); + inline operator const gc_ptr<value>() const noexcept { + return ptr; } - operator const list<value>() const { - return lst()(); + inline operator const list<value>() const noexcept { + return *lst; } - operator const list<list<value> >() const { - return listOfListOfValues(lst()()); + inline operator const list<list<value> >() const noexcept { + return listOfListOfValues(*lst); } - operator const lambda<value(const list<value>&)>() const { - return func(); + inline operator const lvvlambda() const noexcept { + return func; } private: - template<typename T> lambda<T>& vdata() const { - return *reinterpret_cast<lambda<T> *> (const_cast<lambda<char()> *> (&data)); - } - - template<typename T> const lambda<char()>& vdata(const T& v) const { - return *reinterpret_cast<const lambda<char()> *> (&v); - } - - lambda<double()>& num() const { - return vdata<double()> (); - } - - lambda<bool()>& boo() const { - return vdata<bool()> (); - } - - lambda<gc_ptr<value>()>& ptr() const { - return vdata<gc_ptr<value>()> (); - } - - lambda<string()>& str() const { - return vdata<string()> (); - } - - lambda<list<value>()>& lst() const { - return vdata<list<value>()> (); - } - - lambda<value(const list<value>&)>& func() const { - return vdata<value(const list<value>&)> (); - } - - const list<value> listOfValues(const list<list<value> >& l) const { + inline const list<value> listOfValues(const list<list<value> >& l) const noexcept { if (isNil(l)) - return list<value>(); + return nilListValue; return cons<value>(car(l), listOfValues(cdr(l))); } - const list<list<value> > listOfListOfValues(const list<value>& l) const { + inline const list<list<value> > listOfListOfValues(const list<value>& l) const noexcept { if (isNil(l)) return list<list<value> >(); - return cons<list<value> >(list<value>(car(l)), listOfListOfValues(cdr(l))); + return cons<list<value> >(car(l).type == value::List? list<value>(car(l)) : nilPairValue, listOfListOfValues(cdr(l))); } - friend ostream& operator<<(ostream&, const value&); - friend const value::ValueType type(const value& v); + friend ostream& operator<<(ostream&, const value&) noexcept; + friend const value::ValueType type(const value& v) noexcept; + friend const bool setvalue(value& target, const value& v); #ifdef WANT_MAINTAINER_WATCH friend const string watchValue(const value& v); string watch; #endif - ValueType type; - lambda<char()> data; + const ValueType type; + union { + void* mix; + const gc_ptr<list<value> > lst; + const string str; + const lvvlambda func; + const gc_ptr<value> ptr; + const double num; + const bool boo; + }; }; +/** + * Common value constants. + */ +const value nilValue; +const list<value> nilListValue = list<value>(); +const list<value> nilPairValue = mklist<value>(nilValue, nilValue); +const value emptyStringValue(emptyString); +const value trueValue(true); +const value falseValue(false); + #ifdef WANT_MAINTAINER_WATCH /** * Debug utility used to write the contents of a value to a string, easier * to watch than the value itself in a debugger. */ -const string watchValue(const value& v) { +inline const string watchValue(const value& v) { if (v.type == value::List) return watchList<value>(v); odebugstream os; @@ -453,7 +437,7 @@ const string watchValue(const value& v) { /** * Write an escape string to a buffer. */ -const char* escapestr(const char* s, char* buf) { +inline const char* escapestr(const char* const s, char* const buf) noexcept { if (*s == '\0') { *buf = '\0'; return buf; @@ -470,7 +454,7 @@ const char* escapestr(const char* s, char* buf) { /** * Write an escaped string value to a stream. */ -ostream& escvwrite(const string& str, ostream& out) { +inline ostream& escvwrite(const string& str, ostream& out) noexcept { char* buf = gc_cnew(length(str) * 2 + 1); escapestr(c_str(str), buf); out << buf; @@ -480,30 +464,29 @@ ostream& escvwrite(const string& str, ostream& out) { /** * Write a value to a stream. */ -ostream& operator<<(ostream& out, const value& v) { +inline ostream& operator<<(ostream& out, const value& v) noexcept { switch(v.type) { case value::List: - return out << v.lst()(); + return out << *v.lst; case value::Lambda: - return out << "lambda::" << v.func(); + return out << "lambda::" << v.func; case value::Symbol: - return out << v.str()(); + return out << v.str; case value::String: out << '\"'; - escvwrite(v.str()(), out); + escvwrite(v.str, out); return out << '\"'; case value::Number: - return out << v.num()(); + return out << v.num; case value::Bool: - if(v.boo()()) - return out << "true"; + if(v.boo) + return out << trueString; else - return out << "false"; + return out << falseString; case value::Ptr: { - const gc_ptr<value> p = v.ptr()(); - if (p == gc_ptr<value>(NULL)) + if (v.ptr == gc_ptr<value>(NULL)) return out << "gc_ptr::null"; - return out << "gc_ptr::" << p; + return out << "gc_ptr::" << v.ptr; } default: return out << "nil"; @@ -513,70 +496,70 @@ ostream& operator<<(ostream& out, const value& v) { /** * Returns the type of a value. */ -const value::ValueType type(const value& v) { +inline const value::ValueType type(const value& v) noexcept { return v.type; } /** * Returns true if a value is nil. */ -const bool isNil(const value& v) { +inline const bool isNil(const value& v) noexcept { return type(v) == value::Nil; } /** * Returns true if a value is a lambda. */ -const bool isLambda(const value& v) { +inline const bool isLambda(const value& v) noexcept { return type(v) == value::Lambda; } /** * Returns true if a value is a string. */ -const bool isString(const value& v) { +inline const bool isString(const value& v) noexcept { return type(v) == value::String; } /** * Returns true if a value is a symbol. */ -const bool isSymbol(const value& v) { +inline const bool isSymbol(const value& v) noexcept { return type(v) == value::Symbol; } /** * Returns true if a value is a list. */ -const bool isList(const value& v) { +inline const bool isList(const value& v) noexcept { return type(v) == value::List; } /** * Returns true if a value is a number. */ -const bool isNumber(const value& v) { +inline const bool isNumber(const value& v) noexcept { return type(v) == value::Number; } /** * Returns true if a value is a boolean. */ -const bool isBool(const value& v) { +inline const bool isBool(const value& v) noexcept { return type(v) == value::Bool; } /** * Returns true if a value is a pointer. */ -const bool isPtr(const value& v) { +inline const bool isPtr(const value& v) noexcept { return type(v) == value::Ptr; } /** * Returns true if a value is a tagged list. */ -const bool isTaggedList(const value& exp, value tag) { +inline const bool isTaggedList(const value& exp, const value& tag) noexcept { if(isList(exp) && !isNil((list<value>)exp)) return car((list<value>)exp) == tag; return false; @@ -585,16 +568,16 @@ const bool isTaggedList(const value& exp, value tag) { /** * Make a list of values from a list of other things. */ -template<typename T> const list<value> mkvalues(const list<T>& l) { +template<typename T> inline const list<value> mkvalues(const list<T>& l) noexcept { if (isNil(l)) - return list<value>(); + return nilListValue; return cons<value>(car(l), mkvalues(cdr(l))); } /** * Convert a list of values to a list of other things. */ -template<typename T> const list<T> convertValues(const list<value>& l) { +template<typename T> inline const list<T> convertValues(const list<value>& l) noexcept { if (isNil(l)) return list<T>(); return cons<T>(car(l), convertValues<T>(cdr(l))); @@ -603,7 +586,7 @@ template<typename T> const list<T> convertValues(const list<value>& l) { /** * Convert a path string value to a list of values. */ -const list<string> pathTokens(const char* p) { +inline const list<string> pathTokens(const char* const p) noexcept { if (p == NULL || p[0] == '\0') return list<string>(); if (p[0] == '/') @@ -611,23 +594,23 @@ const list<string> pathTokens(const char* p) { return tokenize("/", p); } -const list<value> pathValues(const value& p) { +inline const list<value> pathValues(const value& p) noexcept { return mkvalues(pathTokens(c_str(p))); } /** * Convert a path represented as a list of values to a string value. */ -const value path(const list<value>& p) { +inline const value path(const list<value>& p) noexcept { if (isNil(p)) - return ""; - return string("/") + car(p) + path(cdr(p)); + return emptyString; + return string("/") + (string)car(p) + (string)path(cdr(p)); } /** * Make a uuid value. */ -const value mkuuid() { +inline const value mkuuid() noexcept { apr_uuid_t id; apr_uuid_get(&id); char buf[APR_UUID_FORMATTED_LENGTH]; @@ -638,19 +621,33 @@ const value mkuuid() { /** * Make a random alphanumeric value. */ -const int intrand() { +inline const int intrand() noexcept { const apr_uint64_t now = apr_time_now(); srand((unsigned int)(((now >> 32) ^ now) & 0xffffffff)); return rand() & 0x0FFFF; } -const value mkrand() { +inline const value mkrand() noexcept { char buf[32]; - const char* an = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + const char* const an = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; for (int i =0; i < 32; i++) buf[i] = an[intrand() % 62]; return value(string(buf, 32)); } +/** + * Set a value. Use with moderation. + */ +inline const bool setvalue(value& target, const value& v) { + if (&target == &v) + return true; +#ifdef WANT_MAINTAINER_WATCH + memcpy(&target.watch, &v.watch, sizeof(string)); +#endif + memcpy((void*)&target.type, (void*)&v.type, sizeof(value::ValueType)); + memcpy((void*)&target.mix, (void*)&v.mix, sizeof(value::ValueMix)); + return true; +} + } #endif /* tuscany_value_hpp */ diff --git a/sca-cpp/trunk/kernel/xml-test.cpp b/sca-cpp/trunk/kernel/xml-test.cpp deleted file mode 100644 index 0523cc74a6..0000000000 --- a/sca-cpp/trunk/kernel/xml-test.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/* - * 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 XML handling functions. - */ - -#include <assert.h> -#include "stream.hpp" -#include "string.hpp" -#include "list.hpp" -#include "value.hpp" -#include "element.hpp" -#include "xml.hpp" - -namespace tuscany { - -const string currencyXML = -"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" -"<composite xmlns=\"http://docs.oasis-open.org/ns/opencsa/sca/200912\" targetNamespace=\"http://services\" name=\"currency\">\n" -" <component name=\"CurrencyConverterWebService\">\n" -" <implementation.java class=\"services.CurrencyConverterImpl\"/>\n" -" <service name=\"CurrencyConverter\">\n" -" <binding.ws/>\n" -" </service>\n" -" </component>\n" -" <component name=\"CurrencyConverterWebService2\">\n" -" <implementation.java class=\"services.CurrencyConverterImpl2\"/>\n" -" <service name=\"CurrencyConverter2\">\n" -" <binding.atom/>\n" -" </service>\n" -" <property name=\"currency\">US</property>\n" -" </component>\n" -"</composite>\n"; - -const string customerXML = -"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" -"<customer>\n" -" <name>jdoe</name>\n" -" <address>\n" -" <city>san francisco</city>\n" -" <state>ca</state>\n" -" </address>\n" -" <account>\n" -" <id>1234</id>\n" -" <balance>1000</balance>\n" -" </account>\n" -" <account>\n" -" <id>6789</id>\n" -" <balance>2000</balance>\n" -" </account>\n" -" <account>\n" -" <id>4567</id>\n" -" <balance>3000</balance>\n" -" </account>\n" -"</customer>\n"; - -const string abcXML = -"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" -"<a>\n" -" <m>abc</m>\n" -" <m>def</m>\n" -" <m>xyz</m>\n" -" <m>tuv</m>\n" -"</a>\n"; - -const string xyzXML = -"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" -"<a>\n" -" <m>\n" -" <id>123</id>\n" -" <name>abc</name>\n" -" </m>\n" -" <m>\n" -" <id>234</id>\n" -" <name>def</name>\n" -" </m>\n" -" <m>\n" -" <id>345</id>\n" -" <name>xyz</name>\n" -" </m>\n" -" <m>\n" -" <id>456</id>\n" -" <name>tuv</name>\n" -" </m>\n" -"</a>\n"; - -const bool isName(const value& token) { - return isTaggedList(token, attribute) && attributeName(token) == "name"; -} - -bool testReadXML() { - { - istringstream is(customerXML); - const list<value> c = readXML(streamList(is)); - } - { - istringstream is(currencyXML); - const list<value> c = readXML(streamList(is)); - - const value composite = car(c); - assert(isTaggedList(composite, element)); - assert(elementName(composite) == "composite"); - assert(attributeValue(car(filter<value>(isName, elementChildren(composite)))) == string("currency")); - } - return true; -} - -ostream* xmlWriter(const string& s, ostream* os) { - (*os) << s; - return os; -} - -bool testWriteXML() { - { - istringstream is(customerXML); - const list<value> c = readXML(streamList(is)); - ostringstream os; - writeXML<ostream*>(xmlWriter, &os, c); - assert(str(os) == customerXML); - } - { - istringstream is(currencyXML); - const list<value> c = readXML(streamList(is)); - ostringstream os; - writeXML<ostream*>(xmlWriter, &os, c); - assert(str(os) == currencyXML); - } - return true; -} - -bool testElements() { - { - const list<value> ad = mklist<value>(mklist<value>("city", string("san francisco")), mklist<value>("state", string("ca"))); - const list<value> ac1 = mklist<value>(mklist<value>("id", string("1234")), mklist<value>("balance", 1000)); - const list<value> ac2 = mklist<value>(mklist<value>("id", string("6789")), mklist<value>("balance", 2000)); - const list<value> ac3 = mklist<value>(mklist<value>("id", string("4567")), mklist<value>("balance", 3000)); - { - const list<value> c = mklist<value>(mklist<value>("customer", mklist<value>("name", string("jdoe")), cons<value>("address", ad), mklist<value>("account", mklist<value>(ac1, ac2, ac3)))); - const list<value> e = valuesToElements(c); - const list<value> v = elementsToValues(e); - assert(v == c); - - ostringstream os; - writeXML<ostream*>(xmlWriter, &os, e); - assert(str(os) == customerXML); - } - { - const list<value> c = mklist<value>(mklist<value>("customer", mklist<value>("name", string("jdoe")), cons<value>("address", ad), cons<value>("account", ac1), cons<value>("account", ac2), cons<value>("account", ac3))); - const list<value> e = valuesToElements(c); - const list<value> v = elementsToValues(e); - - ostringstream os; - writeXML<ostream*>(xmlWriter, &os, e); - assert(str(os) == customerXML); - } - } - { - istringstream is(abcXML); - const list<value> c = readXML(streamList(is)); - const list<value> v = elementsToValues(c); - const list<value> e = valuesToElements(v); - ostringstream os; - writeXML<ostream*>(xmlWriter, &os, e); - assert(str(os) == abcXML); - } - { - istringstream is(xyzXML); - const list<value> c = readXML(streamList(is)); - const list<value> v = elementsToValues(c); - const list<value> e = valuesToElements(v); - ostringstream os; - writeXML<ostream*>(xmlWriter, &os, e); - assert(str(os) == xyzXML); - } - { - istringstream is(customerXML); - const list<value> c = readXML(streamList(is)); - const list<value> v = elementsToValues(c); - const list<value> e = valuesToElements(v); - ostringstream os; - writeXML<ostream*>(xmlWriter, &os, e); - assert(str(os) == customerXML); - } - return true; -} - -bool testValues() { - { - const list<value> l = mklist<value>(list<value>() + "ns1:echoString" + (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo")) + (list<value>() + "text" + string("Hello World!"))); - const list<value> e = valuesToElements(l); - const failable<list<string> > lx = writeXML(e); - ostringstream os; - write(content(lx), os); - istringstream is(str(os)); - const list<value> x = readXML(streamList(is)); - const list<value> v = elementsToValues(x); - assert(v == l); - } - return true; -} - -} - -int main() { - tuscany::gc_scoped_pool p; - tuscany::cout << "Testing..." << tuscany::endl; - - tuscany::testReadXML(); - tuscany::testWriteXML(); - tuscany::testElements(); - tuscany::testValues(); - - tuscany::cout << "OK" << tuscany::endl; - - return 0; -} diff --git a/sca-cpp/trunk/kernel/xml.hpp b/sca-cpp/trunk/kernel/xml.hpp deleted file mode 100644 index d00a2905fb..0000000000 --- a/sca-cpp/trunk/kernel/xml.hpp +++ /dev/null @@ -1,412 +0,0 @@ -/* - * 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$ */ - -#ifndef tuscany_xml_hpp -#define tuscany_xml_hpp - -/** - * XML read/write functions. - */ - -#include <libxml/xmlreader.h> -#include <libxml/xmlwriter.h> -#include <libxml/xmlschemas.h> -#include <libxml/globals.h> -#include "string.hpp" -#include "list.hpp" -#include "stream.hpp" -#include "value.hpp" -#include "element.hpp" -#include "monad.hpp" - -namespace tuscany { - -/** - * APR-based memory management functions. - */ - - -/** - * Initializes the libxml2 library. - */ -class XMLParser { -public: - XMLParser() { - debug("xml::XMLParser"); - xmlMemSetup(gc_pool_free, gc_pool_malloc, gc_pool_realloc, gc_pool_strdup); - xmlInitParser(); - } - - ~XMLParser() { - } -} xmlParser; - -/** - * Encapsulates a libxml2 xmlTextReader and its state. - */ -class XMLReader { -public: - enum TokenType { - None = 0, Element = 1, Attribute = 2, Text = 3, EndElement = 15, Identifier = 100, End = 101 - }; - - XMLReader(xmlTextReaderPtr xml) : xml(xml), owner(true), tokenType(None), isEmptyElement(false), hasValue(false), hasAttributes(false) { - debug("xml::XMLReader::xml"); - xmlTextReaderSetParserProp(xml, XML_PARSER_DEFAULTATTRS, 1); - xmlTextReaderSetParserProp(xml, XML_PARSER_SUBST_ENTITIES, 1); - } - - XMLReader(const XMLReader& r) : xml(r.xml), owner(false), tokenType(r.tokenType), isEmptyElement(r.isEmptyElement), hasValue(r.hasValue), hasAttributes(r.hasAttributes) { - 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; - xmlTextReaderClose(xml); - xmlFreeTextReader(xml); - } - - /** - * Read the next XML token and return its type. - */ - int read() { - if (tokenType == End) - return tokenType; - if (tokenType == Element) { - isEmptyElement = xmlTextReaderIsEmptyElement(xml); - hasAttributes = xmlTextReaderHasAttributes(xml); - return tokenType = Identifier; - } - if (tokenType == Identifier && hasAttributes && xmlTextReaderMoveToFirstAttribute(xml) == 1) - return tokenType = Attribute; - if (tokenType == Attribute && xmlTextReaderMoveToNextAttribute(xml) == 1) - return tokenType = Attribute; - if (isEmptyElement && (tokenType == Identifier || tokenType == Attribute)) - return tokenType = EndElement; - if (!xmlTextReaderRead(xml)) - return tokenType = End; - return tokenType = xmlTextReaderNodeType(xml); - } - - operator xmlTextReaderPtr() const { - return xml; - } - -private: - xmlTextReaderPtr xml; - bool owner; - int tokenType; - bool isEmptyElement; - bool hasValue; - bool hasAttributes; -}; - -/** - * Constants used to tag XML tokens. - */ -const value endElement("<"); -const value startElement(">"); - -/** - * Read an XML identifier. - */ -const value readIdentifier(XMLReader& reader) { - const char* name = (const char*)xmlTextReaderConstName(reader); - return name; -} - -/** - * Read XML text. - */ -const value readText(XMLReader& reader) { - const char *val = (const char*)xmlTextReaderConstValue(reader); - return string(val); -} - -/** - * Read an XML attribute. - */ -const value readAttribute(XMLReader& reader) { - const char *name = (const char*)xmlTextReaderConstName(reader); - const char *val = (const char*)xmlTextReaderConstValue(reader); - return mklist<value>(attribute, name, string(val)); -} - -/** - * Read an XML token. - */ -const value readToken(XMLReader& reader) { - const int tokenType = reader.read(); - if (tokenType == XMLReader::None || tokenType == XMLReader::End) - return value(); - if (tokenType == XMLReader::Element) - return startElement; - if (tokenType == XMLReader::Identifier) - return readIdentifier(reader); - if (tokenType == XMLReader::Attribute) - return readAttribute(reader); - if (tokenType == XMLReader::Text) - return readText(reader); - if (tokenType == XMLReader::EndElement) - return endElement; - return readToken(reader); -} - -/** - * Read a list of values from XML tokens. - */ -const list<value> readList(const list<value>& listSoFar, XMLReader& reader) { - const value token = readToken(reader); - if(isNil(token) || endElement == token) - return reverse(listSoFar); - if(startElement == token) - return readList(cons<value>(readList(mklist(element), reader), listSoFar), reader); - return readList(cons(token, listSoFar), reader); -} - -/** - * Read a list of values from a libxml2 XML reader. - */ -const list<value> read(XMLReader& reader) { - value nextToken = readToken(reader); - if (startElement == nextToken) - return mklist<value>(readList(mklist(element), reader)); - return list<value>(); -} - -/** - * Context passed to the read callback function. - */ -class XMLReadContext { -public: - XMLReadContext(const list<string>& ilist) : ilist(ilist) { - } - list<string> ilist; -}; - -/** - * Callback function called by libxml2 to read XML. - */ -int readCallback(void *context, char* buffer, int len) { - XMLReadContext& rc = *static_cast<XMLReadContext*>(context); - if (isNil(rc.ilist)) - return 0; - const list<string> f(fragment(rc.ilist, len)); - const string s(car(f)); - rc.ilist = cdr(f); - memcpy(buffer, c_str(s), length(s)); - return (int)length(s); -} - -/** - * Return true if a list of strings contains an XML document. - */ -const bool isXML(const list<string>& ls) { - if (isNil(ls)) - return false; - return substr(car(ls), 0, 5) == "<?xml"; -} - -/** - * Read a list of values from a list of strings representing an XML document. - */ -const list<value> readXML(const list<string>& ilist) { - debug(ilist, "xml::readXML"); - XMLReadContext cx(ilist); - xmlTextReaderPtr xml = xmlReaderForIO(readCallback, NULL, &cx, NULL, NULL, XML_PARSE_NONET | XML_PARSE_NODICT); - if (xml == NULL) - return list<value>(); - XMLReader reader(xml); - return read(reader); -} - -/** - * Default encoding used to write XML documents. - */ -const char* encoding = "UTF-8"; - - -/** - * Write a list of XML element or attribute tokens. - */ -const list<value> expandElementValues(const value& n, const list<value>& l) { - if (isNil(l)) - return l; - return cons<value>(value(cons<value>(element, cons<value>(n, isList(car(l))? (list<value>)car(l) : mklist(car(l))))), expandElementValues(n, cdr(l))); -} - -const failable<bool> writeList(const list<value>& l, const xmlTextWriterPtr xml) { - if (isNil(l)) - return true; - - // Write an attribute - const value token(car(l)); - if (isTaggedList(token, attribute)) { - if (xmlTextWriterWriteAttribute(xml, (const xmlChar*)c_str(string(attributeName(token))), (const xmlChar*)c_str(string(attributeValue(token)))) < 0) - return mkfailure<bool>("xmlTextWriterWriteAttribute failed"); - - } else if (isTaggedList(token, element)) { - - // Write an element containing a value - if (elementHasValue(token)) { - const value v = elementValue(token); - if (isList(v)) { - - // Write an element per entry in a list of values - const list<value> e = expandElementValues(elementName(token), v); - writeList(e, xml); - - } else { - - // Write an element with a single value - if (xmlTextWriterStartElement(xml, (const xmlChar*)c_str(string(elementName(token)))) < 0) - return mkfailure<bool>("xmlTextWriterStartElement failed"); - - // Write its children - const failable<bool> w = writeList(elementChildren(token), xml); - if (!hasContent(w)) - return w; - - if (xmlTextWriterEndElement(xml) < 0) - return mkfailure<bool>("xmlTextWriterEndElement failed"); - } - } - else { - - // Write an element - if (xmlTextWriterStartElement(xml, (const xmlChar*)c_str(string(elementName(token)))) < 0) - return mkfailure<bool>("xmlTextWriterStartElement failed"); - - // Write its children - const failable<bool> w = writeList(elementChildren(token), xml); - if (!hasContent(w)) - return w; - - if (xmlTextWriterEndElement(xml) < 0) - return mkfailure<bool>("xmlTextWriterEndElement failed"); - } - } else { - - // Write XML text - if (xmlTextWriterWriteString(xml, (const xmlChar*)c_str(string(token))) < 0) - return mkfailure<bool>("xmlTextWriterWriteString failed"); - } - - // Go on - return writeList(cdr(l), xml); -} - -/** - * Write a list of values to a libxml2 XML writer. - */ -const failable<bool> write(const list<value>& l, const xmlTextWriterPtr xml, bool xmlTag) { - if (xmlTag) { - if (xmlTextWriterStartDocument(xml, NULL, encoding, NULL) < 0) - return mkfailure<bool>("xmlTextWriterStartDocument failed"); - } - - const failable<bool> w = writeList(l, xml); - if (!hasContent(w)) - return w; - - if (xmlTag) { - if (xmlTextWriterEndDocument(xml) < 0) - return mkfailure<bool>("xmlTextWriterEndDocument failed"); - } - return true; -} - -/** - * Context passed to the write callback function. - */ -template<typename R> class XMLWriteContext { -public: - XMLWriteContext(const lambda<R(const string&, const R)>& reduce, const R& accum) : reduce(reduce), accum(accum) { - } - const lambda<R(const string&, const R)> reduce; - R accum; -}; - -/** - * Callback function called by libxml2 to write XML out. - */ -template<typename R> int writeCallback(void *context, const char* buffer, int len) { - XMLWriteContext<R>& cx = *static_cast<XMLWriteContext<R>*>(context); - cx.accum = cx.reduce(string(buffer, len), cx.accum); - return len; -} - -/** - * Convert a list of values to an XML document. - */ -template<typename R> const failable<R> writeXML(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& l, const bool xmlTag) { - XMLWriteContext<R> cx(reduce, initial); - xmlOutputBufferPtr out = xmlOutputBufferCreateIO(writeCallback<R>, NULL, &cx, NULL); - if (out == NULL) - return mkfailure<R>("xmlOutputBufferCreateIO failed"); - xmlTextWriterPtr xml = xmlNewTextWriter(out); - if (xml == NULL) - return mkfailure<R>("xmlNewTextWriter failed"); - xmlTextWriterSetIndent(xml, 1); - - const failable<bool> w = write(l, xml, xmlTag); - xmlFreeTextWriter(xml); - if (!hasContent(w)) { - return mkfailure<R>(w); - } - return cx.accum; -} - -template<typename R> const failable<R> writeXML(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& l) { - return writeXML(reduce, initial, l, true); -} - -/** - * Convert a list of values to a list of strings representing an XML document. - */ -const failable<list<string> > writeXML(const list<value>& l, const bool xmlTag) { - debug(l, "xml::writeXML"); - const failable<list<string> > ls = writeXML<list<string> >(rcons<string>, list<string>(), l, xmlTag); - if (!hasContent(ls)) - return ls; - return reverse(list<string>(content(ls))); -} - -const failable<list<string> > writeXML(const list<value>& l) { - return writeXML(l, true); -} - -} -#endif /* tuscany_xml_hpp */ diff --git a/sca-cpp/trunk/kernel/xsd-test.cpp b/sca-cpp/trunk/kernel/xsd-test.cpp deleted file mode 100644 index fbd2ee6dca..0000000000 --- a/sca-cpp/trunk/kernel/xsd-test.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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 validation of a composite file against an SCDL schema. - */ - -#include "string.hpp" -#include "fstream.hpp" -#include <libxml/xmlreader.h> -#include <libxml/xmlschemas.h> - -namespace tuscany { - -bool printNode(xmlTextReaderPtr reader) { - const xmlChar* name = xmlTextReaderConstName(reader); - if(name == NULL) - name = (xmlChar *)"<unknown>"; - const xmlChar* value = xmlTextReaderConstValue(reader); - cerr << xmlTextReaderDepth(reader) << " " << xmlTextReaderNodeType(reader) << " " << name << " " - << xmlTextReaderIsEmptyElement(reader) << " " << xmlTextReaderHasValue(reader); - if(value == NULL) - cerr << endl; - else - cerr << value << endl; - return true; -} - -int xmlRead(void *context, char* buffer, int len) { - return (int)fread(buffer, 1, len, (FILE*)context); -} - -int xmlClose(void *context) { - fclose((FILE*)context); - return 0; -} - -bool readFile(const char*xsdfilename, const char *filename) { - cout << "Loading schema " << xsdfilename << endl; - const xmlDocPtr xsddoc = xmlReadFile(xsdfilename, NULL, XML_PARSE_NONET); - const xmlSchemaParserCtxtPtr xsdctx = xmlSchemaNewDocParserCtxt(xsddoc); - const xmlSchemaPtr xsd = xmlSchemaParse(xsdctx); - const xmlSchemaValidCtxtPtr validctx = xmlSchemaNewValidCtxt(xsd); - - cout << "Reading file " << filename << endl; - FILE* file = fopen(filename, "r"); - if (file != NULL) { - const xmlTextReaderPtr reader = xmlReaderForIO(xmlRead, xmlClose, file, filename, NULL, XML_PARSE_NONET); - xmlTextReaderSetParserProp(reader, XML_PARSER_DEFAULTATTRS, 1); - xmlTextReaderSetParserProp(reader, XML_PARSER_SUBST_ENTITIES, 1); - - if(reader != NULL) { - xmlTextReaderSchemaValidateCtxt(reader, validctx, 0); - - int rc; - while((rc = xmlTextReaderRead(reader)) == 1) { - printNode(reader); - } - if(xmlTextReaderIsValid(reader) != 1) - cout << "Could not validate document" << endl; - xmlFreeTextReader(reader); - if(rc != 0) - cout << "Could not parse document" << endl; - } else - cout << "Could not create parser" << endl; - } else - cout << "Could not open document" << endl; - - xmlSchemaFreeValidCtxt(validctx); - xmlSchemaFree(xsd); - xmlSchemaFreeParserCtxt(xsdctx); - - return true; -} - -} - -int main(int argc, char **argv) { - tuscany::cout << "Testing..." << tuscany::endl; - if(argc != 3) - return 1; - - tuscany::readFile(argv[1], argv[2]); - - xmlCleanupParser(); - - tuscany::cout << "OK" << tuscany::endl; - return 0; -} |