From bd4c1d47aeaf1d4bca76d5713e705b0869d3f2f7 Mon Sep 17 00:00:00 2001 From: jsdelfino Date: Sat, 26 Dec 2009 03:25:25 +0000 Subject: Added missing const qualifiers, macros and util functions to help debugging, and a simple balanced tree implementation for use in lookup tables. git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@893938 13f79535-47bb-0310-9956-ffa450edef68 --- sca-cpp/trunk/kernel/debug.hpp | 9 +- sca-cpp/trunk/kernel/dynlib-test.cpp | 4 +- sca-cpp/trunk/kernel/element.hpp | 2 +- sca-cpp/trunk/kernel/function.hpp | 6 +- sca-cpp/trunk/kernel/gc.hpp | 7 +- sca-cpp/trunk/kernel/kernel-test.cpp | 313 ++++++++++------------------------- sca-cpp/trunk/kernel/list.hpp | 127 +++++++++++--- sca-cpp/trunk/kernel/monad.hpp | 26 +-- sca-cpp/trunk/kernel/parallel.hpp | 2 +- sca-cpp/trunk/kernel/tree.hpp | 125 ++++++++++++++ sca-cpp/trunk/kernel/value.hpp | 226 +++++++++++++++++-------- sca-cpp/trunk/kernel/xml.hpp | 6 +- sca-cpp/trunk/modules/atom/atom.hpp | 4 +- sca-cpp/trunk/modules/http/curl.hpp | 18 +- sca-cpp/trunk/modules/json/json.hpp | 6 +- 15 files changed, 515 insertions(+), 366 deletions(-) create mode 100644 sca-cpp/trunk/kernel/tree.hpp (limited to 'sca-cpp/trunk') diff --git a/sca-cpp/trunk/kernel/debug.hpp b/sca-cpp/trunk/kernel/debug.hpp index 8dad5fdd3c..c06fe55f4a 100644 --- a/sca-cpp/trunk/kernel/debug.hpp +++ b/sca-cpp/trunk/kernel/debug.hpp @@ -26,6 +26,9 @@ * Functions to help log and debug. */ +#include +#include + namespace tuscany { @@ -35,7 +38,7 @@ namespace tuscany * Debug log. */ template const bool debug(const V& v, const std::string& msg) { - std::cerr<< msg << ": " << v << std::endl; + std::cerr << msg << ": " << v << std::endl; return true; } @@ -52,6 +55,9 @@ bool debug_dec(long int& c) { return true; } +/** + * Attribute used to mark unused parameters. + */ #define unused __attribute__ ((unused)) #else @@ -60,6 +66,7 @@ bool debug_dec(long int& c) { #define debug_inc(c) #define debug_dec(c) + #define unused #endif diff --git a/sca-cpp/trunk/kernel/dynlib-test.cpp b/sca-cpp/trunk/kernel/dynlib-test.cpp index 3cc666df1a..9d0e6a2186 100644 --- a/sca-cpp/trunk/kernel/dynlib-test.cpp +++ b/sca-cpp/trunk/kernel/dynlib-test.cpp @@ -42,8 +42,8 @@ extern "C" { return tuscany::test::cppsquare(x); } - const tuscany::lambda csquarel() { - return tuscany::lambda(tuscany::test::cppsquare); + const tuscany::lambda csquarel() { + return tuscany::lambda(tuscany::test::cppsquare); } } diff --git a/sca-cpp/trunk/kernel/element.hpp b/sca-cpp/trunk/kernel/element.hpp index 2b5336ba5c..612752d1df 100644 --- a/sca-cpp/trunk/kernel/element.hpp +++ b/sca-cpp/trunk/kernel/element.hpp @@ -247,7 +247,7 @@ struct selectorLambda { } }; -const lambda selector(const list s) { +const lambda selector(const list s) { return selectorLambda(s); } diff --git a/sca-cpp/trunk/kernel/function.hpp b/sca-cpp/trunk/kernel/function.hpp index fb2ad296d7..54784b5549 100644 --- a/sca-cpp/trunk/kernel/function.hpp +++ b/sca-cpp/trunk/kernel/function.hpp @@ -140,11 +140,11 @@ public: debug_inc(countELambdas); } - template lambda(const F f) : callable(0) { - typedef typename CallableType::template Proxy ProxyType; - + template lambda(const F f) { debug_inc(countLambdas); debug_inc(countFLambdas); + + typedef typename CallableType::template Proxy ProxyType; callable = gc_counting_ptr(new ProxyType(f)); } diff --git a/sca-cpp/trunk/kernel/gc.hpp b/sca-cpp/trunk/kernel/gc.hpp index bb5bbccb24..c9a1a35756 100644 --- a/sca-cpp/trunk/kernel/gc.hpp +++ b/sca-cpp/trunk/kernel/gc.hpp @@ -35,11 +35,10 @@ namespace tuscany /** * Macros used to add or subtract values to reference counters. - * In a multithreaded environment, define MTHREAD_GC to use - * the GCC __sync_add_and_fetch and __sync_sub_and_fetch built - * in functions. + * In a multithreaded environment, use the GCC __sync_add_and_fetch + * and __sync_sub_and_fetch built in functions. */ -#ifdef MTHREAD_GC +#ifdef _REENTRANT #define gc_add_and_fetch(t, v) __sync_add_and_fetch(&(t), v) #define gc_sub_and_fetch(t, v) __sync_sub_and_fetch(&(t), v) diff --git a/sca-cpp/trunk/kernel/kernel-test.cpp b/sca-cpp/trunk/kernel/kernel-test.cpp index 388fbf7436..8a5e4a704d 100644 --- a/sca-cpp/trunk/kernel/kernel-test.cpp +++ b/sca-cpp/trunk/kernel/kernel-test.cpp @@ -20,24 +20,21 @@ /* $Rev$ $Date$ */ /** - * Test core utils. + * Test kernel functions. */ #include -#include -#include #include #include #include #include "function.hpp" #include "list.hpp" #include "slist.hpp" -#include "parallel.hpp" +#include "tree.hpp" #include "value.hpp" -#include "element.hpp" -#include "xml.hpp" #include "monad.hpp" #include "dynlib.hpp" +#include "perf.hpp" namespace tuscany { @@ -55,22 +52,22 @@ const int square(const int x) { return x * x; } -int mapLambda(lambda f, int v) { +int mapLambda(lambda f, int v) { return f(v); } bool testLambda() { - const lambda sq(square); + const lambda sq(square); assert(sq(2) == 4); assert(mapLambda(sq, 2) == 4); assert(mapLambda(square, 2) == 4); - const lambda incf(inc(10)); + const lambda incf(inc(10)); assert(incf(1) == 11); assert(mapLambda(incf, 1) == 11); assert(mapLambda(inc(10), 1) == 11); - lambda l; + lambda l; l = incf; assert(l(1) == 11); l = square; @@ -113,6 +110,10 @@ struct Element { return o.i == i; } }; +std::ostream& operator<<(std::ostream& out, const Element& v) { + out << v.i ; + return out; +} bool testCons() { assert(car(cons(2, mklist(3))) == 2); @@ -195,6 +196,10 @@ struct Complex { x(x), y(y) { } }; +std::ostream& operator<<(std::ostream& out, const Complex& v) { + out << "[" << v.x << ":" << v.y << "]"; + return out; +} bool testComplex() { const list p = mklist(Complex(1, 2), Complex(3, 4)); @@ -219,12 +224,12 @@ const int add(const int x, const int y) { } bool testReduce() { - const lambda r(add); + const lambda r(add); assert(reduce(r, 0, mklist(1, 2, 3)) == 6); return true; } -bool isPositive(int x) { +bool isPositive(const int x) { if(x >= 0) return true; else @@ -306,8 +311,6 @@ bool testSeq() { list s = seq(0.0, 1000.0); assert(1001 == length(s)); - //printLambdaCounters(); - //printListCounters(); assert(1001 == length(map(testSeqMap, s))); @@ -315,9 +318,6 @@ bool testSeq() { assert(201 == length(member(200.0, reverse(s)))); assert(1001 == (reduce(testSeqReduce, 0.0, s))); - //printLambdaCounters(); - //printListCounters(); - return true; } @@ -329,7 +329,7 @@ bool testValue() { assert(value(true) == value(true)); assert(value(1) == value(1)); assert(value("abcd") == value("abcd")); - lambda&)> vl(valueSquare); + lambda&)> vl(valueSquare); assert(value(vl) == value(vl)); assert(value(mklist(1, 2)) == value(mklist(1, 2))); @@ -357,6 +357,40 @@ bool testValueGC() { return true; } +bool testTree() { + const list t = mktree("a", list(), list()); + const list ct = constree("d", constree("f", constree("c", constree("e", constree("b", t))))); + const list mt = mktree(mklist("d", "f", "c", "e", "b", "a")); + assert(mt == ct); + const list l = flatten(mt); + assert(length(l) == 6); + assert(car(l) == "a"); + assert(car(reverse(l)) == "f"); + const list bt = mkbtree(l); + assert(car(bt) == "c"); + return true; +} + +const list lta(const std::string& x) { + return mklist(x.c_str(), (x + x).c_str()); +} + +bool testTreeAssoc() { + const list t = mktree(lta("a"), list(), list()); + const list at = constree(lta("d"), constree(lta("f"), constree(lta("c"), constree(lta("e"), constree(lta("b"), t))))); + const list l = flatten(at); + assert(length(l) == 6); + assert(car(l) == mklist("a", "aa")); + assert(car(reverse(l)) == mklist("f", "ff")); + const list bt = mkbtree(l); + assert(car(bt) == mklist("c", "cc")); + assert(assoctree("a", bt) == mklist("a", "aa")); + assert(assoctree("b", bt) == mklist("b", "bb")); + assert(assoctree("f", bt) == mklist("f", "ff")); + assert(isNil(assoctree("x", bt))); + return true; +} + double fib_aux(double n, double a, double b) { if(n == 0.0) return a; @@ -367,19 +401,31 @@ double fib(double n) { return fib_aux(n, 0.0, 1.0); } -bool testCppPerf() { - struct timeval start; - struct timeval end; - { - gettimeofday(&start, NULL); +struct fibMapPerf { + const bool operator()() const { + list s = seq(0.0, 999.0); + list r = map(fib, s); + assert(1000 == length(r)); + return true; + } +}; +struct nestedFibMapPerf { + const lambda fib; + nestedFibMapPerf(const lambda& fib) : fib(fib) { + } + const bool operator()() const { list s = seq(0.0, 999.0); list r = map(fib, s); assert(1000 == length(r)); + return true; + } +}; - gettimeofday(&end, NULL); - //long t = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000); - //std::cout << "Fib cpp function map perf test " << t << " ms" << std::endl; +bool testCppPerf() { + { + const lambda fml = fibMapPerf(); + std::cout << "Fibonacci map test " << (time(fml, 1, 1) / 1000) << " ms" << std::endl; } { @@ -396,197 +442,8 @@ bool testCppPerf() { } }; - gettimeofday(&start, NULL); - - list s = seq(0.0, 999.0); - list r = map(lambda(nested::fib), s); - assert(1000 == length(r)); - - gettimeofday(&end, NULL); - //long t = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000); - //std::cout << "Fib cpp nested function map perf test " << t << " ms" << std::endl; - } - return true; -} - -bool testAtomicPerf() { - struct timeval start; - struct timeval end; - { - gettimeofday(&start, NULL); - for(int i = 0; i < 10000000;) - i = i + 1; - gettimeofday(&end, NULL); - //long t = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000); - //std::cout << "Loop test " << t << " ms" << std::endl; - } - { - gettimeofday(&start, NULL); - for(int i = 0; i < 10000000;) - __sync_add_and_fetch(&i, 1); - gettimeofday(&end, NULL); - //long t = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000); - //std::cout << "Loop atomic test " << t << " ms" << std::endl; - } - { - pthread_mutex_t mutex; - pthread_mutex_init(&mutex, NULL); - gettimeofday(&start, NULL); - for(int i = 0; i < 10000000;) { - pthread_mutex_lock(&mutex); - i = i + 1; - pthread_mutex_unlock(&mutex); - } - gettimeofday(&end, NULL); - pthread_mutex_destroy(&mutex); - //long t = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000); - //std::cout << "Loop mutex test " << t << " ms" << std::endl; - } - return true; -} - -const int mtsquare(const int x) { - //std::cout << "thread " << threadId() << " mtsquare(" << x << ")\n"; - for(int i = 0; i < 10000000; i++) - ; - return x * x; -} - -bool testWorker() { - worker w(10); - { - const lambda func = curry(lambda (mtsquare), 2); - assert(submit(w, func) == 4); - } - { - const int max = 10; - - list > r; - for(int i = 0; i < max; i++) { - const lambda func = curry(lambda (mtsquare), i); - r = cons(submit(w, func), r); - } - for(int i = max - 1; i >= 0; i--) { - assert(car(r) == i * i); - r = cdr(r); - } - } - shutdown(w); - return true; -} - -const std::string currencyXML = -"\n" -"" -"" -"" -"" -"" -"" -"" -"" -"" -"" -"" -"" -"US" -"" -"" -"\n"; - -const std::string customerXML = -"\n" -"" -"jdoe" -"
san franciscoca
" -"12341000" -"67892000" -"45673000" -"
" -"\n"; - - -const bool isName(const value& token) { - return isTaggedList(token, attribute) && attributeName(token) == "name"; -} - -bool testReadXML() { - { - std::istringstream is(customerXML); - const list c = readXML(streamList(is)); - } - { - std::istringstream is(currencyXML); - const list c = readXML(streamList(is)); - - const value composite = car(c); - assert(isTaggedList(composite, element)); - assert(elementName(composite) == "composite"); - assert(attributeValue(car(filter(isName, elementChildren(composite)))) == std::string("currency")); - } - return true; -} - -std::ostringstream* xmlWriter(const std::string& s, std::ostringstream* os) { - (*os) << s; - return os; -} - -bool testWriteXML() { - { - std::istringstream is(customerXML); - const list c = readXML(streamList(is)); - std::ostringstream os; - writeXML(xmlWriter, &os, c); - assert(os.str() == customerXML); - } - { - std::istringstream is(currencyXML); - const list c = readXML(streamList(is)); - std::ostringstream os; - writeXML(xmlWriter, &os, c); - assert(os.str() == currencyXML); - } - return true; -} - -bool testElement() { - { - const list ad = mklist(mklist("city", std::string("san francisco")), mklist("state", std::string("ca"))); - const list ac1 = mklist(mklist("id", std::string("1234")), mklist("balance", 1000)); - const list ac2 = mklist(mklist("id", std::string("6789")), mklist("balance", 2000)); - const list ac3 = mklist(mklist("id", std::string("4567")), mklist("balance", 3000)); - { - const list c = mklist(mklist("customer", mklist("name", std::string("jdoe")), cons("address", ad), mklist("account", mklist(ac1, ac2, ac3)))); - const list e = valuesToElements(c); - const list v = elementsToValues(e); - assert(v == c); - - std::ostringstream os; - writeXML(xmlWriter, &os, e); - assert(os.str() == customerXML); - } - { - const list c = mklist(mklist("customer", mklist("name", std::string("jdoe")), cons("address", ad), cons("account", ac1), cons("account", ac2), cons("account", ac3))); - const list e = valuesToElements(c); - const list v = elementsToValues(e); - - std::ostringstream os; - writeXML(xmlWriter, &os, e); - assert(os.str() == customerXML); - } - } - { - std::istringstream is(customerXML); - const list c = readXML(streamList(is)); - const list v = elementsToValues(c); - const list e = valuesToElements(v); - std::ostringstream os; - writeXML(xmlWriter, &os, e); - assert(os.str() == customerXML); + const lambda nfml = nestedFibMapPerf(lambda(nested::fib)); + std::cout << "Nested Fibonacci map test " << (time(nfml, 1, 1) / 1000) << " ms" << std::endl; } return true; } @@ -651,8 +508,9 @@ bool testFailableMonad() { assert((m >> success()) == m); assert(m >> failableF >> failableG == m >> failableH); - failable ooops = mkfailure("ooops"); - assert(reason(ooops) == "ooops"); + std::cout << "Failable monad test... "; + failable ooops = mkfailure("test"); + assert(reason(ooops) == "test"); assert(ooops >> failableF >> failableG == ooops); return true; } @@ -683,7 +541,7 @@ const state stateH(const double v) { } bool testStateMonad() { - const lambda(double)> r(result); + const lambda(const double)> r(result); state m = result(2.0); assert((m >> stateF)(0) == stateF(2.0)(0)); @@ -697,14 +555,14 @@ bool testStateMonad() { bool testDynLib() { const failable dl(dynlib(".libs/libdynlib-test" + dynlibExt)); assert(hasContent(dl)); - const failable, std::string> sq(dynlambda("csquare", content(dl))); + const failable, std::string> sq(dynlambda("csquare", content(dl))); assert(hasContent(sq)); - lambda l(content(sq)); + lambda l(content(sq)); assert(l(2) == 4); - const failable()>, std::string> sql(dynlambda()>("csquarel", content(dl))); + const failable()>, std::string> sql(dynlambda()>("csquarel", content(dl))); assert(hasContent(sql)); - lambda()> ll(content(sql)); + lambda()> ll(content(sql)); assert(ll()(3) == 9); return true; } @@ -736,12 +594,9 @@ int main() { tuscany::testSeq(); tuscany::testValue(); tuscany::testValueGC(); - tuscany::testElement(); + tuscany::testTree(); + tuscany::testTreeAssoc(); tuscany::testCppPerf(); - tuscany::testAtomicPerf(); - tuscany::testWorker(); - tuscany::testReadXML(); - tuscany::testWriteXML(); tuscany::testIdMonad(); tuscany::testMaybeMonad(); tuscany::testFailableMonad(); diff --git a/sca-cpp/trunk/kernel/list.hpp b/sca-cpp/trunk/kernel/list.hpp index da00a5a40d..88163e63d2 100644 --- a/sca-cpp/trunk/kernel/list.hpp +++ b/sca-cpp/trunk/kernel/list.hpp @@ -26,6 +26,8 @@ * Simple list functions. */ +#include +#include #include #include "function.hpp" #include "debug.hpp" @@ -35,7 +37,9 @@ namespace tuscany { #ifdef _DEBUG /** - * Debug counters. + * Debug utilities. Counters used to track instances of lists, and + * macro used to write the contents of a list in a string, easier to + * watch in a debugger than the list itself. */ long countLists = 0; long countILists = 0; @@ -59,12 +63,18 @@ bool printListCounters() { return true; } +#define debug_watchList() do { \ + this->watch = watchList(*this); \ + } while (0) + #else #define resetListCounters() #define checkListCounters() true #define printListCounters() +#define debug_watchList(); + #endif @@ -78,18 +88,23 @@ public: list() { debug_inc(countLists); debug_inc(countELists); + debug_watchList(); } - list(const T car, const lambda ()>& cdr) : + list(const T car, const lambda()>& cdr) : car(car), cdr(cdr) { debug_inc(countLists); debug_inc(countILists); + debug_watchList(); } list(const list& p) : car(p.car), cdr(p.cdr) { debug_inc(countLists); debug_inc(countCLists); +#ifdef _DEBUG + watch = p.watch; +#endif } const list& operator=(const list& p) { @@ -97,6 +112,9 @@ public: return *this; car = p.car; cdr = p.cdr; +#ifdef _DEBUG + watch = p.watch; +#endif return *this; } @@ -118,6 +136,34 @@ public: return cdr() == p.cdr(); } + const bool operator<(const list& p) const { + if(this == &p) + return false; + if (isNil(cdr)) + return !isNil(p.cdr); + if (isNil(p.cdr)) + return false; + if (car < p.car) + return true; + if (car != p.car) + return false; + return cdr() < p.cdr(); + } + + const bool operator>(const list& p) const { + if(this == &p) + return false; + if (isNil(cdr)) + return false; + if (isNil(p.cdr)) + return true; + if (car > p.car) + return true; + if (car != p.car) + return false; + return cdr() > p.cdr(); + } + const bool operator!=(const list& p) const { return !this->operator==(p); } @@ -136,13 +182,33 @@ public: template friend const list cdr(const list& p); template friend const bool setCar(list& p, const X& car); template friend const bool setCdr(list& p, const list& cdr); - template friend const bool setCdr(list& p, const lambda ()>& cdr); + template friend const bool setCdr(list& p, const lambda()>& cdr); private: +#ifdef _DEBUG + template friend const std::string watchList(const list& p); + std::string watch; +#endif + T car; - lambda ()> cdr; + lambda()> cdr; }; +#ifdef _DEBUG + +/** + * Debug utility used to write the contents of a list to a string, easier + * to watch than the list itself in a debugger. + */ +template const std::string watchList(const list& p) { + if(isNil(p)) + return "()"; + std::ostringstream os; + os << "(" << car(p) << " ...)"; + return os.str(); +} +#endif + /** * Returns true if the given list is nil. */ @@ -153,25 +219,25 @@ template const bool isNil(const list& p) { /** * Write a list to an output stream. */ +template std::ostream& writeHelper(std::ostream& out, const list& l) { + if (isNil(l)) + return out; + out << " " << car(l); + return writeHelper(out, cdr(l)); +} + template std::ostream& operator<<(std::ostream& out, const list& l) { if(isNil(l)) return out << "()"; - out << "("; - list ml = l; - while(true) { - out << car(ml); - ml = cdr(ml); - if (isNil(ml)) - break; - out << " "; - } + out << "(" << car(l); + writeHelper(out, cdr(l)); return out << ")"; } /** * Construct a (lazy) list from a value and a lambda function that returns the cdr. */ -template const list cons(const T& car, const lambda ()>& cdr) { +template const list cons(const T& car, const lambda()>& cdr) { return list (car, cdr); } @@ -268,7 +334,7 @@ template const bool setCdr(list& p, const list& c) { /** * Sets the cdr of a list to a lambda function. */ -template const bool setCdr(list& p, const lambda ()>& cdr) { +template const bool setCdr(list& p, const lambda()>& cdr) { p.cdr = cdr; return true; } @@ -288,6 +354,13 @@ template const T caddr(const list& p) { return car(cdr(cdr(p))); } +/** + * Returns the car of the cdr of the cdr of the cdr of a list. + */ +template const T cadddr(const list& p) { + return car(cdr(cdr(cdr(p)))); +} + /** * Returns the cdr of a cdr of a list. */ @@ -322,8 +395,8 @@ template const int length(const list& p) { */ template struct appendCdr { const list a; - const lambda ()> fb; - appendCdr(const list& a, const lambda ()>& fb) : + const lambda()> fb; + appendCdr(const list& a, const lambda()>& fb) : a(a), fb(fb) { } const list operator()() const { @@ -331,7 +404,7 @@ template struct appendCdr { } }; -template const list append(const list&a, const lambda ()>& fb) { +template const list append(const list&a, const lambda()>& fb) { if(isNil(a)) return fb(); @@ -348,7 +421,7 @@ template const list append(const list&a, const list& b) { /** * Map a lambda function on a list. */ -template const list map(const lambda& f, const list& p) { +template const list map(const lambda& f, const list& p) { if(isNil(p)) return list (); return cons(f(car(p)), map(f, cdr(p))); @@ -358,8 +431,8 @@ template const list map(const lambda& f, const * Run a reduce lambda function on a list. */ template struct reduceAccumulate { - const lambda f; - reduceAccumulate(const lambda& f) : + const lambda f; + reduceAccumulate(const lambda& f) : f(f) { } R operator()(const R& acc, const list& p) const { @@ -369,13 +442,13 @@ template struct reduceAccumulate { } }; -template const R reduce(const lambda& f, const R& initial, const list& p) { +template const R reduce(const lambda& f, const R& initial, const list& p) { return reduceAccumulate (f)(initial, p); } template struct reduceRightAccumulate { - const lambda f; - reduceRightAccumulate(const lambda& f) : + const lambda f; + reduceRightAccumulate(const lambda& f) : f(f) { } R operator()(const list& p, const R& acc) const { @@ -385,18 +458,18 @@ template struct reduceRightAccumulate { } }; -template const R reduceRight(const lambda& f, const R& initial, const list& p) { +template const R reduceRight(const lambda& f, const R& initial, const list& p) { return reduceRightAccumulate (f)(p, initial); } /** * Run a filter lambda function on a list. */ -template const list filter(const lambda& f, const list& p) { +template const list filter(const lambda& f, const list& p) { if(isNil(p)) return list (); if(f(car(p))) { - const lambda (lambda , list )> ff(filter ); + const lambda(const lambda, const list)> ff(filter); return cons(car(p), curry(ff, f, cdr(p))); } return filter(f, cdr(p)); diff --git a/sca-cpp/trunk/kernel/monad.hpp b/sca-cpp/trunk/kernel/monad.hpp index 31eb390f1c..5449aa38fd 100644 --- a/sca-cpp/trunk/kernel/monad.hpp +++ b/sca-cpp/trunk/kernel/monad.hpp @@ -89,14 +89,14 @@ template const id mkunit(const V& v) { return id(v); } -template const lambda(V)> unit() { +template const lambda(const V)> unit() { return mkunit; } /** * Bind a function to an identity monad. Pass the value in the monad to the function. */ -template const id operator>>(const id& m, const lambda(V)>& f) { +template const id operator>>(const id& m, const lambda(const V)>& f) { return f(content(m)); } @@ -164,7 +164,7 @@ template const maybe mkjust(const V& v) { return maybe(v); } -template const lambda(V)> just() { +template const lambda(const V)> just() { return mkjust; } @@ -186,7 +186,7 @@ template const V content(const maybe& 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 const maybe operator>>(const maybe& m, const lambda(V)>& f) { +template const maybe operator>>(const maybe& m, const lambda(const V)>& f) { if (!hasContent(m)) return m; return f(content(m)); @@ -274,7 +274,7 @@ template const failable mksuccess(const V& v) { return failable(v); } -template const lambda(V)> success() { +template const lambda(const V)> success() { return mksuccess; } @@ -286,7 +286,7 @@ template const failable mkfailure(const F& f) { return failable(false, f); } -template const lambda(V)> failure() { +template const lambda(const V)> failure() { return mkfailure; } @@ -316,7 +316,7 @@ template const F reason(const failable& m) { * if present, or does nothing if there's no value and a failure instead. */ template -const failable operator>>(const failable& m, const lambda(V)>& f) { +const failable operator>>(const failable& m, const lambda(const V)>& f) { if (!hasContent(m)) return m; return f(content(m)); @@ -390,7 +390,7 @@ template const S content(const scp& m) { */ template class state { public: - state(const lambda(S)>& f) : f(f) { + state(const lambda(const S)>& f) : f(f) { } const scp operator()(const S& s) const { @@ -415,7 +415,7 @@ public: } private: - const lambda(S)> f; + const lambda(const S)> f; }; /** @@ -449,7 +449,7 @@ template const state result(const V& v) { * A transformer function takes a state and returns an scp pair carrying a content and a * new (transformed) state. */ -template const state transformer(const lambda(S)>& f) { +template const state transformer(const lambda(const S)>& f) { return state(f); } @@ -459,9 +459,9 @@ template const state transformer(const lambda struct stateBind { const state st; - const lambda(A)>f; + const lambda(const A)>f; - stateBind(const state& st, const lambda(A)>& f) : st(st), f(f) { + stateBind(const state& st, const lambda(const A)>& f) : st(st), f(f) { } const scp operator()(const S& is) const { @@ -472,7 +472,7 @@ template struct stateBind { }; template -const state operator>>(const state& st, const lambda(A)>& f) { +const state operator>>(const state& st, const lambda(const A)>& f) { return state(stateBind(st, f)); } diff --git a/sca-cpp/trunk/kernel/parallel.hpp b/sca-cpp/trunk/kernel/parallel.hpp index 987d662e23..a94764763a 100644 --- a/sca-cpp/trunk/kernel/parallel.hpp +++ b/sca-cpp/trunk/kernel/parallel.hpp @@ -246,7 +246,7 @@ template bool submitFunc(const lambda& func, const future& f */ template const future submit(worker& w, const lambda& func) { const future fut; - const lambda f = curry(lambda, future)>(submitFunc), func, fut); + const lambda f = curry(lambda, future)>(submitFunc), func, fut); enqueue(w.work, f); return fut; } diff --git a/sca-cpp/trunk/kernel/tree.hpp b/sca-cpp/trunk/kernel/tree.hpp new file mode 100644 index 0000000000..f0c85ff403 --- /dev/null +++ b/sca-cpp/trunk/kernel/tree.hpp @@ -0,0 +1,125 @@ +/* + * 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_tree_hpp +#define tuscany_tree_hpp + +/** + * Functions to work with trees. + */ + +#include +#include +#include "function.hpp" +#include "list.hpp" +#include "monad.hpp" +#include "value.hpp" + +namespace tuscany { + +/** + * Make a tree from a leaf and two branches. + */ +template const list mktree(const T& e, const list& left, const list& right) { + return mklist(e, left, right); +} + +/** + * Find a leaf with the given key in a tree. + */ +template const list assoctree(const T& k, const list& tree) { + if (isNil(tree)) + return tree; + if (k == car(car(tree))) + return car(tree); + if (k < car(car(tree))) + return assoctree(k, cadr(tree)); + return assoctree(k, caddr(tree)); +} + +/** + * Construct a new tree from a leaf and a tree. + */ +template const list constree(const T& e, const list& tree) { + if (isNil(tree)) + return mktree(e, list(), list()); + if (e == car(tree)) + return tree; + if (e < car(tree)) + return mktree(car(tree), constree(e, cadr(tree)), caddr(tree)); + return mktree(car(tree), cadr(tree), constree(e, caddr(tree))); +} + +/** + * Make a tree from an unordered list of leaves. + */ +template const list mktree(const list& l) { + if (isNil(l)) + return l; + return constree(car(l), mktree(cdr(l))); +} + +/** + * Convert a tree to an ordered list of leaves. + */ +template const list flatten(const list& tree) { + if (isNil(tree)) + return tree; + return append(flatten(cadr(tree)), cons(car(tree), flatten(caddr(tree)))); +} + +/** + * Sort a list. + */ +template const list sort(const list& l) { + return flatten(mktree(l)); +} + +/** + * Make a balanced tree from an ordered list of leaves. + */ +template const list btreeHelper(const list& elements, const int n) { + if (n == 0) + return cons(list(), elements); + const int leftSize = (n - 1) / 2; { + const list leftResult = btreeHelper(elements, leftSize); { + const list leftTree = car(leftResult); + const list nonLeftElements = cdr(leftResult); + const int rightSize = n - (leftSize + 1); { + const T thisEntry = car(nonLeftElements); + const list rightResult = btreeHelper(cdr(nonLeftElements), rightSize); { + const list rightTree = car(rightResult); + const list remainingElements = cdr(rightResult); { + return cons(mktree(thisEntry, leftTree, rightTree), remainingElements); + } + } + } + } + } +} + +template const list mkbtree(const list& elements) { + return car(btreeHelper(elements, length(elements))); +} + +} + +#endif /* tuscany_tree_hpp */ diff --git a/sca-cpp/trunk/kernel/value.hpp b/sca-cpp/trunk/kernel/value.hpp index a99309869f..e767ead74b 100644 --- a/sca-cpp/trunk/kernel/value.hpp +++ b/sca-cpp/trunk/kernel/value.hpp @@ -32,6 +32,7 @@ #include "gc.hpp" #include "function.hpp" #include "list.hpp" +#include "monad.hpp" #include "debug.hpp" namespace tuscany @@ -40,7 +41,9 @@ namespace tuscany #ifdef _DEBUG /** - * Debug counters. + * Debug utilities. Counters used to track instances of values, and + * macro used to write the contents of a value in a string, easier to + * watch in a debugger than the value itself. */ long int countValues = 0; long int countEValues = 0; @@ -64,12 +67,18 @@ bool printValueCounters() { return true; } +#define debug_watchValue() do { \ + this->watch = watchValue(*this); \ + } while (0) + #else #define resetValueCounters() #define checkValueCounters() true #define printValueCounters() +#define debug_watchValue() + #endif class value; @@ -85,6 +94,7 @@ public: type(value::Undefined) { debug_inc(countValues); debug_inc(countEValues); + debug_watchValue(); } value(const value& v) { @@ -113,6 +123,9 @@ public: default: break; } +#ifdef _DEBUG + watch = v.watch; +#endif } const value& operator=(const value& v) { @@ -141,6 +154,9 @@ public: default: break; } +#ifdef _DEBUG + watch = v.watch; +#endif return *this; } @@ -148,70 +164,84 @@ public: debug_dec(countValues); } - value(const lambda&)>& func) : - type(value::Lambda), data(vdata(func)) { + value(const lambda&)>& func) : type(value::Lambda), data(vdata(func)) { debug_inc(countValues); debug_inc(countVValues); + debug_watchValue(); } - value(const std::string& str) : - type(value::String), data(vdata(result(str))) { + value(const std::string& str) : type(value::String), data(vdata(result(str))) { debug_inc(countValues); debug_inc(countVValues); + debug_watchValue(); } - value(const char* str) : - type(value::Symbol), data(vdata(result(std::string(str)))) { + value(const char* str) : type(value::Symbol), data(vdata(result(std::string(str)))) { debug_inc(countValues); debug_inc(countVValues); + debug_watchValue(); } - value(const list& lst) : - type(value::List), data(vdata(result(lst))) { + value(const list& lst) : type(value::List), data(vdata(result(lst))) { debug_inc(countValues); debug_inc(countVValues); + debug_watchValue(); } - value(const list >& l) : - type(value::List), data(vdata(result(listOfValues(l)))) { + value(const list >& l) : type(value::List), data(vdata(result(listOfValues(l)))) { debug_inc(countValues); debug_inc(countVValues); + debug_watchValue(); } - value(const double num) : - type(value::Number), data(vdata(result(num))) { + value(const double num) : type(value::Number), data(vdata(result(num))) { debug_inc(countValues); debug_inc(countVValues); + debug_watchValue(); } - value(const int num) : - type(value::Number), data(vdata(result((double)num))) { + value(const int num) : type(value::Number), data(vdata(result((double)num))) { debug_inc(countValues); debug_inc(countVValues); + debug_watchValue(); } - value(const bool boo) : - type(value::Bool), data(vdata(result(boo))) { + value(const bool boo) : type(value::Bool), data(vdata(result(boo))) { debug_inc(countValues); debug_inc(countVValues); + debug_watchValue(); } - value(const char chr) : - type(value::Char), data(vdata(result(chr))) { + value(const char chr) : type(value::Char), data(vdata(result(chr))) { debug_inc(countValues); debug_inc(countVValues); + debug_watchValue(); } - value(const gc_ptr ptr) : - type(value::Ptr), data(vdata(result(ptr))) { + value(const gc_ptr ptr) : type(value::Ptr), data(vdata(result(ptr))) { debug_inc(countValues); debug_inc(countVValues); + debug_watchValue(); } - value(const gc_pool_ptr ptr) : - type(value::PoolPtr), data(vdata(result(ptr))) { + value(const gc_pool_ptr ptr) : type(value::PoolPtr), data(vdata(result(ptr))) { debug_inc(countValues); debug_inc(countVValues); + debug_watchValue(); + } + + value(const failable& m) : type(value::List), + data(vdata(result(hasContent(m)? mklist(content(m)) : mklist(value(), reason(m))))) { + debug_inc(countValues); + debug_inc(countVValues); + debug_watchValue(); + } + + value(const maybe& m) : type(value::List), + data(vdata(result(hasContent(m)? mklist(content(m)) : list()))) { + debug_inc(countValues); + debug_inc(countVValues); + debug_watchValue(); } const bool operator!=(const value& v) const { @@ -221,35 +251,75 @@ public: const bool operator==(const value& v) const { if(this == &v) return true; - if(type != v.type) - return false; switch(type) { case value::Undefined: return true; case value::List: - return lst()() == v.lst()(); + return v.type == value::List && lst()() == v.lst()(); case value::Lambda: - return func() == v.func(); + return v.type == value::Lambda && func() == v.func(); case value::Symbol: - return str()() == v.str()(); + return str()() == (std::string)v; case value::String: - return str()() == v.str()(); + return str()() == (std::string)v; case value::Number: - return num()() == v.num()(); + return num()() == (double)v; case value::Bool: - return boo()() == v.boo()(); + return boo()() == (bool)v; case value::Char: - return chr()() == v.chr()(); + return chr()() == (char)v; case value::Ptr: - return ptr()() == v.ptr()(); + return v.type == value::Ptr && ptr()() == v.ptr()(); case value::PoolPtr: - return poolptr()() == v.poolptr()(); + return v.type == value::PoolPtr && poolptr()() == v.poolptr()(); + default: + return false; + } + } + + const bool operator<(const value& v) const { + if(this == &v) + return false; + switch(type) { + case value::List: + return v.type == value::List && lst()() < v.lst()(); + case value::Symbol: + case value::String: + return str()() < (std::string)v; + return str()() < (std::string)v; + case value::Bool: + return boo()() < (bool)v; + case value::Number: + return num()() < (double)v; + case value::Char: + return chr()() < (char)v; + default: + return false; + } + } + + const bool operator>(const value& v) const { + if(this == &v) + return false; + switch(type) { + case value::List: + return v.type == value::List && lst()() > v.lst()(); + case value::Symbol: + case value::String: + return str()() > (std::string)v; + return str()() > (std::string)v; + case value::Bool: + return boo()() > (bool)v; + case value::Number: + return num()() > (double)v; + case value::Char: + return chr()() > (char)v; default: return false; } } - const value operator()(list& args) const { + const value operator()(const list& args) const { return func()(args); } @@ -355,17 +425,12 @@ public: return listOfListOfValues(lst()()); } - operator const lambda&)>() const { + operator const lambda&)>() const { return func(); } - friend std::ostream& operator<<(std::ostream&, const value&); - - ValueType type; - lambda data; - private: - template lambda& vdata() const { + template lambda& vdata() const { return *reinterpret_cast *> (const_cast *> (&data)); } @@ -401,8 +466,8 @@ private: return vdata()> (); } - lambda&)>& func() const { - return vdata&)> (); + lambda&)>& func() const { + return vdata&)> (); } const list listOfValues(const list >& l) const { @@ -417,8 +482,33 @@ private: return cons >(list(car(l)), listOfListOfValues(cdr(l))); } + friend std::ostream& operator<<(std::ostream&, const value&); + friend const value::ValueType type(const value& v); + +#ifdef _DEBUG + friend const std::string watchValue(const value& v); + std::string watch; +#endif + + ValueType type; + lambda data; }; +#ifdef _DEBUG + +/** + * Debug utility used to write the contents of a value to a string, easier + * to watch than the value itself in a debugger. + */ +const std::string watchValue(const value& v) { + if (v.type == value::List) + return watchList(v); + std::ostringstream os; + os << v; + return os.str(); +} +#endif + /** * Write a value to a stream. */ @@ -444,14 +534,14 @@ std::ostream& operator<<(std::ostream& out, const value& v) { case value::Ptr: { const gc_ptr p = v.ptr()(); if (p == gc_ptr(NULL)) - return out << "pointer::null"; - return out << "pointer::" << *p; + return out << "gc_ptr::null"; + return out << "gc_ptr::" << p; } case value::PoolPtr: { const gc_pool_ptr p = v.poolptr()(); if (p == gc_pool_ptr(NULL)) - return out << "pointer::null"; - return out << "pointer::" << *p; + return out << "pool_ptr::null"; + return out << "pool_ptr::" << p; } default: return out << "undefined"; @@ -468,71 +558,71 @@ const value::ValueType type(const value& v) { /** * Returns true if a value is nil. */ -const bool isNil(const value& value) { - return value.type == value::Undefined; +const bool isNil(const value& v) { + return type(v) == value::Undefined; } /** * Returns true if a value is a lambda. */ -const bool isLambda(const value& value) { - return value.type == value::Lambda; +const bool isLambda(const value& v) { + return type(v) == value::Lambda; } /** * Returns true if a value is a string. */ -const bool isString(const value& value) { - return value.type == value::String; +const bool isString(const value& v) { + return type(v) == value::String; } /** * Returns true if a value is a symbol. */ -const bool isSymbol(const value& value) { - return value.type == value::Symbol; +const bool isSymbol(const value& v) { + return type(v) == value::Symbol; } /** * Returns true if a value is a list. */ -const bool isList(const value& value) { - return value.type == value::List; +const bool isList(const value& v) { + return type(v) == value::List; } /** * Returns true if a value is a number. */ -const bool isNumber(const value& value) { - return value.type == value::Number; +const bool isNumber(const value& v) { + return type(v) == value::Number; } /** * Returns true if a value is a boolean. */ -const bool isBool(const value& value) { - return value.type == value::Bool; +const bool isBool(const value& v) { + return type(v) == value::Bool; } /** * Returns true if a value is a character. */ -const bool isChar(const value& value) { - return value.type == value::Char; +const bool isChar(const value& v) { + return type(v) == value::Char; } /** * Returns true if a value is a pointer. */ -const bool isPtr(const value& value) { - return value.type == value::Ptr; +const bool isPtr(const value& v) { + return type(v) == value::Ptr; } /** * Returns true if a value is a pooled pointer. */ -const bool isPoolPtr(const value& value) { - return value.type == value::PoolPtr; +const bool isPoolPtr(const value& v) { + return type(v) == value::PoolPtr; } /** diff --git a/sca-cpp/trunk/kernel/xml.hpp b/sca-cpp/trunk/kernel/xml.hpp index 4b4bcd098e..eee6e290d8 100644 --- a/sca-cpp/trunk/kernel/xml.hpp +++ b/sca-cpp/trunk/kernel/xml.hpp @@ -315,9 +315,9 @@ const failable write(const list& l, const xmlTextWrite */ template class XMLWriteContext { public: - XMLWriteContext(const lambda& reduce, const R& accum) : reduce(reduce), accum(accum) { + XMLWriteContext(const lambda& reduce, const R& accum) : reduce(reduce), accum(accum) { } - const lambda reduce; + const lambda reduce; R accum; }; @@ -333,7 +333,7 @@ template int writeCallback(void *context, const char* buffer, int le /** * Convert a list of values to an XML document. */ -template const failable writeXML(const lambda& reduce, const R& initial, const list& l) { +template const failable writeXML(const lambda& reduce, const R& initial, const list& l) { XMLWriteContext cx(reduce, initial); xmlOutputBufferPtr out = xmlOutputBufferCreateIO(writeCallback, NULL, &cx, NULL); if (out == NULL) diff --git a/sca-cpp/trunk/modules/atom/atom.hpp b/sca-cpp/trunk/modules/atom/atom.hpp index 22489fd1d1..7e2eb66cd2 100644 --- a/sca-cpp/trunk/modules/atom/atom.hpp +++ b/sca-cpp/trunk/modules/atom/atom.hpp @@ -115,7 +115,7 @@ const list entriesElements(const list& l) { * Convert a list of values representing an ATOM entry to an ATOM entry. * The first two values in the list are the entry id and title. */ -template const failable writeATOMEntry(const lambda& reduce, const R& initial, const list& l) { +template const failable writeATOMEntry(const lambda& reduce, const R& initial, const list& l) { return writeXML(reduce, initial, mklist(entryElement(l))); } @@ -130,7 +130,7 @@ const failable, std::string> writeATOMEntry(const list& * Convert a list of values representing an ATOM feed to an ATOM feed. * The first two values in the list are the feed id and title. */ -template const failable writeATOMFeed(const lambda& reduce, const R& initial, const list& l) { +template const failable writeATOMFeed(const lambda& reduce, const R& initial, const list& l) { const list f = list() << element << "feed" << (list() << attribute << "xmlns" << "http://www.w3.org/2005/Atom") << (list() << element << "title" << (list() << attribute << "type" << "text") << car(l)) diff --git a/sca-cpp/trunk/modules/http/curl.hpp b/sca-cpp/trunk/modules/http/curl.hpp index fd2e9857d1..85665c2785 100644 --- a/sca-cpp/trunk/modules/http/curl.hpp +++ b/sca-cpp/trunk/modules/http/curl.hpp @@ -35,6 +35,7 @@ #include "value.hpp" #include "element.hpp" #include "monad.hpp" +#include "parallel.hpp" #include "../atom/atom.hpp" #include "../json/json.hpp" @@ -126,9 +127,9 @@ size_t readCallback(void *ptr, size_t size, size_t nmemb, void *data) { */ template class CURLWriteContext { public: - CURLWriteContext(const lambda& reduce, const R& accum) : reduce(reduce), accum(accum) { + CURLWriteContext(const lambda& reduce, const R& accum) : reduce(reduce), accum(accum) { } - const lambda reduce; + const lambda reduce; R accum; }; @@ -162,7 +163,7 @@ curl_slist* headers(curl_slist* cl, const list& h) { return headers(curl_slist_append(cl, std::string(car(h)).c_str()), cdr(h)); } -template const failable, std::string> apply(const list >& req, const lambda& reduce, const R& initial, const std::string& url, const std::string& verb, const CURLSession& cs) { +template const failable, std::string> apply(const list >& req, const lambda& reduce, const R& initial, const std::string& url, const std::string& verb, const CURLSession& cs) { // Init the curl session CURL* ch = handle(cs); @@ -174,8 +175,6 @@ template const failable, std::string> apply(const list const failable, std::string> apply(const list wcx(reduce, initial); curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, (size_t (*)(void*, size_t, size_t, void*))writeCallback); curl_easy_setopt(ch, CURLOPT_WRITEDATA, &wcx); + curl_easy_setopt(ch, CURLOPT_TCP_NODELAY, true); // Set the request headers curl_slist* hl = headers(NULL, car(req)); @@ -291,7 +291,7 @@ const failable contentType(const list& h) /** * HTTP GET, return the resource at the given URL. */ -template const failable, std::string> get(const lambda& reduce, const R& initial, const std::string& url, const CURLSession& ch) { +template const failable, std::string> get(const lambda& reduce, const R& initial, const std::string& url, const CURLSession& ch) { debug(url, "http::get::url"); const list > req = mklist(list(), list()); return apply(req, reduce, initial, url, "GET", ch); @@ -391,18 +391,18 @@ const failable del(const std::string& url, const CURLSession * HTTP client proxy function. */ struct proxy { - proxy(const std::string& url, const CURLSession& ch) : url(url), ch(ch) { + proxy(const std::string& url) : url(url) { } const value operator()(const list& args) const { - failable val = evalExpr(args, url, ch); + CURLSession cs; + failable val = evalExpr(args, url, cs); if (!hasContent(val)) return value(); return content(val); } const std::string url; - const CURLSession ch; }; } diff --git a/sca-cpp/trunk/modules/json/json.hpp b/sca-cpp/trunk/modules/json/json.hpp index 7d9bba564e..6ce4e3a9a1 100644 --- a/sca-cpp/trunk/modules/json/json.hpp +++ b/sca-cpp/trunk/modules/json/json.hpp @@ -332,10 +332,10 @@ const failable writeList(const list& l, JSObject* o, c */ template class WriteContext { public: - WriteContext(const lambda& reduce, const R& accum, const JSONContext& cx) : cx(cx), reduce(reduce), accum(accum) { + WriteContext(const lambda& reduce, const R& accum, const JSONContext& cx) : cx(cx), reduce(reduce), accum(accum) { } const JSONContext& cx; - const lambda reduce; + const lambda reduce; R accum; }; @@ -352,7 +352,7 @@ template JSBool writeCallback(const jschar *buf, uint32 len, void *d /** * Convert a list of values to a JSON document. */ -template const failable writeJSON(const lambda& reduce, const R& initial, const list& l, const JSONContext& cx) { +template const failable writeJSON(const lambda& reduce, const R& initial, const list& l, const JSONContext& cx) { JSObject* o = JS_NewObject(cx, NULL, NULL, NULL); jsval val = OBJECT_TO_JSVAL(o); const failable w = writeList(l, o, cx); -- cgit v1.2.3