Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
codemercenary committed Dec 2, 2014
2 parents 59066de + fa28796 commit b079fdf
Show file tree
Hide file tree
Showing 17 changed files with 214 additions and 151 deletions.
1 change: 1 addition & 0 deletions autowiring/AnySharedPointer.h
Expand Up @@ -5,6 +5,7 @@
struct AnySharedPointer {
public:
AnySharedPointer(void);
AnySharedPointer(AnySharedPointer&& rhs);
explicit AnySharedPointer(const AnySharedPointer& rhs);

template<class T>
Expand Down
8 changes: 7 additions & 1 deletion autowiring/AutoFilterDescriptor.h
Expand Up @@ -278,7 +278,13 @@ struct AutoFilterDescriptor:
template<class T>
AutoFilterDescriptor(const std::shared_ptr<T>& subscriber) :
AutoFilterDescriptor(
AnySharedPointer(subscriber),
AnySharedPointer(
// Because T::AutoFilter might actually be present in a _base type_ of T, it's important that
// AnySharedPointer be instantiated with a pointer to the base type where the AutoFilter is
// actually defined. In order to obtain this name, we decompose this member function, and
// then take the type of the decomposed result.
std::static_pointer_cast<typename Decompose<decltype(&T::AutoFilter)>::type>(subscriber)
),
&typeid(T),
Decompose<decltype(&T::AutoFilter)>::template Enumerate<AutoFilterDescriptorInput>::types,
CallExtractor<decltype(&T::AutoFilter)>::deferred,
Expand Down
2 changes: 1 addition & 1 deletion autowiring/CallExtractor.h
Expand Up @@ -56,7 +56,7 @@ struct CallExtractor<void (T::*)(Args...)>:
// This exception type indicates that an attempt was made to construct an AutoFilterDescriptor with an
// AnySharedPointer which was not the type of its own member function. Be sure to cast the AnySharedPointer
// to the correct foundation type before attempting to construct an AutoFilterDescriptor.
assert(typeid(typename SelectTypeUnifier<T>::type) == obj->type());
assert(typeid(T) == obj->type());

// Handoff
(((T*) pObj)->*memFn)(
Expand Down
4 changes: 2 additions & 2 deletions autowiring/CoreContext.h
Expand Up @@ -494,7 +494,7 @@ class CoreContext:
std::shared_ptr<typename CreationRules::TActual> retVal;
FindByType(retVal);
if(retVal)
return retVal;
return std::static_pointer_cast<T>(retVal);

// We must make ourselves current for the remainder of this call:
CurrentContextPusher pshr(shared_from_this());
Expand All @@ -519,7 +519,7 @@ class CoreContext:
// Factory registration if sensible to do so, but only after the underlying type has been
// added, so that the proper type can succeed
RegisterFactory(*retVal, autowiring::member_new_type<typename CreationRules::TActual>());
return retVal;
return std::static_pointer_cast<T>(retVal);
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion autowiring/CreationRules.h
Expand Up @@ -122,7 +122,7 @@ struct crh<construction_strategy::standard, T, Args...> {
return ::new (pSpace) TActual(std::forward<Args>(args)...);
}
catch(...) {
// Don't want memory leaks--but we also want to avoid calling the destructor, here, so we cast to void before freeing
// Use our free method, which will correctly invoke the deallocator for this space
Free<TActual>(pSpace, nullptr);
throw;
}
Expand Down
100 changes: 48 additions & 52 deletions autowiring/DeclareElseFilter.h
@@ -1,32 +1,65 @@
// Copyright (C) 2012-2014 Leap Motion, Inc. All rights reserved.
#pragma once

#include "ContextMember.h"
#include "DeclareElseFilter.h"
#include "SatCounter.h"

/// <summary>If Base::AutoFilter is not called, this will execute a Final-Call method</summary>
template<class>
class MicroElseFilter
template<class Base, class... Args>
class MicroElseFilter;

/// <summary>
/// Zero-argument specialization
/// </summary>
template<class Base>
class MicroElseFilter<Base> :
public ContextMember
{
public:
MicroElseFilter(Base* base, void (Base::*filter)(const AutoPacket&)) :
ContextMember("MicroElseFilter"),
base(base),
filter(filter)
{}

protected:
const std::type_info& type;
std::function<void(const AutoPacket&)> m_filter;
Base* base;
void (Base::*filter)(const AutoPacket&);
};

/// <summary>If Base::AutoFilter is not called, this will execute a Final-Call method</summary>
template<class Base, class Arg, class... Args>
class MicroElseFilter<Base, Arg, Args...>:
public MicroElseFilter<Base>
{
public:
MicroElseFilter(const std::type_info& type, const std::function<void(const AutoPacket&)>& filter):
type(type),
m_filter(filter)
MicroElseFilter(Base* base, void (Base::*filter)(const AutoPacket&)) :
MicroElseFilter<Base>(base, filter)
{}

void AutoFilter(const AutoPacket& packet) {
if(packet.GetSatisfaction(type).called) {
/// Base::AutoFilter has already been called for this packet
return;
}
m_filter(packet);
const bool has_all[] = {packet.Has<Arg>(), packet.Has<Args>()... };

for(bool cur : has_all)
if(!cur) {
// Missing decoration, base filter wasn't called
(this->base->*(this->filter))(packet);
return;
}

/// Base::AutoFilter has already been called for this packet
}
};

/// <summary>
/// Creates a MicroElseFilter to be called when the specified AutoFilter routine is not called
/// </summary>
/// <param name="testFilter">The filter whose state is to be tested when determining whether to call</param>
template<class Test, class Base, class... Args>
std::shared_ptr<MicroElseFilter<Base>> DeclareElseFilter(void(Test::*testFilter)(Args...), Base* that, void (Base::*filter)(const AutoPacket&)) {
AutoCurrentContext ctxt;
return ctxt->template Inject<MicroElseFilter<Base, Args...>>(that, filter);
}

/// <summary>
/// Creates a MicroElseFilter class that will call the method provided in the constructor
/// if and only if Base::AutoFilter has not been called.
Expand All @@ -37,42 +70,5 @@ class MicroElseFilter
/// </remarks>
template<class Base>
std::shared_ptr<MicroElseFilter<Base>> DeclareElseFilter(Base* that, void (Base::*filter)(const AutoPacket&)) {
typedef typename SelectTypeUnifier<Base>::type t_repType;

return AutoCurrentContext()->template Inject<MicroElseFilter<Base>>(
typeid(t_repType),
[that, filter] (const AutoPacket& packet) {
return (that->*filter)(packet);
}
);
}

/// <summary>
/// Specialization for the case where the AutoFilter method is registered using DeclareAutoFilter
/// </summary>
/// <remarks>
/// In the constructor of a class that will be Injected into a context call this function as:
/// DeclareElseFilter<Base, Next>(this, &MyClass::ElseNextFilter)
/// where m_NextFilter is a shared pointer to the BasedAutoFilter instance.
/// </remarks>
template<class Base, class Next>
std::shared_ptr<MicroElseFilter<Next>> DeclareElseFilter(
Base* that,
void (Base::*filter)(const AutoPacket&)
)
{
// If this type will use a unifier, we need to declare the else filter on the unifier type,
// not the represented type, because the unifier type will be the actual true type of the
// class in the context.
// TODO: The fact that this is necessary implies that the concept of an else-filter based
// on whether an AutoFilter declared on a particular type may be ill-formed; it might be
// necessary to revisit this concept and instead declare a contingent filter piecewise in
// terms of its input arguments rather than in terms of another filter entry.
typedef typename SelectTypeUnifier<Base>::type t_repType;
return AutoCurrentContext()->template Inject<MicroElseFilter<Next>>(
typeid(t_repType),
[that, filter] (const AutoPacket& packet) {
return (that->*filter)(packet);
}
);
return DeclareElseFilter(&Base::AutoFilter, that, filter);
}
20 changes: 15 additions & 5 deletions autowiring/MicroAutoFilter.h
@@ -1,6 +1,6 @@
// Copyright (C) 2012-2014 Leap Motion, Inc. All rights reserved.
#pragma once

#include "ContextMember.h"
#include "Deferred.h"
#include FUNCTIONAL_HEADER

Expand All @@ -12,15 +12,22 @@
/// The default constructor yields an AutoFilter that does nothing.
/// </remarks>
template<class Ret, class... Args>
struct MicroAutoFilter {
MicroAutoFilter(const std::function<void(Args...)>&&) {}
struct MicroAutoFilter:
public ContextMember
{
MicroAutoFilter(const std::function<void(Args...)>&&):
ContextMember("MicroAutoFilter")
{}

// This AutoFilter method will be identified as invalid due to the return type
Ret AutoFilter(Args...) {}
};
template<class... Args>
struct MicroAutoFilter<void, Args...> {
struct MicroAutoFilter<void, Args...>:
public ContextMember
{
MicroAutoFilter(const std::function<void(Args...)>&& filter):
ContextMember("MicroAutoFilter"),
m_filter(std::move(filter))
{}

Expand All @@ -34,8 +41,11 @@ struct MicroAutoFilter<void, Args...> {
};

template<class... Args>
struct MicroAutoFilter<Deferred, Args...> {
struct MicroAutoFilter<Deferred, Args...> :
public ContextMember
{
MicroAutoFilter(const std::function<void(Args...)>&& filter):
ContextMember("MicroAutoFilter"),
m_filter(std::move(filter))
{}

Expand Down

0 comments on commit b079fdf

Please sign in to comment.