From 8632963dd81fae4ec1cff98c6f9b422d98f5b93b Mon Sep 17 00:00:00 2001 From: Jason Lokerson Date: Wed, 28 Jan 2015 09:32:51 -0800 Subject: [PATCH 01/20] Adding a check to prevent const decorations This is necessary because decorations with a shared pointer to a const type causes resolution problems. --- autowiring/AutoPacket.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/autowiring/AutoPacket.h b/autowiring/AutoPacket.h index 884320ea7..6a724dd06 100644 --- a/autowiring/AutoPacket.h +++ b/autowiring/AutoPacket.h @@ -369,7 +369,10 @@ class AutoPacket: void Decorate(std::shared_ptr ptr) { DecorationKey key(auto_id::key()); - /// Injunction to prevent existential loops: + // We don't want to see this overload used on a const T + static_assert(!std::is_const::value, "Cannot decorate a shared pointer to const T with this overload"); + + // Injunction to prevent existential loops: static_assert(!std::is_same::value, "Cannot decorate a packet with another packet"); // Either decorate, or prevent anyone from decorating From d9bdac551d7be0bb2387782cd43e00296d8181c0 Mon Sep 17 00:00:00 2001 From: Graham Tremper Date: Wed, 28 Jan 2015 14:59:47 -0800 Subject: [PATCH 02/20] Add instructions for building 64 bit android --- README.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index fd28db158..aa30155ad 100644 --- a/README.md +++ b/README.md @@ -72,16 +72,13 @@ via the [find_package](http://www.cmake.org/cmake/help/v3.0/command/find_package ### Arm-linux -Building on Android requires the use of a toolchain file. You will need to use an alternate prefix path if you are trying to cross-compile, the prefix path -should contain your version of the Boost libraries built for Android. To configure, use the following invocation: +Building on Android requires the use of a toolchain file. You will need to use an alternate prefix path if you are trying to cross-compile, the prefix path should contain your version of the Boost libraries built for Android. To configure, use the following invocation: cmake . -DCMAKE_TOOLCHAIN_FILE=toolchain-arm.cmake -DCMAKE_PREFIX_PATH:PATH=/your/lib/path ### Android -Similar requirements to Arm-linux, you must specify a toolchain file. You must also specify the path to your Android toolchain directory. Make sure you update -/opt/android-standalone-toolchain to point to your actual Android standalone toolchain directory. If you aren't cross-compiling, then simply run cmake with -no options. +Similar requirements to Arm-linux, you must specify a toolchain file. You must also specify the path to your Android toolchain directory. Make sure you update `/opt/android-standalone-toolchain` to point to your actual Android standalone toolchain directory. To build for 64 bit android systems, export the environment variable `export ARMv8=true`. If you aren't cross-compiling, then simply run cmake with no options. cmake . -DCMAKE_TOOLCHAIN_FILE=toolchain-android.cmake -DLLVM_ANDROID_TOOLCHAIN_DIR=/opt/android-standalone-toolchain From 8a9c41314beed89c3ae57aa4e2444d31952879e1 Mon Sep 17 00:00:00 2001 From: Jason Lokerson Date: Wed, 28 Jan 2015 18:01:30 -0800 Subject: [PATCH 03/20] Switching GetAll to make use of a temporary buffer `std::get_temporary_buffer` is provided precisely for cases like these where small amounts of memory are required for short periods of time. We might as well make use of it. --- autowiring/AutoPacket.h | 26 +++++++++++++++++--------- autowiring/auto_arg.h | 16 ++++++++++------ 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/autowiring/AutoPacket.h b/autowiring/AutoPacket.h index 6a724dd06..0fe1e947a 100644 --- a/autowiring/AutoPacket.h +++ b/autowiring/AutoPacket.h @@ -287,17 +287,25 @@ class AutoPacket: } /// - /// Returns a vector with a pointer to each decoration of type T, adding a nullptr to the end. + /// Returns a null-terminated temporary buffer containing all decorations /// + /// The buffer, or nullptr if no matching decorations exist + /// + /// The returned buffer must be freed with std::return_temporary_buffer + /// template - std::vector GetAll(int tshift = 0) { - std::vector retval; - auto deco = m_decorations.find(DecorationKey(auto_id::key(), tshift)); - for (auto& dispo : deco->second.m_decorations) { - retval.push_back(dispo.as().get().get()); - } - retval.push_back(nullptr); - return retval; + const T** GetAll(int tshift = 0) const { + std::lock_guard lk(m_lock); + auto q = m_decorations.find(DecorationKey(auto_id::key(), tshift)); + if (q == m_decorations.end()) + return nullptr; + + const auto& decorations = q->second.m_decorations; + const T** retVal = std::get_temporary_buffer(decorations.size() + 1).first; + for (size_t i = 0; i < decorations.size(); i++) + retVal[i] = static_cast(decorations[i]->ptr()); + retVal[decorations.size()] = nullptr; + return retVal; } /// Shares all broadcast data from this packet with the recipient packet diff --git a/autowiring/auto_arg.h b/autowiring/auto_arg.h index 7af6f85e9..bae8c9ca3 100644 --- a/autowiring/auto_arg.h +++ b/autowiring/auto_arg.h @@ -224,17 +224,21 @@ template class auto_arg { public: - typedef std::vector type; + typedef const T** type; // Another compositional structure, used to coerce a vector to a data item struct arg_type { - arg_type(type& value) : - value(value.data()) + arg_type(const T** value) : + value(value) {} - T const ** value; + ~arg_type(void) { + std::return_temporary_buffer(value); + } - operator T const **(void) const { return value; } + const T** value; + + operator const T**(void) const { return value; } }; typedef auto_id id_type; @@ -245,7 +249,7 @@ class auto_arg static const int tshift = 0; template - static std::vector arg(C& packet) { + static const T** arg(C& packet) { return packet.template GetAll(); } }; From 3852059490aeb37d6f42dca5453a46406b4d531c Mon Sep 17 00:00:00 2001 From: Jason Lokerson Date: Wed, 28 Jan 2015 10:42:02 -0800 Subject: [PATCH 04/20] Fixing some linker warnings Have to keep the instantiation of internally used templates internal to the library proper by making use of the "extern" trick. --- autowiring/AutoPacketFactory.h | 2 ++ autowiring/fast_pointer_cast.h | 3 +++ src/autowiring/AutoPacketFactory.cpp | 2 ++ 3 files changed, 7 insertions(+) diff --git a/autowiring/AutoPacketFactory.h b/autowiring/AutoPacketFactory.h index 4858358a7..1d88fb5e0 100644 --- a/autowiring/AutoPacketFactory.h +++ b/autowiring/AutoPacketFactory.h @@ -184,3 +184,5 @@ extern template struct SlotInformationStump; extern template const std::shared_ptr& SharedPointerSlot::as(void) const; extern template std::shared_ptr autowiring::fast_pointer_cast(const std::shared_ptr& Other); extern template class RegType; +extern template struct autowiring::fast_pointer_cast_blind; +extern template struct autowiring::fast_pointer_cast_initializer; diff --git a/autowiring/fast_pointer_cast.h b/autowiring/fast_pointer_cast.h index 254f5272f..23cec36a0 100644 --- a/autowiring/fast_pointer_cast.h +++ b/autowiring/fast_pointer_cast.h @@ -4,6 +4,9 @@ #include MEMORY_HEADER #include TYPE_TRAITS_HEADER +class AutoPacketFactory; +class Object; + namespace autowiring { template struct fast_pointer_cast_blind; diff --git a/src/autowiring/AutoPacketFactory.cpp b/src/autowiring/AutoPacketFactory.cpp index 13c233443..dce0a21be 100644 --- a/src/autowiring/AutoPacketFactory.cpp +++ b/src/autowiring/AutoPacketFactory.cpp @@ -185,3 +185,5 @@ template struct SlotInformationStump; template const std::shared_ptr& SharedPointerSlot::as(void) const; template std::shared_ptr autowiring::fast_pointer_cast(const std::shared_ptr& Other); template class RegType; +template struct autowiring::fast_pointer_cast_blind; +template struct autowiring::fast_pointer_cast_initializer; From 7ecaaee4b9e445fcf44b9718d496671cdf876d9f Mon Sep 17 00:00:00 2001 From: Jonathan Marsden Date: Thu, 29 Jan 2015 10:58:42 -0800 Subject: [PATCH 05/20] Remove empty source file --- src/autowiring/CMakeLists.txt | 8 -------- src/autowiring/uuid.cpp | 3 --- 2 files changed, 11 deletions(-) delete mode 100644 src/autowiring/uuid.cpp diff --git a/src/autowiring/CMakeLists.txt b/src/autowiring/CMakeLists.txt index 833e34c56..a0be966e2 100644 --- a/src/autowiring/CMakeLists.txt +++ b/src/autowiring/CMakeLists.txt @@ -171,14 +171,6 @@ add_conditional_sources( ${PROJECT_SOURCE_DIR}/contrib/autoboost/libs/thread/src/future.cpp ) -if(NOT APPLE) - # avoid warning: has no symbols - set(Autowiring_SRCS - ${Autowiring_SRCS} - uuid.cpp - ) -endif() - add_windows_sources(Autowiring_SRCS CoreThreadWin.cpp InterlockedExchangeWin.cpp diff --git a/src/autowiring/uuid.cpp b/src/autowiring/uuid.cpp deleted file mode 100644 index e824d8c99..000000000 --- a/src/autowiring/uuid.cpp +++ /dev/null @@ -1,3 +0,0 @@ -// Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved. -#include "stdafx.h" -#include "uuid.h" From 1df9c686fab52c91563bd31f186b821794cbd4b7 Mon Sep 17 00:00:00 2001 From: Graham Tremper Date: Thu, 29 Jan 2015 11:41:44 -0800 Subject: [PATCH 06/20] Return an empty null-terminated buffer instead of a nullptr --- autowiring/AutoPacket.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/autowiring/AutoPacket.h b/autowiring/AutoPacket.h index 0fe1e947a..b631bfacc 100644 --- a/autowiring/AutoPacket.h +++ b/autowiring/AutoPacket.h @@ -289,7 +289,7 @@ class AutoPacket: /// /// Returns a null-terminated temporary buffer containing all decorations /// - /// The buffer, or nullptr if no matching decorations exist + /// The null-terminated temporary buffer /// /// The returned buffer must be freed with std::return_temporary_buffer /// @@ -297,8 +297,13 @@ class AutoPacket: const T** GetAll(int tshift = 0) const { std::lock_guard lk(m_lock); auto q = m_decorations.find(DecorationKey(auto_id::key(), tshift)); - if (q == m_decorations.end()) - return nullptr; + + // If decoration doesn't exist, return empty null-terminated buffer + if (q == m_decorations.end()) { + const T** retVal = std::get_temporary_buffer(1).first; + retVal[0] = nullptr; + return retVal; + } const auto& decorations = q->second.m_decorations; const T** retVal = std::get_temporary_buffer(decorations.size() + 1).first; From dbc6472e943ab482f926af5608500d5ac3994284 Mon Sep 17 00:00:00 2001 From: Graham Tremper Date: Fri, 30 Jan 2015 12:02:23 -0800 Subject: [PATCH 07/20] Add test to verify recursive context initiation --- src/autowiring/test/CoreContextTest.cpp | 40 +++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/autowiring/test/CoreContextTest.cpp b/src/autowiring/test/CoreContextTest.cpp index da32abaaa..c31ef3337 100644 --- a/src/autowiring/test/CoreContextTest.cpp +++ b/src/autowiring/test/CoreContextTest.cpp @@ -232,4 +232,44 @@ TEST_F(CoreContextTest, InitiateCausesDelayedHold) { // Starting up the outer context should cause the inner one to self destruct AutoCurrentContext()->Initiate(); ASSERT_TRUE(ctxtWeak.expired()) << "Subcontext containing no threads incorrectly persisted after termination"; +} + +TEST_F(CoreContextTest, InitiateOrder) { + AutoCurrentContext testCtxt; + testCtxt->Initiate(); + { + auto outerCtxt = testCtxt->Create(); + auto middleCtxt = outerCtxt->Create(); + auto innerCtxt = middleCtxt->Create(); + + middleCtxt->Initiate(); + innerCtxt->Initiate(); + outerCtxt->Initiate(); + + EXPECT_TRUE(outerCtxt->IsRunning()); + EXPECT_TRUE(middleCtxt->IsRunning()); + EXPECT_TRUE(innerCtxt->IsRunning()); + + outerCtxt->SignalShutdown(true); + middleCtxt->SignalShutdown(true); + innerCtxt->SignalShutdown(true); + } + + { + auto outerCtxt = testCtxt->Create(); + auto middleCtxt = outerCtxt->Create(); + auto innerCtxt = middleCtxt->Create(); + + innerCtxt->Initiate(); + middleCtxt->Initiate(); + outerCtxt->Initiate(); + + EXPECT_TRUE(outerCtxt->IsRunning()); + EXPECT_TRUE(middleCtxt->IsRunning()); + EXPECT_TRUE(innerCtxt->IsRunning()); + + innerCtxt->SignalShutdown(true); + middleCtxt->SignalShutdown(true); + outerCtxt->SignalShutdown(true); + } } \ No newline at end of file From 4dd67672b3f74fcd1e850a08cd16350b739430cd Mon Sep 17 00:00:00 2001 From: Graham Tremper Date: Fri, 30 Jan 2015 14:12:50 -0800 Subject: [PATCH 08/20] Recursivly attempt to transition children contexts to running state during initialization --- autowiring/CoreContext.h | 4 +- src/autowiring/CoreContext.cpp | 102 +++++++++++++++++---------------- 2 files changed, 56 insertions(+), 50 deletions(-) diff --git a/autowiring/CoreContext.h b/autowiring/CoreContext.h index 371c7d4d1..583af323f 100644 --- a/autowiring/CoreContext.h +++ b/autowiring/CoreContext.h @@ -453,9 +453,9 @@ class CoreContext: /// \internal /// - /// Invoked by a parent context on a child context when the parent has transitioned to the Running state + /// Invoked by a parent context when the parent has transitioned to the Running state /// - void TryTransitionToRunState(void); + void TryTransitionChildrenToRunState(void); /// /// Registers a factory _function_, a lambda which is capable of constructing decltype(fn()) diff --git a/src/autowiring/CoreContext.cpp b/src/autowiring/CoreContext.cpp index aed2f6825..e51558b1a 100644 --- a/src/autowiring/CoreContext.cpp +++ b/src/autowiring/CoreContext.cpp @@ -440,34 +440,8 @@ void CoreContext::Initiate(void) { for (auto q = beginning; q != m_threads.end(); ++q) (*q)->Start(outstanding); } - lk.lock(); - - // We have to hold this to prevent dtors from running in a synchronized context - std::shared_ptr prior; - for (auto childWeak : m_children) { - // Obtain child pointer and lock it down so our iterator stays stable - auto child = childWeak.lock(); - if (!child) - // Expiration while we were attempting to dereference, circle around - continue; - - // Cannot hold a lock safely if we hand off control to a child context - lk.unlock(); - - // Control handoff to the child context must happen outside of a lock: - child->TryTransitionToRunState(); - - // Permit a prior context to expire if needed - prior.reset(); - - // Need to preserve current child context pointer before it goes out of scope in order to - // preserve our iterator. - lk.lock(); - prior = child; - } - - // Release our lock before letting `prior` expire, we can't hold a lock through such an event - lk.unlock(); + + TryTransitionChildrenToRunState(); } void CoreContext::InitiateCoreThreads(void) { @@ -999,31 +973,63 @@ void CoreContext::AddPacketSubscriber(const AutoFilterDescriptor& rhs) { Inject()->AddSubscriber(rhs); } -void CoreContext::TryTransitionToRunState(void) { +void CoreContext::TryTransitionChildrenToRunState(void) { std::unique_lock lk(m_stateBlock->m_lock); - switch (m_state) { - case State::Initiated: - // Can transition to the running state now + + // We have to hold this to prevent dtors from running in a synchronized context + std::shared_ptr prior; + for (auto childWeak : m_children) { + // Obtain child pointer and lock it down so our iterator stays stable + auto child = childWeak.lock(); + if (!child) + // Expiration while we were attempting to dereference, circle around + continue; + + // Cannot hold a lock safely if we hand off control to a child context + lk.unlock(); { - auto q = m_threads.begin(); - m_state = State::Running; - lk.unlock(); - - auto outstanding = IncrementOutstandingThreadCount(); - while (q != m_threads.end()) { - (*q)->Start(outstanding); - q++; + // Get lock of child while we're modifying it's state + std::unique_lock childLk(child->m_stateBlock->m_lock); + + switch (child->m_state) { + case State::Initiated: + // Can transition to the running state now + { + auto q = child->m_threads.begin(); + child->m_state = State::Running; + childLk.unlock(); + + auto outstanding = child->IncrementOutstandingThreadCount(); + while (q != child->m_threads.end()) { + (*q)->Start(outstanding); + q++; + } + } + break; + case State::CanRun: + case State::NotStarted: + case State::Running: + case State::Shutdown: + case State::Abandoned: + // No action need be taken for these states + return; } } - break; - case State::CanRun: - case State::NotStarted: - case State::Running: - case State::Shutdown: - case State::Abandoned: - // No action need be taken for these states - return; + + // Recursivly try to transition children + child->TryTransitionChildrenToRunState(); + + // Permit a prior context to expire if needed + prior.reset(); + + // Need to preserve current child context pointer before it goes out of scope in order to + // preserve our iterator. + lk.lock(); + prior = child; } + + // Release our lock before letting `prior` expire, we can't hold a lock through such an event + lk.unlock(); } void CoreContext::UnsnoopAutoPacket(const ObjectTraits& traits) { From e7349494da17c0b5e1087dd6e0e2e7d6d533dac7 Mon Sep 17 00:00:00 2001 From: Jason Lokerson Date: Fri, 30 Jan 2015 14:59:03 -0800 Subject: [PATCH 09/20] Adding a `get` operation on auto_out Just for convenience for users that are interested in the underlying dumb pointer --- autowiring/auto_out.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/autowiring/auto_out.h b/autowiring/auto_out.h index 9b0577c75..3b081f2dd 100644 --- a/autowiring/auto_out.h +++ b/autowiring/auto_out.h @@ -30,6 +30,11 @@ class auto_out std::shared_ptr& m_value; public: + /// + /// Returns the dumb pointer to the underlying output value + /// + T* get(void) const { return m_value.get(); } + /// /// Releases the internal shared pointer, preventing it from being decorated on the packet /// From d233062a7bd237b50dc0ea877ac538dcb6628f6a Mon Sep 17 00:00:00 2001 From: Jason Lokerson Date: Fri, 30 Jan 2015 18:00:59 -0800 Subject: [PATCH 10/20] Make use of a template template type instead of rebind Template template types are more readable and easily understood than std::rebind --- autowiring/AutoFilterDescriptor.h | 6 ++-- autowiring/AutoFilterDescriptorInput.h | 45 +++++++++++++++++--------- autowiring/AutoPacket.h | 4 +-- autowiring/Decompose.h | 8 ++--- 4 files changed, 39 insertions(+), 24 deletions(-) diff --git a/autowiring/AutoFilterDescriptor.h b/autowiring/AutoFilterDescriptor.h index d7eb15ad9..a981b05c8 100644 --- a/autowiring/AutoFilterDescriptor.h +++ b/autowiring/AutoFilterDescriptor.h @@ -178,7 +178,7 @@ struct AutoFilterDescriptor: std::static_pointer_cast::type>(subscriber) ), &typeid(T), - Decompose::template Enumerate::types, + Decompose::template Enumerate::types, CallExtractor::deferred, &CallExtractor::template Call<&T::AutoFilter> ) @@ -195,7 +195,7 @@ struct AutoFilterDescriptor: AutoFilterDescriptor( AnySharedPointer(std::make_shared(std::forward(fn))), &typeid(Fn), - CallExtractor::template Enumerate::types, + CallExtractor::template Enumerate::types, false, &CallExtractor::template Call<&Fn::operator()> ) @@ -240,7 +240,7 @@ struct AutoFilterDescriptor: // The remainder is fairly straightforward &typeid(pfn), - CallExtractor::template Enumerate::types, + CallExtractor::template Enumerate::types, false, CallExtractor::Call ) diff --git a/autowiring/AutoFilterDescriptorInput.h b/autowiring/AutoFilterDescriptorInput.h index 6576708e7..9e573ffc9 100644 --- a/autowiring/AutoFilterDescriptorInput.h +++ b/autowiring/AutoFilterDescriptorInput.h @@ -16,14 +16,20 @@ struct AutoFilterDescriptorInput { tshift(0) {} - template - AutoFilterDescriptorInput(auto_arg*) : - is_input(auto_arg::is_input), - is_output(auto_arg::is_output), - is_shared(auto_arg::is_shared), - is_multi(auto_arg::is_multi), - ti(&typeid(typename auto_arg::id_type)), - tshift(auto_arg::tshift) + AutoFilterDescriptorInput( + bool is_input, + bool is_output, + bool is_shared, + bool is_multi, + const std::type_info* ti, + int tshift + ) : + is_input(is_input), + is_output(is_output), + is_shared(is_shared), + is_multi(is_multi), + ti(ti), + tshift(tshift) {} const bool is_input; @@ -36,11 +42,20 @@ struct AutoFilterDescriptorInput { operator bool(void) const { return !!ti; } - - template - struct rebind { - operator AutoFilterDescriptorInput() { - return AutoFilterDescriptorInput((auto_arg*)nullptr); - } - }; }; + +template +struct AutoFilterDescriptorInputT: + AutoFilterDescriptorInput +{ + AutoFilterDescriptorInputT(void) : + AutoFilterDescriptorInput( + auto_arg::is_input, + auto_arg::is_output, + auto_arg::is_shared, + auto_arg::is_multi, + &typeid(typename auto_arg::id_type), + auto_arg::tshift + ) + {} +}; \ No newline at end of file diff --git a/autowiring/AutoPacket.h b/autowiring/AutoPacket.h index b631bfacc..7bd0757d7 100644 --- a/autowiring/AutoPacket.h +++ b/autowiring/AutoPacket.h @@ -562,7 +562,7 @@ class AutoPacket: // Add the filter that will ultimately be invoked *this += std::move(autoFilter); - return Wait(cv, Decompose::template Enumerate::types, duration); + return Wait(cv, Decompose::template Enumerate::types, duration); } /// @@ -586,7 +586,7 @@ class AutoPacket: bool Wait(std::chrono::nanoseconds duration, std::condition_variable& cv) { static const AutoFilterDescriptorInput inputs [] = { - static_cast*>(nullptr)..., + AutoFilterDescriptorInputT()..., AutoFilterDescriptorInput() }; diff --git a/autowiring/Decompose.h b/autowiring/Decompose.h index ecd12d917..242a40dd7 100644 --- a/autowiring/Decompose.h +++ b/autowiring/Decompose.h @@ -15,11 +15,11 @@ struct TemplatePack { /// /// The returned array contains one more element than the arity of the decomposed member function /// type. Each element in the array is initialized based on the type of the corresponding argument - /// in the decomposed function. Elements in the array are constructed using the "rebind" structure + /// in the decomposed function. Elements in the array are constructed using the "Generator" type /// which must be an interior type to type T. An instance of type rebind should be castable to the /// base type T, or it must be a function returning a value of type T. /// - template + template class Generator> struct Enumerate { static const T types[N + 1]; }; @@ -34,8 +34,8 @@ struct TemplatePack { }; template -template -const T TemplatePack::Enumerate::types[] = {typename T::template rebind()..., T()}; +template class Generator> +const T TemplatePack::Enumerate::types[] = {Generator()..., T()}; /// /// Provides some static reflection support for member function pointers From 90b39298f11b4cf7290a438dba9111485edcb8dc Mon Sep 17 00:00:00 2001 From: Jimmy Nguyen Date: Fri, 30 Jan 2015 18:59:55 -0800 Subject: [PATCH 11/20] Fixing issue where the AutoPacketGraph CoreRunnable is just dying when OnStart is called --- src/autowiring/AutoPacketGraph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/autowiring/AutoPacketGraph.cpp b/src/autowiring/AutoPacketGraph.cpp index 1204e6e64..ae4933be5 100644 --- a/src/autowiring/AutoPacketGraph.cpp +++ b/src/autowiring/AutoPacketGraph.cpp @@ -74,7 +74,7 @@ void AutoPacketGraph::NewObject(CoreContext&, const ObjectTraits&) { bool AutoPacketGraph::OnStart(void) { LoadEdges(); - return false; + return true; } void AutoPacketGraph::AutoFilter(AutoPacket& packet) { From 1aca8be3afb8a0248a66c6d8cb6834582f702743 Mon Sep 17 00:00:00 2001 From: Graham Tremper Date: Mon, 2 Feb 2015 13:28:33 -0800 Subject: [PATCH 12/20] Remove AutoDesired --- autowiring/Autowired.h | 34 -------------------------- autowiring/CoreContext.h | 2 +- src/autowiring/AutoPacket.cpp | 2 +- src/autowiring/test/AutowiringTest.cpp | 28 --------------------- 4 files changed, 2 insertions(+), 64 deletions(-) diff --git a/autowiring/Autowired.h b/autowiring/Autowired.h index 40432261a..9d7de2395 100644 --- a/autowiring/Autowired.h +++ b/autowiring/Autowired.h @@ -350,40 +350,6 @@ class AutoEnable } }; -/// -/// Attempts to create and inject a dependency, discarding any exceptions. -/// -/// -/// Like AutoRequired, AutoDesired attempts to create an instance of the type -/// to be autowired. However, if creation of the dependency fails, the slot is -/// created and the dependency is satisfied when an instance of the correct type -/// is created and wired later. -/// -/// \include snippets/Autowired_AutoDesired.txt -/// -/// Use AutoDesired instead of AutoRequired or Autowired when creation of the dependency may fail, -/// while, unlike Autowired, still creating the dependency when possible. -/// -/// AutoDesired is functionally equivalent to the following: -/// -/// \include snippets/Autowired_AutoDesired_Alternate.txt -/// -/// If you want to know whether an exception was thrown, replace uses of AutoDesired with the above -/// and perform your own exception handling. -/// -template -class AutoDesired: - public Autowired -{ -public: - AutoDesired(void) { - try { AutoRequired(); } - catch(...) { - CoreContext::CurrentContext()->FilterException(); - } - } -}; - /// /// A version of AutoRequired that forwards constructor arguments to the injected /// type's constructor function. diff --git a/autowiring/CoreContext.h b/autowiring/CoreContext.h index 583af323f..6aa55bde2 100644 --- a/autowiring/CoreContext.h +++ b/autowiring/CoreContext.h @@ -95,7 +95,7 @@ class AutoSearchLambdaDefault: /// * Thread ownership (BasicThread, CoreThread) /// * AutoPacket filter graph scope /// -/// Dependencies can be injected into a context using AutoRequired (or its cousins Autowired and AutoDesired). +/// Dependencies can be injected into a context using AutoRequired (or its cousin Autowired). /// The system looks in the current context for an existing object of the required type to satisfy the dependency. /// If one does not exist, it looks in parent contexts. Finally, if no existing object is found after searching up the /// context tree, a new instance of the required type is created. When another object of the same type is added to the diff --git a/src/autowiring/AutoPacket.cpp b/src/autowiring/AutoPacket.cpp index 7babc66a5..271f66e61 100644 --- a/src/autowiring/AutoPacket.cpp +++ b/src/autowiring/AutoPacket.cpp @@ -227,7 +227,7 @@ void AutoPacket::PulseSatisfaction(DecorationDisposition* pTypeSubs[], size_t nI { std::lock_guard lk(m_lock); for(size_t i = nInfos; i--;) - for(const auto& cur : pTypeSubs[i]->m_subscribers) + for(SatCounter* cur : pTypeSubs[i]->m_subscribers) cur->Increment(); } } diff --git a/src/autowiring/test/AutowiringTest.cpp b/src/autowiring/test/AutowiringTest.cpp index 7850a4ba8..81a961836 100644 --- a/src/autowiring/test/AutowiringTest.cpp +++ b/src/autowiring/test/AutowiringTest.cpp @@ -80,34 +80,6 @@ TEST_F(AutowiringTest, PathologicalAutowiringRace) { AutoRequired(); } -class ChecksForExceptions: - public ExceptionFilter -{ -public: - ChecksForExceptions(void): - m_called(false) - {} - - bool m_called; - - void Filter(void) override { - m_called = true; - } -}; - -class ThrowsExceptionInCtor { -public: - ThrowsExceptionInCtor(void) { - throw std::exception(); - } -}; - -TEST_F(AutowiringTest, AUTOTHROW_CanSeeThrownAutoDesiredExceptions) { - AutoRequired cfe; - AutoDesired(); - ASSERT_TRUE(cfe->m_called) << "Exception was not caught by exception filter in Autowiring context"; -} - class PublicBase { public: PublicBase(void) {} From 3b8f430affa73883ca4c976a46f2aa87cff9a51b Mon Sep 17 00:00:00 2001 From: Jimmy Nguyen Date: Mon, 2 Feb 2015 16:36:51 -0800 Subject: [PATCH 13/20] With help from Graham, added a new template specialization to handle strings when parsing the types from the event handler. Also, renamed the functions from parse to parse to/from string --- autowiring/AutoNetServer.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/autowiring/AutoNetServer.h b/autowiring/AutoNetServer.h index 9061cfa30..42d3dc7f3 100644 --- a/autowiring/AutoNetServer.h +++ b/autowiring/AutoNetServer.h @@ -45,7 +45,7 @@ class AutoNetServer: /// Send a custom event to all clients. template void SendEvent(const std::string& event, Args... args) { - SendEvent(event, std::vector{parse(args)...}); + SendEvent(event, std::vector{parseToString(args)...}); } protected: @@ -68,14 +68,14 @@ class AutoNetServer: if (sizeof...(Args) != args.size()) // TODO: Return some kind of singal to the caller indicating that there is a problem return; - (handler.*pfn)(parse(args[N])...); + (handler.*pfn)(parseFromString::type>(args[N])...); } ); } // parse type to string template - std::string parse(const T& t){ + std::string parseToString(const T& t){ std::ostringstream ss; ss << t; return ss.str(); @@ -83,7 +83,7 @@ class AutoNetServer: // parse string to primative type template - typename std::decay::type parse(const std::string& str){ + inline T parseFromString(const std::string& str){ std::istringstream ss(str); typename std::decay::type val; ss >> std::boolalpha >> val; @@ -95,3 +95,9 @@ class AutoNetServer: return val; } }; + +// template specialization for a string to just return itself unparsed +template<> +inline std::string AutoNetServer::parseFromString(const std::string& str) { + return str; +} From 4b21414cf9ef98fdafb242c6119570b4213161d7 Mon Sep 17 00:00:00 2001 From: Graham Tremper Date: Mon, 2 Feb 2015 17:42:30 -0800 Subject: [PATCH 14/20] Rename 'Object' to 'CoreObject' --- autowiring/AutoPacketFactory.h | 6 +-- autowiring/AutoRestarter.h | 2 +- autowiring/AutowirableSlot.h | 10 ++--- autowiring/Autowired.h | 4 +- autowiring/BasicThread.h | 4 +- autowiring/ContextMember.h | 4 +- autowiring/CoreContext.h | 38 +++++++++---------- autowiring/CoreJob.h | 2 +- autowiring/{Object.h => CoreObject.h} | 6 +-- autowiring/CoreRunnable.h | 8 ++-- autowiring/CoreThread.h | 2 +- autowiring/CreationRules.h | 2 +- autowiring/ExceptionFilter.h | 4 +- autowiring/JunctionBox.h | 6 +-- autowiring/JunctionBoxBase.h | 6 +-- autowiring/JunctionBoxManager.h | 6 +-- autowiring/ObjectPool.h | 1 - autowiring/ObjectTraits.h | 18 ++++----- autowiring/SharedPointerSlot.h | 20 +++++----- autowiring/SlotInformation.h | 2 +- autowiring/TypeIdentifier.h | 6 +-- autowiring/TypeUnifier.h | 8 ++-- autowiring/fast_pointer_cast.h | 2 +- src/autonet/AutoNetServerImpl.cpp | 2 +- src/autowiring/AutoPacketFactory.cpp | 8 ++-- src/autowiring/BasicThread.cpp | 4 +- src/autowiring/CMakeLists.txt | 4 +- src/autowiring/CoreContext.cpp | 28 +++++++------- src/autowiring/{Object.cpp => CoreObject.cpp} | 6 +-- src/autowiring/CoreRunnable.cpp | 6 +-- src/autowiring/CoreThread.cpp | 2 +- src/autowiring/JunctionBoxBase.cpp | 2 +- src/autowiring/JunctionBoxManager.cpp | 4 +- src/autowiring/test/ContextCleanupTest.cpp | 2 +- src/autowiring/test/CoreThreadTest.cpp | 2 +- src/autowiring/test/DecoratorTest.cpp | 2 +- src/autowiring/test/ExceptionFilterTest.cpp | 2 +- src/autowiring/test/FactoryTest.cpp | 4 +- 38 files changed, 122 insertions(+), 123 deletions(-) rename autowiring/{Object.h => CoreObject.h} (81%) rename src/autowiring/{Object.cpp => CoreObject.cpp} (50%) diff --git a/autowiring/AutoPacketFactory.h b/autowiring/AutoPacketFactory.h index 1d88fb5e0..d7b66aa2c 100644 --- a/autowiring/AutoPacketFactory.h +++ b/autowiring/AutoPacketFactory.h @@ -182,7 +182,7 @@ class AutoPacketFactory: // exterior instantation of internally used template instances extern template struct SlotInformationStump; extern template const std::shared_ptr& SharedPointerSlot::as(void) const; -extern template std::shared_ptr autowiring::fast_pointer_cast(const std::shared_ptr& Other); +extern template std::shared_ptr autowiring::fast_pointer_cast(const std::shared_ptr& Other); extern template class RegType; -extern template struct autowiring::fast_pointer_cast_blind; -extern template struct autowiring::fast_pointer_cast_initializer; +extern template struct autowiring::fast_pointer_cast_blind; +extern template struct autowiring::fast_pointer_cast_initializer; diff --git a/autowiring/AutoRestarter.h b/autowiring/AutoRestarter.h index 247c08fd5..f562c7f0f 100644 --- a/autowiring/AutoRestarter.h +++ b/autowiring/AutoRestarter.h @@ -135,7 +135,7 @@ class AutoRestarter: GenerateContext(); } - void Filter(const JunctionBoxBase* pJunctionBox, Object* pRecipient) override { + void Filter(const JunctionBoxBase* pJunctionBox, CoreObject* pRecipient) override { Filter(); } diff --git a/autowiring/AutowirableSlot.h b/autowiring/AutowirableSlot.h index 358fe306f..ec9ef1e3c 100644 --- a/autowiring/AutowirableSlot.h +++ b/autowiring/AutowirableSlot.h @@ -9,7 +9,7 @@ class CoreContext; class DeferrableAutowiring; class GlobalCoreContext; -class Object; +class CoreObject; // Utility routine, for users who need a function that does nothing template @@ -146,7 +146,7 @@ class AutowirableSlot: // of this type MUST be available. The reason for this is that, if the user wishes to know if a // type is autowired, they are required at a minimum to know what that type's inheritance relations // are to other types in the system. - (void) autowiring::fast_pointer_cast_initializer::sc_init; + (void) autowiring::fast_pointer_cast_initializer::sc_init; return !!get(); } @@ -155,7 +155,7 @@ class AutowirableSlot: /// T* get(void) const { // For now, we require that the full type be available to use this method - (void) autowiring::fast_pointer_cast_initializer::sc_init; + (void) autowiring::fast_pointer_cast_initializer::sc_init; return get_unsafe(); } @@ -184,14 +184,14 @@ class AutowirableSlot: // Initialize any blind fast casts to the actually desired type. This is one of a few points // where we can guarantee that the type will be completely defined, because the user is about // to make use of this type. - (void) autowiring::fast_pointer_cast_initializer::sc_init; + (void) autowiring::fast_pointer_cast_initializer::sc_init; return get(); } T& operator*(void) const { // We have to initialize here, in the operator context, because we don't actually know if the // user will be making use of this type. - (void) autowiring::fast_pointer_cast_initializer::sc_init; + (void) autowiring::fast_pointer_cast_initializer::sc_init; return *get(); } diff --git a/autowiring/Autowired.h b/autowiring/Autowired.h index 9d7de2395..7af79c716 100644 --- a/autowiring/Autowired.h +++ b/autowiring/Autowired.h @@ -311,14 +311,14 @@ class AutowiredFast: // !!!!! Read comment in AutoRequired if you get a compiler error here !!!!! AutowiredFast(const std::shared_ptr& ctxt = CoreContext::CurrentContext()) { - (void) autowiring::fast_pointer_cast_initializer::sc_init; + (void) autowiring::fast_pointer_cast_initializer::sc_init; if (ctxt) ctxt->FindByTypeRecursive(*this); } AutowiredFast(const CoreContext* pCtxt) { - (void) autowiring::fast_pointer_cast_initializer::sc_init; + (void) autowiring::fast_pointer_cast_initializer::sc_init; pCtxt->FindByTypeRecursive(*this); } diff --git a/autowiring/BasicThread.h b/autowiring/BasicThread.h index 655250e79..9f843f5bb 100644 --- a/autowiring/BasicThread.h +++ b/autowiring/BasicThread.h @@ -102,13 +102,13 @@ class BasicThread: /// shared pointer passed to it, typically as a last step before return, potentially /// triggering the case described above. /// - virtual void DoRun(std::shared_ptr&& refTracker); + virtual void DoRun(std::shared_ptr&& refTracker); /// /// Performs all cleanup operations that must take place after DoRun /// /// The last reference to the enclosing context held by this thread - virtual void DoRunLoopCleanup(std::shared_ptr&& ctxt, std::shared_ptr&& refTracker); + virtual void DoRunLoopCleanup(std::shared_ptr&& ctxt, std::shared_ptr&& refTracker); void DEPRECATED(Ready(void) const, "Do not call this method, the concept of thread readiness is now deprecated") {} diff --git a/autowiring/ContextMember.h b/autowiring/ContextMember.h index 6734f5c21..a949b2100 100644 --- a/autowiring/ContextMember.h +++ b/autowiring/ContextMember.h @@ -1,6 +1,6 @@ // Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved. #pragma once -#include "Object.h" +#include "CoreObject.h" #include "TeardownNotifier.h" #include MEMORY_HEADER @@ -10,7 +10,7 @@ class CoreContext; /// A class that must be inherited in order to be a member of a context heriarchy /// class ContextMember: - public Object, + public CoreObject, public TeardownNotifier, public std::enable_shared_from_this { diff --git a/autowiring/CoreContext.h b/autowiring/CoreContext.h index 6aa55bde2..ac4258bb1 100644 --- a/autowiring/CoreContext.h +++ b/autowiring/CoreContext.h @@ -234,14 +234,14 @@ class CoreContext: std::vector m_filters; // All known event receivers and receiver proxies originating from this context: - typedef std::set> t_rcvrSet; + typedef std::set> t_rcvrSet; t_rcvrSet m_eventReceivers; // List of eventReceivers to be added when this context in initiated t_rcvrSet m_delayedEventReceivers; // Context members from other contexts that have snooped this context - std::set m_snoopers; + std::set m_snoopers; // Manages events for this context. One JunctionBoxManager is shared between peer contexts const std::shared_ptr m_junctionBoxManager; @@ -252,7 +252,7 @@ class CoreContext: // Clever use of shared pointer to expose the number of outstanding CoreRunnable instances. // Destructor does nothing; this is by design. - std::weak_ptr m_outstanding; + std::weak_ptr m_outstanding; // Creation rules are allowed to refer to private methods in this type template @@ -329,7 +329,7 @@ class CoreContext: /// Adds the named event receiver to the collection of known receivers /// /// The junction box entry corresponding to the receiver type - void AddEventReceiver(const JunctionBoxEntry& pRecvr); + void AddEventReceiver(const JunctionBoxEntry& pRecvr); /// \internal /// @@ -387,7 +387,7 @@ class CoreContext: /// /// The caller is responsible for exterior synchronization /// - std::shared_ptr IncrementOutstandingThreadCount(void); + std::shared_ptr IncrementOutstandingThreadCount(void); /// \internal /// @@ -427,13 +427,13 @@ class CoreContext: /// /// Adds a snooper to the snoopers set /// - void InsertSnooper(std::shared_ptr snooper); + void InsertSnooper(std::shared_ptr snooper); /// \internal /// /// Removes a snooper to the snoopers set /// - void RemoveSnooper(std::shared_ptr snooper); + void RemoveSnooper(std::shared_ptr snooper); /// \internal /// @@ -443,7 +443,7 @@ class CoreContext: /// This method has no effect if the passed value is presently a snooper in this context; the /// snooper collection must therefore be updated prior to the call to this method. /// - void UnsnoopEvents(Object* snooper, const JunctionBoxEntry& traits); + void UnsnoopEvents(CoreObject* snooper, const JunctionBoxEntry& traits); /// \internal /// @@ -628,13 +628,13 @@ class CoreContext: typedef autowiring::CreationRules CreationRules; // Add this type to the TypeRegistry, also ensure that we initialize support for blind - // fast pointer cast to Object. + // fast pointer cast to CoreObject. (void) RegType::r; - (void) autowiring::fast_pointer_cast_initializer::sc_init; + (void) autowiring::fast_pointer_cast_initializer::sc_init; // First see if the base object type has already been injected. This is also necessary to // ensure that a memo slot is created for the type by itself, in cases where the injected - // member does not inherit Object and this member is eventually satisfied by one that does. + // member does not inherit CoreObject and this member is eventually satisfied by one that does. { std::shared_ptr pure; FindByType(pure); @@ -917,7 +917,7 @@ class CoreContext: /// /// The sender of the event /// The recipient of the event - void FilterFiringException(const JunctionBoxBase* pProxy, Object* pRecipient); + void FilterFiringException(const JunctionBoxBase* pProxy, CoreObject* pRecipient); /// /// Registers the specified event receiver to receive messages broadcast within this context. @@ -939,7 +939,7 @@ class CoreContext: // Add EventReceiver if(traits.receivesEvents) - AddEventReceiver(JunctionBoxEntry(this, traits.pObject)); + AddEventReceiver(JunctionBoxEntry(this, traits.pCoreObject)); // Add PacketSubscriber; if(!traits.subscriber.empty()) @@ -966,11 +966,11 @@ class CoreContext: RemoveSnooper(pSnooper); - auto oSnooper = std::static_pointer_cast(pSnooper); + auto oSnooper = std::static_pointer_cast(pSnooper); // Cleanup if its an EventReceiver if(traits.receivesEvents) - UnsnoopEvents(oSnooper.get(), JunctionBoxEntry(this, traits.pObject)); + UnsnoopEvents(oSnooper.get(), JunctionBoxEntry(this, traits.pCoreObject)); // Cleanup if its a packet listener if(!traits.subscriber.empty()) @@ -1192,7 +1192,7 @@ class CoreContext::AutoFactory template class CoreContext::AutoFactoryFn : - public Object, + public CoreObject, public CoreContext::AutoFactory { public: @@ -1207,7 +1207,7 @@ class CoreContext::AutoFactoryFn : template class CoreContext::AutoFactoryFn, Fn> : - public Object, + public CoreObject, CoreContext::AutoFactory... { public: @@ -1222,8 +1222,8 @@ template T* autowiring::crh::New(CoreContext& ctxt, Args&&... args) { // We need to ensure that we can perform a find-by-type cast correctly, so // the dynamic caster entry is added to the registry - (void) autowiring::fast_pointer_cast_initializer>::sc_init; - (void) autowiring::fast_pointer_cast_initializer, Object>::sc_init; + (void) autowiring::fast_pointer_cast_initializer>::sc_init; + (void) autowiring::fast_pointer_cast_initializer, CoreObject>::sc_init; // Now we can go looking for this type: AnySharedPointerT> af; diff --git a/autowiring/CoreJob.h b/autowiring/CoreJob.h index 8cd99376a..8e4f9576c 100644 --- a/autowiring/CoreJob.h +++ b/autowiring/CoreJob.h @@ -4,7 +4,7 @@ #include "CoreRunnable.h" #include "DispatchQueue.h" -class Object; +class CoreObject; class CoreJob: public ContextMember, diff --git a/autowiring/Object.h b/autowiring/CoreObject.h similarity index 81% rename from autowiring/Object.h rename to autowiring/CoreObject.h index 77f564314..29f8ce642 100644 --- a/autowiring/Object.h +++ b/autowiring/CoreObject.h @@ -5,8 +5,8 @@ /// General object base, used to make conversions possible between various shared pointer implementations. /// Withouat an object base, there is no way to do generic autowiring. /// -class Object { +class CoreObject { public: - Object(void); - virtual ~Object(void); + CoreObject(void); + virtual ~CoreObject(void); }; diff --git a/autowiring/CoreRunnable.h b/autowiring/CoreRunnable.h index c3ae76e38..d397b0a4a 100644 --- a/autowiring/CoreRunnable.h +++ b/autowiring/CoreRunnable.h @@ -4,7 +4,7 @@ #include MEMORY_HEADER #include MUTEX_HEADER -class Object; +class CoreObject; class CoreRunnable { public: @@ -19,7 +19,7 @@ class CoreRunnable { bool m_shouldStop; // The outstanding count, held for as long as processing is underway - std::shared_ptr m_outstanding; + std::shared_ptr m_outstanding; protected: std::mutex m_lock; @@ -28,7 +28,7 @@ class CoreRunnable { /// /// A reference to the current outstanding counter /// - const std::shared_ptr& GetOutstanding(void) const; + const std::shared_ptr& GetOutstanding(void) const; /// /// Method invoked from Start when this class is being asked to begin processing @@ -74,7 +74,7 @@ class CoreRunnable { /// Callers should strongly prefer not to override Start if possible. Instead, override OnStart and /// obtain an instance of the outstanding pointer via GetOutstanding /// - virtual bool Start(std::shared_ptr outstanding); + virtual bool Start(std::shared_ptr outstanding); /// /// Stops this runnable, optionally performing graceful cleanup if requested diff --git a/autowiring/CoreThread.h b/autowiring/CoreThread.h index fa812187c..f3b95965f 100644 --- a/autowiring/CoreThread.h +++ b/autowiring/CoreThread.h @@ -27,7 +27,7 @@ class CoreThread: /// /// Overridden here so we can rundown the dispatch queue /// - virtual void DoRunLoopCleanup(std::shared_ptr&& ctxt, std::shared_ptr&& refTracker) override; + virtual void DoRunLoopCleanup(std::shared_ptr&& ctxt, std::shared_ptr&& refTracker) override; public: /// diff --git a/autowiring/CreationRules.h b/autowiring/CreationRules.h index ee56fe5bd..24ca00965 100644 --- a/autowiring/CreationRules.h +++ b/autowiring/CreationRules.h @@ -82,7 +82,7 @@ struct crh typedef T TActual; static_assert( - std::is_base_of::value || !has_static_new::value, + std::is_base_of::value || !has_static_new::value, "If type T provides a static New method, then the constructed type MUST directly inherit Object" ); diff --git a/autowiring/ExceptionFilter.h b/autowiring/ExceptionFilter.h index 01f1f6726..312fba13a 100644 --- a/autowiring/ExceptionFilter.h +++ b/autowiring/ExceptionFilter.h @@ -2,7 +2,7 @@ #pragma once class JunctionBoxBase; -class Object; +class CoreObject; /// /// Implements an exception filter type, invoked when an unhandled exception is thrown @@ -69,5 +69,5 @@ class ExceptionFilter /// /// Implementors can use "throw" with no arguments to trigger a rethrow of the originating exception. /// - virtual void Filter(const JunctionBoxBase* pJunctionBox, Object* pRecipient) {} + virtual void Filter(const JunctionBoxBase* pJunctionBox, CoreObject* pRecipient) {} }; diff --git a/autowiring/JunctionBox.h b/autowiring/JunctionBox.h index e21baa27a..8bb03f78c 100644 --- a/autowiring/JunctionBox.h +++ b/autowiring/JunctionBox.h @@ -50,14 +50,14 @@ class JunctionBox: return (std::lock_guard)m_lock, !m_st.empty(); } - void Add(const JunctionBoxEntry& rhs) override { + void Add(const JunctionBoxEntry& rhs) override { auto casted = rhs.Rebind(); if(casted) // Proposed type is directly one of our receivers Add(casted); } - void Remove(const JunctionBoxEntry& rhs) override { + void Remove(const JunctionBoxEntry& rhs) override { auto casted = rhs.Rebind(); if(casted) Remove(casted); @@ -108,7 +108,7 @@ class JunctionBox: catch (...) { teardown.push_back(ContextDumbToWeak(currentEvent.m_owner)); - // If T doesn't inherit Object, then we need to cast to a unifying type which does + // If T doesn't inherit CoreObject, then we need to cast to a unifying type which does typedef typename SelectTypeUnifier::type TActual; this->FilterFiringException(currentEvent.m_ptr); } diff --git a/autowiring/JunctionBoxBase.h b/autowiring/JunctionBoxBase.h index 2eefd3ec2..d942b6de4 100644 --- a/autowiring/JunctionBoxBase.h +++ b/autowiring/JunctionBoxBase.h @@ -1,6 +1,6 @@ // Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved. #pragma once -#include "Object.h" +#include "CoreObject.h" #include #include MEMORY_HEADER @@ -55,6 +55,6 @@ class JunctionBoxBase { virtual bool HasListeners(void) const = 0; // Event attachment and detachment pure virtuals - virtual void Add(const JunctionBoxEntry& rhs) = 0; - virtual void Remove(const JunctionBoxEntry& rhs) = 0; + virtual void Add(const JunctionBoxEntry& rhs) = 0; + virtual void Remove(const JunctionBoxEntry& rhs) = 0; }; diff --git a/autowiring/JunctionBoxManager.h b/autowiring/JunctionBoxManager.h index 9a1696a94..cf6684655 100644 --- a/autowiring/JunctionBoxManager.h +++ b/autowiring/JunctionBoxManager.h @@ -6,7 +6,7 @@ class CoreContext; class JunctionBoxBase; -class Object; +class CoreObject; template struct JunctionBoxEntry; @@ -29,8 +29,8 @@ class JunctionBoxManager { /// void Initiate(void); - void AddEventReceiver(JunctionBoxEntry receiver); - void RemoveEventReceiver(JunctionBoxEntry pRecvr); + void AddEventReceiver(JunctionBoxEntry receiver); + void RemoveEventReceiver(JunctionBoxEntry pRecvr); protected: // All junction boxes known by this manager: diff --git a/autowiring/ObjectPool.h b/autowiring/ObjectPool.h index b500297e9..0b1e05b7b 100644 --- a/autowiring/ObjectPool.h +++ b/autowiring/ObjectPool.h @@ -1,7 +1,6 @@ // Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved. #pragma once #include "autowiring_error.h" -#include "Object.h" #include "ObjectPoolMonitor.h" #include #include diff --git a/autowiring/ObjectTraits.h b/autowiring/ObjectTraits.h index 808b45686..a0d3499e4 100644 --- a/autowiring/ObjectTraits.h +++ b/autowiring/ObjectTraits.h @@ -8,7 +8,7 @@ #include "BasicThread.h" #include "ExceptionFilter.h" #include "fast_pointer_cast.h" -#include "Object.h" +#include "CoreObject.h" #include #include MEMORY_HEADER @@ -23,7 +23,7 @@ struct ObjectTraits { stump(SlotInformationStump::s_stump), value(value), subscriber(MakeAutoFilterDescriptor(value)), - pObject(autowiring::fast_pointer_cast(value)), + pCoreObject(autowiring::fast_pointer_cast(value)), pContextMember(autowiring::fast_pointer_cast(value)), pCoreRunnable(autowiring::fast_pointer_cast(value)), pBasicThread(autowiring::fast_pointer_cast(value)), @@ -33,7 +33,7 @@ struct ObjectTraits { [this]{ for (auto evt = g_pFirstEventEntry; evt; evt = evt->pFlink) { auto identifier = evt->NewTypeIdentifier(); - if (identifier->IsSameAs(pObject.get())) + if (identifier->IsSameAs(pCoreObject.get())) return true; } // "T" not found in event registry @@ -41,11 +41,11 @@ struct ObjectTraits { }() ) { - // We can instantiate casts to Object here at the point where object traits are being generated - (void) autowiring::fast_pointer_cast_initializer::sc_init; - (void) autowiring::fast_pointer_cast_initializer::sc_init; - (void) autowiring::fast_pointer_cast_initializer::sc_init; - (void) autowiring::fast_pointer_cast_initializer::sc_init; + // We can instantiate casts to CoreObject here at the point where object traits are being generated + (void) autowiring::fast_pointer_cast_initializer::sc_init; + (void) autowiring::fast_pointer_cast_initializer::sc_init; + (void) autowiring::fast_pointer_cast_initializer::sc_init; + (void) autowiring::fast_pointer_cast_initializer::sc_init; } // The type of the passed pointer @@ -94,7 +94,7 @@ struct ObjectTraits { const AutoFilterDescriptor subscriber; // There are a lot of interfaces we support, here they all are: - const std::shared_ptr pObject; + const std::shared_ptr pCoreObject; const std::shared_ptr pContextMember; const std::shared_ptr pCoreRunnable; const std::shared_ptr pBasicThread; diff --git a/autowiring/SharedPointerSlot.h b/autowiring/SharedPointerSlot.h index e02bd8006..915836b30 100644 --- a/autowiring/SharedPointerSlot.h +++ b/autowiring/SharedPointerSlot.h @@ -3,7 +3,7 @@ #include "auto_id.h" #include "autowiring_error.h" #include "fast_pointer_cast.h" -#include "Object.h" +#include "CoreObject.h" #include "SlotInformation.h" #include MEMORY_HEADER #include @@ -56,7 +56,7 @@ struct SharedPointerSlot { public: operator bool(void) const { return !empty(); } - virtual operator std::shared_ptr(void) const { return std::shared_ptr(); } + virtual operator std::shared_ptr(void) const { return std::shared_ptr(); } virtual void* ptr(void) { return nullptr; } virtual const void* ptr(void) const { return nullptr; } @@ -89,7 +89,7 @@ struct SharedPointerSlot { /// Attempts to dynamically assign this slot to the specified object without changing the current type /// /// True if the assignment succeeds - virtual bool try_assign(const std::shared_ptr& rhs) { + virtual bool try_assign(const std::shared_ptr& rhs) { return false; } @@ -197,10 +197,10 @@ struct SharedPointerSlot { } /// - /// Specialization for the Object base type + /// Specialization for the CoreObject base type /// - bool operator==(const std::shared_ptr& rhs) const { - return this->operator std::shared_ptr() == rhs; + bool operator==(const std::shared_ptr& rhs) const { + return this->operator std::shared_ptr() == rhs; } /// @@ -344,9 +344,9 @@ struct SharedPointerSlotT: new (pSpace) SharedPointerSlotT(*this); } - bool try_assign(const std::shared_ptr& rhs) override { + bool try_assign(const std::shared_ptr& rhs) override { // Just perform a dynamic cast: - auto casted = autowiring::fast_pointer_cast_blind::cast(rhs); + auto casted = autowiring::fast_pointer_cast_blind::cast(rhs); if (!casted) return false; @@ -354,8 +354,8 @@ struct SharedPointerSlotT: return true; } - virtual operator std::shared_ptr(void) const override { - return autowiring::fast_pointer_cast_blind::cast(SharedPointerSlotT::get()); + virtual operator std::shared_ptr(void) const override { + return autowiring::fast_pointer_cast_blind::cast(SharedPointerSlotT::get()); } using SharedPointerSlotT::operator=; diff --git a/autowiring/SlotInformation.h b/autowiring/SlotInformation.h index 7384b9d2a..c49a82e97 100644 --- a/autowiring/SlotInformation.h +++ b/autowiring/SlotInformation.h @@ -75,7 +75,7 @@ struct use_unifier: std::integral_constant< bool, std::is_class::value && - !std::is_base_of::value + !std::is_base_of::value > {}; diff --git a/autowiring/TypeIdentifier.h b/autowiring/TypeIdentifier.h index 6e4c66b35..73db0b5f9 100644 --- a/autowiring/TypeIdentifier.h +++ b/autowiring/TypeIdentifier.h @@ -1,11 +1,11 @@ // Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved. #pragma once -#include "Object.h" +#include "CoreObject.h" #include // Checks if an Object* listens to a event T; struct TypeIdentifierBase { - virtual bool IsSameAs(const Object* obj) = 0; + virtual bool IsSameAs(const CoreObject* obj) = 0; virtual const std::type_info& Type() = 0; }; @@ -14,7 +14,7 @@ template public TypeIdentifierBase { // true if "obj" is an event receiver for T - bool IsSameAs(const Object* obj) override { + bool IsSameAs(const CoreObject* obj) override { return !!dynamic_cast(obj); } diff --git a/autowiring/TypeUnifier.h b/autowiring/TypeUnifier.h index fcc8e0974..889cbd63a 100644 --- a/autowiring/TypeUnifier.h +++ b/autowiring/TypeUnifier.h @@ -1,10 +1,10 @@ // Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved. #pragma once -#include "Object.h" +#include "CoreObject.h" #include RVALUE_HEADER #include TYPE_TRAITS_HEADER -class TypeUnifier: public Object {}; +class TypeUnifier: public CoreObject {}; template class TypeUnifierComplex: @@ -25,11 +25,11 @@ class TypeUnifierComplex: /// template< class T, - bool inheritsObject = std::is_base_of::value + bool inheritsCoreObject = std::is_base_of::value > struct SelectTypeUnifier; -// Anyone already inheriting Object can just use Object +// Anyone already inheriting CoreObject can just use CoreObject template struct SelectTypeUnifier { typedef T type; diff --git a/autowiring/fast_pointer_cast.h b/autowiring/fast_pointer_cast.h index 23cec36a0..d012f49ac 100644 --- a/autowiring/fast_pointer_cast.h +++ b/autowiring/fast_pointer_cast.h @@ -5,7 +5,7 @@ #include TYPE_TRAITS_HEADER class AutoPacketFactory; -class Object; +class CoreObject; namespace autowiring { template diff --git a/src/autonet/AutoNetServerImpl.cpp b/src/autonet/AutoNetServerImpl.cpp index 1ab621c18..ce8922cae 100644 --- a/src/autonet/AutoNetServerImpl.cpp +++ b/src/autonet/AutoNetServerImpl.cpp @@ -250,7 +250,7 @@ void AutoNetServerImpl::NewObject(CoreContext& ctxt, const ObjectTraits& object) { Json::array listenerTypes; for(const auto& event : m_EventTypes) { - if(event->IsSameAs(object.pObject.get())) + if(event->IsSameAs(object.pCoreObject.get())) listenerTypes.push_back(autowiring::demangle(event->Type())); } diff --git a/src/autowiring/AutoPacketFactory.cpp b/src/autowiring/AutoPacketFactory.cpp index dce0a21be..584fa4e8f 100644 --- a/src/autowiring/AutoPacketFactory.cpp +++ b/src/autowiring/AutoPacketFactory.cpp @@ -55,7 +55,7 @@ std::shared_ptr AutoPacketFactory::GetInternalOutstanding(void) { if (retVal) return retVal; - std::shared_ptr outstanding = GetOutstanding(); + std::shared_ptr outstanding = GetOutstanding(); retVal = std::shared_ptr( (void*)1, [this, outstanding] (void*) mutable { @@ -183,7 +183,7 @@ void AutoPacketFactory::ResetPacketStatistics(void) { template struct SlotInformationStump; template const std::shared_ptr& SharedPointerSlot::as(void) const; -template std::shared_ptr autowiring::fast_pointer_cast(const std::shared_ptr& Other); +template std::shared_ptr autowiring::fast_pointer_cast(const std::shared_ptr& Other); template class RegType; -template struct autowiring::fast_pointer_cast_blind; -template struct autowiring::fast_pointer_cast_initializer; +template struct autowiring::fast_pointer_cast_blind; +template struct autowiring::fast_pointer_cast_initializer; diff --git a/src/autowiring/BasicThread.cpp b/src/autowiring/BasicThread.cpp index 6c8293b66..3b954c262 100644 --- a/src/autowiring/BasicThread.cpp +++ b/src/autowiring/BasicThread.cpp @@ -21,7 +21,7 @@ std::mutex& BasicThread::GetLock(void) { return m_state->m_lock; } -void BasicThread::DoRun(std::shared_ptr&& refTracker) { +void BasicThread::DoRun(std::shared_ptr&& refTracker) { assert(m_running); // Make our own session current before we do anything else: @@ -56,7 +56,7 @@ void BasicThread::DoRun(std::shared_ptr&& refTracker) { DoRunLoopCleanup(pusher.Pop(), std::move(refTracker)); } -void BasicThread::DoRunLoopCleanup(std::shared_ptr&& ctxt, std::shared_ptr&& refTracker) { +void BasicThread::DoRunLoopCleanup(std::shared_ptr&& ctxt, std::shared_ptr&& refTracker) { // Take a copy of our state condition shared pointer while we still hold a reference to // ourselves. This is the only member out of our collection of members that we actually // need to hold a reference to. diff --git a/src/autowiring/CMakeLists.txt b/src/autowiring/CMakeLists.txt index a0be966e2..83d646693 100644 --- a/src/autowiring/CMakeLists.txt +++ b/src/autowiring/CMakeLists.txt @@ -81,6 +81,8 @@ set(Autowiring_SRCS CoreContextStateBlock.h CoreJob.cpp CoreJob.h + CoreObject.cpp + CoreObject.h CoreRunnable.cpp CoreRunnable.h CoreThread.cpp @@ -127,8 +129,6 @@ set(Autowiring_SRCS MicroAutoFilter.h MicroBolt.h NewAutoFilter.h - Object.cpp - Object.h ObjectPool.h ObjectPoolMonitor.cpp ObjectPoolMonitor.h diff --git a/src/autowiring/CoreContext.cpp b/src/autowiring/CoreContext.cpp index e51558b1a..9185567bf 100644 --- a/src/autowiring/CoreContext.cpp +++ b/src/autowiring/CoreContext.cpp @@ -193,9 +193,9 @@ const std::type_info& CoreContext::GetAutoTypeId(const AnySharedPointer& ptr) co return pObjTraits->type; } -std::shared_ptr CoreContext::IncrementOutstandingThreadCount(void) { +std::shared_ptr CoreContext::IncrementOutstandingThreadCount(void) { // Optimistic check - std::shared_ptr retVal = m_outstanding.lock(); + std::shared_ptr retVal = m_outstanding.lock(); if(retVal) return retVal; @@ -208,14 +208,14 @@ std::shared_ptr CoreContext::IncrementOutstandingThreadCount(void) { // Increment the parent's outstanding count as well. This will be held by the lambda, and will cause the enclosing // context's outstanding thread count to be incremented by one as long as we have any threads still running in our // context. This property is relied upon in order to get the Wait function to operate properly. - std::shared_ptr parentCount; + std::shared_ptr parentCount; if(m_pParent) parentCount = m_pParent->IncrementOutstandingThreadCount(); auto self = shared_from_this(); retVal.reset( - (Object*)1, - [this, self, parentCount](Object*) { + (CoreObject*)1, + [this, self, parentCount](CoreObject*) { // Object being destroyed, notify all recipients std::lock_guard lk(m_stateBlock->m_lock); @@ -244,7 +244,7 @@ void CoreContext::AddInternal(const ObjectTraits& traits) { auto q = m_typeMemos.find(traits.actual_type); if(q != m_typeMemos.end()) { auto& v = q->second; - if(*v.m_value == traits.pObject) + if(*v.m_value == traits.pCoreObject) throw std::runtime_error("An attempt was made to add the same value to the same context more than once"); if(*v.m_value) throw std::runtime_error("An attempt was made to add the same type to the same context more than once"); @@ -274,7 +274,7 @@ void CoreContext::AddInternal(const ObjectTraits& traits) { // Event receivers: if(traits.receivesEvents) { - JunctionBoxEntry entry(this, traits.pObject); + JunctionBoxEntry entry(this, traits.pCoreObject); // Add to our vector of local receivers first: (std::lock_guard)m_stateBlock->m_lock, @@ -760,7 +760,7 @@ void CoreContext::UpdateDeferredElements(std::unique_lock&& lk, cons // Determine whether the current candidate element satisfies the autowiring we are considering. // This is done internally via a dynamic cast on the interface type for which this polymorphic // base type was constructed. - if(!value.m_value->try_assign(entry.pObject)) + if(!value.m_value->try_assign(entry.pCoreObject)) continue; // Success, assign the traits @@ -818,7 +818,7 @@ void CoreContext::UpdateDeferredElements(std::unique_lock&& lk, cons cur.first->Finalize(cur.second); } -void CoreContext::AddEventReceiver(const JunctionBoxEntry& entry) { +void CoreContext::AddEventReceiver(const JunctionBoxEntry& entry) { { std::lock_guard lk(m_stateBlock->m_lock); @@ -869,7 +869,7 @@ void CoreContext::RemoveEventReceivers(const t_rcvrSet& receivers) { m_pParent->RemoveEventReceivers(receivers); } -void CoreContext::UnsnoopEvents(Object* oSnooper, const JunctionBoxEntry& receiver) { +void CoreContext::UnsnoopEvents(CoreObject* oSnooper, const JunctionBoxEntry& receiver) { { std::lock_guard lk(m_stateBlock->m_lock); if( @@ -924,7 +924,7 @@ void CoreContext::FilterException(void) { throw; } -void CoreContext::FilterFiringException(const JunctionBoxBase* pProxy, Object* pRecipient) { +void CoreContext::FilterFiringException(const JunctionBoxBase* pProxy, CoreObject* pRecipient) { // Filter in order: for(CoreContext* pCur = this; pCur; pCur = pCur->GetParentContext().get()) for(ExceptionFilter* filter : pCur->m_filters) { @@ -954,12 +954,12 @@ void CoreContext::AddDeferredUnsafe(DeferrableAutowiring* deferrable) { entry.pFirst = deferrable; } -void CoreContext::InsertSnooper(std::shared_ptr snooper) { +void CoreContext::InsertSnooper(std::shared_ptr snooper) { (std::lock_guard)m_stateBlock->m_lock, m_snoopers.insert(snooper.get()); } -void CoreContext::RemoveSnooper(std::shared_ptr snooper) { +void CoreContext::RemoveSnooper(std::shared_ptr snooper) { (std::lock_guard)m_stateBlock->m_lock, m_snoopers.erase(snooper.get()); } @@ -1038,7 +1038,7 @@ void CoreContext::UnsnoopAutoPacket(const ObjectTraits& traits) { // If the passed value is currently a snooper, then the caller has snooped a context and also // one of its parents. End here. - if ( m_snoopers.count(traits.pObject.get()) ) + if ( m_snoopers.count(traits.pCoreObject.get()) ) return; } diff --git a/src/autowiring/Object.cpp b/src/autowiring/CoreObject.cpp similarity index 50% rename from src/autowiring/Object.cpp rename to src/autowiring/CoreObject.cpp index 462cd157f..212628d45 100644 --- a/src/autowiring/Object.cpp +++ b/src/autowiring/CoreObject.cpp @@ -1,7 +1,7 @@ // Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved. #include "stdafx.h" -#include "Object.h" +#include "CoreObject.h" -Object::Object(void) {} +CoreObject::CoreObject(void){} -Object::~Object(void) {} +CoreObject::~CoreObject(void){} diff --git a/src/autowiring/CoreRunnable.cpp b/src/autowiring/CoreRunnable.cpp index 101351e91..dbcb42b6f 100644 --- a/src/autowiring/CoreRunnable.cpp +++ b/src/autowiring/CoreRunnable.cpp @@ -13,11 +13,11 @@ CoreRunnable::CoreRunnable(void): CoreRunnable::~CoreRunnable(void) {} -const std::shared_ptr& CoreRunnable::GetOutstanding(void) const { +const std::shared_ptr& CoreRunnable::GetOutstanding(void) const { return m_outstanding; } -bool CoreRunnable::Start(std::shared_ptr outstanding) { +bool CoreRunnable::Start(std::shared_ptr outstanding) { std::lock_guard lk(m_lock); if(m_wasStarted || m_outstanding || m_shouldStop) // We have already been started or stopped, end here @@ -46,7 +46,7 @@ void CoreRunnable::Stop(bool graceful) { } if (m_outstanding) { - std::shared_ptr outstanding; + std::shared_ptr outstanding; std::lock_guard lk(m_lock); // Ensure we do not invoke the outstanding count dtor while holding a lock diff --git a/src/autowiring/CoreThread.cpp b/src/autowiring/CoreThread.cpp index 8073c8852..3f748494d 100644 --- a/src/autowiring/CoreThread.cpp +++ b/src/autowiring/CoreThread.cpp @@ -10,7 +10,7 @@ CoreThread::CoreThread(const char* pName): CoreThread::~CoreThread(void){} -void CoreThread::DoRunLoopCleanup(std::shared_ptr&& ctxt, std::shared_ptr&& refTracker) { +void CoreThread::DoRunLoopCleanup(std::shared_ptr&& ctxt, std::shared_ptr&& refTracker) { try { // If we are asked to rundown while we still have elements in our dispatch queue, // we must try to process them: diff --git a/src/autowiring/JunctionBoxBase.cpp b/src/autowiring/JunctionBoxBase.cpp index aebbf1703..84bd743a1 100644 --- a/src/autowiring/JunctionBoxBase.cpp +++ b/src/autowiring/JunctionBoxBase.cpp @@ -15,7 +15,7 @@ void JunctionBoxBase::TerminateAll(const std::list>& } void JunctionBoxBase::FilterFiringException(const AnySharedPointer& pRecipient) const { - std::shared_ptr obj = *pRecipient; + std::shared_ptr obj = *pRecipient; // Obtain the current context and pass control: CoreContext::CurrentContext()->FilterFiringException(this, obj.get()); diff --git a/src/autowiring/JunctionBoxManager.cpp b/src/autowiring/JunctionBoxManager.cpp index 66a19e340..d955247db 100644 --- a/src/autowiring/JunctionBoxManager.cpp +++ b/src/autowiring/JunctionBoxManager.cpp @@ -36,13 +36,13 @@ void JunctionBoxManager::Initiate(void) { q.second->Initiate(); } -void JunctionBoxManager::AddEventReceiver(JunctionBoxEntry receiver) { +void JunctionBoxManager::AddEventReceiver(JunctionBoxEntry receiver) { // Notify all junctionboxes that there is a new event for(const auto& q: m_junctionBoxes) q.second->Add(receiver); } -void JunctionBoxManager::RemoveEventReceiver(JunctionBoxEntry receiver) { +void JunctionBoxManager::RemoveEventReceiver(JunctionBoxEntry receiver) { // Notify all compatible senders that we're going away: for(const auto& q : m_junctionBoxes) q.second->Remove(receiver); diff --git a/src/autowiring/test/ContextCleanupTest.cpp b/src/autowiring/test/ContextCleanupTest.cpp index 92dd4bf70..675a2a913 100644 --- a/src/autowiring/test/ContextCleanupTest.cpp +++ b/src/autowiring/test/ContextCleanupTest.cpp @@ -74,7 +74,7 @@ TEST_F(ContextCleanupTest, VerifyContextDtor) { AutoRequired simple; objVerifier = simple; - // Each ObjectTraits instance holds 2 strong references to SimpleObject, as Object type and as ContextMember type. + // Each ObjectTraits instance holds 2 strong references to SimpleObject, as CoreObject type and as ContextMember type. // One instance is held in CoreContext::m_concreteTypes and the other in the CoreContext::m_typeMemos. // Finally, once more reference is held by the shared_ptr inheritance of simple. EXPECT_EQ(5, objVerifier.use_count()) << "Unexpected number of references to a newly constructed object"; diff --git a/src/autowiring/test/CoreThreadTest.cpp b/src/autowiring/test/CoreThreadTest.cpp index f4f1ac9ad..685658bd5 100644 --- a/src/autowiring/test/CoreThreadTest.cpp +++ b/src/autowiring/test/CoreThreadTest.cpp @@ -60,7 +60,7 @@ TEST_F(CoreThreadTest, VerifyStartSpam) { ctxt->Initiate(); // This shouldn't cause another thread to be created: - instance->Start(std::shared_ptr((Object*) 1, [] (Object*) {})); + instance->Start(std::shared_ptr((CoreObject*) 1, [] (CoreObject*) {})); EXPECT_FALSE(instance->m_multiHit) << "Thread was run more than once unexpectedly"; } diff --git a/src/autowiring/test/DecoratorTest.cpp b/src/autowiring/test/DecoratorTest.cpp index 2b2370cbe..9feb6aed0 100644 --- a/src/autowiring/test/DecoratorTest.cpp +++ b/src/autowiring/test/DecoratorTest.cpp @@ -33,7 +33,7 @@ TEST_F(DecoratorTest, VerifyCorrectExtraction) { } TEST_F(DecoratorTest, VerifyEmptyExtraction) { - auto obj = std::make_shared(); + auto obj = std::make_shared(); // Should be possible to obtain this value and have it remain valid even after the descriptor is gone const AutoFilterDescriptorInput* v = MakeAutoFilterDescriptor(obj).GetAutoFilterInput(); diff --git a/src/autowiring/test/ExceptionFilterTest.cpp b/src/autowiring/test/ExceptionFilterTest.cpp index bdae24668..782e56541 100644 --- a/src/autowiring/test/ExceptionFilterTest.cpp +++ b/src/autowiring/test/ExceptionFilterTest.cpp @@ -71,7 +71,7 @@ class GenericFilter: } } - virtual void Filter(const JunctionBoxBase* pJunctionBox, Object* pRecipient) override { + virtual void Filter(const JunctionBoxBase* pJunctionBox, CoreObject* pRecipient) override { m_hit = true; try { throw; diff --git a/src/autowiring/test/FactoryTest.cpp b/src/autowiring/test/FactoryTest.cpp index eb3d5b8f2..70f6efdf1 100644 --- a/src/autowiring/test/FactoryTest.cpp +++ b/src/autowiring/test/FactoryTest.cpp @@ -20,7 +20,7 @@ class ClassWithIntegralCtor static_assert(!has_simple_constructor::value, "A class without a simple constructor was incorrectly identified as having one"); class ClassWithStaticNew: - public Object + public CoreObject { public: ClassWithStaticNew(bool madeByFactory = false): @@ -37,7 +37,7 @@ class ClassWithStaticNew: static_assert(has_simple_constructor::value, "Class with default-argument constructor was not correctly detected as such "); static_assert(has_static_new::value, "Class with static allocator was not correctly detected as having one"); -static_assert(!has_static_new::value, "Static New detected on a class that does not have a static New"); +static_assert(!has_static_new::value, "Static New detected on a class that does not have a static New"); TEST_F(FactoryTest, VerifyFactoryCall) { // Try to create the static new type: From 5feece7f8e72f3d34c828269d6362c5ae8af9214 Mon Sep 17 00:00:00 2001 From: Graham Tremper Date: Mon, 2 Feb 2015 18:13:21 -0800 Subject: [PATCH 15/20] typedef 'Object' until all clients of autowiring have switched to 'CoreObject' --- autowiring/CoreObject.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/autowiring/CoreObject.h b/autowiring/CoreObject.h index 29f8ce642..78e52ab9c 100644 --- a/autowiring/CoreObject.h +++ b/autowiring/CoreObject.h @@ -10,3 +10,6 @@ class CoreObject { CoreObject(void); virtual ~CoreObject(void); }; + +// Temporarily typedef to old name of 'CoreObject' until all users of Autowiring have been updated +typedef CoreObject Object; From 94c3b59da3d3b78c7d83064eb3c5bbc79d621957 Mon Sep 17 00:00:00 2001 From: Graham Tremper Date: Tue, 3 Feb 2015 11:02:44 -0800 Subject: [PATCH 16/20] Add old header name to be compatible with older versions of autowiring --- autowiring/Object.h | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 autowiring/Object.h diff --git a/autowiring/Object.h b/autowiring/Object.h new file mode 100644 index 000000000..dc19d99eb --- /dev/null +++ b/autowiring/Object.h @@ -0,0 +1,3 @@ +// Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved. +#pragma once +#include "CoreObject.h" From 09b5a97287c5e8c2c3d2ca9e5796addf9ffac518 Mon Sep 17 00:00:00 2001 From: Jason Lokerson Date: Tue, 3 Feb 2015 14:51:49 -0800 Subject: [PATCH 17/20] Adding constructor detection for speculative output types If an `AutoFilter` signature contains a by-reference output type of the form `T&`, and `T(AutoPacket&)` can be constructed, then this construction signature will be invoked instead of the default constructor, even when no default constructor exists. This provides output decorations with a way of obtaining the current packet during construction in order to provide a superior strategy for implementing new AutoFilter argument behaviors. --- autowiring/auto_arg.h | 31 +++++++++++++++++-- .../test/AutoFilterCollapseRulesTest.cpp | 26 ++++++++++++++++ 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/autowiring/auto_arg.h b/autowiring/auto_arg.h index bae8c9ca3..c95e7f1d9 100644 --- a/autowiring/auto_arg.h +++ b/autowiring/auto_arg.h @@ -88,6 +88,32 @@ class auto_arg>: public auto_arg {}; +/// +/// Construction helper for output-by-reference decoration types +/// +/// +/// If an output decoration type T has a constructor of the form T(AutoPacket&), then this constructor should +/// be invoked preferentially when T is being constructed. +/// +template::value, bool has_autofilter = std::is_constructible::value> +struct auto_arg_ctor_helper; + +template +struct auto_arg_ctor_helper { + static std::shared_ptr arg(AutoPacket& packet) { + return std::make_shared(packet); + } +}; + +template +struct auto_arg_ctor_helper { + static_assert(has_default, "Cannot speculatively construct an output argument of type T, it doesn't have any available constructors"); + + static std::shared_ptr arg(AutoPacket&) { + return std::make_shared(); + } +}; + /// /// Specialization for "T&" ~ auto_out /// @@ -114,9 +140,8 @@ class auto_arg static const bool is_multi = false; static const int tshift = 0; - template - static std::shared_ptr arg(C&) { - return std::make_shared(); + static std::shared_ptr arg(AutoPacket& packet) { + return auto_arg_ctor_helper::arg(packet); } }; diff --git a/src/autowiring/test/AutoFilterCollapseRulesTest.cpp b/src/autowiring/test/AutoFilterCollapseRulesTest.cpp index 3266590ff..7ce36aab9 100644 --- a/src/autowiring/test/AutoFilterCollapseRulesTest.cpp +++ b/src/autowiring/test/AutoFilterCollapseRulesTest.cpp @@ -181,3 +181,29 @@ TEST_F(AutoFilterCollapseRulesTest, SharedPtrNoDefaultTest) { AutoRequired factory; auto packet = factory->NewPacket(); } + +class WantsAutoPacketInput { +public: + WantsAutoPacketInput(void): + pPacket(nullptr) + {} + + WantsAutoPacketInput(AutoPacket& packet): + pPacket(&packet) + {} + + AutoPacket* pPacket; +}; + +class ConstructsWantsAutoPacketInput { +public: + void AutoFilter(AutoPacket& packet, WantsAutoPacketInput& wapi) { + ASSERT_EQ(&packet, wapi.pPacket) << "Speculatively constructed output type did not have the correct constructor overload invoked"; + } +}; + +TEST_F(AutoFilterCollapseRulesTest, CtorRequiredWPI) { + // This is enough to kick off the AutoFilter above and cause an exception, if one is going to occur + AutoRequired(); + AutoRequired()->NewPacket(); +} From dd718ee4dd6241095f6c2c00e4686e2a5a0565ac Mon Sep 17 00:00:00 2001 From: Jason Lokerson Date: Tue, 3 Feb 2015 14:59:28 -0800 Subject: [PATCH 18/20] Reduce the template instantiation depth for AutoFilter Should make it easier to understand template instantiation errors arising due to bad AutoFilter arguments. --- autowiring/AutoFilterDescriptor.h | 38 +++++++++++++-------------- autowiring/AutoPacketFactory.h | 2 +- autowiring/CallExtractor.h | 15 +++++------ autowiring/auto_tuple.h | 7 +++-- src/autowiring/test/DecoratorTest.cpp | 2 +- 5 files changed, 30 insertions(+), 34 deletions(-) diff --git a/autowiring/AutoFilterDescriptor.h b/autowiring/AutoFilterDescriptor.h index a981b05c8..ddfd2b67f 100644 --- a/autowiring/AutoFilterDescriptor.h +++ b/autowiring/AutoFilterDescriptor.h @@ -293,26 +293,24 @@ struct AutoFilterDescriptor: bool operator>=(const AutoFilterDescriptor& rhs) const { return !(*this < rhs);} }; -template::value> -class AutoFilterDescriptorSelect: - public std::true_type -{ -public: - AutoFilterDescriptorSelect(const std::shared_ptr& subscriber) : - desc(subscriber) - {} - - const AutoFilterDescriptor desc; -}; +/// +/// Utility routine to support the creation of an AutoFilterDescriptor from T::AutoFilter +/// +/// +/// This method will return an empty descriptor in the case that T::AutoFilter is not defined +/// +template +AutoFilterDescriptor MakeAutoFilterDescriptor(const std::shared_ptr& ptr) { + return MakeAutoFilterDescriptor(ptr, std::integral_constant::value>()); +} +/// +/// Alias for AutoFilterDescriptor(ptr) +/// template -class AutoFilterDescriptorSelect: - public std::false_type -{ -public: - AutoFilterDescriptorSelect(const std::shared_ptr&) {} - const AutoFilterDescriptor desc; -}; +AutoFilterDescriptor MakeAutoFilterDescriptor(const std::shared_ptr& ptr, std::true_type) { + return AutoFilterDescriptor(ptr); +} /// /// Utility routine to support the creation of an AutoFilterDescriptor from T::AutoFilter @@ -321,8 +319,8 @@ class AutoFilterDescriptorSelect: /// This method will return an empty descriptor in the case that T::AutoFilter is not defined /// template -AutoFilterDescriptor MakeAutoFilterDescriptor(const std::shared_ptr& ptr) { - return std::move(AutoFilterDescriptorSelect(ptr).desc); +AutoFilterDescriptor MakeAutoFilterDescriptor(const std::shared_ptr&, std::false_type) { + return AutoFilterDescriptor(); } namespace std { diff --git a/autowiring/AutoPacketFactory.h b/autowiring/AutoPacketFactory.h index d7b66aa2c..07fa3af59 100644 --- a/autowiring/AutoPacketFactory.h +++ b/autowiring/AutoPacketFactory.h @@ -98,7 +98,7 @@ class AutoPacketFactory: /// template void AddSubscriber(const std::shared_ptr& rhs) { - AddSubscriber(MakeAutoFilterDescriptor(rhs)); + AddSubscriber(AutoFilterDescriptor(rhs)); } /// diff --git a/autowiring/CallExtractor.h b/autowiring/CallExtractor.h index f29e417e4..fbc2e9997 100644 --- a/autowiring/CallExtractor.h +++ b/autowiring/CallExtractor.h @@ -24,12 +24,11 @@ namespace autowiring { template struct CallExtractorSetup { - CallExtractorSetup(AutoPacket& packet): + template + CallExtractorSetup(AutoPacket& packet, Ts&&... args) : packet(packet), pshr(packet.GetContext()), - args( - (auto_arg::arg(packet))... - ) + args(std::forward(args)...) {} AutoPacket& packet; @@ -70,7 +69,7 @@ struct CallExtractor>: const void* pfn = obj->ptr(); // Setup, handoff, commit - CallExtractorSetup extractor(packet); + CallExtractorSetup extractor(packet, (auto_arg::arg(packet))...); ((t_pfn)pfn)( static_cast::arg_type>(autowiring::get(extractor.args))... ); @@ -102,7 +101,7 @@ struct CallExtractor> : assert(typeid(auto_id) == obj->type()); // Extract, call, commit - CallExtractorSetup extractor(packet); + CallExtractorSetup extractor(packet, (auto_arg::arg(packet))...); (((T*) pObj)->*memFn)( static_cast::arg_type>(autowiring::get(extractor.args))... ); @@ -126,7 +125,7 @@ struct CallExtractor> : const void* pObj = obj->ptr(); // Extract, call, commit - CallExtractorSetup extractor(packet); + CallExtractorSetup extractor(packet, (auto_arg::arg(packet))...); (((const T*) pObj)->*memFn)( static_cast::arg_type>(autowiring::get(extractor.args))... ); @@ -158,7 +157,7 @@ struct CallExtractor> : *(T*) pObj += [pObj, pAutoPacket] { // Extract, call, commit - CallExtractorSetup extractor(*pAutoPacket); + CallExtractorSetup extractor(*pAutoPacket, (auto_arg::arg(*pAutoPacket))...); (((T*) pObj)->*memFn)( static_cast::arg_type>(autowiring::get(extractor.args))... ); diff --git a/autowiring/auto_tuple.h b/autowiring/auto_tuple.h index 1fe04e92c..37be3e044 100644 --- a/autowiring/auto_tuple.h +++ b/autowiring/auto_tuple.h @@ -65,10 +65,9 @@ namespace autowiring { tuple(void) = default; - template - tuple(T&& arg, Ts&&... args) : - tuple(std::forward(args)...), - tuple_value(std::forward(arg)) + tuple(Arg&& arg, Args&&... args) : + tuple(std::forward(args)...), + tuple_value(std::forward(arg)) {} template diff --git a/src/autowiring/test/DecoratorTest.cpp b/src/autowiring/test/DecoratorTest.cpp index 9feb6aed0..3ded3b1cb 100644 --- a/src/autowiring/test/DecoratorTest.cpp +++ b/src/autowiring/test/DecoratorTest.cpp @@ -22,7 +22,7 @@ TEST_F(DecoratorTest, VerifyCorrectExtraction) { // Run our prop extractor based on a known decorator: AutoRequired filterA; - AutoFilterDescriptor desc = MakeAutoFilterDescriptor(filterA); + AutoFilterDescriptor desc(static_cast&>(filterA)); for(const AutoFilterDescriptorInput* cur = desc.GetAutoFilterInput(); *cur; cur++) v.push_back(cur->ti); ASSERT_EQ(2UL, v.size()) << "Extracted an insufficient number of types from a known filter function"; From f8557c643c9b8129750303075b80e26b1ed59a99 Mon Sep 17 00:00:00 2001 From: Jason Lokerson Date: Tue, 3 Feb 2015 15:51:59 -0800 Subject: [PATCH 19/20] Bumped version number --- version.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.cmake b/version.cmake index 04842a5a3..4119f968f 100644 --- a/version.cmake +++ b/version.cmake @@ -1 +1 @@ -set(autowiring_VERSION 0.4.1) +set(autowiring_VERSION 0.4.2) From 235219b9ad24a708f2dbb1c2c88aeea2204e9af4 Mon Sep 17 00:00:00 2001 From: Graham Tremper Date: Tue, 3 Feb 2015 18:10:03 -0800 Subject: [PATCH 20/20] Add 'is_constructable' to shim --- autowiring/C++11/boost_type_traits.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/autowiring/C++11/boost_type_traits.h b/autowiring/C++11/boost_type_traits.h index 82e346f7d..dc0aa2467 100644 --- a/autowiring/C++11/boost_type_traits.h +++ b/autowiring/C++11/boost_type_traits.h @@ -53,4 +53,15 @@ namespace std { { typedef _Type type; }; + + template + struct is_constructible { + template + static std::true_type select(decltype(U(*static_cast::type*>(nullptr)...))*); + + template + static std::false_type select(...); + + static const bool value = decltype(select(static_cast(nullptr)))::value; + }; }