summaryrefslogtreecommitdiffstats
path: root/sca-cpp/trunk/kernel
diff options
context:
space:
mode:
authorjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2010-01-02 10:27:26 +0000
committerjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2010-01-02 10:27:26 +0000
commit95fa76f5f3208d913320c13a05171ecdcd7134c2 (patch)
tree872e101cd2fb1505baf313940e48c6b615fd6725 /sca-cpp/trunk/kernel
parent1d04916fda43146fb62488c20ba03b7b3006c8e9 (diff)
Performance improvements when running both in multi-threaded and pre-forked HTTPD. Changed memory management to use Apache APR pools instead of ref counting pointers as it's much faster and easier to integrate with the Python and Ruby interpreters. Changed to use simple pool-based string and stream implementations instead of the STL ones, which cause a lots of mutex locks in a multi-threaded environment. Added build options to compile with threading and profiling.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@895165 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to '')
-rw-r--r--sca-cpp/trunk/kernel/Makefile.am14
-rw-r--r--sca-cpp/trunk/kernel/debug.hpp27
-rw-r--r--sca-cpp/trunk/kernel/dynlib.hpp25
-rw-r--r--sca-cpp/trunk/kernel/element.hpp4
-rw-r--r--sca-cpp/trunk/kernel/fstream.hpp152
-rw-r--r--sca-cpp/trunk/kernel/function.hpp40
-rw-r--r--sca-cpp/trunk/kernel/gc.hpp405
-rw-r--r--sca-cpp/trunk/kernel/kernel-test.cpp122
-rw-r--r--sca-cpp/trunk/kernel/list.hpp110
-rw-r--r--sca-cpp/trunk/kernel/mem-test.cpp162
-rw-r--r--sca-cpp/trunk/kernel/monad.hpp49
-rw-r--r--sca-cpp/trunk/kernel/parallel-test.cpp55
-rw-r--r--sca-cpp/trunk/kernel/parallel.hpp32
-rw-r--r--sca-cpp/trunk/kernel/slist.hpp96
-rw-r--r--sca-cpp/trunk/kernel/sstream.hpp234
-rw-r--r--sca-cpp/trunk/kernel/stream.hpp148
-rw-r--r--sca-cpp/trunk/kernel/string-test.cpp196
-rw-r--r--sca-cpp/trunk/kernel/string.hpp288
-rw-r--r--sca-cpp/trunk/kernel/tree.hpp4
-rw-r--r--sca-cpp/trunk/kernel/value.hpp184
-rw-r--r--sca-cpp/trunk/kernel/xml-test.cpp69
-rw-r--r--sca-cpp/trunk/kernel/xml.hpp83
-rw-r--r--sca-cpp/trunk/kernel/xsd-test.cpp26
23 files changed, 1707 insertions, 818 deletions
diff --git a/sca-cpp/trunk/kernel/Makefile.am b/sca-cpp/trunk/kernel/Makefile.am
index 4dfc285e90..507454439a 100644
--- a/sca-cpp/trunk/kernel/Makefile.am
+++ b/sca-cpp/trunk/kernel/Makefile.am
@@ -15,7 +15,7 @@
# specific language governing permissions and limitations
# under the License.
-noinst_PROGRAMS = kernel-test parallel-test xml-test xsd-test
+noinst_PROGRAMS = string-test kernel-test mem-test parallel-test xml-test xsd-test
testdir=$(prefix)/test
test_LTLIBRARIES = libdynlib-test.la
@@ -25,12 +25,18 @@ include_HEADERS = *.hpp
INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE}
-kernel_test_SOURCES = kernel-test.cpp
-kernel_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1
+string_test_SOURCES = string-test.cpp
+string_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1
libdynlib_test_la_SOURCES = dynlib-test.cpp
libdynlib_test_la_LIBADD = -L${APR_LIB} -lapr-1 -laprutil-1
+kernel_test_SOURCES = kernel-test.cpp
+kernel_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1
+
+mem_test_SOURCES = mem-test.cpp
+mem_test_LDADD = -L${APR_LIB} -lapr-1 -laprutil-1
+
parallel_test_SOURCES = parallel-test.cpp
parallel_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1
@@ -40,4 +46,4 @@ xml_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1
xsd_test_SOURCES = xsd-test.cpp
xsd_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1
-TESTS = kernel-test parallel-test xml-test
+TESTS = string-test kernel-test mem-test parallel-test xml-test
diff --git a/sca-cpp/trunk/kernel/debug.hpp b/sca-cpp/trunk/kernel/debug.hpp
index c06fe55f4a..c51ee6c974 100644
--- a/sca-cpp/trunk/kernel/debug.hpp
+++ b/sca-cpp/trunk/kernel/debug.hpp
@@ -23,24 +23,15 @@
#define tuscany_debug_hpp
/**
- * Functions to help log and debug.
+ * Debug functions and macros.
*/
-#include <string>
-#include <ostream>
-
namespace tuscany
{
#ifdef _DEBUG
-/**
- * Debug log.
- */
-template<typename V> const bool debug(const V& v, const std::string& msg) {
- std::cerr << msg << ": " << v << std::endl;
- return true;
-}
+//#define _DEBUG_WATCH
/**
* Increment / decrement a debug counter.
@@ -55,20 +46,18 @@ bool debug_dec(long int& c) {
return true;
}
-/**
- * Attribute used to mark unused parameters.
- */
-#define unused __attribute__ ((unused))
-
#else
-#define debug(v, msg)
-
#define debug_inc(c)
#define debug_dec(c)
-#define unused
+#endif
+/**
+ * Attribute used to mark unused parameters.
+ */
+#ifndef unused
+#define unused __attribute__ ((unused))
#endif
}
diff --git a/sca-cpp/trunk/kernel/dynlib.hpp b/sca-cpp/trunk/kernel/dynlib.hpp
index 10a5a030cb..a000653455 100644
--- a/sca-cpp/trunk/kernel/dynlib.hpp
+++ b/sca-cpp/trunk/kernel/dynlib.hpp
@@ -38,9 +38,9 @@ namespace tuscany {
* OS specific dynamic library file extension.
*/
#ifdef IS_DARWIN
-const std::string dynlibExt(".dylib");
+const string dynlibExt(".dylib");
#else
-const std::string dynlibExt(".so");
+const string dynlibExt(".so");
#endif
/**
@@ -51,7 +51,7 @@ public:
lib() : dl(NULL) {
}
- lib(const std::string& name) : dl(new DynLib(name)) {
+ lib(const string& name) : dl(new (gc_new<DynLib>()) DynLib(name)) {
}
~lib() {
@@ -60,41 +60,42 @@ public:
private:
class DynLib {
public:
- DynLib(const std::string& name) : name(name), h(dlopen(name.c_str(), RTLD_NOW)) {
+ DynLib(const string& name) : name(name), h(dlopen(c_str(name), RTLD_NOW)) {
}
+
~DynLib() {
if (h == NULL)
return;
dlclose(h);
}
- const std::string name;
+ const string name;
void* h;
};
gc_ptr<DynLib> dl;
- friend const failable<lib, std::string> dynlib(const std::string& name);
- template<typename S> friend const failable<lambda<S>, std::string> dynlambda(const std::string& name, const lib& l);
+ friend const failable<lib> dynlib(const string& name);
+ template<typename S> friend const failable<lambda<S> > dynlambda(const string& name, const lib& l);
};
/**
* Load a dynamic library.
*/
-const failable<lib, std::string> dynlib(const std::string& name) {
+const failable<lib> dynlib(const string& name) {
const lib l(name);
if (l.dl->h == NULL)
- return mkfailure<lib, std::string>("Could not load library: " + name + ": " + dlerror());
+ return mkfailure<lib>(string("Could not load library: ") + name + ": " + dlerror());
return l;
}
/**
* Find a lambda function in a dynamic library.
*/
-template<typename S> const failable<lambda<S>, std::string> dynlambda(const std::string& name, const lib& l) {
- const void* s = dlsym(l.dl->h, name.c_str());
+template<typename S> const failable<lambda<S> > dynlambda(const string& name, const lib& l) {
+ const void* s = dlsym(l.dl->h, c_str(name));
if (s == NULL)
- return mkfailure<lambda<S>, std::string>(std::string("Could not load symbol: " + name));
+ return mkfailure<lambda<S> >(string("Could not load symbol: ") + name);
return lambda<S>((S*)s);
}
diff --git a/sca-cpp/trunk/kernel/element.hpp b/sca-cpp/trunk/kernel/element.hpp
index 612752d1df..4570110e96 100644
--- a/sca-cpp/trunk/kernel/element.hpp
+++ b/sca-cpp/trunk/kernel/element.hpp
@@ -98,7 +98,7 @@ const value elementHasValue(const list<value>& l) {
const list<value> r = reverse(l);
if (isSymbol(car(r)))
return false;
- if(isList(car(r)) && isSymbol(car<value>(car(r))))
+ if(isList(car(r)) && !isNil((list<value>)car(r)) && isSymbol(car<value>(car(r))))
return false;
return true;
}
@@ -201,7 +201,7 @@ const value valueToElement(const value& t) {
return mklist(element, n, v);
// Convert a list value
- if (!isSymbol(car<value>(v)))
+ if (isNil((list<value>)v) || !isSymbol(car<value>(v)))
return cons(element, cons(n, mklist<value>(valuesToElements(v))));
// Convert a nested name value pair value
diff --git a/sca-cpp/trunk/kernel/fstream.hpp b/sca-cpp/trunk/kernel/fstream.hpp
new file mode 100644
index 0000000000..3d6b1edade
--- /dev/null
+++ b/sca-cpp/trunk/kernel/fstream.hpp
@@ -0,0 +1,152 @@
+/*
+ * 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_fstream_hpp
+#define tuscany_fstream_hpp
+
+/**
+ * File based streams.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include "string.hpp"
+#include "stream.hpp"
+
+namespace tuscany {
+
+/*
+ * Output stream backed by a FILE.
+ */
+class ofstream : public ostream {
+public:
+ ofstream(const string& path) : file(fopen(c_str(path), "wb")), owned(true) {
+ }
+
+ ofstream(FILE* file) : file(file), owned(false) {
+ }
+
+ ofstream(const ofstream& os) : file(os.file), owned(false) {
+ }
+
+ ~ofstream() {
+ if (!owned)
+ return;
+ if (file == NULL)
+ return;
+ fclose(file);
+ }
+
+ ofstream& vprintf(const char* fmt, ...) {
+ va_list args;
+ va_start (args, fmt);
+ vfprintf (file, fmt, args);
+ va_end (args);
+ return *this;
+ }
+
+ ofstream& flush() {
+ fflush(file);
+ return *this;
+ }
+
+private:
+ FILE* file;
+ bool owned;
+};
+
+/*
+ * Input stream backed by a FILE.
+ */
+class ifstream : public istream {
+public:
+ ifstream(const string& path) : file(fopen(c_str(path), "rb")), owned(true) {
+ }
+
+ ifstream(FILE* file) : file(file), owned(false) {
+ }
+
+ ifstream(const ifstream& is) : file(is.file), owned(false) {
+ }
+
+ ~ifstream() {
+ if (!owned)
+ return;
+ if (file == NULL)
+ return;
+ fclose(file);
+ }
+
+ const int read(void* buf, int size) {
+ return fread(buf, 1, size, file);
+ }
+
+ const bool eof() {
+ return feof(file);
+ }
+
+ const bool fail() {
+ return file == NULL;
+ }
+
+ const int get() {
+ return fgetc(file);
+ }
+
+ const int peek() {
+ int c = fgetc(file);
+ if (c == -1)
+ return c;
+ ungetc(c, file);
+ return c;
+ }
+
+private:
+ FILE* file;
+ bool owned;
+};
+
+/**
+ * Standard streams.
+ */
+ofstream cout(stdout);
+ofstream cerr(stderr);
+ifstream cin(stdin);
+
+/**
+ * Debug log stream.
+ */
+#ifdef _DEBUG
+
+template<typename V> const bool debug(const V& v, const string& msg) {
+ cerr << msg << ": " << v << endl;
+ return true;
+}
+
+#else
+
+#define debug(v, msg)
+
+#endif
+
+}
+
+#endif /* tuscany_fstream_hpp */
diff --git a/sca-cpp/trunk/kernel/function.hpp b/sca-cpp/trunk/kernel/function.hpp
index 54784b5549..26f566fde6 100644
--- a/sca-cpp/trunk/kernel/function.hpp
+++ b/sca-cpp/trunk/kernel/function.hpp
@@ -26,7 +26,8 @@
* Lambda function type.
*/
-#include <iostream>
+#include <bits/move.h>
+#include "fstream.hpp"
#include "gc.hpp"
#include "debug.hpp"
@@ -55,13 +56,13 @@ bool checkLambdaCounters() {
}
bool printLambdaCounters() {
- std::cout << "countLambdas " << countLambdas << std::endl;
- std::cout << "countELambdas " << countELambdas << std::endl;
- std::cout << "countFLambdas " << countFLambdas << std::endl;
- std::cout << "countCLambdas " << countCLambdas << std::endl;
- std::cout << "countProxies " << countProxies << std::endl;
- std::cout << "countFProxies " << countFProxies << std::endl;
- std::cout << "countCProxies " << countCProxies << std::endl;
+ cout << "countLambdas " << countLambdas << endl;
+ cout << "countELambdas " << countELambdas << endl;
+ cout << "countFLambdas " << countFLambdas << endl;
+ cout << "countCLambdas " << countCLambdas << endl;
+ cout << "countProxies " << countProxies << endl;
+ cout << "countFProxies " << countFProxies << endl;
+ cout << "countCProxies " << countCProxies << endl;
return true;
}
@@ -79,7 +80,7 @@ bool printLambdaCounters() {
template<typename R, typename... P> class Callable {
public:
- Callable() : refCount(0) {
+ Callable() {
}
virtual const int size() const = 0;
@@ -116,19 +117,6 @@ public:
private:
const F function;
};
-
-private:
- friend class gc_counting_ptr<Callable>;
-
- unsigned int refCount;
-
- unsigned int acquire() {
- return gc_add_and_fetch(refCount, (unsigned int)1);
- }
-
- unsigned int release() {
- return gc_sub_and_fetch(refCount, (unsigned int)1);
- }
};
template<typename S> class lambda;
@@ -145,7 +133,7 @@ public:
debug_inc(countFLambdas);
typedef typename CallableType::template Proxy<F> ProxyType;
- callable = gc_counting_ptr<CallableType>(new ProxyType(f));
+ callable = gc_ptr<CallableType>(new (gc_new<ProxyType>()) ProxyType(f));
}
lambda(const lambda& l) {
@@ -179,15 +167,15 @@ public:
return (*callable)(std::forward<P>(p)...);
}
- template<typename S> friend std::ostream& operator<<(std::ostream&, const lambda<S>&);
+ template<typename S> friend ostream& operator<<(ostream&, const lambda<S>&);
template<typename S> friend const bool isNil(const lambda<S>& l);
private:
typedef Callable<R,P...> CallableType;
- gc_counting_ptr<CallableType> callable;
+ gc_ptr<CallableType> callable;
};
-template<typename S> std::ostream& operator<<(std::ostream& out, const lambda<S>& l) {
+template<typename S> ostream& operator<<(ostream& out, const lambda<S>& l) {
return out << "lambda::" << l.callable;
}
diff --git a/sca-cpp/trunk/kernel/gc.hpp b/sca-cpp/trunk/kernel/gc.hpp
index c9a1a35756..3d20245c69 100644
--- a/sca-cpp/trunk/kernel/gc.hpp
+++ b/sca-cpp/trunk/kernel/gc.hpp
@@ -23,399 +23,236 @@
#define tuscany_gc_hpp
/**
- * Garbage collected pointer.
+ * Garbage collected memory management, using APR memory pools.
*/
+#include <stdlib.h>
#include <apr_general.h>
#include <apr_pools.h>
-#include <iostream>
+#include <assert.h>
+#include <new>
+#include "debug.hpp"
namespace tuscany
{
/**
- * Macros used to add or subtract values to reference counters.
- * In a multithreaded environment, use the GCC __sync_add_and_fetch
- * and __sync_sub_and_fetch built in functions.
+ * Pointer to a value.
*/
-#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)
-
-#else
-
-#define gc_add_and_fetch(t, v) ((t) = (t) + (v))
-#define gc_sub_and_fetch(t, v) ((t) = (t) - (v))
-
-#endif
-
template<typename T> class gc_ptr {
public:
- gc_ptr(T* p = 0) throw() : countingRef(p == 0? 0 : new CountingRef(p)) {
+ gc_ptr(T* ptr = NULL) throw() : ptr(ptr) {
}
~gc_ptr() throw() {
- release();
}
- gc_ptr(const gc_ptr& r) throw() : countingRef(r.countingRef) {
- acquire(r.countingRef);
+ gc_ptr(const gc_ptr& r) throw() : ptr(r.ptr) {
}
gc_ptr& operator=(const gc_ptr& r) throw() {
if(this == &r)
return *this;
- acquire(r.countingRef);
- release();
- countingRef = r.countingRef;
+ ptr = r.ptr;
return *this;
}
const bool operator==(const gc_ptr& r) const throw() {
if (this == &r)
return true;
- if (countingRef == NULL)
- return r.countingRef == NULL;
- if (r.countingRef == NULL)
- return false;
- return countingRef-> ptr == r.countingRef->ptr;
+ return ptr == r.ptr;
}
const bool operator!=(const gc_ptr& r) const throw() {
- return !this->operator ==(r);
+ return !this->operator==(r);
}
T& operator*() const throw() {
- return *countingRef->ptr;
+ return *ptr;
}
T* operator->() const throw() {
- return countingRef->ptr;
+ return ptr;
}
operator T*() const throw() {
- return countingRef->ptr;
- }
-
- template<typename X> friend std::ostream& operator<<(std::ostream&, const gc_ptr<X>&);
-
-private:
- struct CountingRef {
- T* ptr;
- unsigned count;
-
- CountingRef(T* p) throw() :
- ptr(p), count(1) {
- }
- }* countingRef;
-
- void acquire(CountingRef* ref) throw() {
- if(ref)
- gc_add_and_fetch(ref->count, (unsigned int)1);
+ return ptr;
}
- void release() throw() {
- if(countingRef) {
- unsigned rc = gc_sub_and_fetch(countingRef->count, (unsigned int)1);
- if(rc == 0) {
- delete countingRef->ptr;
- delete countingRef;
- }
- }
- }
+ T* ptr;
};
-template<typename T> std::ostream& operator<<(std::ostream& out, const gc_ptr<T>& p) {
- return out << p.countingRef->ptr;
-}
-
/**
- * Garbage collected pointer to an array.
+ * Garbage collected APR memory pool.
*/
-template<typename T> class gc_aptr {
+class gc_pool {
public:
- gc_aptr(T* p = 0) throw() : countingRef(p == 0? 0 : new CountingRef(p)) {
+ gc_pool() : p(NULL) {
}
- ~gc_aptr() throw() {
- release();
+ gc_pool(apr_pool_t* p) : p(p) {
}
- gc_aptr(const gc_aptr& r) throw() : countingRef(r.countingRef) {
- acquire(r.countingRef);
+ gc_pool(const gc_pool& pool) : p(pool.p) {
}
- gc_aptr& operator=(const gc_aptr& r) throw() {
- if(this == &r)
+ gc_pool& operator=(const gc_pool& pool) {
+ if (this == &pool)
return *this;
- acquire(r.countingRef);
- release();
- countingRef = r.countingRef;
+ p = pool.p;
return *this;
}
- const bool operator==(const gc_aptr& r) const throw() {
- if (this == &r)
- return true;
- if (countingRef == NULL)
- return r.countingRef == NULL;
- if (r.countingRef == NULL)
- return false;
- return countingRef-> ptr == r.countingRef->ptr;
- }
-
- const bool operator!=(const gc_aptr& r) const throw() {
- return !this->operator ==(r);
- }
-
- T& operator*() const throw() {
- return *countingRef->ptr;
- }
-
- T* operator->() const throw() {
- return countingRef->ptr;
- }
-
- operator T*() const throw() {
- return countingRef->ptr;
+ operator apr_pool_t*() const {
+ return p;
}
- template<typename X> friend std::ostream& operator<<(std::ostream&, const gc_aptr<X>&);
-
private:
- struct CountingRef {
- T* ptr;
- unsigned count;
-
- CountingRef(T* p) throw() :
- ptr(p), count(1) {
- }
- }* countingRef;
-
- void acquire(CountingRef* ref) throw() {
- if(ref)
- gc_add_and_fetch(ref->count, (unsigned int)1);
- }
+ friend const bool destroy(gc_pool& pool);
+ friend class gc_global_pool_t;
+ friend class gc_scoped_pool;
- void release() throw() {
- if(countingRef) {
- unsigned rc = gc_sub_and_fetch(countingRef->count, (unsigned int)1);
- if(rc == 0) {
- delete[] countingRef->ptr;
- delete countingRef;
- }
- }
- }
+ apr_pool_t* p;
};
-template<typename T> std::ostream& operator<<(std::ostream& out, const gc_aptr<T>& p) {
- return out << p.countingRef->ptr;
-}
-
/**
- * Garbage collected pointer to a reference counting object.
+ * Destroy a memory pool.
*/
-template<typename T> class gc_counting_ptr {
-public:
- gc_counting_ptr(T* p = 0) throw() : ptr(p) {
- acquire(p);
- }
-
- ~gc_counting_ptr() throw() {
- release();
- }
-
- gc_counting_ptr(const gc_counting_ptr& r) throw() : ptr(r.ptr) {
- acquire(ptr);
- }
-
- gc_counting_ptr& operator=(const gc_counting_ptr& r) throw() {
- if(this == &r)
- return *this;
- acquire(r.ptr);
- release();
- ptr = r.ptr;
- return *this;
- }
-
- const bool operator==(const gc_counting_ptr& r) const throw() {
- if (this == &r)
- return true;
- return ptr == r.ptr;
- }
-
- const bool operator!=(const gc_counting_ptr& r) const throw() {
- return !this->operator ==(r);
- }
-
- T& operator*() const throw() {
- return *ptr;
- }
-
- T* operator->() const throw() {
- return ptr;
- }
-
- operator T*() const throw() {
- return ptr;
- }
-
- template<typename X> friend std::ostream& operator<<(std::ostream&, const gc_counting_ptr<X>&);
-
-private:
- T* ptr;
-
- void acquire(T* p) throw() {
- if(p)
- p->acquire();
- }
-
- void release() throw() {
- if(ptr) {
- if(ptr->release() == 0) {
- delete ptr;
- }
- }
- }
-};
-
-template<typename T> std::ostream& operator<<(std::ostream& out, const gc_counting_ptr<T>& p) {
- return out << p.ptr;
+const bool destroy(gc_pool& pool) {
+ apr_pool_destroy(pool.p);
+ return true;
}
/**
- * Apache Portable Runtime library context
+ * Default global memory pool.
*/
-class APRContext {
+class gc_apr_context_t {
public:
- APRContext() {
+ gc_apr_context_t() {
apr_initialize();
}
- ~APRContext() {
- apr_terminate();
+ ~gc_apr_context_t() {
+ //apr_terminate();
}
};
-APRContext aprContext;
+gc_apr_context_t gc_apr_context;
-/**
- * Garbage collected memory pool, using an APR pool.
- */
-class gc_pool {
+class gc_global_pool_t : public gc_pool {
public:
- gc_pool() : aprPool(new APRPool) {
+ gc_global_pool_t() {
+ apr_pool_create(&p, NULL);
}
- operator apr_pool_t*() const {
- return aprPool->p;
+ ~gc_global_pool_t() {
+ //apr_pool_destroy(p);
}
+};
-private:
- class APRPool {
- friend class gc_pool;
- friend class gc_counting_ptr<APRPool>;
-
- unsigned int refCount;
- apr_pool_t* p;
-
- APRPool() : refCount(0) {
- apr_pool_create(&p, NULL);
- }
-
- ~APRPool() {
- apr_pool_destroy(p);
- }
-
- unsigned int acquire() {
- return gc_add_and_fetch(refCount, (unsigned int)1);
- }
+gc_global_pool_t gc_global_pool;
- unsigned int release() {
- return gc_sub_and_fetch(refCount, (unsigned int)1);
- }
- };
+/**
+ * Maintain a stack of memory pools.
+ */
+#ifdef _REENTRANT
+__thread
+#endif
+apr_pool_t* gc_pool_stack = NULL;
- const gc_counting_ptr<APRPool> aprPool;
-};
+/**
+ * Return the current memory pool.
+ */
+apr_pool_t* gc_current_pool() {
+ apr_pool_t* p = gc_pool_stack;
+ if (p != NULL)
+ return p;
+ apr_pool_t* g = gc_global_pool;
+ gc_pool_stack = g;
+ return g;
+}
/**
- * Garbage collected pointer to pooled memory.
+ * A memory pool scope, used to setup a scope in which a particular pool
+ * will be used for all allocations.
*/
-template<typename T> class gc_pool_ptr {
+class gc_scoped_pool : public gc_pool {
public:
- gc_pool_ptr(T* ptr = 0) throw() : ptr(ptr) {
- }
-
- ~gc_pool_ptr() throw() {
- }
-
- gc_pool_ptr(const gc_pool_ptr& r) throw() : ptr(r.ptr) {
- }
-
- gc_pool_ptr& operator=(const gc_pool_ptr& r) throw() {
- if(this == &r)
- return *this;
- ptr = r.ptr;
- return *this;
- }
- const bool operator==(const gc_pool_ptr& r) const throw() {
- if (this == &r)
- return true;
- return ptr == r.ptr;
- }
-
- const bool operator!=(const gc_pool_ptr& r) const throw() {
- return !this->operator ==(r);
+ gc_scoped_pool() : gc_pool(NULL), prev(gc_current_pool()), owned(true) {
+ apr_pool_create(&p, NULL);
+ gc_pool_stack = p;
}
- T& operator*() const throw() {
- return *ptr;
+ gc_scoped_pool(apr_pool_t* pool) : gc_pool(pool), prev(gc_current_pool()), owned(false) {
+ gc_pool_stack = p;
}
- T* operator->() const throw() {
- return ptr;
+ ~gc_scoped_pool() {
+ if (owned)
+ apr_pool_destroy(p);
+ if (prev != NULL)
+ gc_pool_stack = prev;
}
- operator T*() const throw() {
- return ptr;
+private:
+ gc_scoped_pool(const unused gc_scoped_pool& pool) : gc_pool(pool.p), prev(NULL), owned(false) {
}
- template<typename X> friend std::ostream& operator<<(std::ostream&, const gc_pool_ptr<X>&);
-
-private:
- T* ptr;
+ apr_pool_t* prev;
+ bool owned;
};
-template<typename T> std::ostream& operator<<(std::ostream& out, const gc_pool_ptr<T>& p) {
- return out << p.ptr;
-}
-
/**
- * Cleanup function, called by the APR pool to cleanup registered resources.
- * Calls the allocated object's destructor.
+ * 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_cleanupCallback(void* v) {
+template<typename T> apr_status_t gc_pool_cleanup(void* v) {
T* t = static_cast<T*>(v);
t->~T();
return APR_SUCCESS;
}
-/**
- * Returns a pointer to an object allocated from a memory pool.
- */
-template<typename T> gc_pool_ptr<T> gc_pool_new(const gc_pool& mp) {
+template<typename T> T* gc_new(apr_pool_t* p) {
+ void* m = apr_palloc(p, sizeof(T));
+ apr_pool_cleanup_register(p, m, gc_pool_cleanup<T>, apr_pool_cleanup_null) ;
+ return static_cast<T*>(m);
+}
+
+template<typename T> T* gc_new() {
+ return gc_new<T>(gc_current_pool());
+}
+
+template<typename T> apr_status_t gc_pool_acleanup(void* v) {
+ int* m = static_cast<int*>(v);
+ int n = *m;
+ T* t = static_cast<T*>(m + 1);
+ for (int i = 0; i < n; i++, t++)
+ t->~T();
+ return APR_SUCCESS;
+}
- // Allocate memory from the pool
- void* m = apr_palloc(mp, sizeof(T));
+template<typename T> T* gc_anew(apr_pool_t* p, int n) {
+ int* m = static_cast<int*>(apr_palloc(p, sizeof(int) + sizeof(T[n])));
+ *m = n;
+ apr_pool_cleanup_register(p, m, gc_pool_acleanup<T>, apr_pool_cleanup_null) ;
+ return static_cast<T*>(m + 1);
+}
- // Register a cleanup callback
- apr_pool_cleanup_register(mp, m, gc_pool_cleanupCallback<T>, apr_pool_cleanup_null) ;
+template<typename T> T* gc_anew(int n) {
+ return gc_anew<T>(gc_current_pool(), n);
+}
- // Run the requested type's constructor over the allocated memory
- return new (m) T();
+/**
+ * Allocate an array of chars.
+ */
+char* gc_cnew(apr_pool_t* p, int n) {
+ return static_cast<char*>(apr_palloc(p, n));
+}
+
+char* gc_cnew(int n) {
+ return gc_cnew(gc_current_pool(), n);
}
}
+
#endif /* tuscany_gc_hpp */
diff --git a/sca-cpp/trunk/kernel/kernel-test.cpp b/sca-cpp/trunk/kernel/kernel-test.cpp
index 8a5e4a704d..c4f76c13c9 100644
--- a/sca-cpp/trunk/kernel/kernel-test.cpp
+++ b/sca-cpp/trunk/kernel/kernel-test.cpp
@@ -24,12 +24,10 @@
*/
#include <assert.h>
-#include <iostream>
-#include <string>
-#include <sstream>
+#include "string.hpp"
+#include "sstream.hpp"
#include "function.hpp"
#include "list.hpp"
-#include "slist.hpp"
#include "tree.hpp"
#include "value.hpp"
#include "monad.hpp"
@@ -77,7 +75,10 @@ bool testLambda() {
bool testLambdaGC() {
resetLambdaCounters();
- testLambda();
+ {
+ gc_scoped_pool gc;
+ testLambda();
+ }
assert(checkLambdaCounters());
return true;
}
@@ -87,18 +88,15 @@ int countElements = 0;
struct Element {
int i;
- Element() :
- i(0) {
+ Element() : i(0) {
countElements++;
}
- Element(int i) :
- i(i) {
+ Element(int i) : i(i) {
countElements++;
}
- Element(const Element& o) :
- i(o.i) {
+ Element(const Element& o) : i(o.i) {
countElements++;
}
@@ -110,7 +108,7 @@ struct Element {
return o.i == i;
}
};
-std::ostream& operator<<(std::ostream& out, const Element& v) {
+ostream& operator<<(ostream& out, const Element& v) {
out << v.i ;
return out;
}
@@ -124,23 +122,14 @@ bool testCons() {
return true;
}
-bool testSet() {
- list<int> l = mklist(1, 2, 3);
- setCar(l, 4);
- setCdr(l, mklist(5, 6));
- assert(car(l) == 4);
- assert(cadr(l) == 5);
- assert(caddr(l) == 6);
- assert(isNil(cdddr(l)));
- return true;
-}
-
bool testListGC() {
resetLambdaCounters();
resetListCounters();
countElements = 0;
- testCons();
- testSet();
+ {
+ gc_scoped_pool gc;
+ testCons();
+ }
assert(checkLambdaCounters());
assert(checkListCounters());
assert(countElements == 0);
@@ -148,13 +137,13 @@ bool testListGC() {
}
bool testOut() {
- std::ostringstream os1;
+ ostringstream os1;
os1 << list<int> ();
- assert(os1.str() == "()");
+ assert(str(os1) == "()");
- std::ostringstream os2;
+ ostringstream os2;
os2 << mklist(1, 2, 3);
- assert(os2.str() == "(1 2 3)");
+ assert(str(os2) == "(1 2 3)");
return true;
}
@@ -180,10 +169,7 @@ bool testAppend() {
assert(car(cdr(cdr(append(mklist(1), mklist(2, 3))))) == 3);
assert(isNil(cdr(cdr(cdr(append(mklist(1), mklist(2, 3)))))));
- list<int> l;
- l << 1 << 2 << 3;
- assert(l == mklist(1, 2, 3));
- assert(list<int>() << 1 << 2 << 3 == mklist(1, 2, 3));
+ assert(list<int>() + 1 + 2 + 3 == mklist(1, 2, 3));
return true;
}
@@ -196,7 +182,7 @@ struct Complex {
x(x), y(y) {
}
};
-std::ostream& operator<<(std::ostream& out, const Complex& v) {
+ostream& operator<<(ostream& out, const Complex& v) {
out << "[" << v.x << ":" << v.y << "]";
return out;
}
@@ -266,9 +252,9 @@ bool testListRef() {
}
bool testAssoc() {
- const list<list<std::string> > l = mklist(mklist<std::string>("x", "X"), mklist<std::string>("a", "A"), mklist<std::string>("y", "Y"), mklist<std::string>("a", "AA"));
- assert(assoc<std::string>("a", l) == mklist<std::string>("a", "A"));
- assert(isNil(assoc<std::string>("z", l)));
+ 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)));
const list<list<value> > u = mklist(mklist<value>("x", "X"), mklist<value>("a", "A"), mklist<value>("y", "Y"), mklist<value>("a", "AA"));
assert(assoc<value>("a", u) == mklist<value>("a", "A"));
@@ -279,21 +265,21 @@ bool testAssoc() {
}
bool testZip() {
- const list<std::string> k = mklist<std::string>("x", "a", "y", "a");
- const list<std::string> v = mklist<std::string>("X", "A", "Y", "AA");
- const list<list<std::string> > z = mklist(k, v);
- const list<list<std::string> > u = mklist(mklist<std::string>("x", "X"), mklist<std::string>("a", "A"), mklist<std::string>("y", "Y"), mklist<std::string>("a", "AA"));
+ 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);
+ const list<list<string> > u = mklist(mklist<string>("x", "X"), mklist<string>("a", "A"), mklist<string>("y", "Y"), mklist<string>("a", "AA"));
assert(zip(k, v) == u);
assert(unzip(u) == z);
return true;
}
bool testTokenize() {
- assert(tokenize("/", "aaa/bbb/ccc/ddd") == mklist<std::string>("aaa", "bbb", "ccc", "ddd"));
- assert(tokenize("/", "/bbb/ccc/ddd") == mklist<std::string>("", "bbb", "ccc", "ddd"));
- assert(tokenize("/", "/bbb/ccc/") == mklist<std::string>("", "bbb", "ccc"));
- assert(tokenize("/", "/bbb//ccc/") == mklist<std::string>("", "bbb", "", "ccc"));
- assert(tokenize("/", "abc/def/") == mklist<std::string>("abc", "def"));
+ assert(tokenize("/", "aaa/bbb/ccc/ddd") == mklist<string>("aaa", "bbb", "ccc", "ddd"));
+ assert(tokenize("/", "/bbb/ccc/ddd") == mklist<string>("", "bbb", "ccc", "ddd"));
+ assert(tokenize("/", "/bbb/ccc/") == mklist<string>("", "bbb", "ccc"));
+ assert(tokenize("/", "/bbb//ccc/") == mklist<string>("", "bbb", "", "ccc"));
+ assert(tokenize("/", "abc/def/") == mklist<string>("abc", "def"));
return true;
}
@@ -336,13 +322,11 @@ bool testValue() {
const list<value> v = mklist<value>(mklist<value>("x", "X"), mklist<value>("a", "A"), mklist<value>("y", "Y"));
assert(cadr((list<list<value> >)value(v)) == mklist<value>("a", "A"));
- const value pv(gc_ptr<value>(new value(1)));
+ const value pv(gc_ptr<value>(new (gc_new<value>()) value(1)));
assert(*(gc_ptr<value>)pv == value(1));
- const list<value> lpv = mklist<value>(gc_ptr<value>(new value(1)), gc_ptr<value>(new value(2)));
+ const list<value> lpv = mklist<value>(gc_ptr<value>(new (gc_new<value>()) value(1)), gc_ptr<value>(new (gc_new<value>()) value(2)));
assert(*(gc_ptr<value>)car(lpv) == value(1));
- *(gc_ptr<value>)cadr(lpv) = value(3);
- assert(*(gc_ptr<value>)cadr(lpv) == value(3));
return true;
}
@@ -350,7 +334,10 @@ bool testValueGC() {
resetLambdaCounters();
resetListCounters();
resetValueCounters();
- testValue();
+ {
+ gc_scoped_pool gc;
+ testValue();
+ }
assert(checkValueCounters());
assert(checkLambdaCounters());
assert(checkListCounters());
@@ -371,8 +358,8 @@ bool testTree() {
return true;
}
-const list<value> lta(const std::string& x) {
- return mklist<value>(x.c_str(), (x + x).c_str());
+const list<value> lta(const string& x) {
+ return mklist<value>(c_str(x), c_str(x + x));
}
bool testTreeAssoc() {
@@ -425,7 +412,7 @@ struct nestedFibMapPerf {
bool testCppPerf() {
{
const lambda<bool()> fml = fibMapPerf();
- std::cout << "Fibonacci map test " << (time(fml, 1, 1) / 1000) << " ms" << std::endl;
+ cout << "Fibonacci map test " << (time(fml, 1, 1) / 1000) << " ms" << endl;
}
{
@@ -443,7 +430,7 @@ bool testCppPerf() {
};
const lambda<bool()> nfml = nestedFibMapPerf(lambda<double(const double)>(nested::fib));
- std::cout << "Nested Fibonacci map test " << (time(nfml, 1, 1) / 1000) << " ms" << std::endl;
+ cout << "Nested Fibonacci map test " << (time(nfml, 1, 1) / 1000) << " ms" << endl;
}
return true;
}
@@ -490,26 +477,26 @@ bool testMaybeMonad() {
return true;
}
-const failable<int, std::string> failableF(const int v) {
+const failable<int> failableF(const int v) {
return v * 2;
}
-const failable<int, std::string> failableG(const int v) {
+const failable<int> failableG(const int v) {
return v * 3;
}
-const failable<int, std::string> failableH(const int v) {
+const failable<int> failableH(const int v) {
return failableF(v) >> failableG;
}
bool testFailableMonad() {
- const failable<int, std::string> m(2);
+ const failable<int> m(2);
assert(m >> failableF == failableF(2));
- assert((m >> success<int, std::string>()) == m);
+ assert((m >> success<int, string>()) == m);
assert(m >> failableF >> failableG == m >> failableH);
- std::cout << "Failable monad test... ";
- failable<int, std::string> ooops = mkfailure<int, std::string>("test");
+ cout << "Failable monad test... " << endl;
+ failable<int> ooops = mkfailure<int>("test");
assert(reason(ooops) == "test");
assert(ooops >> failableF >> failableG == ooops);
return true;
@@ -553,14 +540,14 @@ bool testStateMonad() {
}
bool testDynLib() {
- const failable<lib, std::string> dl(dynlib(".libs/libdynlib-test" + dynlibExt));
+ const failable<lib> dl(dynlib(string(".libs/libdynlib-test") + dynlibExt));
assert(hasContent(dl));
- const failable<lambda<int(const int)>, std::string> sq(dynlambda<int(const int)>("csquare", content(dl)));
+ const failable<lambda<int(const int)>> sq(dynlambda<int(const int)>("csquare", content(dl)));
assert(hasContent(sq));
lambda<int(const int)> l(content(sq));
assert(l(2) == 4);
- const failable<lambda<lambda<int(const int)>()>, std::string> sql(dynlambda<lambda<int(const int)>()>("csquarel", content(dl)));
+ const failable<lambda<lambda<int(const int)>()>> sql(dynlambda<lambda<int(const int)>()>("csquarel", content(dl)));
assert(hasContent(sql));
lambda<lambda<int(const int)>()> ll(content(sql));
assert(ll()(3) == 9);
@@ -570,12 +557,11 @@ bool testDynLib() {
}
int main() {
- std::cout << "Testing..." << std::endl;
+ tuscany::cout << "Testing..." << tuscany::endl;
tuscany::testLambda();
tuscany::testLambdaGC();
tuscany::testCons();
- tuscany::testSet();
tuscany::testListGC();
tuscany::testOut();
tuscany::testEquals();
@@ -603,7 +589,7 @@ int main() {
tuscany::testStateMonad();
tuscany::testDynLib();
- std::cout << "OK" << std::endl;
+ tuscany::cout << "OK" << tuscany::endl;
return 0;
}
diff --git a/sca-cpp/trunk/kernel/list.hpp b/sca-cpp/trunk/kernel/list.hpp
index 88163e63d2..653f49dfe5 100644
--- a/sca-cpp/trunk/kernel/list.hpp
+++ b/sca-cpp/trunk/kernel/list.hpp
@@ -26,9 +26,9 @@
* Simple list functions.
*/
-#include <string>
-#include <sstream>
-#include <iostream>
+#include <assert.h>
+#include "string.hpp"
+#include "fstream.hpp"
#include "function.hpp"
#include "debug.hpp"
@@ -56,28 +56,33 @@ bool checkListCounters() {
}
bool printListCounters() {
- std::cout << "countLists " << countLists << std::endl;
- std::cout << "countELists " << countELists << std::endl;
- std::cout << "countILists " << countILists << std::endl;
- std::cout << "countCLists " << countCLists << std::endl;
+ cout << "countLists " << countLists << endl;
+ cout << "countELists " << countELists << endl;
+ cout << "countILists " << countILists << endl;
+ cout << "countCLists " << countCLists << endl;
return true;
}
-#define debug_watchList() do { \
- this->watch = watchList(*this); \
- } while (0)
-
#else
#define resetListCounters()
#define checkListCounters() true
#define printListCounters()
+#endif
+
+#ifdef _DEBUG_WATCH
+
+#define debug_watchList() do { \
+ this->watch = watchList(*this); \
+ } while (0)
+
+#else
+
#define debug_watchList();
#endif
-
/**
* A car/cdr lisp-like pair, base structure to construct lists.
*/
@@ -91,28 +96,26 @@ public:
debug_watchList();
}
- list(const T car, const lambda<list<T>()>& cdr) :
- car(car), cdr(cdr) {
+ 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) {
+ list(const list& p) : car(p.car), cdr(p.cdr) {
debug_inc(countLists);
debug_inc(countCLists);
-#ifdef _DEBUG
+#ifdef _DEBUG_WATCH
watch = p.watch;
#endif
}
- const list& operator=(const list<T>& p) {
+ const list<T>& operator=(const list<T>& p) {
if(this == &p)
return *this;
car = p.car;
cdr = p.cdr;
-#ifdef _DEBUG
+#ifdef _DEBUG_WATCH
watch = p.watch;
#endif
return *this;
@@ -172,41 +175,34 @@ public:
return (list<list<T> >)T(*this);
}
- list<T>& operator<<(const T& v) {
- *this = append(*this, mklist(v));
- return *this;
- }
+private:
+#ifdef _DEBUG_WATCH
+ template<typename X> friend const string watchList(const list<X>& p);
+ string watch;
+#endif
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 setCar(list<X>& p, const X& car);
- template<typename X> friend const bool setCdr(list<X>& p, const list<X>& cdr);
- template<typename X> friend const bool setCdr(list<X>& p, const lambda<list<X>()>& cdr);
-
-private:
-#ifdef _DEBUG
- template<typename X> friend const std::string watchList(const list<X>& p);
- std::string watch;
-#endif
T car;
lambda<list<T>()> cdr;
};
-#ifdef _DEBUG
+#ifdef _DEBUG_WATCH
/**
* 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 std::string watchList(const list<T>& p) {
+template<typename T> const string watchList(const list<T>& p) {
if(isNil(p))
return "()";
- std::ostringstream os;
+ ostringstream<string::npos> os;
os << "(" << car(p) << " ...)";
- return os.str();
+ return str(os);
}
+
#endif
/**
@@ -219,14 +215,14 @@ template<typename T> const bool isNil(const list<T>& p) {
/**
* Write a list to an output stream.
*/
-template<typename T> std::ostream& writeHelper(std::ostream& out, const list<T>& l) {
+template<typename T> ostream& writeHelper(ostream& out, const list<T>& l) {
if (isNil(l))
return out;
out << " " << car(l);
return writeHelper(out, cdr(l));
}
-template<typename T> std::ostream& operator<<(std::ostream& out, const list<T>& l) {
+template<typename T> ostream& operator<<(ostream& out, const list<T>& l) {
if(isNil(l))
return out << "()";
out << "(" << car(l);
@@ -305,6 +301,8 @@ template<typename T> const list<T> mklist(const T& a, const T& b, const T& c, co
* Returns the car of a list.
*/
template<typename T> const T car(const list<T>& p) {
+ // Abort if trying to access the car of a nil list
+ assert(!isNil(p.cdr));
return p.car;
}
@@ -316,31 +314,6 @@ template<typename T> const list<T> cdr(const list<T>& p) {
}
/**
- * Sets the car of a list.
- */
-template<typename T> const bool setCar(list<T>& p, const T& car) {
- p.car = car;
- return true;
-}
-
-/**
- * Sets the cdr of a list.
- */
-template<typename T> const bool setCdr(list<T>& p, const list<T>& c) {
- p.cdr = result(c);
- return true;
-}
-
-/**
- * Sets the cdr of a list to a lambda function.
- */
-template<typename T> const bool setCdr(list<T>& p, const lambda<list<T>()>& cdr) {
- p.cdr = cdr;
- return true;
-}
-
-
-/**
* Returns the car of the cdr of a list.
*/
template<typename T> const T cadr(const list<T>& p) {
@@ -419,6 +392,17 @@ template<typename T> const list<T> append(const list<T>&a, const list<T>& b) {
}
/**
+ * Append a value to a list.
+ */
+template<typename T> 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) {
+ 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) {
diff --git a/sca-cpp/trunk/kernel/mem-test.cpp b/sca-cpp/trunk/kernel/mem-test.cpp
new file mode 100644
index 0000000000..b1164a5a36
--- /dev/null
+++ b/sca-cpp/trunk/kernel/mem-test.cpp
@@ -0,0 +1,162 @@
+/*
+ * 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 memory allocation functions.
+ */
+
+#include <assert.h>
+#include "stream.hpp"
+#include "string.hpp"
+#include "gc.hpp"
+#include "function.hpp"
+#include "perf.hpp"
+
+namespace tuscany {
+
+int countElements = 0;
+int maxElements = 0;
+
+class Element {
+public:
+ Element() : i(0) {
+ countElements++;
+ if (countElements > maxElements)
+ maxElements = countElements;
+ }
+
+ Element(int i) : i(i) {
+ countElements++;
+ if (countElements > maxElements)
+ maxElements = countElements;
+ }
+
+ Element(const Element& o) : i(o.i) {
+ countElements++;
+ if (countElements > maxElements)
+ maxElements = countElements;
+ }
+
+ ~Element() {
+ countElements--;
+ }
+
+ const bool operator==(const Element& o) const {
+ return o.i == i;
+ }
+
+private:
+ friend ostream& operator<<(ostream& out, const Element& v);
+
+ int i;
+ char c[20];
+};
+
+ostream& operator<<(ostream& out, const Element& v) {
+ out << v.i ;
+ return out;
+}
+
+bool poolAlloc(Element** 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) {
+ if (count == 0)
+ return true;
+ // Do nothing to free the element, but cycle through them just
+ // to get a fair comparison with the other memory alloc tests
+ 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 int count = 100000;
+ const lambda<bool()> pl = poolAllocPerf(count);
+ maxElements = 0;
+ cout << "Memory pool alloc test " << (time(pl, 1, 1) / count) << " ms" << endl;
+ assert(countElements == 0);
+ assert(maxElements == count);
+ return true;
+}
+
+bool stdAlloc(Element** 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) {
+ 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 int count = 100000;
+ const lambda<bool()> sl = stdAllocPerf(count);
+ maxElements = 0;
+ cout << "Memory standard alloc test " << (time(sl, 1, 1) / count) << " ms" << endl;
+ assert(countElements == 0);
+ assert(maxElements == count);
+ return true;
+}
+
+}
+
+int main() {
+ tuscany::cout << "Testing..." << tuscany::endl;
+
+ tuscany::testPoolAllocPerf();
+ tuscany::testStdAllocPerf();
+
+ tuscany::cout << "OK" << tuscany::endl;
+
+ return 0;
+}
diff --git a/sca-cpp/trunk/kernel/monad.hpp b/sca-cpp/trunk/kernel/monad.hpp
index 5449aa38fd..d2057cf367 100644
--- a/sca-cpp/trunk/kernel/monad.hpp
+++ b/sca-cpp/trunk/kernel/monad.hpp
@@ -26,11 +26,10 @@
* Simple monad implementations.
*/
-#include <string>
-#include <iostream>
-
#include "function.hpp"
#include "debug.hpp"
+#include "string.hpp"
+#include "stream.hpp"
namespace tuscany
{
@@ -70,7 +69,7 @@ private:
/**
* Write an identity monad to a stream.
*/
-template<typename V> std::ostream& operator<<(std::ostream& out, const id<V>& m) {
+template<typename V> ostream& operator<<(ostream& out, const id<V>& m) {
out << content(m);
return out;
}
@@ -148,7 +147,7 @@ private:
/**
* Write a maybe monad to a stream.
*/
-template<typename V> std::ostream& operator<<(std::ostream& out, const maybe<V>& m) {
+template<typename V> ostream& operator<<(ostream& out, const maybe<V>& m) {
if (!hasContent(m)) {
out << "nothing";
return out;
@@ -203,7 +202,7 @@ template<typename R, typename V> const maybe<R> operator>>(const maybe<V>& m, co
* To get the value in the monad, just cast it to the value type.
* To get the failure in the monad, cast it to the failure type.
*/
-template<typename V, typename F> class failable {
+template<typename V, typename F = string> class failable {
public:
failable() : hasv(false) {
}
@@ -211,22 +210,7 @@ public:
failable(const V& v) : hasv(true), v(v) {
}
- failable(const failable<V, F>& m) : hasv(m.hasv) {
- if (hasv)
- v = m.v;
- else
- f = m.f;
- }
-
- const failable<V, F>& operator=(const failable<V, F>& m) {
- if(this == &m)
- return *this;
- hasv = m.hasv;
- if (hasv)
- v = m.v;
- else
- f = m.f;
- return *this;
+ failable(const failable<V, F>& m) : hasv(m.hasv), v(m.v), f(m.f) {
}
const bool operator!=(const failable<V, F>& m) const {
@@ -242,23 +226,28 @@ public:
}
private:
- bool hasv;
- V v;
- F f;
-
failable(const bool hasv, const F& f) : hasv(hasv), f(f) {
}
+ // Prevent mutation
+ const failable<V, F>& operator=(const failable<V, F>& m) {
+ return *this;
+ }
+
template<typename A, typename B> friend const bool hasContent(const failable<A, B>& m);
template<typename A, typename B> friend const A content(const failable<A, B>& m);
template<typename A, typename B> friend const B reason(const failable<A, B>& m);
template<typename A, typename B> friend const failable<A, B> mkfailure(const B& f);
+
+ bool hasv;
+ V v;
+ F f;
};
/**
* Write a failable monad to a stream.
*/
-template<typename V, typename F> std::ostream& operator<<(std::ostream& out, const failable<V, F>& m) {
+template<typename V, typename F> ostream& operator<<(ostream& out, const failable<V, F>& m) {
if (!hasContent(m)) {
out << reason(m);
return out;
@@ -286,6 +275,10 @@ template<typename V, typename F> const failable<V, F> mkfailure(const F& f) {
return failable<V, F>(false, f);
}
+template<typename V> const failable<V> mkfailure(const char* f) {
+ return mkfailure<V, string>(string(f));
+}
+
template<typename V, typename F> const lambda<failable<V, F>(const V)> failure() {
return mkfailure<V, F>;
}
@@ -421,7 +414,7 @@ private:
/**
* Write a state monad to a stream.
*/
-template<typename S, typename V> std::ostream& operator<<(std::ostream& out, const state<S, V>& m) {
+template<typename S, typename V> ostream& operator<<(ostream& out, const state<S, V>& m) {
const S s = m;
const V v = m;
out << '(' << s << ' ' << v << ')';
diff --git a/sca-cpp/trunk/kernel/parallel-test.cpp b/sca-cpp/trunk/kernel/parallel-test.cpp
index 8ae2eeed2c..b47501a58d 100644
--- a/sca-cpp/trunk/kernel/parallel-test.cpp
+++ b/sca-cpp/trunk/kernel/parallel-test.cpp
@@ -24,8 +24,8 @@
*/
#include <assert.h>
-#include <iostream>
-#include <string>
+#include "stream.hpp"
+#include "string.hpp"
#include "function.hpp"
#include "list.hpp"
#include "perf.hpp"
@@ -33,6 +33,8 @@
namespace tuscany {
+#ifdef _REENTRANT
+
int inci = 0;
struct incPerf {
@@ -84,25 +86,25 @@ bool testAtomicPerf() {
const int count = 100000;
{
const lambda<bool()> l = incPerf();
- std::cout << "Non-atomic inc test " << time(l, 1000, count) << " ms" << std::endl;
+ cout << "Non-atomic inc test " << time(l, 1000, count) << " ms" << endl;
assert(inci == count + 1000);
}
{
const lambda<bool()> l = addAndFetchPerf();
- std::cout << "Atomic inc test " << time(l, 1000, count) << " ms" << std::endl;
+ 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);
- std::cout << "Locked inc test " << time(l, 1000, count) << " ms" << std::endl;
+ cout << "Locked inc test " << time(l, 1000, count) << " ms" << endl;
assert(muxi == count + 1000);
pthread_mutex_destroy(&mutex);
}
{
const lambda<bool()> l = tlsPerf();
- std::cout << "Thread local inc test " << time(l, 1000, count) << " ms" << std::endl;
+ cout << "Thread local inc test " << time(l, 1000, count) << " ms" << endl;
assert(tlsi == count + 1000);
}
return true;
@@ -114,38 +116,51 @@ const int mtsquare(const int x) {
return x * x;
}
+bool checkResults(const list<future<int> > r, int i) {
+ if (isNil(r))
+ return true;
+ assert(car(r) == i * i);
+ checkResults(cdr(r), i + 1);
+ return true;
+}
+
+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);
+ return cons(submit(w, func), submitSquares(w, max, i + 1));
+}
+
bool testWorker() {
- worker w(10);
+ worker w(20);
{
const lambda<int()> func = curry(lambda<int(const int)> (mtsquare), 2);
assert(submit(w, func) == 4);
}
{
- const int max = 10;
-
- list<future<int> > r;
- for(int i = 0; i < max; i++) {
- const lambda<int()> func = curry(lambda<int(const int)> (mtsquare), i);
- r = cons(submit(w, func), r);
- }
- for(int i = max - 1; i >= 0; i--) {
- assert(car(r) == i * i);
- r = cdr(r);
- }
+ const int max = 20;
+ const list<future<int> > r(submitSquares(w, max, 0));
+ checkResults(r, 0);
}
shutdown(w);
return true;
}
+#endif
+
}
int main() {
- std::cout << "Testing..." << std::endl;
+ tuscany::cout << "Testing..." << tuscany::endl;
+#ifdef _REENTRANT
tuscany::testAtomicPerf();
tuscany::testWorker();
+#else
+ tuscany::cout << "Skipped multi-thread tests" << tuscany::endl;
+#endif
- std::cout << "OK" << std::endl;
+ tuscany::cout << "OK" << tuscany::endl;
return 0;
}
diff --git a/sca-cpp/trunk/kernel/parallel.hpp b/sca-cpp/trunk/kernel/parallel.hpp
index a94764763a..33cb735b84 100644
--- a/sca-cpp/trunk/kernel/parallel.hpp
+++ b/sca-cpp/trunk/kernel/parallel.hpp
@@ -26,13 +26,18 @@
* Simple parallel work execution functions.
*/
+#ifdef _REENTRANT
#include <pthread.h>
#include <sys/syscall.h>
+#include <unistd.h>
+#endif
#include "function.hpp"
namespace tuscany {
+#ifdef _REENTRANT
+
/**
* Returns the current thread id.
*/
@@ -48,8 +53,7 @@ template<typename T> class future {
private:
template<typename X> class futureValue {
public:
- futureValue() :
- refCount(0), hasValue(false) {
+ futureValue() : hasValue(false) {
pthread_mutex_init(&valueMutex, NULL);
pthread_cond_init(&valueCond, NULL);
}
@@ -59,14 +63,6 @@ private:
pthread_cond_destroy(&valueCond);
}
- unsigned int acquire() {
- return __sync_add_and_fetch(&refCount, (unsigned int)1);
- }
-
- unsigned int release() {
- return __sync_sub_and_fetch(&refCount, (unsigned int)1);
- }
-
bool set(const T& v) {
pthread_mutex_lock(&valueMutex);
if(hasValue) {
@@ -91,33 +87,28 @@ private:
}
private:
- unsigned refCount;
pthread_mutex_t valueMutex;
pthread_cond_t valueCond;
bool hasValue;
X value;
};
- gc_counting_ptr<futureValue<T> > fvalue;
+ 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);
public:
- future() : fvalue(new futureValue<T>()) {
- //std::cout << "future() threadId " << threadId() << "\n";
+ future() : fvalue(new (gc_new<futureValue<T> >()) futureValue<T>()) {
}
~future() {
- //std::cout << "~future() threadId " << threadId() << "\n";
}
future(const future& f) : fvalue(f.fvalue) {
- //std::cout << "future(const future& f) threadId " << threadId() << "\n";
}
const future& operator=(const future& f) {
- //std::cout << "future::operator=(const future& f) threadId " << threadId() << "\n";
if (&f == this)
return *this;
fvalue = f.fvalue;
@@ -132,7 +123,6 @@ public:
operator const T() const {
return fvalue->get();
}
-
};
/**
@@ -140,7 +130,7 @@ public:
*/
template<typename T> class queue {
public:
- queue(int max) : max(max), size(0), tail(0), head(0), values(new T[max]) {
+ queue(int max) : max(max), size(0), tail(0), head(0), values(new (gc_anew<T>(max)) T[max]) {
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&full, NULL);
pthread_cond_init(&empty, NULL);
@@ -160,7 +150,7 @@ private:
pthread_mutex_t mutex;
pthread_cond_t full;
pthread_cond_t empty;
- gc_aptr<T> values;
+ gc_ptr<T> values;
template<typename X> friend const int enqueue(queue<X>& q, const X& v);
template<typename X> friend const X dequeue(queue<X>& q);
@@ -280,5 +270,7 @@ const bool shutdown(worker& w) {
return true;
}
+#endif
+
}
#endif /* tuscany_parallel_hpp */
diff --git a/sca-cpp/trunk/kernel/slist.hpp b/sca-cpp/trunk/kernel/slist.hpp
deleted file mode 100644
index 705152cb29..0000000000
--- a/sca-cpp/trunk/kernel/slist.hpp
+++ /dev/null
@@ -1,96 +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_slist_hpp
-#define tuscany_slist_hpp
-
-/**
- * Useful functions to work with lists of strings and character streams.
- */
-
-#include <iostream>
-#include <string>
-#include "function.hpp"
-#include "list.hpp"
-
-namespace tuscany {
-
-/**
- * Tokenize a string into a list of strings.
- */
-const list<std::string> tokenize(const std::string& sep, const std::string& str) {
- struct nested {
- static const list<std::string> tokenize(const std::string& sep, const std::string& str, const unsigned int start = 0) {
- if (start >= str.length())
- return list<std::string>();
- const unsigned int i = str.find_first_of(sep, start);
- if (i == std::string::npos)
- return mklist(str.substr(start));
- return cons(str.substr(start, i - start), tokenize(sep, str, i + 1));
- }
- };
- return nested::tokenize(sep, str, 0);
-}
-
-/**
- * Returns a lazy list view of an input stream.
- */
-struct ilistRead{
- std::istream &is;
- ilistRead(std::istream& is) : is(is) {
- }
- const list<std::string> operator()() {
- char buffer[1024];
- is.read(buffer, 1024);
- const int n = is.gcount();
- if (n ==0)
- return list<std::string>();
- return cons(std::string(buffer, n), (*this)());
- }
-};
-
-const list<std::string> streamList(std::istream& is) {
- return ilistRead(is)();
-}
-
-/**
- * Fragment the first element of a list of strings to fit the given max length.
- */
-const list<std::string> fragment(list<std::string> l, unsigned int max) {
- const std::string s = car(l);
- if (s.length() <= max)
- return l;
- return cons(s.substr(0, max), cons(s.substr(max), cdr(l)));
-}
-
-/**
- * Write a list of strings to an output stream.
- */
-std::ostream& write(const list<std::string>& l, std::ostream& os) {
- if(isNil(l))
- return os;
- os << car(l);
- return write(cdr(l), os);
-}
-
-}
-
-#endif /* tuscany_slist_hpp */
diff --git a/sca-cpp/trunk/kernel/sstream.hpp b/sca-cpp/trunk/kernel/sstream.hpp
new file mode 100644
index 0000000000..5fcdb0c22b
--- /dev/null
+++ b/sca-cpp/trunk/kernel/sstream.hpp
@@ -0,0 +1,234 @@
+/*
+ * 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_sstream_hpp
+#define tuscany_sstream_hpp
+
+/**
+ * Char buffer based streams.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <memory.h>
+#include "string.hpp"
+#include "stream.hpp"
+#include "list.hpp"
+
+namespace tuscany {
+
+/**
+ * Instrumentable memcpy.
+ */
+void* stream_memcpy(void* t, const void* s, const size_t n) {
+ return memcpy(t, s, n);
+}
+
+/**
+ * Output stream backed by a char buffer.
+ */
+class ostringstream : public ostream {
+public:
+ ostringstream() : len(0) {
+ }
+
+ ~ostringstream() {
+ }
+
+ ostringstream(const ostringstream& os) {
+ len = os.len;
+ buf = os.buf;
+ }
+
+ ostringstream& vprintf(const char* fmt, ...) {
+ va_list args;
+ va_start (args, fmt);
+ string s;
+ s.len = vsnprintf(NULL, 0, fmt, args);
+ s.buf = gc_cnew(s.len + 1);
+ vsnprintf(s.buf, s.len + 1, fmt, args);
+ buf = cons(s, buf);
+ len += s.len;
+ va_end (args);
+ return *this;
+ }
+
+ ostringstream& flush() {
+ return *this;
+ }
+
+private:
+ static const bool strHelper(const list<string> l, char* buf) {
+ if (isNil(l))
+ return true;
+ const string c = car(l);
+ char* b = buf - length(c);
+ memcpy(b, c_str(c), length(c));
+ return strHelper(cdr(l), b);
+ }
+
+ const string str() {
+ if (isNil(buf))
+ return string();
+ string s;
+ s.len = len;
+ s.buf = gc_cnew(s.len + 1);
+ strHelper(buf, s.buf + len);
+ s.buf[s.len] = '\0';
+ return s;
+ }
+
+ friend const string str(ostringstream& os);
+
+ int len;
+ list<string> buf;
+};
+
+/**
+ * Return a string representation of a stream.
+ */
+const string str(ostringstream& os) {
+ return os.str();
+}
+
+/**
+ * Input stream backed by a char buffer
+ */
+class istringstream : public istream {
+public:
+ istringstream(const string& s) {
+ cur = 0;
+ const int slen = length(s);
+ len = slen;
+ buf = c_str(s);
+ }
+
+ ~istringstream() {
+ }
+
+ istringstream(const istringstream& is) {
+ len = is.len;
+ cur = is.cur;
+ buf = is.buf;
+ }
+
+ const int read(void* b, int size) {
+ const int n = len - cur;
+ if (n == 0)
+ return 0;
+ if (n > size) {
+ stream_memcpy(b, buf + cur, size);
+ cur = cur + size;
+ return size;
+ }
+ stream_memcpy(b, buf + cur, n);
+ cur = cur + n;
+ return n;
+ }
+
+ const bool eof() {
+ return cur == len;
+ }
+
+ const bool fail() {
+ return false;
+ }
+
+ const int get() {
+ if (eof())
+ return -1;
+ const int c = buf[cur];
+ cur += 1;
+ return c;
+ }
+
+ const int peek() {
+ if (eof())
+ return -1;
+ return buf[cur];
+ }
+
+private:
+ int len;
+ int cur;
+ const char* buf;
+};
+
+/**
+ * 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 string& str, const int start = 0) {
+ if (start >= length(str))
+ return list<string>();
+ const int 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, str, i + 1));
+ }
+ };
+ return nested::tokenize(sep, str, 0);
+}
+
+/**
+ * Returns a lazy list view of an input stream.
+ */
+struct ilistRead{
+ istream &is;
+ ilistRead(istream& is) : is(is) {
+ }
+ const list<string> operator()() {
+ char buffer[1024];
+ const int 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)();
+}
+
+/**
+ * Fragment the first element of a list of strings to fit the given max length.
+ */
+const list<string> fragment(list<string> l, int max) {
+ const string s = car(l);
+ if (length(s) <= max)
+ return l;
+ return cons(substr(s, 0, max), cons(substr(s, max), cdr(l)));
+}
+
+/**
+ * Write a list of strings to an output stream.
+ */
+ostream& write(const list<string>& l, ostream& os) {
+ if(isNil(l))
+ return os;
+ os << car(l);
+ return write(cdr(l), os);
+}
+
+}
+
+#endif /* tuscany_sstream_hpp */
diff --git a/sca-cpp/trunk/kernel/stream.hpp b/sca-cpp/trunk/kernel/stream.hpp
new file mode 100644
index 0000000000..a3e532c4ce
--- /dev/null
+++ b/sca-cpp/trunk/kernel/stream.hpp
@@ -0,0 +1,148 @@
+/*
+ * 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_stream_hpp
+#define tuscany_stream_hpp
+
+/**
+ * Basic stream type and functions.
+ */
+
+#include <stdarg.h>
+#include "debug.hpp"
+#include "gc.hpp"
+#include "string.hpp"
+
+namespace tuscany {
+
+/**
+ * Base output stream.
+ */
+class ostream {
+public:
+ virtual ostream& vprintf(const char* fmt, ...) = 0;
+ virtual ostream& flush() = 0;
+};
+
+/**
+ * Flush a stream.
+ */
+ostream& flush(ostream& os) {
+ return os.flush();
+}
+
+/**
+ * Write simple values to a stream.
+ */
+ostream& operator<<(ostream& os, const char* v) {
+ return os.vprintf("%s", v);
+}
+
+ostream& operator<<(ostream& os, const unsigned char* v) {
+ return os.vprintf("%s", v);
+}
+
+ostream& operator<<(ostream& os, const char v) {
+ return os.vprintf("%c", v);
+}
+
+ostream& operator<<(ostream& os, const int v) {
+ return os.vprintf("%d", v);
+}
+
+ostream& operator<<(ostream& os, const long int v) {
+ return os.vprintf("%ld", v);
+}
+
+ostream& operator<<(ostream& os, const double v) {
+ return os.vprintf("%g", v);
+}
+
+ostream& operator<<(ostream& os, const void* v) {
+ return os.vprintf("%p", v);
+}
+
+ostream& operator<<(ostream& os, const string& v) {
+ return os.vprintf("%s", c_str(v));
+}
+
+class stream_endl {
+} endl;
+
+ostream& operator<<(ostream& os, unused const stream_endl e) {
+ os.vprintf("%s", "\n");
+ return os.flush();
+}
+
+/*
+ * Input stream.
+ */
+class istream {
+public:
+ virtual const int read(void* buf, int size) = 0;
+ virtual const bool eof() = 0;
+ virtual const bool fail() = 0;
+ virtual const int get() = 0;
+ virtual const int peek() = 0;
+};
+
+/**
+ * Read from an input stream.
+ */
+const int read(istream& is, void * buf, int size) {
+ return is.read(buf, size);
+}
+
+/**
+ * Return true if the end of an input stream has been reached.
+ */
+const bool eof(istream& is) {
+ return is.eof();
+}
+
+/**
+ * Return true if an input stream can't be accessed.
+ */
+const bool fail(istream& is) {
+ return is.fail();
+}
+
+/**
+ * Read a character from a stream.
+ */
+const int get(istream& is) {
+ return is.get();
+}
+
+/**
+ * Peek a character from a stream.
+ */
+const int peek(istream& is) {
+ return is.peek();
+}
+
+template<typename T> ostream& operator<<(ostream& out, const gc_ptr<T>& p) {
+ return out << p.ptr;
+}
+
+}
+
+#endif /* tuscany_stream_hpp */
diff --git a/sca-cpp/trunk/kernel/string-test.cpp b/sca-cpp/trunk/kernel/string-test.cpp
new file mode 100644
index 0000000000..323756c7e4
--- /dev/null
+++ b/sca-cpp/trunk/kernel/string-test.cpp
@@ -0,0 +1,196 @@
+/*
+ * 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 string functions.
+ */
+
+#include <assert.h>
+#include <string>
+#include "sstream.hpp"
+#include "string.hpp"
+#include "list.hpp"
+#include "perf.hpp"
+
+namespace tuscany {
+
+bool testCopies() {
+ resetStringCopyCounters();
+ string x("abcd");
+ assert(checkStringCopyCounters(1));
+ resetStringCopyCounters();
+ string y = string("abcd");
+ assert(checkStringCopyCounters(1));
+ resetStringCopyCounters();
+ string z = y;
+ assert(checkStringCopyCounters(0));
+ resetStringCopyCounters();
+ const list<string> pl = list<string>() + "abcd" + "efgh";
+ printStringCopyCounters();
+ resetStringCopyCounters();
+ const list<string> cl = cons<string>("efgh", mklist<string>("abcd"));
+ printStringCopyCounters();
+ return true;
+}
+
+bool testString() {
+ const string s("abcd");
+ assert(length(s) == 4);
+ assert(!strcmp(c_str(s), "abcd"));
+
+ assert(s == "abcd");
+ assert(s == string("abcd"));
+ assert(s != "zbcd");
+
+ assert(s < "zbcd");
+ assert(s < "zbc");
+ assert(s < "abzd");
+ assert(s < "abcdz");
+
+ assert(s > "Abcd");
+ assert(s > "Abc");
+ assert(s > "abCd");
+ assert(s > "Abcdz");
+
+ const string x = "abcd";
+ assert(!strcmp(c_str(x), "abcd"));
+
+ const string y = string("abcd");
+ assert(!strcmp(c_str(y), "abcd"));
+
+ assert(string("ab") + "cd" == "abcd");
+
+ assert(find("abcd", "cd") == 2);
+ assert(find("abcd", "xy") == length("abcd"));
+ assert(substr("abcdef", 4) == "ef");
+ assert(substr("abcdef", 4, 2) == "ef");
+ assert(substr("abcdef", 4, 3) == "ef");
+ assert(substr("abcdef", 6, 3) == "");
+ return true;
+}
+
+bool testStream() {
+ ostringstream os;
+ os << "ab" << "cd";
+ cout << str(os) << endl;
+ assert(str(os) == "abcd");
+
+ ostringstream cs;
+ cs << "\'";
+ assert(str(cs) == "\'");
+ cs << '\'';
+ assert(str(cs) == "\'\'");
+
+ istringstream is("abcd");
+ char b[2];
+ assert(read(is, b, 2) == 2);
+ assert(string("ab") == string(b, 2));
+ assert(eof(is) == false);
+ assert(read(is, b, 2) == 2);
+ assert(string("cd") == string(b, 2));
+ assert(eof(is) == true);
+ assert(read(is, b, 2) == 0);
+ return true;
+}
+
+std::string stdAdd(std::string& x, std::string& y) {
+ return x + y;
+}
+
+string add(string& x, string& y) {
+ return x + y;
+}
+
+char charBuffer[16384];
+
+struct addStrings{
+ const int size;
+ addStrings(const int size) : size(size) {
+ }
+ bool operator()() const {
+ const int sz = size / 4;
+ string x(charBuffer, sz);
+ string y(charBuffer, sz);
+ assert(length(add(x, y)) == sz * 2);
+ return true;
+ }
+};
+
+struct addStdStrings{
+ const int size;
+ addStdStrings(const int size) : size(size) {
+ }
+ bool operator()() const {
+ const int 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() {
+ memset(charBuffer, 'A', 16384);
+ charBuffer[16384] = '\0';
+
+ const int count = 100000;
+ {
+ const lambda<bool()> a16 = addStrings(16);
+ cout << "string test " << time(a16, 5, count) << " ms" << endl;
+ const lambda<bool()> a32 =addStrings(32);
+ cout << "string test " << time(a32, 5, count) << " ms" << endl;
+ const lambda<bool()> a256 =addStrings(256);
+ cout << "string test " << time(a256, 5, count) << " ms" << endl;
+ const lambda<bool()> a1024 =addStrings(1024);
+ cout << "string test " << time(a1024, 5, count) << " ms" << endl;
+ const lambda<bool()> a4096 =addStrings(4096);
+ cout << "string test " << time(a4096, 5, count) << " ms" << endl;
+ }
+ {
+ const lambda<bool()> a16 =addStdStrings(16);
+ cout << "Std string test " << time(a16, 5, count) << " ms" << endl;
+ const lambda<bool()> a32 =addStdStrings(32);
+ cout << "Std string test " << time(a32, 5, count) << " ms" << endl;
+ const lambda<bool()> a256 =addStdStrings(256);
+ cout << "Std string test " << time(a256, 5, count) << " ms" << endl;
+ const lambda<bool()> a1024 =addStdStrings(1024);
+ cout << "Std string test " << time(a1024, 5, count) << " ms" << endl;
+ const lambda<bool()> a4096 =addStdStrings(4096);
+ cout << "Std string test " << time(a4096, 5, count) << " ms" << endl;
+ }
+
+ return true;
+}
+
+}
+
+int main() {
+ tuscany::cout << "Testing..." << tuscany::endl;
+
+ tuscany::testCopies();
+ tuscany::testString();
+ tuscany::testStream();
+ tuscany::testStringPerf();
+
+ tuscany::cout << "OK" << tuscany::endl;
+
+ return 0;
+}
diff --git a/sca-cpp/trunk/kernel/string.hpp b/sca-cpp/trunk/kernel/string.hpp
new file mode 100644
index 0000000000..f065bcc9a4
--- /dev/null
+++ b/sca-cpp/trunk/kernel/string.hpp
@@ -0,0 +1,288 @@
+/*
+ * 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_string_hpp
+#define tuscany_string_hpp
+
+/**
+ * Simple and fast string type backed by a char buffer
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <memory.h>
+#include <stdio.h>
+#include "gc.hpp"
+
+namespace tuscany {
+
+#ifdef _DEBUG
+
+/**
+ * Debug utilities. Counters used to track string copies.
+ */
+long countStringCopies = 0;
+
+bool resetStringCopyCounters() {
+ countStringCopies = 0;
+ return true;
+}
+
+bool checkStringCopyCounters(long c) {
+ return countStringCopies == c;
+}
+
+bool printStringCopyCounters() {
+ printf("countStringCopies %ld\n", countStringCopies);
+ return true;
+}
+
+#else
+
+#define resetStringCopyCounters()
+#define checkStringCopyCounters(c) true
+#define printStringCopyCounters()
+
+#endif
+
+/**
+ * Instrumented memcpy.
+ */
+void* string_memcpy(void* t, const void* s, const size_t n) {
+#ifdef _DEBUG
+ countStringCopies += 1;
+#endif
+ return memcpy(t, s, n);
+}
+
+char stringEmptyBuffer[1] = { '\0' };
+
+/**
+ * String class. The maximum string size is specified as a template parameter.
+ */
+class string {
+public:
+ string() : 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);
+ }
+
+ string(const char* s, const int n) {
+ len = n;
+ if (len == 0) {
+ buf = stringEmptyBuffer;
+ return;
+ }
+ buf = gc_cnew(len + 1);
+ string_memcpy(buf, s, len);
+ buf[len] = '\0';
+ }
+
+ string(const int n, const char c) {
+ len = n;
+ if (len == 0) {
+ buf = stringEmptyBuffer;
+ return;
+ }
+ buf = gc_cnew(len + 1);
+ memset(buf, c, n);
+ buf[len] = '\0';
+ }
+
+ string(const string& s) {
+ len = s.len;
+ buf = s.buf;
+ }
+
+ const string& operator=(const string& s) {
+ if (&s == this)
+ return *this;
+ len = s.len;
+ buf = s.buf;
+ return *this;
+ }
+
+ const bool operator==(const string& s) const {
+ if (len != s.len)
+ return false;
+ if (buf == s.buf)
+ return true;
+ return memcmp(buf, s.buf, len) == 0;
+ }
+
+ const bool operator!=(const string& s) const {
+ return !(*this == s);
+ }
+
+ const bool operator==(const char* s) const {
+ if (buf == s)
+ return true;
+ return strcmp(buf, s) == 0;
+ }
+
+ const bool operator!=(const char* s) const {
+ return !(*this == s);
+ }
+
+ const bool operator<(const string& s) const {
+ const int n = len < s.len? len : s.len;
+ const int c = memcmp(buf, s.buf, n);
+ if (c < 0)
+ return true;
+ if (c == 0)
+ return len < s.len;
+ return false;
+ }
+
+ const bool operator>(const string& s) const {
+ const int n = len < s.len? len : s.len;
+ int c = memcmp(buf, s.buf, n);
+ if (c > 0)
+ return true;
+ if (c == 0)
+ return len > s.len;
+ return false;
+ }
+
+private:
+ 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 int length(const string& s);
+ friend const char* c_str(const string& s);
+ friend const int find(const string& s1, const char* s2, const int start);
+ friend const string substr(const string& s, const int pos, const int n);
+
+ int len;
+ char* buf;
+};
+
+/**
+ * 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;
+}
+
+const string operator+(const string& a, const char* b) {
+ string s;
+ const int 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;
+}
+
+/**
+ * Returns the length of a string.
+ */
+const int length(const string& s) {
+ return s.len;
+}
+
+/**
+ * Returns a string as a C zero terminated string.
+ */
+const char* c_str(const string& s) {
+ return s.buf;
+}
+
+/**
+ * Find the first occurrence of string s2 in s1, starting at the given position.
+ */
+const int find(const string& s1, const char* s2, const int start) {
+ if (start >= s1.len)
+ return s1.len;
+ const char *f = strstr(s1.buf + start, s2);
+ if (f == NULL)
+ return s1.len;
+ return f - s1.buf;
+}
+
+const int find(const string& s1, const char* s2) {
+ return find(s1, s2, 0);
+}
+
+const bool contains(const string& s1, const char* s2) {
+ return find(s1, s2) != length(s1);
+}
+
+/**
+ * Find the first occurence of any character from a string in a string.
+ */
+const int find_first_of(const string& s1, const string& s2) {
+ return strcspn(c_str(s1), c_str(s2));
+}
+
+/**
+ * Find the last occurence of a character in a string.
+ */
+const int find_last(const string& s, const char c) {
+ const char* cs = c_str(s);
+ const char* f = strrchr(cs, c);
+ if (f == NULL)
+ return length(s);
+ return f - cs;
+}
+
+/**
+ * Return a substring of a string.
+ */
+const string substr(const string& s, const int pos, const int n) {
+ if (pos >= s.len)
+ return string();
+ if (pos + n > s.len)
+ return string(s.buf + pos, s.len - pos);
+ return string(s.buf + pos, n);
+}
+
+const string substr(const string& s, const int pos) {
+ return substr(s, pos, length(s));
+}
+
+/**
+ * Common string constants.
+ */
+
+string trueString("true");
+string falseString("false");
+string emptyString("");
+
+}
+
+#endif /* tuscany_string_hpp */
diff --git a/sca-cpp/trunk/kernel/tree.hpp b/sca-cpp/trunk/kernel/tree.hpp
index f0c85ff403..436385aa1b 100644
--- a/sca-cpp/trunk/kernel/tree.hpp
+++ b/sca-cpp/trunk/kernel/tree.hpp
@@ -26,8 +26,8 @@
* Functions to work with trees.
*/
-#include <iostream>
-#include <string>
+#include "stream.hpp"
+#include "string.hpp"
#include "function.hpp"
#include "list.hpp"
#include "monad.hpp"
diff --git a/sca-cpp/trunk/kernel/value.hpp b/sca-cpp/trunk/kernel/value.hpp
index e767ead74b..d2c5f12e95 100644
--- a/sca-cpp/trunk/kernel/value.hpp
+++ b/sca-cpp/trunk/kernel/value.hpp
@@ -26,9 +26,9 @@
* Generic value type.
*/
-#include <string>
-#include <iostream>
-#include <sstream>
+#include <stdlib.h>
+#include "string.hpp"
+#include "sstream.hpp"
#include "gc.hpp"
#include "function.hpp"
#include "list.hpp"
@@ -60,23 +60,29 @@ bool checkValueCounters() {
}
bool printValueCounters() {
- std::cout << "countValues " << countValues << std::endl;
- std::cout << "countEValues " << countEValues << std::endl;
- std::cout << "countCValues " << countCValues << std::endl;
- std::cout << "countVValues " << countVValues << std::endl;
+ cout << "countValues " << countValues << endl;
+ cout << "countEValues " << countEValues << endl;
+ cout << "countCValues " << countCValues << endl;
+ cout << "countVValues " << countVValues << endl;
return true;
}
-#define debug_watchValue() do { \
- this->watch = watchValue(*this); \
- } while (0)
-
#else
#define resetValueCounters()
#define checkValueCounters() true
#define printValueCounters()
+#endif
+
+#ifdef _DEBUG_WATCH
+
+#define debug_watchValue() do { \
+ this->watch = watchValue(*this); \
+ } while (0)
+
+#else
+
#define debug_watchValue()
#endif
@@ -90,8 +96,7 @@ public:
Undefined, Symbol, String, List, Number, Bool, Char, Lambda, Ptr, PoolPtr
};
- value() :
- type(value::Undefined) {
+ value() : type(value::Undefined) {
debug_inc(countValues);
debug_inc(countEValues);
debug_watchValue();
@@ -123,43 +128,11 @@ public:
default:
break;
}
-#ifdef _DEBUG
+#ifdef _DEBUG_WATCH
watch = v.watch;
#endif
}
- 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::Char:
- chr() = v.chr();
- case value::Ptr:
- ptr() = v.ptr();
- case value::PoolPtr:
- poolptr() = v.poolptr();
- default:
- break;
- }
-#ifdef _DEBUG
- watch = v.watch;
-#endif
- return *this;
- }
-
virtual ~value() {
debug_dec(countValues);
}
@@ -170,13 +143,13 @@ public:
debug_watchValue();
}
- value(const std::string& str) : type(value::String), data(vdata(result(str))) {
+ value(const 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(string(str)))) {
debug_inc(countValues);
debug_inc(countVValues);
debug_watchValue();
@@ -218,19 +191,21 @@ public:
debug_watchValue();
}
+#ifdef _GC_REFCOUNT
value(const gc_ptr<value> ptr) : type(value::Ptr), data(vdata(result(ptr))) {
debug_inc(countValues);
debug_inc(countVValues);
debug_watchValue();
}
+#endif
- value(const gc_pool_ptr<value> ptr) : type(value::PoolPtr), data(vdata(result(ptr))) {
+ value(const gc_ptr<value> ptr) : type(value::PoolPtr), data(vdata(result(ptr))) {
debug_inc(countValues);
debug_inc(countVValues);
debug_watchValue();
}
- value(const failable<value, std::string>& m) : type(value::List),
+ value(const failable<value>& m) : type(value::List),
data(vdata(result(hasContent(m)? mklist<value>(content(m)) : mklist<value>(value(), reason(m))))) {
debug_inc(countValues);
debug_inc(countVValues);
@@ -244,6 +219,38 @@ public:
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::Char:
+ chr() = v.chr();
+ case value::Ptr:
+ ptr() = v.ptr();
+ case value::PoolPtr:
+ poolptr() = v.poolptr();
+ default:
+ break;
+ }
+#ifdef _DEBUG_WATCH
+ watch = v.watch;
+#endif
+ return *this;
+ }
+
const bool operator!=(const value& v) const {
return !this->operator==(v);
}
@@ -259,9 +266,8 @@ public:
case value::Lambda:
return v.type == value::Lambda && func() == v.func();
case value::Symbol:
- return str()() == (std::string)v;
case value::String:
- return str()() == (std::string)v;
+ return str()() == (string)v;
case value::Number:
return num()() == (double)v;
case value::Bool:
@@ -285,8 +291,7 @@ public:
return v.type == value::List && lst()() < v.lst()();
case value::Symbol:
case value::String:
- return str()() < (std::string)v;
- return str()() < (std::string)v;
+ return str()() < (string)v;
case value::Bool:
return boo()() < (bool)v;
case value::Number:
@@ -306,8 +311,7 @@ public:
return v.type == value::List && lst()() > v.lst()();
case value::Symbol:
case value::String:
- return str()() > (std::string)v;
- return str()() > (std::string)v;
+ return str()() > (string)v;
case value::Bool:
return boo()() > (bool)v;
case value::Number:
@@ -323,25 +327,25 @@ public:
return func()(args);
}
- operator const std::string() const {
+ operator const string() const {
switch(type) {
case value::Symbol:
case value::String:
return str()();
case value::Number: {
- std::ostringstream sos;
- sos << num()();
- return sos.str();
+ ostringstream os;
+ os << num()();
+ return tuscany::str(os);
}
case value::Bool:
- return boo()()? "true" : "false";
+ return boo()()? trueString : falseString;
case value::Char: {
- std::ostringstream sos;
- sos << chr()();
- return sos.str();
+ ostringstream os;
+ os << chr()();
+ return tuscany::str(os);
}
default:
- return "";
+ return emptyString;
}
}
@@ -349,7 +353,7 @@ public:
switch(type) {
case value::Symbol:
case value::String:
- return atof(str()().c_str());
+ return atof(c_str(str()()));
case value::Number:
return (double)num()();
case value::Bool:
@@ -365,7 +369,7 @@ public:
switch(type) {
case value::Symbol:
case value::String:
- return atoi(str()().c_str());
+ return atoi(c_str(str()()));
case value::Number:
return (int)num()();
case value::Bool:
@@ -381,7 +385,7 @@ public:
switch(type) {
case value::Symbol:
case value::String:
- return str()() == "true";
+ return str()() == string("true");
case value::Number:
return (int)num()() != 0;
case value::Bool:
@@ -409,11 +413,13 @@ public:
}
}
+#ifdef _GC_REFCOUNT
operator const gc_ptr<value>() const {
return ptr()();
}
+#endif
- operator const gc_pool_ptr<value>() const {
+ operator const gc_ptr<value>() const {
return poolptr()();
}
@@ -454,12 +460,12 @@ private:
return vdata<gc_ptr<value>()> ();
}
- lambda<gc_pool_ptr<value>()>& poolptr() const {
- return vdata<gc_pool_ptr<value>()> ();
+ lambda<gc_ptr<value>()>& poolptr() const {
+ return vdata<gc_ptr<value>()> ();
}
- lambda<std::string()>& str() const {
- return vdata<std::string()> ();
+ lambda<string()>& str() const {
+ return vdata<string()> ();
}
lambda<list<value>()>& lst() const {
@@ -482,37 +488,38 @@ private:
return cons<list<value> >(list<value>(car(l)), listOfListOfValues(cdr(l)));
}
- friend std::ostream& operator<<(std::ostream&, const value&);
+ friend ostream& operator<<(ostream&, const value&);
friend const value::ValueType type(const value& v);
-#ifdef _DEBUG
- friend const std::string watchValue(const value& v);
- std::string watch;
+#ifdef _DEBUG_WATCH
+ friend const string watchValue(const value& v);
+ string watch;
#endif
ValueType type;
lambda<char()> data;
};
-#ifdef _DEBUG
+#ifdef _DEBUG_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 std::string watchValue(const value& v) {
+const string watchValue(const value& v) {
if (v.type == value::List)
return watchList<value>(v);
- std::ostringstream os;
+ ostringstream<string::npos> os;
os << v;
- return os.str();
+ return str(os);
}
+
#endif
/**
* Write a value to a stream.
*/
-std::ostream& operator<<(std::ostream& out, const value& v) {
+ostream& operator<<(ostream& out, const value& v) {
switch(v.type) {
case value::List:
return out << v.lst()();
@@ -538,8 +545,8 @@ std::ostream& operator<<(std::ostream& out, const value& v) {
return out << "gc_ptr::" << p;
}
case value::PoolPtr: {
- const gc_pool_ptr<value> p = v.poolptr()();
- if (p == gc_pool_ptr<value>(NULL))
+ const gc_ptr<value> p = v.poolptr()();
+ if (p == gc_ptr<value>(NULL))
return out << "pool_ptr::null";
return out << "pool_ptr::" << p;
}
@@ -634,5 +641,14 @@ const bool isTaggedList(const value& exp, value tag) {
return false;
}
+/**
+ * Make a list of values from a list of other things.
+ */
+template<typename T> const list<value> mkvalues(const list<T>& l) {
+ if (isNil(l))
+ return list<value>();
+ return cons<value>(car(l), mkvalues(cdr(l)));
+}
+
}
#endif /* tuscany_value_hpp */
diff --git a/sca-cpp/trunk/kernel/xml-test.cpp b/sca-cpp/trunk/kernel/xml-test.cpp
index 88c476ffef..585a2e519d 100644
--- a/sca-cpp/trunk/kernel/xml-test.cpp
+++ b/sca-cpp/trunk/kernel/xml-test.cpp
@@ -24,9 +24,8 @@
*/
#include <assert.h>
-#include <iostream>
-#include <string>
-#include <sstream>
+#include "stream.hpp"
+#include "string.hpp"
#include "list.hpp"
#include "value.hpp"
#include "element.hpp"
@@ -34,7 +33,7 @@
namespace tuscany {
-const std::string currencyXML =
+const string currencyXML =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<composite xmlns=\"http://docs.oasis-open.org/ns/opencsa/sca/200903\" "
"xmlns:t=\"http://tuscany.apache.org/xmlns/sca/1.1\" "
@@ -56,7 +55,7 @@ const std::string currencyXML =
"</composite>"
"\n";
-const std::string customerXML =
+const string customerXML =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<customer>"
"<name>jdoe</name>"
@@ -74,78 +73,78 @@ const bool isName(const value& token) {
bool testReadXML() {
{
- std::istringstream is(customerXML);
+ istringstream is(customerXML);
const list<value> c = readXML(streamList(is));
}
{
- std::istringstream is(currencyXML);
+ 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)))) == std::string("currency"));
+ assert(attributeValue(car(filter<value>(isName, elementChildren(composite)))) == string("currency"));
}
return true;
}
-std::ostringstream* xmlWriter(const std::string& s, std::ostringstream* os) {
+ostream* xmlWriter(const string& s, ostream* os) {
(*os) << s;
return os;
}
bool testWriteXML() {
{
- std::istringstream is(customerXML);
+ istringstream is(customerXML);
const list<value> c = readXML(streamList(is));
- std::ostringstream os;
- writeXML<std::ostringstream*>(xmlWriter, &os, c);
- assert(os.str() == customerXML);
+ ostringstream os;
+ writeXML<ostream*>(xmlWriter, &os, c);
+ assert(str(os) == customerXML);
}
{
- std::istringstream is(currencyXML);
+ istringstream is(currencyXML);
const list<value> c = readXML(streamList(is));
- std::ostringstream os;
- writeXML<std::ostringstream*>(xmlWriter, &os, c);
- assert(os.str() == currencyXML);
+ ostringstream os;
+ writeXML<ostream*>(xmlWriter, &os, c);
+ assert(str(os) == currencyXML);
}
return true;
}
bool testElement() {
{
- const list<value> ad = mklist<value>(mklist<value>("city", std::string("san francisco")), mklist<value>("state", std::string("ca")));
- const list<value> ac1 = mklist<value>(mklist<value>("id", std::string("1234")), mklist<value>("balance", 1000));
- const list<value> ac2 = mklist<value>(mklist<value>("id", std::string("6789")), mklist<value>("balance", 2000));
- const list<value> ac3 = mklist<value>(mklist<value>("id", std::string("4567")), mklist<value>("balance", 3000));
+ 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", std::string("jdoe")), cons<value>("address", ad), mklist<value>("account", mklist<value>(ac1, ac2, ac3))));
+ 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);
- std::ostringstream os;
- writeXML<std::ostringstream*>(xmlWriter, &os, e);
- assert(os.str() == customerXML);
+ ostringstream os;
+ writeXML<ostream*>(xmlWriter, &os, e);
+ assert(str(os) == customerXML);
}
{
- const list<value> c = mklist<value>(mklist<value>("customer", mklist<value>("name", std::string("jdoe")), cons<value>("address", ad), cons<value>("account", ac1), cons<value>("account", ac2), cons<value>("account", ac3)));
+ 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);
- std::ostringstream os;
- writeXML<std::ostringstream*>(xmlWriter, &os, e);
- assert(os.str() == customerXML);
+ ostringstream os;
+ writeXML<ostream*>(xmlWriter, &os, e);
+ assert(str(os) == customerXML);
}
}
{
- std::istringstream is(customerXML);
+ istringstream is(customerXML);
const list<value> c = readXML(streamList(is));
const list<value> v = elementsToValues(c);
const list<value> e = valuesToElements(v);
- std::ostringstream os;
- writeXML<std::ostringstream*>(xmlWriter, &os, e);
- assert(os.str() == customerXML);
+ ostringstream os;
+ writeXML<ostream*>(xmlWriter, &os, e);
+ assert(str(os) == customerXML);
}
return true;
}
@@ -153,13 +152,13 @@ bool testElement() {
}
int main() {
- std::cout << "Testing..." << std::endl;
+ tuscany::cout << "Testing..." << tuscany::endl;
tuscany::testReadXML();
tuscany::testWriteXML();
tuscany::testElement();
- std::cout << "OK" << std::endl;
+ tuscany::cout << "OK" << tuscany::endl;
return 0;
}
diff --git a/sca-cpp/trunk/kernel/xml.hpp b/sca-cpp/trunk/kernel/xml.hpp
index eee6e290d8..84cfc30475 100644
--- a/sca-cpp/trunk/kernel/xml.hpp
+++ b/sca-cpp/trunk/kernel/xml.hpp
@@ -30,9 +30,9 @@
#include <libxml/xmlwriter.h>
#include <libxml/xmlschemas.h>
#include <libxml/globals.h>
-#include <string>
+#include "string.hpp"
#include "list.hpp"
-#include "slist.hpp"
+#include "stream.hpp"
#include "value.hpp"
#include "element.hpp"
#include "monad.hpp"
@@ -127,7 +127,7 @@ const value readIdentifier(XMLReader& reader) {
*/
const value readText(XMLReader& reader) {
const char *val = (const char*)xmlTextReaderConstValue(reader);
- return std::string(val);
+ return string(val);
}
/**
@@ -136,7 +136,7 @@ const value readText(XMLReader& reader) {
const value readAttribute(XMLReader& reader) {
const char *name = (const char*)xmlTextReaderConstName(reader);
const char *val = (const char*)xmlTextReaderConstValue(reader);
- return mklist<value>(attribute, name, std::string(val));
+ return mklist<value>(attribute, name, string(val));
}
/**
@@ -186,9 +186,9 @@ const list<value> read(XMLReader& reader) {
*/
class XMLReadContext {
public:
- XMLReadContext(const list<std::string>& ilist) : ilist(ilist) {
+ XMLReadContext(const list<string>& ilist) : ilist(ilist) {
}
- list<std::string> ilist;
+ list<string> ilist;
};
/**
@@ -198,17 +198,17 @@ int readCallback(void *context, char* buffer, int len) {
XMLReadContext& rc = *static_cast<XMLReadContext*>(context);
if (isNil(rc.ilist))
return 0;
- rc.ilist = fragment(rc.ilist, len);
- std::string s = car(rc.ilist);
- rc.ilist = cdr(rc.ilist);
- s.copy(buffer, s.length());
- return s.length();
+ 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 length(s);
}
/**
- * Read a list values from a list of strings representing an XML document.
+ * Read a list of values from a list of strings representing an XML document.
*/
-const list<value> readXML(const list<std::string>& ilist) {
+const list<value> readXML(const list<string>& ilist) {
XMLReadContext cx(ilist);
xmlTextReaderPtr xml = xmlReaderForIO(readCallback, NULL, &cx, NULL, NULL, XML_PARSE_NONET);
if (xml == NULL)
@@ -232,15 +232,15 @@ const list<value> expandElementValues(const value& n, const list<value>& l) {
return cons<value>(value(cons<value>(element, cons<value>(n, (list<value>)car(l)))), expandElementValues(n, cdr(l)));
}
-const failable<bool, std::string> writeList(const list<value>& l, const xmlTextWriterPtr xml) {
+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*)std::string(attributeName(token)).c_str(), (const xmlChar*)std::string(attributeValue(token)).c_str()) < 0)
- return mkfailure<bool, std::string>("xmlTextWriterWriteAttribute failed");
+ 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)) {
@@ -256,38 +256,37 @@ const failable<bool, std::string> writeList(const list<value>& l, const xmlTextW
} else {
// Write an element with a single value
- if (xmlTextWriterStartElement(xml, (const xmlChar*)std::string(elementName(token)).c_str()) < 0)
- return mkfailure<bool, std::string>("xmlTextWriterStartElement failed");
+ if (xmlTextWriterStartElement(xml, (const xmlChar*)c_str(string(elementName(token)))) < 0)
+ return mkfailure<bool>("xmlTextWriterStartElement failed");
// Write its children
- const failable<bool, std::string> w = writeList(elementChildren(token), xml);
+ const failable<bool> w = writeList(elementChildren(token), xml);
if (!hasContent(w))
return w;
if (xmlTextWriterEndElement(xml) < 0)
- return mkfailure<bool, std::string>("xmlTextWriterEndElement failed");
+ return mkfailure<bool>("xmlTextWriterEndElement failed");
}
}
else {
// Write an element
- if (xmlTextWriterStartElement(xml, (const xmlChar*)std::string(elementName(token)).c_str()) < 0)
- return mkfailure<bool, std::string>("xmlTextWriterStartElement failed");
+ if (xmlTextWriterStartElement(xml, (const xmlChar*)c_str(string(elementName(token)))) < 0)
+ return mkfailure<bool>("xmlTextWriterStartElement failed");
// Write its children
- const failable<bool, std::string> w = writeList(elementChildren(token), xml);
+ const failable<bool> w = writeList(elementChildren(token), xml);
if (!hasContent(w))
return w;
if (xmlTextWriterEndElement(xml) < 0)
- return mkfailure<bool, std::string>("xmlTextWriterEndElement failed");
+ return mkfailure<bool>("xmlTextWriterEndElement failed");
}
} else {
// Write XML text
- if (xmlTextWriterWriteString(xml, (const xmlChar*)std::string(token).c_str()) < 0)
- return mkfailure<bool, std::string>("xmlTextWriterWriteString failed");
-
+ if (xmlTextWriterWriteString(xml, (const xmlChar*)c_str(string(token))) < 0)
+ return mkfailure<bool>("xmlTextWriterWriteString failed");
}
// Go on
@@ -297,16 +296,16 @@ const failable<bool, std::string> writeList(const list<value>& l, const xmlTextW
/**
* Write a list of values to a libxml2 XML writer.
*/
-const failable<bool, std::string> write(const list<value>& l, const xmlTextWriterPtr xml) {
+const failable<bool> write(const list<value>& l, const xmlTextWriterPtr xml) {
if (xmlTextWriterStartDocument(xml, NULL, encoding, NULL) < 0)
- return mkfailure<bool, std::string>("xmlTextWriterStartDocument failed");
+ return mkfailure<bool>(string("xmlTextWriterStartDocument failed"));
- const failable<bool, std::string> w = writeList(l, xml);
+ const failable<bool> w = writeList(l, xml);
if (!hasContent(w))
return w;
if (xmlTextWriterEndDocument(xml) < 0)
- return mkfailure<bool, std::string>("xmlTextWriterEndDocument failed");
+ return mkfailure<bool>("xmlTextWriterEndDocument failed");
return true;
}
@@ -315,9 +314,9 @@ const failable<bool, std::string> write(const list<value>& l, const xmlTextWrite
*/
template<typename R> class XMLWriteContext {
public:
- XMLWriteContext(const lambda<R(const std::string&, const R)>& reduce, const R& accum) : reduce(reduce), accum(accum) {
+ XMLWriteContext(const lambda<R(const string&, const R)>& reduce, const R& accum) : reduce(reduce), accum(accum) {
}
- const lambda<R(const std::string&, const R)> reduce;
+ const lambda<R(const string&, const R)> reduce;
R accum;
};
@@ -326,26 +325,26 @@ public:
*/
template<typename R> int writeCallback(void *context, const char* buffer, int len) {
XMLWriteContext<R>& cx = *static_cast<XMLWriteContext<R>*>(context);
- cx.accum = cx.reduce(std::string(buffer, len), cx.accum);
+ 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, std::string> writeXML(const lambda<R(const std::string&, const R)>& reduce, const R& initial, const list<value>& l) {
+template<typename R> const failable<R> writeXML(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& l) {
XMLWriteContext<R> cx(reduce, initial);
xmlOutputBufferPtr out = xmlOutputBufferCreateIO(writeCallback<R>, NULL, &cx, NULL);
if (out == NULL)
- return mkfailure<R, std::string>("xmlOutputBufferCreateIO failed");
+ return mkfailure<R>("xmlOutputBufferCreateIO failed");
xmlTextWriterPtr xml = xmlNewTextWriter(out);
if (xml == NULL)
- return mkfailure<R, std::string>("xmlNewTextWriter failed");
+ return mkfailure<R>("xmlNewTextWriter failed");
- const failable<bool, std::string> w = write(l, xml);
+ const failable<bool> w = write(l, xml);
xmlFreeTextWriter(xml);
if (!hasContent(w)) {
- return mkfailure<R, std::string>(reason(w));
+ return mkfailure<R>(reason(w));
}
return cx.accum;
}
@@ -353,11 +352,11 @@ template<typename R> const failable<R, std::string> writeXML(const lambda<R(cons
/**
* Convert a list of values to a list of strings representing an XML document.
*/
-const failable<list<std::string>, std::string> writeXML(const list<value>& l) {
- const failable<list<std::string>, std::string> ls = writeXML<list<std::string> >(rcons<std::string>, list<std::string>(), l);
+const failable<list<string> > writeXML(const list<value>& l) {
+ const failable<list<string> > ls = writeXML<list<string> >(rcons<string>, list<string>(), l);
if (!hasContent(ls))
return ls;
- return reverse(list<std::string>(content(ls)));
+ return reverse(list<string>(content(ls)));
}
}
diff --git a/sca-cpp/trunk/kernel/xsd-test.cpp b/sca-cpp/trunk/kernel/xsd-test.cpp
index 818c03ba68..0fc432c649 100644
--- a/sca-cpp/trunk/kernel/xsd-test.cpp
+++ b/sca-cpp/trunk/kernel/xsd-test.cpp
@@ -23,8 +23,8 @@
* Test validation of a composite file against an SCDL schema.
*/
-#include <iostream>
-#include <string>
+#include "string.hpp"
+#include "fstream.hpp"
#include <libxml/xmlreader.h>
#include <libxml/xmlschemas.h>
@@ -35,12 +35,12 @@ bool printNode(xmlTextReaderPtr reader) {
if(name == NULL)
name = (xmlChar *)"<unknown>";
const xmlChar* value = xmlTextReaderConstValue(reader);
- std::cout << xmlTextReaderDepth(reader) << " " << xmlTextReaderNodeType(reader) << " " << name << " "
+ cout << xmlTextReaderDepth(reader) << " " << xmlTextReaderNodeType(reader) << " " << name << " "
<< xmlTextReaderIsEmptyElement(reader) << " " << xmlTextReaderHasValue(reader);
if(value == NULL)
- std::cout << std::endl;
+ cout << endl;
else
- std::cout << value << std::endl;
+ cout << value << endl;
return true;
}
@@ -54,13 +54,13 @@ int xmlClose(void *context) {
}
bool readFile(const char*xsdfilename, const char *filename) {
- std::cout << "Loading schemas...\n";
+ cout << "Loading schemas...\n";
const xmlDocPtr xsddoc = xmlReadFile(xsdfilename, NULL, XML_PARSE_NONET);
const xmlSchemaParserCtxtPtr xsdctx = xmlSchemaNewDocParserCtxt(xsddoc);
const xmlSchemaPtr xsd = xmlSchemaParse(xsdctx);
const xmlSchemaValidCtxtPtr validctx = xmlSchemaNewValidCtxt(xsd);
- std::cout << "Reading file...\n";
+ cout << "Reading file...\n";
FILE* file = fopen(filename, "r");
if (file != NULL) {
const xmlTextReaderPtr reader = xmlReaderForIO(xmlRead, xmlClose, file, filename, NULL, XML_PARSE_NONET);
@@ -75,14 +75,14 @@ bool readFile(const char*xsdfilename, const char *filename) {
printNode(reader);
}
if(xmlTextReaderIsValid(reader) != 1)
- std::cout << "Could not validate document" << std::endl;
+ cout << "Could not validate document" << endl;
xmlFreeTextReader(reader);
if(rc != 0)
- std::cout << "Could not parse document" << std::endl;
+ cout << "Could not parse document" << endl;
} else
- std::cout << "Could not create parser" << std::endl;
+ cout << "Could not create parser" << endl;
} else
- std::cout << "Could not open document" << std::endl;
+ cout << "Could not open document" << endl;
xmlSchemaFreeValidCtxt(validctx);
xmlSchemaFree(xsd);
@@ -94,7 +94,7 @@ bool readFile(const char*xsdfilename, const char *filename) {
}
int main(int argc, char **argv) {
- std::cout << "Testing..." << std::endl;
+ tuscany::cout << "Testing..." << tuscany::endl;
if(argc != 3)
return 1;
@@ -102,6 +102,6 @@ int main(int argc, char **argv) {
xmlCleanupParser();
- std::cout << "OK" << std::endl;
+ tuscany::cout << "OK" << tuscany::endl;
return 0;
}