Skip to content

Commit

Permalink
AutoPacket has Reset, Initialize and Finalize methods. Now, all tests…
Browse files Browse the repository at this point in the history
… pass.
  • Loading branch information
GabrielHare committed Jul 30, 2014
1 parent eaa554e commit 5ccee33
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 41 deletions.
37 changes: 33 additions & 4 deletions autowiring/AutoPacket.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
#include STL_UNORDERED_MAP
#include EXCEPTION_PTR_HEADER

struct SatCounter;
class AutoPacketFactory;
class AutoPacketProfiler;
struct AutoFilterDescriptor;
Expand Down Expand Up @@ -58,15 +57,45 @@ class AutoPacket:
t_decorationMap m_decorations;

/// <summary>
/// Last change call with unsatisfied optional arguments
/// Resets satisfaction counters and decoration status.
/// </summary>
void ResolveOptions(void);
/// <remarks>
/// Is it expected that AutoPacketFactory will call methods in the following order:
/// AutoPacket(); //Construction in ObjectPool
/// Initialize(); //Issued from ObjectPool
/// Decorate();
/// ... //More Decorate calls
/// Finalize(); //Returned to ObjectPool
/// Initialize();
/// ... //More Issue & Return cycles
/// ~AutoPacket(); //Destruction in ObjectPool
/// Reset() must be called before the body of Initialize() in order to begin in the
/// correct state. It must also be called after the body of Finalize() in order to
/// avoid holding shared_ptr references.
/// Therefore Reset() is called at the conclusion of both AutoPacket() and Finalize().
/// </remarks>
void Reset(void);

/// <summary>
/// Resets counters, then decrements subscribers requiring AutoPacket argument.
/// Decrements subscribers requiring AutoPacket argument then calls all initializing subscribers.
/// </summary>
/// <remarks>
/// Initialize is called when a packet is issued by the AutoPacketFactory.
/// It is not called when the Packet is created since that could result in
/// spurious calls when no packet is issued.
/// </remarks>
void Initialize(void);

/// <summary>
/// Last chance call with unsatisfied optional arguments.
/// </summary>
/// <remarks>
/// This is called when the packet is returned to the AutoPacketFactory.
/// It is not called when the Packet is destroyed, since that could result in
/// suprious calles when no packet is issued.
/// </remarks>
void Finalize(void);

/// <summary>
/// Marks the specified entry as being unsatisfiable
/// </summary>
Expand Down
73 changes: 36 additions & 37 deletions src/autowiring/AutoPacket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include "SatCounter.h"
#include <list>

#include <iostream>

AutoPacket::AutoPacket(AutoPacketFactory& factory)
{
// Traverse all contexts, adding their packet subscriber vectors one at a time:
Expand Down Expand Up @@ -52,46 +54,23 @@ AutoPacket::AutoPacket(AutoPacketFactory& factory)
}
}

// Invoke any output-only AutoFilter routines
Initialize();
Reset();
}

AutoPacket::~AutoPacket() {
// Last chance for AutoFilter call
ResolveOptions();
}
// This must appear in .cpp in order to avoid compilation failure due to:
// "Arithmetic on a point to an incomplete type 'SatCounter'"
AutoPacket::~AutoPacket() {}

ObjectPool<AutoPacket> AutoPacket::CreateObjectPool(AutoPacketFactory& factory) {
return ObjectPool<AutoPacket>(
~0,
~0,
[&factory] { return new AutoPacket(factory); },
[] (AutoPacket& packet) {
// Last chance for AutoFilter optional calls
packet.ResolveOptions();

// Reinitialize the whole packet:
packet.Initialize();
}
[] (AutoPacket& packet) { packet.Initialize(); },
[] (AutoPacket& packet) { packet.Finalize(); }
);
}

void AutoPacket::ResolveOptions(void) {
// Queue calls to ensure that calls to Decorate inside of AutoFilter methods
// will NOT effect the resolution of optional arguments.
std::list<SatCounter*> callQueue;
{
std::lock_guard<std::mutex> lk(m_lock);
for(auto& decoration : m_decorations)
for(auto& satCounter : decoration.second.m_subscribers)
if(!satCounter.second)
if(satCounter.first->Resolve())
callQueue.push_back(satCounter.first);
}
for (SatCounter* call : callQueue)
call->CallAutoFilter(*this);
}

void AutoPacket::MarkUnsatisfiable(const std::type_info& info) {
DecorationDisposition* decoration;
{
Expand Down Expand Up @@ -165,16 +144,18 @@ void AutoPacket::PulseSatisfaction(DecorationDisposition* pTypeSubs[], size_t nI
}
}

void AutoPacket::Initialize(void) {
void AutoPacket::Reset(void) {
// Initialize all counters:
{
std::lock_guard<std::mutex> lk(m_lock);
for(auto& satCounter : m_satCounters)
satCounter.Reset();
for(auto& decoration : m_decorations)
decoration.second.Reset();
}
std::lock_guard<std::mutex> lk(m_lock);
for(auto& satCounter : m_satCounters)
satCounter.Reset();

// Clear all references:
for(auto& decoration : m_decorations)
decoration.second.Reset();
}

void AutoPacket::Initialize(void) {
// Find all subscribers with no required or optional arguments:
std::list<SatCounter*> callCounters;
for (auto& satCounter : m_satCounters)
Expand All @@ -190,6 +171,24 @@ void AutoPacket::Initialize(void) {
UpdateSatisfaction(typeid(AutoPacket));
}

void AutoPacket::Finalize(void) {
// Queue calls to ensure that calls to Decorate inside of AutoFilter methods
// will NOT effect the resolution of optional arguments.
std::list<SatCounter*> callQueue;
{
std::lock_guard<std::mutex> lk(m_lock);
for(auto& decoration : m_decorations)
for(auto& satCounter : decoration.second.m_subscribers)
if(!satCounter.second)
if(satCounter.first->Resolve())
callQueue.push_back(satCounter.first);
}
for (SatCounter* call : callQueue)
call->CallAutoFilter(*this);

Reset();
}

bool AutoPacket::HasSubscribers(const std::type_info& ti) const {
return m_decorations.count(ti) != 0;
}

0 comments on commit 5ccee33

Please sign in to comment.