Vuo  2.4.1
VuoNodeSynchronization.cc
Go to the documentation of this file.
1
10#include <sstream>
12#include "VuoNodeRegistry.hh"
13#include "VuoRuntimeState.hh"
15
20void 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
29void 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
52void 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
61void 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
82void 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
107void 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
150void 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
183void 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
227extern "C"
228{
229
233void vuoLockNodes(VuoCompositionState *compositionState, unsigned long *nodeIndices, unsigned long nodeCount, unsigned long eventId)
234{
236 runtimeState->persistentState->nodeSynchronization->lockNodes(compositionState, nodeIndices, nodeCount, eventId);
237}
238
242void vuoLockNode(VuoCompositionState *compositionState, unsigned long nodeIndex, unsigned long eventId)
243{
245 runtimeState->persistentState->nodeSynchronization->lockNode(compositionState, nodeIndex, eventId);
246}
247
251void vuoUnlockNodes(VuoCompositionState *compositionState, unsigned long *nodeIndices, unsigned long nodeCount)
252{
254 runtimeState->persistentState->nodeSynchronization->unlockNodes(compositionState, nodeIndices, nodeCount);
255}
256
260void vuoUnlockNode(VuoCompositionState *compositionState, unsigned long nodeIndex)
261{
263 runtimeState->persistentState->nodeSynchronization->unlockNode(compositionState, nodeIndex);
264}
265
266}