Skip to content

Commit

Permalink
Eliminate is_shared from DecorationKey
Browse files Browse the repository at this point in the history
This variable being present here prevents proper accumulation of multidecorate values and makes it harder to understand what's going on.  Centralize the behavior and make use of trait properties when deciding whether a filter should be called.
  • Loading branch information
codemercenary committed Jun 11, 2015
1 parent b780497 commit b93518f
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 142 deletions.
37 changes: 15 additions & 22 deletions autowiring/AutoPacket.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ class AutoPacket:
/// A satisfaction pulse will call any AutoFilter instances which are satisfied by the
/// decoration of the passed decoration types.
/// </remarks>
void PulseSatisfaction(DecorationDisposition* pTypeSubs[], size_t nInfos);
void PulseSatisfactionUnsafe(std::unique_lock<std::mutex> lk, DecorationDisposition* pTypeSubs [], size_t nInfos);

/// <summary>Unsynchronized runtime counterpart to Has</summary>
bool HasUnsafe(const DecorationKey& key) const;
Expand Down Expand Up @@ -189,7 +189,7 @@ class AutoPacket:
template<class T>
bool Has(int tshift=0) const {
std::lock_guard<std::mutex> lk(m_lock);
return HasUnsafe(DecorationKey(auto_id<T>::key(), true, tshift));
return HasUnsafe(DecorationKey(auto_id<T>::key(), tshift));
}

/// <summary>
Expand All @@ -201,7 +201,7 @@ class AutoPacket:

const T* retVal;
if (!Get(retVal, tshift))
ThrowNotDecoratedException(DecorationKey(auto_id<T>::key(), false, tshift));
ThrowNotDecoratedException(DecorationKey(auto_id<T>::key(), tshift));
return *retVal;
}

Expand All @@ -214,7 +214,7 @@ class AutoPacket:
/// </remarks>
template<class T>
bool Get(const T*& out, int tshift=0) const {
DecorationKey key(auto_id<T>::key(), false, tshift);
DecorationKey key(auto_id<T>::key(), tshift);
const DecorationDisposition* pDisposition = GetDisposition(key);
if (pDisposition) {
switch (pDisposition->m_decorations.size()) {
Expand Down Expand Up @@ -254,7 +254,7 @@ class AutoPacket:
template<class T>
bool Get(const std::shared_ptr<const T>*& out, int tshift=0) const {
// Decoration must be present and the shared pointer itself must also be present
DecorationKey key(auto_id<T>::key(), true, tshift);
DecorationKey key(auto_id<T>::key(), tshift);
const DecorationDisposition* pDisposition = GetDisposition(key);
if (!pDisposition) {
out = nullptr;
Expand Down Expand Up @@ -317,7 +317,7 @@ class AutoPacket:
template<class T>
const T** GetAll(int tshift = 0) const {
std::lock_guard<std::mutex> lk(m_lock);
auto q = m_decorations.find(DecorationKey(auto_id<T>::key(), true, tshift));
auto q = m_decorations.find(DecorationKey(auto_id<T>::key(), tshift));

// If decoration doesn't exist, return empty null-terminated buffer
if (q == m_decorations.end()) {
Expand Down Expand Up @@ -354,8 +354,7 @@ class AutoPacket:
/// </remarks>
template<class T>
void Unsatisfiable(void) {
MarkUnsatisfiable(DecorationKey(auto_id<T>::key(), false, 0));
MarkUnsatisfiable(DecorationKey(auto_id<T>::key(), true, 0));
MarkUnsatisfiable(DecorationKey(auto_id<T>::key(), 0));
}

/// <summary>
Expand All @@ -372,7 +371,7 @@ class AutoPacket:
auto ptr = std::make_shared<T>(std::forward<T&&>(t));
Decorate(
AnySharedPointer(ptr),
DecorationKey(auto_id<T>::key(), true, 0)
DecorationKey(auto_id<T>::key(), 0)
);
return *ptr;
}
Expand All @@ -388,7 +387,7 @@ class AutoPacket:
/// </remarks>
template<class T>
void Decorate(std::shared_ptr<T> ptr) {
DecorationKey key(auto_id<T>::key(), true, 0);
DecorationKey key(auto_id<T>::key(), 0);

// We don't want to see this overload used on a const T
static_assert(!std::is_const<T>::value, "Cannot decorate a shared pointer to const T with this overload");
Expand Down Expand Up @@ -438,11 +437,9 @@ class AutoPacket:
// Perform standard decoration with a short initialization:
std::unique_lock<std::mutex> lk(m_lock);
DecorationDisposition* pTypeSubs[1 + sizeof...(Ts)] = {
&DecorateImmediateUnsafe(DecorationKey(auto_id<T>::key(), false, 0), &immed),
&DecorateImmediateUnsafe(DecorationKey(auto_id<Ts>::key(), false, 0), &immeds)...
&DecorateImmediateUnsafe(DecorationKey(auto_id<T>::key(), 0), &immed),
&DecorateImmediateUnsafe(DecorationKey(auto_id<Ts>::key(), 0), &immeds)...
};
lk.unlock();


// Pulse satisfaction:
MakeAtExit([this, &pTypeSubs] {
Expand All @@ -454,12 +451,10 @@ class AutoPacket:
}

// Now trigger a rescan to hit any deferred, unsatisfiable entries:
for (const std::type_info* ti : {&auto_id<T>::key(), &auto_id<Ts>::key()...}) {
MarkUnsatisfiable(DecorationKey(*ti, true, 0));
MarkUnsatisfiable(DecorationKey(*ti, false, 0));
}
for (const std::type_info* ti : {&auto_id<T>::key(), &auto_id<Ts>::key()...})
MarkUnsatisfiable(DecorationKey(*ti, 0));
}),
PulseSatisfaction(pTypeSubs, 1 + sizeof...(Ts));
PulseSatisfactionUnsafe(std::move(lk), pTypeSubs, 1 + sizeof...(Ts));
}

/// <summary>
Expand Down Expand Up @@ -512,9 +507,7 @@ class AutoPacket:
/// <returns>True if the indicated type has been requested for use by some consumer</returns>
template<class T>
bool HasSubscribers(void) const {
return
HasSubscribers(DecorationKey(auto_id<T>::key(), false, 0)) ||
HasSubscribers(DecorationKey(auto_id<T>::key(), true, 0));
return HasSubscribers(DecorationKey(auto_id<T>::key(), 0));
}

struct SignalStub {
Expand Down
37 changes: 21 additions & 16 deletions autowiring/DecorationDisposition.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,39 +13,31 @@ struct DecorationKey {

DecorationKey(const DecorationKey& rhs) :
ti(rhs.ti),
is_shared(rhs.is_shared),
tshift(rhs.tshift)
{}

explicit DecorationKey(const std::type_info& ti, bool is_shared, int tshift) :
explicit DecorationKey(const std::type_info& ti, int tshift) :
ti(&ti),
is_shared(is_shared),
tshift(tshift)
{}

// The type index
const std::type_info* ti = nullptr;

// True if this decoration can be used with AutoFilters that accept a shared_ptr input type
bool is_shared = false;

// Zero refers to a decoration created on this packet, a positive number [tshift] indicates
// a decoration attached [tshift] packets ago.
int tshift = -1;

bool operator==(const DecorationKey& rhs) const {
return ti == rhs.ti && is_shared == rhs.is_shared && tshift == rhs.tshift;
return ti == rhs.ti && tshift == rhs.tshift;
}
};

namespace std {
template<>
struct hash<DecorationKey> {
size_t operator()(const DecorationKey& key) const {
return
key.tshift +
(key.is_shared ? 0x80000 : 0x70000) +
key.ti->hash_code();
return key.tshift + key.ti->hash_code();
}
};
}
Expand All @@ -61,10 +53,6 @@ enum class DispositionState {
// Everything attached, ready to go
Satisfied,

// Unsatisfiable, and the callers on this decoration cannot accept a non-null
// entry--IE, they accept const references as inputs.
UnsatisfiableNoCall,

// This decoration will never be satisfied. Calls are generated with a null
// shared pointer passed as the value.
Unsatisfiable
Expand Down Expand Up @@ -100,7 +88,24 @@ struct DecorationDisposition
std::vector<SatCounter*> m_publishers;

// Satisfaction counters
std::vector<SatCounter*> m_subscribers;
struct Subscriber {
Subscriber(void) {}

Subscriber(bool is_optional, SatCounter* satCounter):
is_optional{is_optional},
satCounter{satCounter}
{}

// Optional flag. If this flag is set, it indicates that the referenced AutoFilter could still
// be called even if the decoration is not attached to the packet--IE, the AutoFilter accepts a
// shared pointer or an array
bool is_optional = false;

// The satisfaction counter itself
SatCounter* satCounter = nullptr;
};

std::vector<Subscriber> m_subscribers;

// The current state of this disposition
DispositionState m_state = DispositionState::Unsatisfied;
Expand Down
Loading

0 comments on commit b93518f

Please sign in to comment.