Xcos: "Region to superblock" fixed
[scilab.git] / scilab / modules / scicos / includes / Controller.hxx
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2014-2016 - Scilab Enterprises - Clement DAVID
4  * Copyright (C) 2017 - ESI Group - Clement DAVID
5  *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14  *
15  */
16
17 #ifndef CONTROLLER_HXX_
18 #define CONTROLLER_HXX_
19
20 #include <atomic>
21 #include <string>
22 #include <vector>
23 #include <unordered_map>
24
25 #include "utilities.hxx"
26 #include "Model.hxx"
27 #include "View.hxx"
28 #include "model/BaseObject.hxx"
29
30 #include "dynlib_scicos.h"
31
32 namespace org_scilab_modules_scicos
33 {
34
35 /**
36  * Controller from the MVC pattern
37  *
38  * All calls to objects should use this controller, all usable objects are referenced by this controller.
39  */
40 class SCICOS_IMPEXP Controller
41 {
42 public:
43 #if !defined SWIG
44     static View* register_view(const std::string& name, View* v);
45     static void unregister_view(View* v);
46     static View* unregister_view(const std::string& name);
47     static View* look_for_view(const std::string& name);
48 #endif /* !defined SWIG */
49
50     /*
51      * SWIG mapped API
52      */
53
54     static void end_simulation();
55
56     Controller();
57     ~Controller();
58
59     ScicosID createObject(kind_t k)
60     {
61         return createBaseObject(k)->id();
62     }
63
64     unsigned referenceObject(const ScicosID uid) const
65     {
66         return referenceBaseObject(getBaseObject(uid))->refCount();
67     }
68
69     void deleteObject(ScicosID uid)
70     {
71         deleteBaseObject(getBaseObject(uid));
72     }
73
74     ScicosID cloneObject(ScicosID uid, bool cloneChildren, bool clonePorts);
75
76     kind_t getKind(ScicosID uid) const;
77     std::vector<ScicosID> getAll(kind_t k) const;
78     void sortAndFillKind(std::vector<ScicosID>& uids, std::vector<int>& kind);
79
80     /*
81      * C++ API
82      */
83 #if !defined SWIG
84     model::BaseObject* createBaseObject(kind_t k);
85     template<typename T>
86     T* createBaseObject(kind_t k)
87     {
88         return static_cast<T*>(createBaseObject(k));
89     }
90     model::BaseObject* referenceBaseObject(model::BaseObject* o) const;
91     template<typename T>
92     T* referenceBaseObject(T* o) const
93     {
94         referenceBaseObject(static_cast<model::BaseObject*>(o));
95         return o;
96     }
97     template<typename T>
98     T* referenceBaseObject(model::BaseObject* o) const
99     {
100         referenceBaseObject(o);
101         return static_cast<T*>(o);
102     }
103     void deleteBaseObject(model::BaseObject* o);
104
105     model::BaseObject* getBaseObject(ScicosID uid) const;
106     template<typename T>
107     T* getBaseObject(ScicosID uid) const
108     {
109         return static_cast<T*>(getBaseObject(uid));
110     }
111
112     struct cloned_pair_t
113     {
114         model::BaseObject* initial;
115         model::BaseObject* cloned;
116
117         cloned_pair_t(model::BaseObject* i, model::BaseObject* c) : initial(i), cloned(c) {};
118     };
119     typedef std::unordered_map<ScicosID, cloned_pair_t> cloned_t;
120
121     model::BaseObject* cloneBaseObject(cloned_t& mapped, model::BaseObject* initial, bool cloneChildren, bool clonePorts);
122 #endif /* !defined SWIG */
123
124     /*
125      * C++ API: getters and setters
126      */
127     template<typename K, typename T>
128     bool getObjectProperty(K* object, object_properties_t p, T& v) const
129     {
130         static_assert(std::is_base_of<model::BaseObject, K>::value, "object should be an MVC object");
131
132         lock(&m_instance.onModelStructuralModification);
133         bool ret = m_instance.model.getObjectProperty(object, p, v);
134         unlock(&m_instance.onModelStructuralModification);
135         return ret;
136     };
137
138     template<typename K, typename T>
139     update_status_t setObjectProperty(K* object, object_properties_t p, T const& v)
140     {
141         static_assert(std::is_base_of<model::BaseObject, K>::value, "object should be an MVC object");
142
143         lock(&m_instance.onModelStructuralModification);
144         update_status_t status = m_instance.model.setObjectProperty(object, p, v);
145         unlock(&m_instance.onModelStructuralModification);
146
147         lock(&m_instance.onViewsStructuralModification);
148         for (view_set_t::iterator iter = m_instance.allViews.begin(); iter != m_instance.allViews.end(); ++iter)
149         {
150             (*iter)->propertyUpdated(object->id(), object->kind(), p, status);
151         }
152         unlock(&m_instance.onViewsStructuralModification);
153         return status;
154     };
155
156     /*
157      * SWIG mapped API: getters and setters
158      */
159
160     bool getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, double& v) const;
161     bool getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, int& v) const;
162     bool getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, bool& v) const;
163     bool getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, std::string& v) const;
164     bool getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, ScicosID& v) const;
165     bool getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, std::vector<double>& v) const;
166     bool getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, std::vector<int>& v) const;
167     bool getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, std::vector<bool>& v) const;
168     bool getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, std::vector< std::string >& v) const;
169     bool getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, std::vector<ScicosID>& v) const;
170
171     update_status_t setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, double v);
172     update_status_t setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, int v);
173     update_status_t setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, bool v);
174     update_status_t setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, ScicosID v);
175     update_status_t setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, const std::string& v);
176     update_status_t setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, const std::vector<double>& v);
177     update_status_t setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, const std::vector<int>& v);
178     update_status_t setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, const std::vector<bool>& v);
179     update_status_t setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, const std::vector< std::string >& v);
180     update_status_t setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, const std::vector<ScicosID>& v);
181
182 private:
183     typedef std::vector<View*> view_set_t;
184     typedef std::vector<std::string> view_name_set_t;
185
186     /**
187      * Shared data through all instance of the controllers
188      */
189     struct SharedData
190     {
191         std::atomic_flag onModelStructuralModification;
192         Model model;
193
194         std::atomic_flag onViewsStructuralModification;
195         view_name_set_t allNamedViews;
196         view_set_t allViews;
197
198         SharedData();
199         ~SharedData();
200     };
201
202     /*
203      * Helpers
204      */
205
206     static inline void lock(std::atomic_flag* m)
207     {
208         while (m->test_and_set(std::memory_order_acquire))  // acquire lock
209             ; // spin
210     }
211
212     static inline void unlock(std::atomic_flag* m)
213     {
214         m->clear(std::memory_order_release);
215     }
216
217     /**
218      * Shared instance of the data
219      *
220      * This will be allocated on-demand by Controller::get_instance()
221      */
222     static SharedData m_instance;
223
224     /*
225      * per instance data, for performance reasons
226      */
227     std::string _strShared;
228     std::vector<double> _vecDblShared;
229     std::vector<int> _vecIntShared;
230     std::vector<std::string> _vecStrShared;
231     std::vector<ScicosID> _vecIDShared;
232
233     /*
234      * Methods
235      */
236
237     template<typename T> void cloneProperties(model::BaseObject* initial, model::BaseObject* clone);
238     template<typename T> void cloneProperties(model::BaseObject* initial, model::BaseObject* clone, T& temporary);
239     template<typename T> bool getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, T& v) const;
240     template<typename T> update_status_t setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, T v);
241
242     void deepClone(cloned_t& mapped, model::BaseObject* initial, model::BaseObject* clone, object_properties_t p, bool cloneIfNotFound);
243     void deepCloneVector(cloned_t& mapped, model::BaseObject* initial, model::BaseObject* clone, object_properties_t p, bool cloneIfNotFound);
244     void updateChildrenRelatedPropertiesAfterClone(cloned_t& mapped);
245     void unlinkVector(model::BaseObject* o, object_properties_t uid_prop, object_properties_t ref_prop);
246     void unlink(model::BaseObject* o, object_properties_t uid_prop, object_properties_t ref_prop);
247     void deleteVector(model::BaseObject* o, object_properties_t uid_prop);
248     void deleteOwnedReference(model::BaseObject* o, object_properties_t uid_prop);
249 };
250
251 } /* namespace org_scilab_modules_scicos */
252
253 #endif /* CONTROLLER_HXX_ */