Skip to content

Commit 6e4022a

Browse files
authored
Merge pull request #1033 from leapmotion/misc-fixes
Miscellaneous minor fixes
2 parents 8e0a804 + 4e7d0be commit 6e4022a

16 files changed

+132
-51
lines changed

src/autowiring/AutoPacketFactory.cpp

+10-10
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ bool AutoPacketFactory::IsRunning(void) const {
2121
}
2222

2323
std::shared_ptr<AutoPacket> AutoPacketFactory::CurrentPacket(void) {
24-
std::lock_guard<std::mutex> lk(m_lock);
24+
std::lock_guard<std::mutex> lk(m_apfLock);
2525
return m_curPacket.lock();
2626
}
2727

2828
std::shared_ptr<AutoPacket> AutoPacketFactory::NewPacket(void) {
2929
std::shared_ptr<AutoPacketInternal> retVal;
3030
bool isFirstPacket;
3131
{
32-
std::lock_guard<std::mutex> lk(m_lock);
32+
std::lock_guard<std::mutex> lk(m_apfLock);
3333

3434
if (ShouldStop())
3535
throw autowiring_error("Attempted to create a packet on an AutoPacketFactory that was already terminated");
@@ -84,14 +84,14 @@ std::shared_ptr<void> AutoPacketFactory::GetInternalOutstanding(void) {
8484
}
8585

8686
std::vector<AutoFilterDescriptor> AutoPacketFactory::GetAutoFilters(void) const {
87-
std::lock_guard<std::mutex> lk(m_lock);
87+
std::lock_guard<std::mutex> lk(m_apfLock);
8888
std::vector<AutoFilterDescriptor> retVal;
8989
retVal.assign(m_autoFilters.begin(), m_autoFilters.end());
9090
return retVal;
9191
}
9292

9393
SatCounter* AutoPacketFactory::CreateSatCounterList(void) const {
94-
std::lock_guard<std::mutex> lk(m_lock);
94+
std::lock_guard<std::mutex> lk(m_apfLock);
9595

9696
// Trivial return check
9797
if (m_autoFilters.empty())
@@ -113,7 +113,7 @@ SatCounter* AutoPacketFactory::CreateSatCounterList(void) const {
113113

114114
bool AutoPacketFactory::OnStart(void) {
115115
// Initialize first packet
116-
std::lock_guard<std::mutex>{m_lock},
116+
std::lock_guard<std::mutex>{m_apfLock},
117117
m_nextPacket = ConstructPacket();
118118
return true;
119119
}
@@ -124,7 +124,7 @@ void AutoPacketFactory::OnStop(bool graceful) {
124124
std::shared_ptr<AutoPacketInternal> nextPacket;
125125

126126
// Lock destruction precedes local variables
127-
std::lock_guard<std::mutex>{m_lock},
127+
std::lock_guard<std::mutex>{m_apfLock},
128128
autoFilters.swap(m_autoFilters),
129129
nextPacket.swap(m_nextPacket);
130130
}
@@ -156,14 +156,14 @@ void AutoPacketFactory::Clear(void) {
156156
}
157157

158158
const AutoFilterDescriptor& AutoPacketFactory::AddSubscriber(const AutoFilterDescriptor& rhs) {
159-
std::lock_guard<std::mutex> lk(m_lock);
159+
std::lock_guard<std::mutex> lk(m_apfLock);
160160
m_autoFilters.insert(rhs);
161161
return rhs;
162162
}
163163

164164
void AutoPacketFactory::RemoveSubscriber(const AutoFilterDescriptor& autoFilter) {
165165
// Trivial removal from the autofilter set:
166-
std::lock_guard<std::mutex> lk(m_lock);
166+
std::lock_guard<std::mutex> lk(m_apfLock);
167167
m_autoFilters.erase(autoFilter);
168168
}
169169

@@ -186,7 +186,7 @@ size_t AutoPacketFactory::GetOutstandingPacketCount(void) const {
186186
}
187187

188188
void AutoPacketFactory::RecordPacketDuration(std::chrono::nanoseconds duration) {
189-
std::unique_lock<std::mutex> lk(m_lock);
189+
std::unique_lock<std::mutex> lk(m_apfLock);
190190
m_packetDurationSum += duration.count();
191191
m_packetDurationSqSum += duration.count() * duration.count();
192192
}
@@ -202,7 +202,7 @@ double AutoPacketFactory::GetPacketLifetimeStandardDeviation(void) {
202202
}
203203

204204
void AutoPacketFactory::ResetPacketStatistics(void) {
205-
std::unique_lock<std::mutex> lk(m_lock);
205+
std::unique_lock<std::mutex> lk(m_apfLock);
206206
m_packetCount = 0;
207207
m_packetDurationSum = 0.0;
208208
m_packetDurationSqSum = 0.0;

src/autowiring/AutoPacketFactory.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class AutoPacketFactory:
2828

2929
private:
3030
// Lock for this type
31-
mutable std::mutex m_lock;
31+
mutable std::mutex m_apfLock;
3232

3333
// Internal outstanding reference for issued packet:
3434
std::weak_ptr<void> m_outstandingInternal;
@@ -60,7 +60,7 @@ class AutoPacketFactory:
6060
/// </summary>
6161
template<class T>
6262
void AppendAutoFiltersTo(T& container) const {
63-
std::lock_guard<std::mutex> lk(m_lock);
63+
std::lock_guard<std::mutex> lk(m_apfLock);
6464
container.insert(container.end(), m_autoFilters.begin(), m_autoFilters.end());
6565
}
6666

src/autowiring/CoreRunnable.cpp

+7-2
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@ bool CoreRunnable::Start(std::shared_ptr<CoreObject> outstanding) {
2424
return true;
2525

2626
m_wasStarted = true;
27-
m_outstanding = outstanding;
27+
m_outstanding = std::move(outstanding);
28+
outstanding.reset();
2829
if(!OnStart()) {
2930
m_shouldStop = true;
31+
3032
m_outstanding.reset();
3133

3234
// Immediately invoke a graceless stop in response
@@ -38,20 +40,23 @@ bool CoreRunnable::Start(std::shared_ptr<CoreObject> outstanding) {
3840
}
3941

4042
void CoreRunnable::Stop(bool graceful) {
43+
std::unique_lock<std::mutex> lk(m_lock);
4144
if (!m_shouldStop) {
4245
// Stop flag should be pulled high
4346
m_shouldStop = true;
4447

4548
// Do not call this method more than once:
49+
lk.unlock();
4650
OnStop(graceful);
51+
lk.lock();
4752
}
4853

4954
if (m_outstanding) {
5055
// Ensure we do not invoke the outstanding count dtor while holding a lock
5156
std::shared_ptr<CoreObject> outstanding;
52-
std::lock_guard<std::mutex>{m_lock},
5357
outstanding.swap(m_outstanding);
5458
}
59+
lk.unlock();
5560

5661
// Everything looks good now
5762
m_cv.notify_all();

src/autowiring/CoreThread.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ void CoreThread::DoRunLoopCleanup(std::shared_ptr<CoreContext>&& ctxt, std::shar
1414
// Kill everything in the dispatch queue and also run it down
1515
{
1616
CurrentContextPusher pshr(ctxt);
17+
// Only allow one thread at a time to clean up the dispatch queue
18+
std::lock_guard<std::mutex> lk(m_stoppingLock);
1719
Rundown();
1820
}
1921

@@ -27,6 +29,9 @@ void CoreThread::Run() {
2729
}
2830

2931
void CoreThread::OnStop(bool graceful) {
32+
// Only allow one thread at a time to clean up the dispatch queue
33+
std::lock_guard<std::mutex> lk(m_stoppingLock);
34+
3035
// Base class handling first:
3136
BasicThread::OnStop(graceful);
3237

src/autowiring/CoreThread.h

+5
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ class CoreThread:
3737
virtual ~CoreThread(void);
3838

3939
protected:
40+
/// <summary>
41+
/// While stopping, make sure we do it exclusively
42+
/// </summary>
43+
std::mutex m_stoppingLock;
44+
4045
/// <summary>
4146
/// Overridden here so we can rundown the dispatch queue
4247
/// </summary>

src/autowiring/Parallel.h

+67-28
Original file line numberDiff line numberDiff line change
@@ -150,15 +150,23 @@ class parallel {
150150
operator+=(_Fx&& fx) {
151151
using RetType = typename std::remove_cv<decltype(fx())>::type;
152152

153+
auto block = m_block;
154+
if (!block)
155+
return;
156+
153157
// Increment remain jobs. This is decremented by calls to "Pop"
154-
(std::lock_guard<std::mutex>)m_block->m_lock, ++m_block->m_outstandingCount;
158+
(std::lock_guard<std::mutex>)block->m_lock, ++block->m_outstandingCount;
159+
160+
block->dq += [this, fx] {
161+
auto block = m_block;
162+
if (!block)
163+
return;
155164

156-
m_block->dq += [this, fx] {
157165
auto result = std::make_shared<RetType>(fx());
158166

159-
std::lock_guard<std::mutex>{m_block->m_lock},
160-
m_block->m_queue[auto_id_t<RetType>{}].emplace_back(std::move(result));
161-
m_block->m_queueUpdated.notify_all();
167+
std::lock_guard<std::mutex>{block->m_lock},
168+
block->m_queue[auto_id_t<RetType>{}].emplace_back(std::move(result));
169+
block->m_queueUpdated.notify_all();
162170
};
163171
}
164172

@@ -168,48 +176,68 @@ class parallel {
168176
std::is_same<void, typename std::result_of<_Fx()>::type>::value
169177
>::type
170178
operator+=(_Fx&& fx) {
179+
auto block = m_block;
180+
if (!block)
181+
return;
182+
171183
// Increment remain jobs. This is decremented by calls to "Pop"
172-
(std::lock_guard<std::mutex>)m_block->m_lock, ++m_block->m_outstandingCount;
184+
(std::lock_guard<std::mutex>)block->m_lock, ++block->m_outstandingCount;
185+
186+
block->dq += [this, fx] {
187+
auto block = m_block;
188+
if (!block)
189+
return;
173190

174-
m_block->dq += [this, fx] {
175191
fx();
176192

177-
std::lock_guard<std::mutex>{m_block->m_lock},
178-
m_block->m_nVoidEntries++;
179-
m_block->m_queueUpdated.notify_all();
193+
std::lock_guard<std::mutex>{block->m_lock},
194+
block->m_nVoidEntries++;
195+
block->m_queueUpdated.notify_all();
180196
};
181197
}
182198

183199
// Discard the most recent result. Blocks until the next result arives.
184200
template<typename T>
185201
void Pop(void) {
186-
std::unique_lock<std::mutex> lk(m_block->m_lock);
187-
if (!m_block->m_outstandingCount)
202+
auto block = m_block;
203+
if (!block)
204+
return;
205+
206+
std::unique_lock<std::mutex> lk(block->m_lock);
207+
if (!block->m_outstandingCount)
188208
throw std::out_of_range("No outstanding jobs");
189209

190210
if (std::is_same<void, T>::value) {
191-
m_block->m_queueUpdated.wait(lk, [this] { return m_block->m_nVoidEntries != 0; });
192-
m_block->m_nVoidEntries--;
211+
block->m_queueUpdated.wait(lk, [this] { auto block = m_block; return block ? block->m_nVoidEntries != 0 : true; });
212+
block->m_nVoidEntries--;
193213
} else {
194-
auto& qu = m_block->m_queue[auto_id_t<T>{}];
195-
m_block->m_queueUpdated.wait(lk, [&qu] { return !qu.empty(); });
214+
auto& qu = block->m_queue[auto_id_t<T>{}];
215+
block->m_queueUpdated.wait(lk, [&qu] { return !qu.empty(); });
196216
qu.pop_front();
197217
}
198218

199-
--m_block->m_outstandingCount;
219+
--block->m_outstandingCount;
200220
}
201221

202222
// Get the most result from the most recent job. Blocks until a result arrives
203223
// if there isn't one already available
204224
template<typename T>
205225
T Top(void) {
206-
std::unique_lock<std::mutex> lk(m_block->m_lock);
226+
auto block = m_block;
227+
if (!block)
228+
return T{};
229+
230+
std::unique_lock<std::mutex> lk(block->m_lock);
207231

208-
if (m_block->m_queue[auto_id_t<T>{}].empty())
209-
m_block->m_queueUpdated.wait(lk, [this]{
210-
return !m_block->m_queue[auto_id_t<T>{}].empty();
232+
if (block->m_queue[auto_id_t<T>{}].empty())
233+
block->m_queueUpdated.wait(lk, [this]{
234+
auto block = m_block;
235+
if (!block)
236+
return true;
237+
238+
return !block->m_queue[auto_id_t<T>{}].empty();
211239
});
212-
return *static_cast<T*>(m_block->m_queue[auto_id_t<T>{}].front().ptr());
240+
return *static_cast<T*>(block->m_queue[auto_id_t<T>{}].front().ptr());
213241
}
214242

215243
// Get a collection containing all entries of the specified type
@@ -225,19 +253,30 @@ class parallel {
225253
/// If a stop call has been made, this method will also block until all owned threads have quit
226254
/// </remarks>
227255
void barrier(void) {
228-
std::unique_lock<std::mutex> lk(m_block->m_lock);
229-
m_block->m_queueUpdated.wait(lk, [this] {
230-
size_t totalReady = m_block->m_nVoidEntries;
231-
for (auto& entry : m_block->m_queue)
256+
auto block = m_block;
257+
if (!block)
258+
return;
259+
260+
std::unique_lock<std::mutex> lk(block->m_lock);
261+
block->m_queueUpdated.wait(lk, [this] {
262+
auto block = m_block;
263+
if (!block)
264+
return true;
265+
size_t totalReady = block->m_nVoidEntries;
266+
for (auto& entry : block->m_queue)
232267
totalReady += entry.second.size();
233-
return m_block->m_outstandingCount == totalReady;
268+
return block->m_outstandingCount == totalReady;
234269
});
235270
}
236271

237272
// Get an iterator to the begining of out queue of job results
238273
template<typename T>
239274
parallel_iterator<T> begin(void) {
240-
return{ *this, m_block->m_outstandingCount };
275+
auto block = m_block;
276+
if (!block)
277+
return{ *this, 0 };
278+
279+
return{ *this, block->m_outstandingCount };
241280
}
242281

243282
// Iterator representing no jobs results remaining

src/autowiring/auto_id.h

+7
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ namespace autowiring {
5858
)
5959
{}
6060

61+
#if !defined(_MSC_VER)
62+
#pragma clang diagnostic push
63+
#pragma clang diagnostic ignored "-Wc++1z-compat-mangling"
64+
#endif
6165
auto_id_block(
6266
int index,
6367
const std::type_info* ti,
@@ -75,6 +79,9 @@ namespace autowiring {
7579
pToObj(pToObj),
7680
pFromObj(pFromObj)
7781
{}
82+
#if !defined(_MSC_VER)
83+
#pragma clang diagnostic pop
84+
#endif
7885

7986
// Index and underlying type. Indexes are guaranteed to start at 1. The index value of 0
8087
// is reserved as the invalid index.

src/autowiring/test/AnySharedPointerTest.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ TEST_F(AnySharedPointerTest, CanHoldCoreObject) {
175175
ASSERT_EQ(co, x) << "Held CoreObject was not equivalent to constructed instance";
176176
}
177177

178+
template<> const autowiring::fast_pointer_cast_initializer<CoreObject, CoreObject> autowiring::fast_pointer_cast_initializer<CoreObject, CoreObject>::sc_init;
179+
178180
TEST_F(AnySharedPointerTest, CanFastCastToSelf) {
179181
(void)autowiring::fast_pointer_cast_initializer<CoreObject, CoreObject>::sc_init;
180182

src/autowiring/test/ContextMemberTest.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,9 @@ namespace {
176176
}
177177

178178
TEST_F(ContextMemberTest, PathologicalResetCase) {
179+
if (std::thread::hardware_concurrency() == 1)
180+
return; // Don't bother running on a single-core machine
181+
179182
Autowired<TypeThatIsNotInjected>* pv;
180183
volatile std::atomic<size_t> nBarr{ 0 };
181184
volatile bool proceed = true;

0 commit comments

Comments
 (0)