Xcos MVC: use ScicosID() instead of 0
[scilab.git] / scilab / modules / scicos / src / cpp / Controller.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2014-2014 - Scilab Enterprises - Clement DAVID
4  *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13  *
14  */
15
16 #include <atomic>
17 #include <string>
18 #include <vector>
19 #include <map>
20 #include <utility>
21 #include <algorithm>
22 #include <iterator>
23
24 #include "utilities.hxx"
25
26 #define REF_DEBUG 0
27 #if REF_DEBUG
28 #include "scilabWrite.hxx"
29 #define REF_PRINT(uid, refCount) \
30         do { \
31         std::stringstream print; \
32         print << "referenceObject( " << uid << " ) : " << refCount << std::endl; \
33         scilabForcedWrite(print.str().data()); \
34         } while(0)
35 #define UNREF_PRINT(uid, count) \
36         do { \
37         std::stringstream print; \
38         print << "unreferenceObject( " << uid << " ) : " << refCount << std::endl; \
39         scilabForcedWrite(print.str().data()); \
40         } while(0)
41 #define CLONE_PRINT(uid, clone) \
42         do { \
43         std::stringstream print; \
44         print << "cloneObject( " << uid << " ) : " << clone << std::endl; \
45         scilabForcedWrite(print.str().data()); \
46         } while(0)
47 #else
48 #define REF_PRINT(uid, refCount)
49 #define UNREF_PRINT(uid, refCount)
50 #define CLONE_PRINT(uid, clone)
51 #endif
52
53 #include "Controller.hxx"
54 #include "model/BaseObject.hxx"
55
56 #include "LoggerView.hxx"
57
58 extern "C" {
59 #include "scicos.h"
60 }
61
62 namespace org_scilab_modules_scicos
63 {
64
65 static inline void lock(std::atomic_flag* m)
66 {
67     while (m->test_and_set(std::memory_order_acquire))  // acquire lock
68         ; // spin
69 }
70
71 static inline void unlock(std::atomic_flag* m)
72 {
73     m->clear(std::memory_order_release);
74 }
75
76 /*
77  * Implement SharedData methods
78  */
79 Controller::SharedData::SharedData() :
80     onModelStructuralModification(), model(),
81     onViewsStructuralModification(), allNamedViews(), allViews()
82 {
83     unlock(&onModelStructuralModification);
84     unlock(&onViewsStructuralModification);
85 }
86
87 Controller::SharedData::~SharedData()
88 {
89     lock(&onViewsStructuralModification);
90     for (view_set_t::iterator iter = allViews.begin(); iter != allViews.end(); ++iter)
91     {
92         delete *iter;
93     }
94     unlock(&onViewsStructuralModification);
95 }
96
97 Controller::SharedData Controller::m_instance;
98
99 View* Controller::register_view(const std::string& name, View* v)
100 {
101     lock(&m_instance.onViewsStructuralModification);
102
103     m_instance.allNamedViews.push_back(name);
104     m_instance.allViews.push_back(v);
105
106     unlock(&m_instance.onViewsStructuralModification);
107     return v;
108 }
109
110 void Controller::unregister_view(View* v)
111 {
112     lock(&m_instance.onViewsStructuralModification);
113
114     view_set_t::iterator it = std::find(m_instance.allViews.begin(), m_instance.allViews.end(), v);
115     if (it != m_instance.allViews.end())
116     {
117         size_t d = std::distance(m_instance.allViews.begin(), it);
118         m_instance.allNamedViews.erase(m_instance.allNamedViews.begin() + d);
119         m_instance.allViews.erase(m_instance.allViews.begin() + d);
120     }
121
122     unlock(&m_instance.onViewsStructuralModification);
123 }
124
125 View* Controller::unregister_view(const std::string& name)
126 {
127     View* view = nullptr;
128
129     lock(&m_instance.onViewsStructuralModification);
130
131     view_name_set_t::iterator it = std::find(m_instance.allNamedViews.begin(), m_instance.allNamedViews.end(), name);
132     if (it != m_instance.allNamedViews.end())
133     {
134         size_t d = std::distance(m_instance.allNamedViews.begin(), it);
135         view = *(m_instance.allViews.begin() + d);
136         m_instance.allNamedViews.erase(m_instance.allNamedViews.begin() + d);
137         m_instance.allViews.erase(m_instance.allViews.begin() + d);
138     }
139     unlock(&m_instance.onViewsStructuralModification);
140
141     return view;
142 }
143
144 View* Controller::look_for_view(const std::string& name)
145 {
146     View* view = nullptr;
147
148     lock(&m_instance.onViewsStructuralModification);
149     view_name_set_t::iterator it = std::find(m_instance.allNamedViews.begin(), m_instance.allNamedViews.end(), name);
150     if (it != m_instance.allNamedViews.end())
151     {
152         size_t d = std::distance(m_instance.allNamedViews.begin(), it);
153         view = *(m_instance.allViews.begin() + d);
154     }
155     unlock(&m_instance.onViewsStructuralModification);
156
157     return view;
158 }
159
160 void Controller::end_simulation()
161 {
162     end_scicos_sim();
163 }
164
165 Controller::Controller()
166 {
167 }
168
169 Controller::~Controller()
170 {
171 }
172
173 ScicosID Controller::createObject(kind_t k)
174 {
175     lock(&m_instance.onModelStructuralModification);
176     ScicosID uid = m_instance.model.createObject(k);
177     unlock(&m_instance.onModelStructuralModification);
178
179     lock(&m_instance.onViewsStructuralModification);
180     for (view_set_t::iterator iter = m_instance.allViews.begin(); iter != m_instance.allViews.end(); ++iter)
181     {
182         (*iter)->objectCreated(uid, k);
183     }
184     unlock(&m_instance.onViewsStructuralModification);
185
186     return uid;
187 }
188
189 unsigned Controller::referenceObject(const ScicosID uid) const
190 {
191     lock(&m_instance.onModelStructuralModification);
192
193     unsigned refCount = m_instance.model.referenceObject(uid);
194     REF_PRINT(uid, refCount);
195
196     auto o = m_instance.model.getObject(uid);
197     unlock(&m_instance.onModelStructuralModification);
198     if (o == nullptr)
199     {
200         // defensive programming
201         return 0u;
202     }
203
204     lock(&m_instance.onViewsStructuralModification);
205     for (view_set_t::iterator iter = m_instance.allViews.begin(); iter != m_instance.allViews.end(); ++iter)
206     {
207         (*iter)->objectReferenced(uid, o->kind(), refCount);
208     }
209     unlock(&m_instance.onViewsStructuralModification);
210
211     return refCount;
212 }
213
214 void Controller::deleteObject(ScicosID uid)
215 {
216     // if this object is the empty uid, ignore it : is is not stored in the model
217     if (uid == ScicosID())
218     {
219         return;
220     }
221
222     lock(&m_instance.onModelStructuralModification);
223
224     auto initial = m_instance.model.getObject(uid);
225     if (initial == nullptr)
226     {
227         // defensive programming
228         unlock(&m_instance.onModelStructuralModification);
229         return;
230     }
231     const kind_t k = initial->kind();
232
233     // if this object has been referenced somewhere else do not delete it but decrement the reference counter
234     unsigned& refCount = m_instance.model.referenceCount(uid);
235     unlock(&m_instance.onModelStructuralModification);
236     if (refCount > 0)
237     {
238         --refCount;
239         UNREF_PRINT(uid, refCount);
240
241         lock(&m_instance.onViewsStructuralModification);
242         for (view_set_t::iterator iter = m_instance.allViews.begin(); iter != m_instance.allViews.end(); ++iter)
243         {
244             (*iter)->objectUnreferenced(uid, k, refCount);
245         }
246         unlock(&m_instance.onViewsStructuralModification);
247         return;
248     }
249
250     // We need to delete this object and cleanup all the referenced model object
251
252     // disconnect / remove references of weak connected objects and decrement the reference count of all strongly connected objects.
253     if (k == ANNOTATION)
254     {
255         unlinkVector(uid, k, PARENT_DIAGRAM, CHILDREN);
256         unlinkVector(uid, k, PARENT_BLOCK, CHILDREN);
257         // RELATED_TO is not referenced back
258     }
259     else if (k == BLOCK)
260     {
261         unlinkVector(uid, k, PARENT_DIAGRAM, CHILDREN);
262         unlinkVector(uid, k, PARENT_BLOCK, CHILDREN);
263
264         deleteVector(uid, k, INPUTS);
265         deleteVector(uid, k, OUTPUTS);
266         deleteVector(uid, k, EVENT_INPUTS);
267         deleteVector(uid, k, EVENT_OUTPUTS);
268
269         unlink(uid, k, CHILDREN, PARENT_BLOCK);
270         deleteVector(uid, k, CHILDREN);
271         // FIXME what about REFERENCED_PORT ?
272     }
273     else if (k == DIAGRAM)
274     {
275         unlink(uid, k, CHILDREN, PARENT_DIAGRAM);
276         deleteVector(uid, k, CHILDREN);
277     }
278     else if (k == LINK)
279     {
280         unlinkVector(uid, k, PARENT_DIAGRAM, CHILDREN);
281         unlinkVector(uid, k, PARENT_BLOCK, CHILDREN);
282
283         unlinkVector(uid, k, SOURCE_PORT, CONNECTED_SIGNALS);
284         unlinkVector(uid, k, DESTINATION_PORT, CONNECTED_SIGNALS);
285     }
286     else if (k == PORT)
287     {
288         unlinkVector(uid, k, SOURCE_BLOCK, INPUTS);
289         unlinkVector(uid, k, SOURCE_BLOCK, OUTPUTS);
290         unlinkVector(uid, k, SOURCE_BLOCK, EVENT_INPUTS);
291         unlinkVector(uid, k, SOURCE_BLOCK, EVENT_OUTPUTS);
292
293         unlink(uid, k, CONNECTED_SIGNALS, SOURCE_PORT);
294         unlink(uid, k, CONNECTED_SIGNALS, DESTINATION_PORT);
295     }
296
297     // delete the object
298     lock(&m_instance.onModelStructuralModification);
299     m_instance.model.deleteObject(uid);
300     unlock(&m_instance.onModelStructuralModification);
301
302     lock(&m_instance.onViewsStructuralModification);
303     for (view_set_t::iterator iter = m_instance.allViews.begin(); iter != m_instance.allViews.end(); ++iter)
304     {
305         (*iter)->objectDeleted(uid, k);
306     }
307     unlock(&m_instance.onViewsStructuralModification);
308 }
309
310 void Controller::unlinkVector(ScicosID uid, kind_t k, object_properties_t uid_prop, object_properties_t ref_prop)
311 {
312     ScicosID v;
313     getObjectProperty(uid, k, uid_prop, v);
314     if (v != ScicosID())
315     {
316         auto o = getObject(v);
317         if (o == nullptr)
318         {
319             return;
320         }
321
322         std::vector<ScicosID> children;
323         getObjectProperty(o->id(), o->kind(), ref_prop, children);
324
325         std::vector<ScicosID>::iterator it = std::find(children.begin(), children.end(), uid);
326         if (it != children.end())
327         {
328             children.erase(it);
329         }
330
331         setObjectProperty(o->id(), o->kind(), ref_prop, children);
332     }
333 }
334
335 void Controller::unlink(ScicosID uid, kind_t k, object_properties_t uid_prop, object_properties_t ref_prop)
336 {
337     std::vector<ScicosID> v;
338     getObjectProperty(uid, k, uid_prop, v);
339     for (const ScicosID id : v)
340     {
341         if (id != ScicosID())
342         {
343             auto o = getObject(id);
344             if (o == nullptr)
345             {
346                 continue;
347             }
348
349             // Find which end of the link is connected to the port
350             ScicosID oppositeRef;
351             getObjectProperty(o->id(), o->kind(), ref_prop, oppositeRef);
352             if (oppositeRef == uid)
353             {
354                 setObjectProperty(o->id(), o->kind(), ref_prop, ScicosID());
355             }
356         }
357     }
358 }
359
360 void Controller::deleteVector(ScicosID uid, kind_t k, object_properties_t uid_prop)
361 {
362     std::vector<ScicosID> children;
363     getObjectProperty(uid, k, uid_prop, children);
364
365     for (ScicosID id : children)
366     {
367         deleteObject(id);
368     }
369 }
370
371 template<typename T>
372 void Controller::cloneProperties(model::BaseObject* initial, ScicosID clone)
373 {
374     for (int i = 0; i < MAX_OBJECT_PROPERTIES; ++i)
375     {
376         enum object_properties_t p = static_cast<enum object_properties_t>(i);
377
378         T value;
379         bool status = getObjectProperty(initial->id(), initial->kind(), p, value);
380         if (status)
381         {
382             setObjectProperty(clone, initial->kind(), p, value);
383         }
384     }
385 }
386
387 ScicosID Controller::cloneObject(std::map<ScicosID, ScicosID>& mapped, ScicosID uid, bool cloneChildren, bool clonePorts)
388 {
389     auto initial = getObject(uid);
390     const kind_t k = initial->kind();
391     ScicosID o = createObject(k);
392     mapped.insert(std::make_pair(uid, o));
393
394     // Get then set all properties per type that do not manage ScicosID
395     cloneProperties<double>(initial, o);
396     cloneProperties<int>(initial, o);
397     cloneProperties<bool>(initial, o);
398     cloneProperties<std::string>(initial, o);
399     cloneProperties<std::vector<double> >(initial, o);
400     cloneProperties<std::vector<int> >(initial, o);
401     cloneProperties<std::vector<std::string> >(initial, o);
402
403     // deep copy children, manage ScicosID and std::vector<ScicosID>
404     if (k == ANNOTATION)
405     {
406         deepClone(mapped, uid, o, k, PARENT_DIAGRAM, false);
407         deepClone(mapped, uid, o, k, PARENT_BLOCK, false);
408         deepClone(mapped, uid, o, k, RELATED_TO, true);
409     }
410     else if (k == BLOCK)
411     {
412         deepClone(mapped, uid, o, k, PARENT_DIAGRAM, false);
413         if (clonePorts)
414         {
415             // Only copy the block, without any port
416             deepCloneVector(mapped, uid, o, k, INPUTS, true);
417             deepCloneVector(mapped, uid, o, k, OUTPUTS, true);
418             deepCloneVector(mapped, uid, o, k, EVENT_INPUTS, true);
419             deepCloneVector(mapped, uid, o, k, EVENT_OUTPUTS, true);
420         }
421
422         deepClone(mapped, uid, o, k, PARENT_BLOCK, false);
423         if (cloneChildren)
424         {
425             deepCloneVector(mapped, uid, o, k, CHILDREN, true);
426         }
427         // FIXME what about REFERENCED_PORT ?
428     }
429     else if (k == DIAGRAM)
430     {
431         if (cloneChildren)
432         {
433             deepCloneVector(mapped, uid, o, k, CHILDREN, true);
434         }
435     }
436     else if (k == LINK)
437     {
438         deepClone(mapped, uid, o, k, PARENT_DIAGRAM, false);
439         deepClone(mapped, uid, o, k, PARENT_BLOCK, false);
440         deepClone(mapped, uid, o, k, SOURCE_PORT, false);
441         deepClone(mapped, uid, o, k, DESTINATION_PORT, false);
442     }
443     else if (k == PORT)
444     {
445         deepClone(mapped, uid, o, k, SOURCE_BLOCK, false);
446         deepCloneVector(mapped, uid, o, k, CONNECTED_SIGNALS, false);
447     }
448     return o;
449 }
450
451 void Controller::deepClone(std::map<ScicosID, ScicosID>& mapped, ScicosID uid, ScicosID clone, kind_t k, object_properties_t p, bool cloneIfNotFound)
452 {
453     ScicosID v;
454     getObjectProperty(uid, k, p, v);
455
456     ScicosID cloned = ScicosID();
457
458     std::map<ScicosID, ScicosID>::iterator it = mapped.find(v);
459     if (it != mapped.end())
460     {
461         cloned = it->second;
462     }
463     else
464     {
465         if (cloneIfNotFound)
466         {
467             if (v != ScicosID())
468             {
469                 cloned = cloneObject(mapped, v, true, true);
470             }
471             else
472             {
473                 cloned = ScicosID();
474             }
475         }
476         else
477         {
478             cloned = ScicosID();
479         }
480     }
481
482     setObjectProperty(clone, k, p, cloned);
483     // When cloning a Link, connect both extremities together
484     if ((p == SOURCE_PORT || p == DESTINATION_PORT) && cloned != ScicosID())
485     {
486         setObjectProperty(cloned, PORT, CONNECTED_SIGNALS, clone);
487     }
488 }
489
490 void Controller::deepCloneVector(std::map<ScicosID, ScicosID>& mapped, ScicosID uid, ScicosID clone, kind_t k, object_properties_t p, bool cloneIfNotFound)
491 {
492     std::vector<ScicosID> v;
493     getObjectProperty(uid, k, p, v);
494
495     std::vector<ScicosID> cloned;
496     cloned.reserve(v.size());
497
498     for (const ScicosID & id : v)
499     {
500         if (id == ScicosID())
501         {
502             // Deleted Block, the cloning is done at Adapter level
503             cloned.push_back(id);
504             continue;
505         }
506
507         std::map<ScicosID, ScicosID>::iterator it = mapped.find(id);
508         if (it != mapped.end())
509         {
510             if (k == PORT)
511             {
512                 // We get here if we are cloning a block connected to a link that comes before itself in the objects list,
513                 // so which has already been cloned but could not be connected yet.
514                 int port_kind;
515                 getObjectProperty(clone, PORT, PORT_KIND, port_kind);
516                 if (port_kind == PORT_IN || port_kind == PORT_EIN)
517                 {
518                     setObjectProperty(it->second, LINK, DESTINATION_PORT, clone);
519                 }
520                 else
521                 {
522                     // FIXME: fix case for implicit ports, in which case connect the first unconnected link end, it doesn't matter which one
523                     setObjectProperty(it->second, LINK, SOURCE_PORT, clone);
524                 }
525             }
526             cloned.push_back(it->second);
527         }
528         else
529         {
530             if (cloneIfNotFound)
531             {
532                 if (id != ScicosID())
533                 {
534                     cloned.push_back(cloneObject(mapped, id, true, true));
535                 }
536                 else
537                 {
538                     cloned.push_back(ScicosID());
539                 }
540             }
541             else
542             {
543                 cloned.push_back(ScicosID());
544             }
545         }
546     }
547
548     setObjectProperty(clone, k, p, cloned);
549 }
550
551 ScicosID Controller::cloneObject(ScicosID uid, bool cloneChildren, bool clonePorts)
552 {
553     std::map<ScicosID, ScicosID> mapped;
554     ScicosID clone = cloneObject(mapped, uid, cloneChildren, clonePorts);
555     CLONE_PRINT(uid, clone);
556
557     return clone;
558 }
559
560 kind_t Controller::getKind(ScicosID uid) const
561 {
562     lock(&m_instance.onModelStructuralModification);
563
564     kind_t kind = m_instance.model.getKind(uid);
565
566     unlock(&m_instance.onModelStructuralModification);
567     return kind;
568 }
569
570 std::vector<ScicosID> Controller::getAll(kind_t k) const
571 {
572     lock(&m_instance.onModelStructuralModification);
573
574     auto vec = m_instance.model.getAll(k);
575
576     unlock(&m_instance.onModelStructuralModification);
577     return vec;
578 }
579
580 void Controller::sortAndFillKind(std::vector<ScicosID>& uids, std::vector<int>& kinds)
581 {
582     lock(&m_instance.onModelStructuralModification);
583
584     // create a container of pair
585     struct local_pair
586     {
587         ScicosID first;
588         int second;
589     };
590     std::vector<local_pair> container(uids.size());
591
592     // fill it
593     for (size_t i = 0; i < uids.size(); ++i)
594     {
595         container[i] = { uids[i], m_instance.model.getKind(uids[i]) };
596     }
597
598     // sort according to the kinds
599     std::stable_sort(container.begin(), container.end(), [] (const local_pair & a, const local_pair & b)
600     {
601         return a.second < b.second;
602     });
603
604     // move things back
605     uids.clear();
606     kinds.reserve(uids.capacity());
607     for (const auto & v : container)
608     {
609         uids.push_back(v.first);
610         kinds.push_back(v.second);
611     }
612
613     unlock(&m_instance.onModelStructuralModification);
614 }
615
616 template<typename T>
617 bool Controller::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, T& v) const
618 {
619     lock(&m_instance.onModelStructuralModification);
620     bool ret = m_instance.model.getObjectProperty(uid, k, p, v);
621     unlock(&m_instance.onModelStructuralModification);
622     return ret;
623 }
624
625 bool Controller::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, double& v) const
626 {
627     return getObjectProperty<>(uid, k, p, v);
628 }
629 bool Controller::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, int& v) const
630 {
631     return getObjectProperty<>(uid, k, p, v);
632 }
633 bool Controller::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, bool& v) const
634 {
635     return getObjectProperty<>(uid, k, p, v);
636 }
637 bool Controller::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, std::string& v) const
638 {
639     return getObjectProperty<>(uid, k, p, v);
640 }
641 bool Controller::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, ScicosID& v) const
642 {
643     return getObjectProperty<>(uid, k, p, v);
644 }
645 bool Controller::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, std::vector<double>& v) const
646 {
647     return getObjectProperty<>(uid, k, p, v);
648 }
649 bool Controller::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, std::vector<int>& v) const
650 {
651     return getObjectProperty<>(uid, k, p, v);
652 }
653 bool Controller::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, std::vector<bool>& v) const
654 {
655     return getObjectProperty<>(uid, k, p, v);
656 }
657 bool Controller::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, std::vector< std::string >& v) const
658 {
659     return getObjectProperty<>(uid, k, p, v);
660 }
661 bool Controller::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, std::vector<ScicosID>& v) const
662 {
663     return getObjectProperty<>(uid, k, p, v);
664 }
665
666 template<typename T>
667 update_status_t Controller::setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, T v)
668 {
669     lock(&m_instance.onModelStructuralModification);
670     update_status_t status = m_instance.model.setObjectProperty(uid, k, p, v);
671     unlock(&m_instance.onModelStructuralModification);
672
673     lock(&m_instance.onViewsStructuralModification);
674     for (view_set_t::iterator iter = m_instance.allViews.begin(); iter != m_instance.allViews.end(); ++iter)
675     {
676         (*iter)->propertyUpdated(uid, k, p, status);
677     }
678     unlock(&m_instance.onViewsStructuralModification);
679     return status;
680 }
681
682 update_status_t Controller::setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, double v)
683 {
684     return setObjectProperty<>(uid, k, p, v);
685 }
686 update_status_t Controller::setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, int v)
687 {
688     return setObjectProperty<>(uid, k, p, v);
689 }
690 update_status_t Controller::setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, bool v)
691 {
692     return setObjectProperty<>(uid, k, p, v);
693 }
694 update_status_t Controller::setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, ScicosID v)
695 {
696     return setObjectProperty<>(uid, k, p, v);
697 }
698 update_status_t Controller::setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, const std::string& v)
699 {
700     return setObjectProperty<>(uid, k, p, v);
701 }
702 update_status_t Controller::setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, const std::vector<double>& v)
703 {
704     return setObjectProperty<>(uid, k, p, v);
705 }
706 update_status_t Controller::setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, const std::vector<int>& v)
707 {
708     return setObjectProperty<>(uid, k, p, v);
709 }
710 update_status_t Controller::setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, const std::vector<bool>& v)
711 {
712     return setObjectProperty<>(uid, k, p, v);
713 }
714 update_status_t Controller::setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, const std::vector< std::string >& v)
715 {
716     return setObjectProperty<>(uid, k, p, v);
717 }
718 update_status_t Controller::setObjectProperty(ScicosID uid, kind_t k, object_properties_t p, const std::vector<ScicosID>& v)
719 {
720     return setObjectProperty<>(uid, k, p, v);
721 }
722
723 model::BaseObject* Controller::getObject(ScicosID uid) const
724 {
725     lock(&m_instance.onModelStructuralModification);
726     model::BaseObject* o = m_instance.model.getObject(uid);
727     unlock(&m_instance.onModelStructuralModification);
728     return o;
729 }
730
731 } /* namespace org_scilab_modules_scicos */
732