Vuo  2.3.2
VuoNodeSynchronization.cc
Go to the documentation of this file.
1 
10 #include <sstream>
12 #include "VuoNodeRegistry.hh"
13 #include "VuoRuntimeState.hh"
15 
20 void VuoNodeSynchronization::lockNodes(VuoCompositionState *compositionState, unsigned long *nodeIndices, unsigned long nodeCount, unsigned long eventId)
21 {
22  for (unsigned long i = 0; i < nodeCount; ++i)
23  lockNode(compositionState, nodeIndices[i], eventId);
24 }
25 
29 void VuoNodeSynchronization::lockNode(VuoCompositionState *compositionState, unsigned long nodeIndex, unsigned long eventId)
30 {
31  recordWaiting(compositionState, eventId, nodeIndex);
32 
33  {
34  NodeContext *nodeContext = vuoGetNodeContext(compositionState, nodeIndex);
35 
36  std::unique_lock<std::mutex> lock(* static_cast<std::mutex *>(nodeContext->nodeMutex));
37  static_cast<std::condition_variable *>(nodeContext->nodeConditionVariable)->wait(lock, [nodeContext, eventId]()
38  {
39  if (nodeContext->claimingEventId == 0)
40  nodeContext->claimingEventId = eventId;
41 
42  return nodeContext->claimingEventId == eventId;
43  });
44  }
45 
46  recordLocked(compositionState, eventId, nodeIndex);
47 }
48 
52 void VuoNodeSynchronization::unlockNodes(VuoCompositionState *compositionState, unsigned long *nodeIndices, unsigned long nodeCount)
53 {
54  for (unsigned long i = 0; i < nodeCount; ++i)
55  unlockNode(compositionState, nodeIndices[i]);
56 }
57 
61 void VuoNodeSynchronization::unlockNode(VuoCompositionState *compositionState, unsigned long nodeIndex)
62 {
63  unsigned long eventId = 0;
64 
65  {
66  NodeContext *nodeContext = vuoGetNodeContext(compositionState, nodeIndex);
67 
68  std::unique_lock<std::mutex> lock(* static_cast<std::mutex *>(nodeContext->nodeMutex));
69 
70  eventId = nodeContext->claimingEventId;
71  nodeContext->claimingEventId = 0;
72 
73  static_cast<std::condition_variable *>(nodeContext->nodeConditionVariable)->notify_all();
74  }
75 
76  recordUnlocked(compositionState, eventId, nodeIndex);
77 }
78 
82 void VuoNodeSynchronization::recordWaiting(VuoCompositionState *compositionState, unsigned long eventId, unsigned long nodeIndex)
83 {
84  if (! VuoIsDebugEnabled())
85  return;
86 
87  std::lock_guard<std::mutex> lock(statusMutex);
88 
89  auto i = statusWaiting.find(compositionState->compositionIdentifier);
90  if (i != statusWaiting.end())
91  {
92  auto j = i->second.find(eventId);
93  if (j != i->second.end())
94  {
95  auto k = std::find(j->second.begin(), j->second.end(), nodeIndex);
96  if (k != j->second.end())
97  return;
98  }
99  }
100 
101  statusWaiting[compositionState->compositionIdentifier][eventId].push_back(nodeIndex);
102 }
103 
107 void VuoNodeSynchronization::recordLocked(VuoCompositionState *compositionState, unsigned long eventId, unsigned long nodeIndex)
108 {
109  if (! VuoIsDebugEnabled())
110  return;
111 
112  std::lock_guard<std::mutex> lock(statusMutex);
113 
114  auto i = statusWaiting.find(compositionState->compositionIdentifier);
115  if (i != statusWaiting.end())
116  {
117  auto j = i->second.find(eventId);
118  if (j != i->second.end())
119  {
120  auto k = std::find(j->second.begin(), j->second.end(), nodeIndex);
121  if (k != j->second.end())
122  {
123  j->second.erase(k);
124  if (j->second.empty())
125  i->second.erase(j);
126  if (i->second.empty())
127  statusWaiting.erase(i);
128  }
129  }
130  }
131 
132  i = statusLocked.find(compositionState->compositionIdentifier);
133  if (i != statusLocked.end())
134  {
135  auto j = i->second.find(eventId);
136  if (j != i->second.end())
137  {
138  auto k = std::find(j->second.begin(), j->second.end(), nodeIndex);
139  if (k != j->second.end())
140  return;
141  }
142  }
143 
144  statusLocked[compositionState->compositionIdentifier][eventId].push_back(nodeIndex);
145 }
146 
150 void VuoNodeSynchronization::recordUnlocked(VuoCompositionState *compositionState, unsigned long eventId, unsigned long nodeIndex)
151 {
152  if (! VuoIsDebugEnabled())
153  return;
154 
155  std::lock_guard<std::mutex> lock(statusMutex);
156 
157  auto i = statusLocked.find(compositionState->compositionIdentifier);
158  if (i != statusLocked.end())
159  {
160  auto j = i->second.find(eventId);
161  if (j != i->second.end())
162  {
163  auto k = std::find(j->second.begin(), j->second.end(), nodeIndex);
164  if (k != j->second.end())
165  {
166  j->second.erase(k);
167  if (j->second.empty())
168  i->second.erase(j);
169  if (i->second.empty())
170  statusLocked.erase(i);
171 
172  return;
173  }
174  }
175  }
176 
177  VDebugLog("Error: Node %lu was unlocked without having been locked", nodeIndex);
178 }
179 
183 void VuoNodeSynchronization::print(void)
184 {
185  if (! VuoIsDebugEnabled())
186  {
187  VUserLog("Enable debug mode to record status.");
188  return;
189  }
190 
191  std::lock_guard<std::mutex> lock(statusMutex);
192 
193  ostringstream oss;
194  oss << "=== locked ===" << endl << endl;
195  for (auto i : statusLocked)
196  {
197  oss << i.first << ":" << endl;
198  for (auto j : i.second)
199  {
200  oss << " eventId " << j.first << ":";
201  for (unsigned long nodeIndex : j.second)
202  oss << " " << nodeIndex;
203  oss << endl;
204  }
205  oss << endl;
206  }
207  oss << endl;
208 
209  oss << "=== waiting to lock ===" << endl << endl;
210  for (auto i : statusWaiting)
211  {
212  oss << i.first << ":" << endl;
213  for (auto j : i.second)
214  {
215  oss << " eventId " << j.first << ":";
216  for (unsigned long nodeIndex : j.second)
217  oss << " " << nodeIndex;
218  oss << endl;
219  }
220  oss << endl;
221  }
222  oss << endl;
223 
224  VUserLog("\n%s", oss.str().c_str());
225 }
226 
227 extern "C"
228 {
229 
233 void vuoLockNodes(VuoCompositionState *compositionState, unsigned long *nodeIndices, unsigned long nodeCount, unsigned long eventId)
234 {
236  runtimeState->persistentState->nodeSynchronization->lockNodes(compositionState, nodeIndices, nodeCount, eventId);
237 }
238 
242 void vuoLockNode(VuoCompositionState *compositionState, unsigned long nodeIndex, unsigned long eventId)
243 {
245  runtimeState->persistentState->nodeSynchronization->lockNode(compositionState, nodeIndex, eventId);
246 }
247 
251 void vuoUnlockNodes(VuoCompositionState *compositionState, unsigned long *nodeIndices, unsigned long nodeCount)
252 {
254  runtimeState->persistentState->nodeSynchronization->unlockNodes(compositionState, nodeIndices, nodeCount);
255 }
256 
260 void vuoUnlockNode(VuoCompositionState *compositionState, unsigned long nodeIndex)
261 {
263  runtimeState->persistentState->nodeSynchronization->unlockNode(compositionState, nodeIndex);
264 }
265 
266 }