Skip to content

Commit

Permalink
Merge pull request #1032 from leapmotion/fix-approx-use_count
Browse files Browse the repository at this point in the history
Workaround approximate use_count in std::shared_ptr
  • Loading branch information
jdonald authored Nov 2, 2017
2 parents f798aa8 + 262da0e commit 8e0a804
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 10 deletions.
19 changes: 15 additions & 4 deletions src/autotesting/AutowiringEnclosure.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <autowiring/demangle.h>
#include <autowiring/at_exit.h>
#include MEMORY_HEADER
#include THREAD_HEADER

#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
#error Please include your version of gtest.h before including the autowiring enclosure
Expand Down Expand Up @@ -50,15 +51,25 @@ struct TestInfoProxy {
};

namespace autowiring {
namespace testing {
namespace autotesting {
struct hung {
CoreContext& ctxt;
};

std::ostream& operator<<(std::ostream& os, const hung& lhs) {
inline std::ostream& operator<<(std::ostream& os, const hung& lhs) {
autowiring::dbg::PrintRunnables(os, lhs.ctxt);
return os;
}

template<typename T, typename Duration>
inline bool WaitForUseCount(const T& type, long useCount, Duration duration) {
const auto limit = std::chrono::steady_clock::now() + duration;
do {
if (useCount == type.use_count()) return true;
std::this_thread::yield();
} while (std::chrono::steady_clock::now() < limit);
return false;
}
}
}

Expand Down Expand Up @@ -135,7 +146,7 @@ class AutowiringEnclosure:
// Do not allow teardown to take more than 5 seconds. This is considered a "timely teardown" limit.
// If it takes more than this amount of time to tear down, the test case itself should invoke SignalShutdown
// and Wait itself with the extended teardown period specified.
ASSERT_TRUE(ctxt->Wait(std::chrono::seconds(5))) << "Test case took too long to tear down, unit tests running after this point are untrustworthy. Runnable dump:\n" << autowiring::testing::hung{ *ctxt };
ASSERT_TRUE(ctxt->Wait(std::chrono::seconds(5))) << "Test case took too long to tear down, unit tests running after this point are untrustworthy. Runnable dump:\n" << autowiring::autotesting::hung{ *ctxt };

// Global context should return to quiescence:
if (!allowGlobalReferences)
Expand All @@ -151,7 +162,7 @@ class AutowiringEnclosure:
}

// No more references to this context except for the pointer we hold ourselves
ASSERT_TRUE(ctxt.unique()) << "Detected a dangling context reference after test termination, context may be leaking";
ASSERT_TRUE(autowiring::autotesting::WaitForUseCount(ctxt, 1L, std::chrono::seconds(5))) << "Detected a dangling context reference after test termination, context may be leaking";
ctxt = {};
}
};
6 changes: 3 additions & 3 deletions src/autowiring/test/ContextCleanupTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "stdafx.h"
#include "TestFixtures/SimpleObject.hpp"
#include "TestFixtures/SimpleThreaded.hpp"
#include "autotesting/AutowiringEnclosure.h"
#include <autowiring/autowiring.h>
#include <autowiring/CoreContext.h>
#include THREAD_HEADER
Expand All @@ -19,7 +20,7 @@ TEST_F(ContextCleanupTest, ValidateTeardownOrder) {

std::weak_ptr<WeakPtrChecker> self;
};

// Construct, the destroy
std::make_shared<WeakPtrChecker>();
}
Expand Down Expand Up @@ -227,6 +228,5 @@ TEST_F(ContextCleanupTest, VerifyThreadShutdownInterleave) {
ctxt->SignalShutdown(true);

// At this point, the thread must have returned AND released its shared pointer to the enclosing context
ASSERT_EQ(initCount, ctxt.use_count()) << "Context thread persisted even after it should have fallen out of scope";
ASSERT_TRUE(autowiring::autotesting::WaitForUseCount(ctxt, initCount, std::chrono::seconds(5))) << "Context thread persisted even after it should have fallen out of scope";
}

5 changes: 3 additions & 2 deletions src/autowiring/test/ContextMapTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "stdafx.h"
#include "TestFixtures/ExitRaceThreaded.hpp"
#include "TestFixtures/SimpleThreaded.hpp"
#include "autotesting/AutowiringEnclosure.h"
#include <autowiring/autowiring.h>
#include <autowiring/ContextMap.h>
#include <string>
Expand Down Expand Up @@ -76,11 +77,11 @@ TEST_F(ContextMapTest, VerifyWithThreads) {
// Terminate whole context, wait for it to respond
context->SignalShutdown();
context->Wait();
ASSERT_EQ(1UL, context.use_count()) << "Context reference should have been unique after thread expiration";
ASSERT_TRUE(autowiring::autotesting::WaitForUseCount(context, 1L, std::chrono::seconds(5))) << "Context reference should have been unique after thread expiration";
}

// Release our threaded entity:
ASSERT_EQ(1UL, threaded.use_count()) << "Thread was holding a self-reference even after context termination has completed";
ASSERT_TRUE(autowiring::autotesting::WaitForUseCount(threaded, 1L, std::chrono::seconds(5))) << "Thread was holding a self-reference even after context termination has completed";
threaded.reset();
ASSERT_TRUE(weakContext.expired()) << "Context still existed even after the last reference to it should have been gone";

Expand Down
3 changes: 2 additions & 1 deletion src/autowiring/test/CoreThreadTest.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (C) 2012-2017 Leap Motion, Inc. All rights reserved.
#include "stdafx.h"
#include "TestFixtures/SimpleThreaded.hpp"
#include "autotesting/AutowiringEnclosure.h"
#include <autowiring/at_exit.h>
#include <autowiring/autowiring.h>
#include <algorithm>
Expand Down Expand Up @@ -570,7 +571,7 @@ TEST_F(CoreThreadTest, ContextWaitTimesOutInOnStop) {
// Let BIOS back out now:
bios->Continue();
ASSERT_TRUE(ctxt->Wait(std::chrono::seconds(5))) << "Context did not complete in a timely fashion";
ASSERT_EQ(2UL, ctxt.use_count()) << "Entity held a context shared pointer after teardown has taken place";
ASSERT_TRUE(autowiring::autotesting::WaitForUseCount(ctxt, 2L, std::chrono::seconds(5))) << "Entity held a context shared pointer after teardown has taken place";
}

TEST_F(CoreThreadTest, SubContextHoldsParentContext) {
Expand Down

0 comments on commit 8e0a804

Please sign in to comment.