Skip to content

Commit

Permalink
Implemented unsafe solution.
Browse files Browse the repository at this point in the history
FIXME: There is a race condition in Autowire.
PROBLEM: If the desired context member is added between the FindByTypeRecursive and AddDeferred calls then the notification will not be satisfied.
  • Loading branch information
Gabriel Hare committed Aug 22, 2014
1 parent 97f0e62 commit 451f5c8
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 2 deletions.
19 changes: 17 additions & 2 deletions autowiring/CoreContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ class CoreContext:
// This is a list of concrete types, indexed by the true type of each element.
std::vector<AnySharedPointer> m_concreteTypes;

// This is a memoization map used to memoize any already-detected interfaces. The map
// This is a memoization map used to memoize any already-detected interfaces.
mutable std::unordered_map<std::type_index, MemoEntry> m_typeMemos;

// All known context members, exception filters:
Expand Down Expand Up @@ -871,6 +871,10 @@ class CoreContext:
/// </summary>
template<class T>
bool Autowire(AutowirableSlot<T>& slot) {
// FIXME: This is subject to a race condition!
// If the desired member is added between FindByTypeRecursive
// and AddDeferred it will never be wired!

if(FindByTypeRecursive(slot))
return true;

Expand All @@ -883,7 +887,8 @@ class CoreContext:
/// Adds a post-attachment listener in this context for a particular autowired member
/// </summary>
/// <returns>
/// A pointer to a deferrable autowiring function which the caller may safely ignore if it's not needed
/// A pointer to a deferrable autowiring function which the caller may safely ignore if it's not needed.
/// Returns nullptr if the call was made immediately.
/// </returns>
/// <remarks>
/// This method will succeed if slot was constructed in this context or any parent context. If the
Expand All @@ -902,6 +907,16 @@ class CoreContext:
/// </remarks>
template<class T, class Fn>
const AutowirableSlotFn<T, Fn>* NotifyWhenAutowired(Fn&& listener) {
/// GOAL: Check for satisfaction, return if satisfied, defer if not.
/// PROBLEM: UpdateDeferredElements only applies to NEW members.
/// PROBLEM: This needs to occur in a single atomic sequence.

std::shared_ptr<T> slot;
if (FindByTypeRecursive(slot)) {
listener();
return nullptr;
}

auto retVal = MakeAutowirableSlotFn<T>(
shared_from_this(),
std::forward<Fn>(listener)
Expand Down
3 changes: 3 additions & 0 deletions src/autowiring/CoreContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,9 @@ void CoreContext::BuildCurrentState(void) {
}

void CoreContext::CancelAutowiringNotification(DeferrableAutowiring* pDeferrable) {
if (!pDeferrable)
return;

std::lock_guard<std::mutex> lk(m_stateBlock->m_lock);
auto q = m_typeMemos.find(pDeferrable->GetType());
if(q == m_typeMemos.end())
Expand Down

0 comments on commit 451f5c8

Please sign in to comment.