Back to index

easystroke  0.5.5.1
var.h
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008-2009, Thomas Jaeger <ThJaeger@gmail.com>
00003  *
00004  * Permission to use, copy, modify, and/or distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
00009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00011  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
00013  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
00014  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 #ifndef __VAR_H__
00017 #define __VAR_H__
00018 
00019 #include <set>
00020 #include <boost/shared_ptr.hpp>
00021 #include <glibmm.h>
00022 #include "util.h"
00023 
00024 class Base {
00025 public:
00026        virtual void notify() = 0;
00027 };
00028 
00029 class Notifier : public Base {
00030        sigc::slot<void> f;
00031 public:
00032        Notifier(sigc::slot<void> f_) : f(f_) {}
00033        virtual void notify() { f(); }
00034 };
00035 
00036 class Atomic {
00037        std::set<Base *> update_queue;
00038 public:
00039        void defer(Base *out) { update_queue.insert(out); }
00040        ~Atomic() {
00041               for (std::set<Base *>::iterator i = update_queue.begin(); i != update_queue.end(); i++)
00042                      (*i)->notify();
00043        }
00044 };
00045 
00046 template <class T> class Out {
00047        std::set<Base *> out;
00048 protected:
00049        void update() {
00050               for (std::set<Base *>::iterator i = out.begin(); i != out.end(); i++)
00051                      (*i)->notify();
00052        }
00053 public:
00054        void connect(Base *s) { out.insert(s); }
00055        virtual T get() const = 0;
00056 };
00057 
00058 template <class T> class In {
00059 public:
00060        virtual void set(const T x) = 0;
00061 };
00062 
00063 template <class T> class IO : public In<T>, public Out<T> {};
00064 
00065 template <class T> class Source : public IO<T>, private Base {
00066        T x;
00067 public:
00068        Source() {}
00069        Source(T x_) : x(x_) {}
00070        virtual void set(const T x_) {
00071               x = x_;
00072               Out<T>::update();
00073        }
00074        virtual T get() const { return x; }
00075        const T &ref() const { return x; }
00076        // write_refs are evil
00077        T &write_ref(Atomic &a) {
00078               a.defer(this);
00079               return x;
00080        }
00081        virtual void notify() { Out<T>::update(); }
00082        // unsafe_refs even more so
00083        T &unsafe_ref() { return x; }
00084 };
00085 
00086 template <class T> class Var : public IO<T>, private Base {
00087        Out<T> &in;
00088        T x;
00089 public:
00090        Var(Out<T> &in_) : in(in_), x(in.get()) { in.connect(this); }
00091        virtual void notify() { set(in.get()); }
00092        virtual void set(const T x_) {
00093               x = x_;
00094               Out<T>::update();
00095        }
00096        virtual T get() const { return x; }
00097 };
00098 
00099 template <class X, class Y> class Fun : public Out<Y>, private Base {
00100        sigc::slot<Y, X> f;
00101        Out<X> &in;
00102 public:
00103        Fun(sigc::slot<Y, X> f_, Out<X> &in_) : f(f_), in(in_) { in.connect(this); }
00104        virtual Y get() const { return f(in.get()); }
00105        virtual void notify() { Out<Y>::update(); }
00106 };
00107 
00108 template <class X, class Y> Fun<X, Y> *fun(Y (*f)(X), Out<X> &in) {
00109        return new Fun<X, Y>(sigc::ptr_fun(f), in);
00110 }
00111 
00112 template <class X, class Y, class Z> class Fun2 : public Out<Z>, private Base {
00113        sigc::slot<Z, X, Y> f;
00114        Out<X> &inX;
00115        Out<Y> &inY;
00116 public:
00117        Fun2(sigc::slot<Z, X, Y> f_, Out<X> &inX_, Out<Y> &inY_) : f(f_), inX(inX_), inY(inY_) {
00118               inX.connect(this);
00119               inY.connect(this);
00120        }
00121        virtual Z get() const { return f(inX.get(), inY.get()); }
00122        virtual void notify() { Out<Z>::update(); }
00123 };
00124 
00125 template <class X1, class X2, class Y> Fun2<X1, X2, Y> *fun2(Y (*f)(X1, X2), Out<X1> &in1, Out<X2> &in2) {
00126        return new Fun2<X1, X2, Y>(sigc::ptr_fun(f), in1, in2);
00127 }
00128 
00129 template <class X, class Y> class Bijection : public IO<Y>, private Base {
00130        sigc::slot<Y, X> f;
00131        sigc::slot<X, Y> g;
00132        IO<X> &in;
00133 public:
00134        Bijection(sigc::slot<Y, X> f_, sigc::slot<X, Y> g_, IO<X> &in_) : f(f_), g(g_), in(in_) {
00135               in.connect(this);
00136        }
00137        virtual Y get() const { return f(in.get()); }
00138        virtual void notify() { Out<Y>::update(); }
00139        virtual void set(const Y y) { in.set(g(y)); }
00140 };
00141 
00142 class Watcher : private Base {
00143 public:
00144        template <class T> void watch(Out<T> &v) { v.connect(this); }
00145 };
00146 
00147 class TimeoutWatcher : public Watcher, Timeout {
00148        int ms;
00149 public:
00150        TimeoutWatcher(int ms_) : ms(ms_) {}
00151        virtual void notify() { set_timeout(ms); }
00152        void execute_now() {
00153               if (remove_timeout())
00154                      timeout();
00155        }
00156 };
00157 #endif