00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <basix/dynamic.hpp>
00014
00016
00017 namespace mmx {
00018
00019
00020
00021
00022
00023 dynamic_rep::dynamic_rep (const generic& val2):
00024 val (val2) {}
00025
00026 dynamic_rep::~dynamic_rep () {
00027 for (nat i=0; i<N(obs); i++)
00028 obs[i]->destroy ();
00029 obs= vector<observer> ();
00030 }
00031
00032 void
00033 assign (const dynamic& d, const generic& val) {
00034 if (val == d->val) return;
00035 inside (d) -> val= val;
00036 for (nat i=0; i<N(d->obs); i++)
00037 d->obs[i]->modify ();
00038 }
00039
00040 void
00041 message (const dynamic& d, const generic& msg) {
00042 for (nat i=0; i<N(d->obs); i++)
00043 d->obs[i]->message (msg);
00044 }
00045
00046 void
00047 attach (const dynamic& d, const observer& o) {
00048 inside (d) -> obs << o;
00049 }
00050
00051 void
00052 detach (const observer& o) {
00053 vector<observer>& obs= o->ref->obs;
00054 for (nat i=0; i<N(obs); i++)
00055 if (hard_eq (obs[i], o)) {
00056 obs= append (range (obs, 0, i), range (obs, i+1, N(obs)));
00057 return;
00058 }
00059 ERROR ("observer not attached");
00060 }
00061
00062
00063
00064
00065
00066 void (*dynamic_event) (const string& id, const generic& val) = NULL;
00067
00068 string
00069 unique_identifier (const dynamic& g) {
00070 return "mmx-" * as_string (hard_hash (g));
00071 }
00072
00073 class output_observer_rep: public observer_rep {
00074 public:
00075 inline output_observer_rep (dynamic_rep* arg): observer_rep (arg) {}
00076 inline ~output_observer_rep () {}
00077 inline nat observer_type () const { return OUTPUT_OBSERVER; }
00078 inline void destroy () const {}
00079 inline void modify () const {
00080 if (dynamic_event == NULL) return;
00081 dynamic_event (unique_identifier (dynamic (ref, true)), ref->val); }
00082 };
00083
00084 observer
00085 output_observer (dynamic_rep* arg) {
00086 return observer (new output_observer_rep (arg));
00087 }
00088
00089 syntactic
00090 flatten (const dynamic& g) {
00091 syntactic r=
00092 apply ("$dynamic", syntactic (unique_identifier (g)), flatten (g->val));
00093 for (nat i=0; i<N(g->obs); i++)
00094 if (g->obs[i]->observer_type () == OUTPUT_OBSERVER)
00095 return r;
00096 attach (g, output_observer (inside (g)));
00097 inside (g) -> ref_count++;
00098 return r;
00099 }
00100
00101
00102
00103
00104
00105 class updater;
00106 void destroy (const updater& u);
00107
00108 class updater_rep: public rep_struct {
00109 public:
00110 routine fun;
00111 dynamic_rep* ret;
00112 vector<dynamic> args;
00113 vector<observer> obs;
00114
00115 inline updater_rep (const routine& fun2, dynamic_rep* ret2,
00116 const vector<dynamic>& args2):
00117 fun (fun2), ret (ret2), args (args2) {}
00118 inline ~updater_rep () {}
00119 void update () const;
00120
00121 friend class observer;
00122 };
00123
00124 class updater {
00125 INDIRECT_PROTO (updater, updater_rep)
00126 public:
00127 inline updater (const routine& fun, dynamic_rep* ret,
00128 const vector<dynamic>& args):
00129 rep (new updater_rep (fun, ret, args)) {}
00130 friend void destroy (const updater& u);
00131 friend class updater_rep;
00132 };
00133 INDIRECT_IMPL (updater, updater_rep)
00134
00135
00136
00137
00138
00139 class argument_observer_rep: public observer_rep {
00140 public:
00141 updater u;
00142
00143 inline argument_observer_rep (dynamic_rep* arg, const updater& u2):
00144 observer_rep (arg), u (u2) {}
00145 inline ~argument_observer_rep () {}
00146 inline nat observer_type () const { return ARGUMENT_OBSERVER; }
00147 inline void destroy () const { mmx::destroy (u); }
00148 inline void modify () const { u->update (); }
00149 };
00150
00151 observer
00152 argument_observer (dynamic_rep* arg, const updater& u) {
00153 return observer (new argument_observer_rep (arg, u));
00154 }
00155
00156 class result_observer_rep: public observer_rep {
00157 public:
00158 updater u;
00159
00160 inline result_observer_rep (dynamic_rep* res, const updater& u2):
00161 observer_rep (res), u (u2) {}
00162 inline ~result_observer_rep () {}
00163 inline nat observer_type () const { return RESULT_OBSERVER; }
00164 inline void destroy () const { mmx::destroy (u); }
00165 inline void modify () const {}
00166 };
00167
00168 observer
00169 result_observer (dynamic_rep* arg, const updater& u) {
00170 return observer (new result_observer_rep (arg, u));
00171 }
00172
00173
00174
00175
00176
00177 generic
00178 apply (const routine& fun, const vector<dynamic>& args) {
00179 vector<generic> a= fill<generic> (N (args));
00180 for (nat i= 0; i<N(a); i++)
00181 a[i]= args[i]->val;
00182 generic r= fun->apply (a);
00183 return r;
00184 }
00185
00186 void
00187 updater_rep::update () const {
00188 vector<generic> a= fill<generic> (N (args));
00189 for (nat i= 0; i<N(a); i++) a[i]= args[i]->val;
00190 assign (dynamic (ret, true), fun->apply (a));
00191 }
00192
00193 dynamic::dynamic (const routine& fun, const vector<dynamic>& args):
00194 rep (new dynamic_rep (apply (fun, args)))
00195 {
00196 updater u (fun, rep, args);
00197 for (nat i=0; i<N(args); i++) {
00198 observer arg_obs= argument_observer (inside (args[i]), u);
00199 attach (args[i], arg_obs);
00200 inside (u) -> obs << arg_obs;
00201 }
00202 observer res_obs= result_observer (rep, u);
00203 rep->obs << res_obs;
00204 inside (u) -> obs << res_obs;
00205 }
00206
00207 void
00208 destroy (const updater& u) {
00209 for (nat i=0; i<N(u->obs); i++) detach (u->obs[i]);
00210 inside (u) -> args = vector<dynamic> ();
00211 inside (u) -> obs = vector<observer> ();
00212 }
00213
00214 }