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