YARP
Yet Another Robot Platform
Nodes.cpp
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3  * SPDX-License-Identifier: BSD-3-Clause
4  */
5 
6 #include <yarp/os/Nodes.h>
7 
8 #include <yarp/os/Log.h>
10 #include <yarp/os/Node.h>
11 
12 #include <map>
13 #include <mutex>
14 
15 using namespace yarp::os;
16 
18 {
19 public:
20  Private();
21  ~Private();
22 
23  void clear();
24  Node* getNode(const std::string& name, bool create);
25  void add(Contactable& contactable);
26  void update(Contactable& contactable);
27  void prepare(const std::string& name);
28  void remove(Contactable& contactable);
29  Contact query(const std::string& name, const std::string& category);
30  void interrupt();
31  bool enable(bool flag);
32  Contact getParent(const std::string& name);
33  Contact getURI(const std::string& name);
34  void setActiveName(const std::string& name);
35  std::string getActiveName();
36  bool requireActiveName();
37  void addExternalNode(const std::string& name, Node& node);
38  void removeExternalNode(const std::string& name);
39 
40  // Port name
41  // Pointer to Node
42  // true = is external
43  std::map<std::string, std::pair<Node*, bool>> nodes_map;
44 
45  std::mutex mutex;
46  bool active{false};
47  std::string active_name;
48  Node* dummy{nullptr};
49 };
50 
52 {
53  clear();
54 }
55 
57 {
58  clear();
59 }
60 
62 {
63  mutex.lock();
64  for (auto& n : nodes_map) {
65  if (n.second.first != nullptr) {
66  if (!n.second.second) {
67  delete n.second.first;
68  n.second.first = nullptr;
69  }
70  }
71  }
72  nodes_map.clear();
73  mutex.unlock();
74 
75  active = true;
76  active_name = "";
77  if (dummy != nullptr) {
78  delete dummy;
79  dummy = nullptr;
80  }
81 }
82 
83 Node* yarp::os::Nodes::Private::getNode(const std::string& name, bool create)
84 {
85  NestedContact nc(name);
86  if (!nc.isNested()) {
87  return nullptr;
88  }
89  Node* node = nullptr;
90  auto it = nodes_map.find(nc.getNodeName());
91  if (it != nodes_map.end()) {
92  node = it->second.first;
93  } else if (create) {
94  mutex.lock();
95  node = new Node();
96  it = nodes_map.find(nc.getNodeName());
97  if (it == nodes_map.end()) {
98  nodes_map[nc.getNodeName()] = std::make_pair(node, false);
99  node->prepare(nc.getNodeName());
100  } else {
101  // The node was created by some other thread while this
102  // thread was waiting on the lock.
103  delete node;
104  node = it->second.first;
105  }
106  mutex.unlock();
107  }
108  return node;
109 }
110 
112 {
113  NestedContact nc(contactable.getName());
114  if (!nc.isNested()) {
115  return;
116  }
117  if (!active) {
118  return;
119  }
120  Node* node = getNode(contactable.getName(), true);
121  if (node != nullptr) {
122  node->add(contactable);
123  }
124 }
125 
127 {
128  NestedContact nc(contactable.getName());
129  if (!nc.isNested()) {
130  return;
131  }
132  if (!active) {
133  return;
134  }
135  Node* node = getNode(contactable.getName(), true);
136  if (node != nullptr) {
137  node->update(contactable);
138  }
139 }
140 
141 void yarp::os::Nodes::Private::prepare(const std::string& name)
142 {
143  NestedContact nc(name);
144  if (!nc.isNested()) {
145  return;
146  }
147  if (!active) {
148  return;
149  }
150  getNode(name, true);
151 }
152 
154 {
155  if (!active) {
156  return;
157  }
158  Node* node = getNode(contactable.getName(), false);
159  if (node != nullptr) {
160  node->remove(contactable);
161  }
162 }
163 
164 Contact yarp::os::Nodes::Private::query(const std::string& name, const std::string& category)
165 {
166  if (!active) {
167  return Contact();
168  }
169  Contact result;
170  mutex.lock();
171  for (const auto& n : nodes_map) {
172  result = n.second.first->query(name, category);
173  if (result.isValid()) {
174  break;
175  }
176  }
177  mutex.unlock();
178  return result;
179 }
180 
182 {
183  if (!active) {
184  return;
185  }
186  for (const auto& n : nodes_map) {
187  n.second.first->interrupt();
188  }
189 }
190 
192 {
193  if (!flag) {
194  clear();
195  }
196  active = flag;
197  return active;
198 }
199 
201 {
202  Contact result;
203  NestedContact nc(name);
204  mutex.lock();
205  auto it = nodes_map.find(nc.getNodeName());
206  if (it != nodes_map.end()) {
207  result = it->second.first->where();
208  }
209  mutex.unlock();
210  return result;
211 }
213 {
214  Contact result;
215  NestedContact nc(name);
216  mutex.lock();
217  auto it = nodes_map.find(nc.getNodeName());
218  if (it != nodes_map.end()) {
219  result = it->second.first->query(nc.getNestedName());
220  }
221  mutex.unlock();
222  return result;
223 }
224 
225 void yarp::os::Nodes::Private::setActiveName(const std::string& name)
226 {
227  nodes_map[name].second = true;
228  active_name = name;
229 }
230 
232 {
233  return active_name;
234 }
235 
237 {
238  if (active_name.empty()) {
239  dummy = new Node("...");
240  }
241  return true;
242 }
243 
244 void yarp::os::Nodes::Private::addExternalNode(const std::string& name, Node& node)
245 {
246  mutex.lock();
247  yAssert(nodes_map.find(name) == nodes_map.end());
248  nodes_map[name] = std::make_pair(&node, true);
249  mutex.unlock();
250 }
251 
252 void yarp::os::Nodes::Private::removeExternalNode(const std::string& name)
253 {
254  mutex.lock();
255  nodes_map.erase(name);
256  mutex.unlock();
257 }
258 
259 
261  mPriv(new yarp::os::Nodes::Private())
262 {
263 }
264 
266 {
267  delete mPriv;
268 }
269 
270 void Nodes::add(Contactable& contactable)
271 {
272  mPriv->add(contactable);
273 }
274 
275 void Nodes::remove(Contactable& contactable)
276 {
277  mPriv->remove(contactable);
278 }
279 
280 Contact Nodes::query(const std::string& name, const std::string& category)
281 {
282  return mPriv->query(name, category);
283 }
284 
286 {
287  mPriv->interrupt();
288 }
289 
290 bool Nodes::enable(bool flag)
291 {
292  return mPriv->enable(flag);
293 }
294 
296 {
297  mPriv->clear();
298 }
299 
300 Contact Nodes::getParent(const std::string& name)
301 {
302  return mPriv->getParent(name);
303 }
304 
305 Contact Nodes::getURI(const std::string& name)
306 {
307  return mPriv->getURI(name);
308 }
309 
310 void Nodes::prepare(const std::string& name)
311 {
312  mPriv->prepare(name);
313 }
314 
315 void Nodes::update(Contactable& contactable)
316 {
317  mPriv->update(contactable);
318 }
319 
320 void Nodes::setActiveName(const std::string& name)
321 {
322  mPriv->setActiveName(name);
323 }
324 
325 std::string Nodes::getActiveName()
326 {
327  return mPriv->getActiveName();
328 }
329 
331 {
332  return mPriv->requireActiveName();
333 }
334 
335 void Nodes::addExternalNode(const std::string& name, Node& node)
336 {
337  mPriv->addExternalNode(name, node);
338 }
339 
340 void Nodes::removeExternalNode(const std::string& name)
341 {
342  mPriv->removeExternalNode(name);
343 }
#define yAssert(x)
Definition: Log.h:294
Represents how to reach a part of a YARP network.
Definition: Contact.h:36
bool isValid() const
Checks if a Contact is tagged as valid.
Definition: Contact.cpp:298
An abstract port.
Definition: Contactable.h:35
virtual std::string getName() const
Get name of port.
Definition: Contactable.cpp:14
A placeholder for rich contact information.
Definition: NestedContact.h:24
std::string getNodeName() const
std::string getNestedName() const
The Node class.
Definition: Node.h:24
void prepare(const std::string &name)
prepare if it is not already been done, opens the port of the Node.
Definition: Node.cpp:607
void update(Contactable &contactable)
update should update the contactable with new information.
Definition: Node.cpp:578
void remove(Contactable &contactable) override
remove specified contactable from the list of contactables associated with this Node.
Definition: Node.cpp:583
void add(Contactable &contactable) override
add a contactable to this node.
Definition: Node.cpp:573
std::map< std::string, std::pair< Node *, bool > > nodes_map
Definition: Nodes.cpp:43
bool enable(bool flag)
Definition: Nodes.cpp:191
void addExternalNode(const std::string &name, Node &node)
Definition: Nodes.cpp:244
void add(Contactable &contactable)
Definition: Nodes.cpp:111
void prepare(const std::string &name)
Definition: Nodes.cpp:141
Contact query(const std::string &name, const std::string &category)
Definition: Nodes.cpp:164
std::string getActiveName()
Definition: Nodes.cpp:231
Contact getParent(const std::string &name)
Definition: Nodes.cpp:200
Node * getNode(const std::string &name, bool create)
Definition: Nodes.cpp:83
void removeExternalNode(const std::string &name)
Definition: Nodes.cpp:252
Contact getURI(const std::string &name)
Definition: Nodes.cpp:212
void remove(Contactable &contactable)
Definition: Nodes.cpp:153
void setActiveName(const std::string &name)
Definition: Nodes.cpp:225
std::string active_name
Definition: Nodes.cpp:47
void update(Contactable &contactable)
Definition: Nodes.cpp:126
The Nodes class.
Definition: Nodes.h:32
void removeExternalNode(const std::string &name)
removeExternalNode erase the node from the container.
Definition: Nodes.cpp:340
void remove(Contactable &contactable) override
remove a Contactable from the Node specified in the contactable's name.
Definition: Nodes.cpp:275
virtual ~Nodes()
Definition: Nodes.cpp:265
virtual Contact query(const std::string &name, const std::string &category="") override
query the list of Node to find a Contact with the specified name.
Definition: Nodes.cpp:280
void addExternalNode(const std::string &name, Node &node)
addExternalNode adds a Node to this container.
Definition: Nodes.cpp:335
Contact getURI(const std::string &name)
getURI queries the Node specified in the name parameter to get Contact information about the specifie...
Definition: Nodes.cpp:305
std::string getActiveName()
getActiveName getter for the currently active node's name
Definition: Nodes.cpp:325
bool enable(bool flag)
enable setter for the activity state of the container.
Definition: Nodes.cpp:290
bool requireActiveName()
requireActiveName if there is no active node, creates a temporary one.
Definition: Nodes.cpp:330
void clear()
clear empties the container
Definition: Nodes.cpp:295
void add(Contactable &contactable) override
add a Contactable to the Node specified in the contactable name (see NestedContact....
Definition: Nodes.cpp:270
void setActiveName(const std::string &name)
setActiveName setter for the currently active node
Definition: Nodes.cpp:320
void prepare(const std::string &name)
prepare checks for the existence of the node specified in the name parameter.
Definition: Nodes.cpp:310
void interrupt()
interrupt delegates interrupt call to all of the Node in this container.
Definition: Nodes.cpp:285
virtual void update(Contactable &contactable)
update a Node information in this container.
Definition: Nodes.cpp:315
Contact getParent(const std::string &name)
getParent get info about node associated with the specified port.
Definition: Nodes.cpp:300
An interface to the operating system, including Port based communication.
The main, catch-all namespace for YARP.
Definition: dirs.h:16