summaryrefslogtreecommitdiffstats
path: root/sca-cpp/branches/lightweight-sca/kernel/function.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'sca-cpp/branches/lightweight-sca/kernel/function.hpp')
-rw-r--r--sca-cpp/branches/lightweight-sca/kernel/function.hpp238
1 files changed, 238 insertions, 0 deletions
diff --git a/sca-cpp/branches/lightweight-sca/kernel/function.hpp b/sca-cpp/branches/lightweight-sca/kernel/function.hpp
new file mode 100644
index 0000000000..60117dab98
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/kernel/function.hpp
@@ -0,0 +1,238 @@
+/*
+ * 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_function_hpp
+#define tuscany_function_hpp
+
+/**
+ * Lambda function type.
+ */
+
+#include <utility>
+#include "fstream.hpp"
+#include "gc.hpp"
+#include "config.hpp"
+
+namespace tuscany {
+
+#ifdef WANT_MAINTAINER_COUNTERS
+
+/**
+ * Debug counters.
+ */
+long int countProxies;
+long int countFProxies = 0;
+long int countCProxies = 0;
+long int countLambdas = 0;
+long int countELambdas = 0;
+long int countCLambdas = 0;
+long int countFLambdas = 0;
+
+bool resetLambdaCounters() {
+ countLambdas = countELambdas = countCLambdas = countFLambdas = countProxies = countFProxies = countCProxies = 0;
+ return true;
+}
+
+bool checkLambdaCounters() {
+ return countLambdas == 0;
+}
+
+bool printLambdaCounters() {
+ 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;
+}
+
+#else
+
+#define resetLambdaCounters()
+#define checkLambdaCounters() true
+#define printLambdaCounters()
+
+#endif
+
+/**
+ * Lambda function type.
+ */
+
+template<typename R, typename... P> class Callable {
+public:
+ Callable() {
+ }
+
+ virtual const size_t size() const = 0;
+
+ virtual const R operator()(P... p) const = 0;
+
+ virtual ~Callable() {
+ }
+
+ template<typename F> class Proxy: public Callable {
+ public:
+ Proxy(const F& f) : function(f) {
+ debug_inc(countProxies);
+ debug_inc(countFProxies);
+ }
+
+ Proxy(const Proxy& p) : function(p.function) {
+ debug_inc(countProxies);
+ debug_inc(countCProxies);
+ }
+
+ ~Proxy() {
+ debug_dec(countProxies);
+ }
+
+ virtual const R operator() (P... p) const {
+ return function(std::forward<P>(p)...);
+ }
+
+ virtual const size_t size() const {
+ return sizeof(function);
+ }
+
+ private:
+ const F function;
+ };
+};
+
+template<typename S> class lambda;
+
+template<typename R, typename... P> class lambda<R(P...)> {
+public:
+ lambda() : callable(0) {
+ debug_inc(countLambdas);
+ debug_inc(countELambdas);
+ }
+
+ template<typename F> lambda(const F f) {
+ debug_inc(countLambdas);
+ debug_inc(countFLambdas);
+
+ typedef typename CallableType::template Proxy<F> ProxyType;
+ callable = gc_ptr<CallableType>(new (gc_new<ProxyType>()) ProxyType(f));
+ }
+
+ lambda(const lambda& l) {
+ debug_inc(countLambdas);
+ debug_inc(countCLambdas);
+ callable = l.callable;
+ }
+
+ const lambda& operator=(const lambda& l) {
+ if (this == &l)
+ return *this;
+ callable = l.callable;
+ return *this;
+ }
+
+ ~lambda() {
+ debug_dec(countLambdas);
+ }
+
+ const bool operator==(const lambda& l) const {
+ if (this == &l)
+ return true;
+ return callable == l.callable;
+ }
+
+ const bool operator!=(const lambda& l) const {
+ return !this->operator==(l);
+ }
+
+ const R operator()(P... p) const {
+ return (*callable)(std::forward<P>(p)...);
+ }
+
+ 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_ptr<CallableType> callable;
+};
+
+template<typename S> ostream& operator<<(ostream& out, const lambda<S>& l) {
+ return out << "lambda::" << l.callable;
+}
+
+/**
+ * Return true if a lambda is nil.
+ */
+template<typename S> const bool isNil(const lambda<S>& l) {
+ return ((void*)l.callable) == 0;
+}
+
+/**
+ * Curry a lambda function.
+ */
+template<typename R, typename T, typename... P> class curried {
+public:
+ curried(const lambda<R(T, P...)>& f, const T& v): v(v), f(f) {
+ }
+
+ const R operator()(P... p) const {
+ return f(v, std::forward<P>(p)...);
+ }
+
+private:
+ const T v;
+ const lambda<R(T, P...)>f;
+};
+
+template<typename R, typename T, typename... P> const lambda<R(P...)> curry(const lambda<R(T, P...)>& f, const T& t) {
+ return curried<R, T, P...>(f, t);
+}
+
+template<typename R, typename T, typename U, typename... P> const lambda<R(P...)> curry(const lambda<R(T, U, P...)>& f, const T& t, const U& u) {
+ return curry(curry(f, t), u);
+}
+
+template<typename R, typename T, typename U, typename V, typename... P> const lambda<R(P...)> curry(const lambda<R(T, U, V, P...)>& f, const T& t, const U& u, const V& v) {
+ return curry(curry(curry(f, t), u), v);
+}
+
+/**
+ * A lambda function that returns the given value.
+ */
+template<typename T> class returnResult {
+public:
+ returnResult(const T& v) :
+ v(v) {
+ }
+ const T operator()() const {
+ return v;
+ }
+private:
+ const T v;
+};
+
+template<typename T> const lambda<T()> result(const T& v) {
+ return returnResult<T> (v);
+}
+
+}
+#endif /* tuscany_function_hpp */