23 KiB
23 KiB
PHASE 3: SAFE REFERENCES INTEGRATION - DETAILED IMPLEMENTATION SUBPLAN
Executive Summary
Duration: 80-100 hours (2-3 weeks) Team Size: 6-8 specialized agents Primary Goal: Replace all raw pointers with safe, validated references Critical Issues Addressed: #4 (logout crash), memory safety, dangling pointers
Phase 3 Architecture Overview
Core Components
References/
├── SafeObjectReference.h/cpp (550 lines) - Core reference wrapper
├── ReferenceValidator.h/cpp (450 lines) - Validation engine
├── ReferenceCache.h/cpp (600 lines) - Performance optimization
├── ReferenceTracking.h/cpp (400 lines) - Lifetime tracking
├── WeakReference.h/cpp (300 lines) - Non-owning references
├── ReferencePool.h/cpp (350 lines) - Memory pooling
├── ReferenceDebugger.h/cpp (250 lines) - Debug utilities
└── tests/ (3000+ lines) - Comprehensive testing
Detailed Task Breakdown
Task 3.1: Safe Reference Architecture Design
Duration: 10 hours Assigned Agents:
- Primary: cpp-architecture-optimizer (memory patterns)
- Support: concurrency-threading-specialist (thread safety)
- Review: database-optimizer (cache design) Dependencies: Phase 2 complete Deliverables:
// SafeObjectReference.h
template<typename T>
class SafeObjectReference {
public:
using ObjectType = T;
using GuidType = ObjectGuid;
using ValidationFunc = std::function<bool(const T*)>;
// Construction
SafeObjectReference() = default;
explicit SafeObjectReference(ObjectGuid guid);
explicit SafeObjectReference(T* object);
// Access
T* operator->() const { return Get(); }
T& operator*() const { return *Get(); }
T* Get() const;
T* GetIfValid() const;
// Validation
bool IsValid() const;
bool IsExpired() const;
void Refresh();
// Comparison
bool operator==(const SafeObjectReference& other) const;
explicit operator bool() const { return IsValid(); }
// Metadata
ObjectGuid GetGuid() const { return m_guid; }
std::chrono::steady_clock::time_point GetLastValidation() const;
uint32_t GetAccessCount() const { return m_accessCount; }
private:
ObjectGuid m_guid;
mutable std::weak_ptr<T> m_cachedPtr;
mutable std::chrono::steady_clock::time_point m_lastValidation;
mutable std::atomic<uint32_t> m_accessCount{0};
mutable std::shared_mutex m_mutex;
// Validation
T* ValidateAndGet() const;
bool ValidateGuid() const;
void UpdateCache(T* object) const;
};
// Specializations for common types
using SafePlayerRef = SafeObjectReference<Player>;
using SafeCreatureRef = SafeObjectReference<Creature>;
using SafeGroupRef = SafeObjectReference<Group>;
using SafeBotRef = SafeObjectReference<Bot>;
Task 3.2: Reference Validator Implementation
Duration: 12 hours Assigned Agents:
- Primary: cpp-server-debugger (validation logic)
- Support: trinity-integration-tester (game object validation) Dependencies: Task 3.1 Deliverables:
// ReferenceValidator.h
class ReferenceValidator {
public:
enum ValidationLevel {
BASIC = 0, // GUID exists
STANDARD = 1, // Object accessible
STRICT = 2, // All invariants valid
PARANOID = 3 // Deep validation
};
struct ValidationResult {
bool isValid;
std::string reason;
ValidationLevel level;
std::chrono::microseconds validationTime;
};
// Core validation
template<typename T>
static ValidationResult Validate(const ObjectGuid& guid, ValidationLevel level = STANDARD);
// Specialized validations
static bool ValidatePlayer(Player* player);
static bool ValidateBot(Bot* bot);
static bool ValidateGroup(Group* group);
static bool ValidateCreature(Creature* creature);
// Bulk validation
template<typename Container>
static std::vector<ValidationResult> ValidateBatch(const Container& refs);
// Custom validators
using CustomValidator = std::function<bool(void*)>;
static void RegisterCustomValidator(TypeIndex type, CustomValidator validator);
// Performance monitoring
static std::chrono::microseconds GetAverageValidationTime();
static uint64_t GetValidationCount() { return s_validationCount; }
private:
// Validation implementations
static bool ValidateMemory(void* ptr);
static bool ValidateVTable(void* ptr, TypeIndex expectedType);
static bool ValidateObjectState(WorldObject* object);
static bool ValidateMapPresence(WorldObject* object);
// Custom validators
static std::unordered_map<TypeIndex, CustomValidator> s_customValidators;
// Metrics
static std::atomic<uint64_t> s_validationCount;
static std::atomic<uint64_t> s_totalValidationTimeUs;
// Thread safety
static std::shared_mutex s_validatorMutex;
};
Task 3.3: Reference Cache System
Duration: 14 hours Assigned Agents:
- Primary: database-optimizer (cache algorithms)
- Support: resource-monitor-limiter (memory management) Dependencies: Task 3.2 Deliverables:
// ReferenceCache.h
class ReferenceCache {
public:
struct CacheEntry {
void* objectPtr;
ObjectGuid guid;
TypeIndex typeIndex;
std::chrono::steady_clock::time_point lastAccess;
std::chrono::steady_clock::time_point lastValidation;
uint32_t accessCount;
uint32_t hitCount;
bool isValid;
};
struct CacheStats {
uint64_t totalHits{0};
uint64_t totalMisses{0};
uint64_t evictions{0};
double hitRate{0.0};
size_t currentSize{0};
size_t maxSize{0};
std::chrono::microseconds avgLookupTime{0};
};
// Cache configuration
explicit ReferenceCache(size_t maxSize = 10000);
void SetEvictionPolicy(EvictionPolicy policy);
void SetTTL(std::chrono::milliseconds ttl);
// Cache operations
template<typename T>
T* Get(const ObjectGuid& guid);
template<typename T>
void Put(const ObjectGuid& guid, T* object);
void Invalidate(const ObjectGuid& guid);
void InvalidateType(TypeIndex type);
void Clear();
// Batch operations
template<typename T>
std::vector<T*> GetBatch(const std::vector<ObjectGuid>& guids);
void Prefetch(const std::vector<ObjectGuid>& guids);
// Performance
CacheStats GetStats() const;
void OptimizeCache();
void Resize(size_t newSize);
// Memory management
size_t GetMemoryUsage() const;
void TrimMemory();
private:
// Cache storage
struct CacheNode {
CacheEntry entry;
std::shared_ptr<CacheNode> prev;
std::shared_ptr<CacheNode> next;
};
std::unordered_map<ObjectGuid, std::shared_ptr<CacheNode>> m_cache;
std::shared_ptr<CacheNode> m_lruHead;
std::shared_ptr<CacheNode> m_lruTail;
// Configuration
size_t m_maxSize;
std::chrono::milliseconds m_ttl{5000};
EvictionPolicy m_evictionPolicy{EvictionPolicy::LRU};
// Statistics
mutable CacheStats m_stats;
// Thread safety
mutable std::shared_mutex m_cacheMutex;
// Internal methods
void EvictLRU();
void EvictExpired();
void UpdateLRU(std::shared_ptr<CacheNode> node);
bool IsExpired(const CacheEntry& entry) const;
};
enum class EvictionPolicy {
LRU, // Least Recently Used
LFU, // Least Frequently Used
TTL, // Time To Live
ADAPTIVE // Dynamic based on access patterns
};
Task 3.4: Reference Lifetime Tracking
Duration: 10 hours Assigned Agents:
- Primary: cpp-server-debugger (lifetime management)
- Support: windows-memory-profiler (leak detection) Dependencies: Task 3.3 Deliverables:
// ReferenceTracking.h
class ReferenceTracking {
public:
struct ReferenceInfo {
ObjectGuid guid;
TypeIndex type;
uint32_t strongCount;
uint32_t weakCount;
std::chrono::steady_clock::time_point creationTime;
std::chrono::steady_clock::time_point lastAccess;
std::vector<std::string> holders; // Debug info
};
// Tracking operations
static void TrackCreation(const ObjectGuid& guid, TypeIndex type);
static void TrackAccess(const ObjectGuid& guid);
static void TrackDeletion(const ObjectGuid& guid);
// Reference counting
static void IncrementStrong(const ObjectGuid& guid);
static void DecrementStrong(const ObjectGuid& guid);
static void IncrementWeak(const ObjectGuid& guid);
static void DecrementWeak(const ObjectGuid& guid);
// Leak detection
static std::vector<ReferenceInfo> FindLeaks();
static std::vector<ReferenceInfo> FindDanglingReferences();
static std::vector<ReferenceInfo> FindCircularReferences();
// Reporting
static std::string GenerateReport();
static void DumpToFile(const std::filesystem::path& path);
// Debugging
static ReferenceInfo GetReferenceInfo(const ObjectGuid& guid);
static std::vector<ObjectGuid> GetReferencesHeldBy(const ObjectGuid& holder);
static std::vector<ObjectGuid> GetReferencesTo(const ObjectGuid& target);
// Memory analysis
static size_t GetTotalMemoryUsage();
static std::unordered_map<TypeIndex, size_t> GetMemoryByType();
private:
struct TrackingData {
ReferenceInfo info;
std::set<ObjectGuid> referencedBy;
std::set<ObjectGuid> references;
};
static std::unordered_map<ObjectGuid, TrackingData> s_tracking;
static std::shared_mutex s_trackingMutex;
// Cycle detection
static bool HasCycle(const ObjectGuid& start,
std::set<ObjectGuid>& visited,
std::set<ObjectGuid>& recursion);
};
Task 3.5: Weak Reference Implementation
Duration: 8 hours Assigned Agents:
- Primary: cpp-architecture-optimizer (weak pointer patterns)
- Support: concurrency-threading-specialist (atomic operations) Dependencies: Task 3.4 Deliverables:
// WeakReference.h
template<typename T>
class WeakReference {
public:
// Construction
WeakReference() = default;
WeakReference(const SafeObjectReference<T>& strong);
// Conversion
SafeObjectReference<T> Lock() const;
bool TryLock(SafeObjectReference<T>& out) const;
// Query
bool Expired() const;
size_t UseCount() const;
// Reset
void Reset();
void Reset(const SafeObjectReference<T>& strong);
// Comparison
bool operator==(const WeakReference& other) const;
private:
ObjectGuid m_guid;
mutable std::weak_ptr<T> m_weakPtr;
mutable std::shared_mutex m_mutex;
// Helper methods
std::shared_ptr<T> TryGetShared() const;
};
// Specialized weak references for common types
using WeakPlayerRef = WeakReference<Player>;
using WeakBotRef = WeakReference<Bot>;
using WeakGroupRef = WeakReference<Group>;
Task 3.6: Reference Pool Optimization
Duration: 10 hours Assigned Agents:
- Primary: resource-monitor-limiter (memory pooling)
- Support: windows-memory-profiler (allocation tracking) Dependencies: Task 3.5 Deliverables:
// ReferencePool.h
class ReferencePool {
public:
struct PoolStats {
size_t totalAllocated{0};
size_t currentInUse{0};
size_t peakUsage{0};
size_t recycled{0};
double fragmentationRatio{0.0};
};
// Pool configuration
explicit ReferencePool(size_t initialSize = 1000, size_t maxSize = 10000);
// Allocation
template<typename T>
SafeObjectReference<T> Allocate(const ObjectGuid& guid);
template<typename T>
void Deallocate(SafeObjectReference<T>& ref);
// Batch operations
template<typename T>
std::vector<SafeObjectReference<T>> AllocateBatch(const std::vector<ObjectGuid>& guids);
// Pool management
void Reserve(size_t count);
void Shrink();
void Defragment();
// Statistics
PoolStats GetStats() const;
size_t GetMemoryUsage() const;
// Debugging
void ValidatePool();
std::vector<ObjectGuid> GetActiveReferences() const;
private:
struct PoolBlock {
std::byte storage[sizeof(SafeObjectReference<WorldObject>)];
bool inUse{false};
TypeIndex type;
};
std::vector<std::unique_ptr<PoolBlock[]>> m_blocks;
std::queue<PoolBlock*> m_freeList;
size_t m_blockSize{100};
size_t m_maxBlocks{100};
PoolStats m_stats;
mutable std::mutex m_poolMutex;
// Internal methods
void AllocateNewBlock();
PoolBlock* GetFreeBlock();
void ReturnBlock(PoolBlock* block);
};
Task 3.7: Migration from Raw Pointers
Duration: 14 hours Assigned Agents:
- Primary: cpp-server-debugger (refactoring)
- Support: trinity-integration-tester (compatibility)
- Review: code-quality-reviewer (safety verification) Dependencies: Tasks 3.1-3.6 Deliverables:
// Migration utilities
class PointerMigration {
public:
// Automated migration
template<typename T>
static SafeObjectReference<T> MigratePointer(T* rawPtr);
// Bulk migration
template<typename T>
static std::vector<SafeObjectReference<T>> MigrateBatch(const std::vector<T*>& ptrs);
// Legacy compatibility
template<typename T>
class LegacyAdapter {
public:
explicit LegacyAdapter(SafeObjectReference<T> ref) : m_ref(std::move(ref)) {}
// Implicit conversion for backward compatibility
operator T*() const { return m_ref.GetIfValid(); }
T* operator->() const { return m_ref.GetIfValid(); }
private:
SafeObjectReference<T> m_ref;
};
};
// Migration macros for gradual transition
#define MIGRATE_PTR(ptr) PointerMigration::MigratePointer(ptr)
#define SAFE_ACCESS(ref) ((ref).GetIfValid())
#define VALIDATE_REF(ref) do { if (!(ref).IsValid()) return; } while(0)
Task 3.8: Reference Debugging Tools
Duration: 8 hours Assigned Agents:
- Primary: cpp-server-debugger (debug tools)
- Support: windows-memory-profiler (memory visualization) Dependencies: Task 3.7 Deliverables:
// ReferenceDebugger.h
class ReferenceDebugger {
public:
struct DebugInfo {
std::string typeName;
ObjectGuid guid;
void* address;
size_t refCount;
std::vector<std::string> callStack;
std::chrono::steady_clock::time_point timestamp;
};
// Debug operations
static void EnableDebugging();
static void DisableDebugging();
static bool IsDebuggingEnabled();
// Breakpoints
static void SetBreakpoint(const ObjectGuid& guid);
static void SetBreakpointOnType(TypeIndex type);
static void ClearBreakpoints();
// Watches
static void WatchReference(const ObjectGuid& guid);
static std::vector<DebugInfo> GetWatchedReferences();
// Visualization
static std::string VisualizeReferenceGraph();
static void ExportGraphToDot(const std::filesystem::path& path);
// Assertions
template<typename T>
static void AssertValid(const SafeObjectReference<T>& ref, const std::string& message);
template<typename T>
static void AssertNotDangling(const SafeObjectReference<T>& ref);
private:
static bool s_debuggingEnabled;
static std::set<ObjectGuid> s_breakpoints;
static std::set<TypeIndex> s_typeBreakpoints;
static std::map<ObjectGuid, DebugInfo> s_watches;
static std::mutex s_debugMutex;
};
Task 3.9: Integration Testing Suite
Duration: 12 hours Assigned Agents:
- Primary: test-automation-engineer (test design)
- Support: trinity-integration-tester (game integration) Dependencies: Tasks 3.7-3.8 Deliverables:
// SafeReferenceTests.cpp
class SafeReferenceTests : public ::testing::Test {
protected:
void TestDanglingPointerPrevention() {
auto player = CreateTestPlayer();
SafePlayerRef safeRef(player->GetGUID());
// Delete the player
player->RemoveFromWorld();
delete player;
// Reference should be invalid
EXPECT_FALSE(safeRef.IsValid());
EXPECT_EQ(safeRef.GetIfValid(), nullptr);
// No crash on access attempt
EXPECT_NO_THROW({
if (auto* p = safeRef.GetIfValid()) {
p->GetName(); // Would crash with raw pointer
}
});
}
void TestGroupLeaderLogoutScenario() {
// Issue #4: Crash when group leader logs out
auto leader = CreateTestPlayer();
auto follower = CreateTestBot();
auto group = CreateGroup(leader, follower);
SafePlayerRef leaderRef(leader->GetGUID());
follower->SetLeaderReference(leaderRef);
// Leader logs out
SimulateLogout(leader);
// Bot should handle gracefully
EXPECT_FALSE(follower->GetLeaderReference().IsValid());
EXPECT_NO_THROW(follower->UpdateAI(100));
}
void TestConcurrentAccess() {
SafePlayerRef ref(CreateTestPlayer()->GetGUID());
std::atomic<bool> stop{false};
std::atomic<uint32_t> successCount{0};
// Multiple threads accessing same reference
std::vector<std::thread> threads;
for (int i = 0; i < 10; ++i) {
threads.emplace_back([&]() {
while (!stop) {
if (auto* player = ref.GetIfValid()) {
player->GetLevel();
successCount++;
}
}
});
}
std::this_thread::sleep_for(std::chrono::seconds(1));
stop = true;
for (auto& t : threads) {
t.join();
}
EXPECT_GT(successCount, 0);
}
void TestMemoryLeakPrevention() {
const size_t initialMemory = GetMemoryUsage();
for (int i = 0; i < 10000; ++i) {
auto player = CreateTestPlayer();
SafePlayerRef ref(player->GetGUID());
// Circular reference scenario
player->SetSelfReference(ref);
// Cleanup
player->RemoveFromWorld();
delete player;
}
const size_t finalMemory = GetMemoryUsage();
const size_t leaked = finalMemory - initialMemory;
EXPECT_LT(leaked, 1024 * 1024); // Less than 1MB leaked
}
};
Task 3.10: Performance Optimization
Duration: 10 hours Assigned Agents:
- Primary: resource-monitor-limiter (optimization)
- Support: windows-memory-profiler (profiling)
- Review: database-optimizer (cache tuning) Dependencies: Task 3.9 Deliverables:
- Cache hit ratio optimization (>95%)
- Lock-free fast path implementation
- Memory pool tuning
- Batch operation optimization
Task 3.11: Documentation and Training
Duration: 8 hours Assigned Agents:
- Primary: code-quality-reviewer (documentation)
- Support: test-automation-engineer (examples) Dependencies: Task 3.10 Deliverables:
- Complete API documentation
- Migration guide with examples
- Performance tuning guide
- Common pitfalls and solutions
Testing Strategy
Unit Testing Requirements
- 100% coverage of SafeObjectReference methods
- All validator edge cases covered
- Cache correctness verification
- Thread safety validation
Integration Testing Requirements
- Group system integration
- Combat system integration
- Quest system integration
- Cross-module reference passing
Stress Testing Requirements
- 10,000 concurrent references
- 1 million reference operations/second
- 24-hour memory stability test
- Network disconnect scenarios
Performance Testing Requirements
- Reference access: <50ns average
- Validation: <1μs for basic level
- Cache lookup: <100ns average
- Memory overhead: <64 bytes per reference
Risk Mitigation
Technical Risks
- Performance Regression: Implement fast-path for valid references
- Memory Overhead: Use pooling and compression
- Validation Cost: Multi-level validation with caching
- Migration Complexity: Phased migration with adapters
Integration Risks
- Legacy Code Compatibility: Adapter pattern for gradual migration
- Third-party Addons: Compatibility layer maintained
- Database References: Lazy loading with validation
Success Criteria
Functional Requirements
- ✅ Zero crashes from dangling pointers
- ✅ Issue #4 (logout crash) completely resolved
- ✅ All raw pointers replaced in bot module
- ✅ Thread-safe reference access
- ✅ Automatic cleanup on object deletion
Performance Requirements
- ✅ <50ns average access time
- ✅ <64 bytes memory per reference
- ✅ >95% cache hit ratio
- ✅ <0.1% CPU overhead
Quality Requirements
- ✅ 100% test coverage
- ✅ Zero memory leaks
- ✅ Full backward compatibility
- ✅ Complete migration documentation
Agent Coordination Matrix
| Task | Primary Agent | Support Agents | Review Agent |
|---|---|---|---|
| 3.1 | cpp-architecture-optimizer | concurrency-threading-specialist | database-optimizer |
| 3.2 | cpp-server-debugger | trinity-integration-tester | code-quality-reviewer |
| 3.3 | database-optimizer | resource-monitor-limiter | cpp-architecture-optimizer |
| 3.4 | cpp-server-debugger | windows-memory-profiler | code-quality-reviewer |
| 3.5 | cpp-architecture-optimizer | concurrency-threading-specialist | cpp-server-debugger |
| 3.6 | resource-monitor-limiter | windows-memory-profiler | database-optimizer |
| 3.7 | cpp-server-debugger | trinity-integration-tester | code-quality-reviewer |
| 3.8 | cpp-server-debugger | windows-memory-profiler | test-automation-engineer |
| 3.9 | test-automation-engineer | trinity-integration-tester | code-quality-reviewer |
| 3.10 | resource-monitor-limiter | windows-memory-profiler | database-optimizer |
| 3.11 | code-quality-reviewer | test-automation-engineer | cpp-architecture-optimizer |
Rollback Strategy
Phase 3 Rollback Points
- Pre-Reference: Before any reference implementation
- Core-Complete: After core reference system
- Migration-Ready: Before pointer migration
- Production: After full validation
Rollback Procedure
# Checkpoint creation
git tag phase3-checkpoint-1 # Before reference implementation
git tag phase3-checkpoint-2 # After core system
git tag phase3-checkpoint-3 # Before migration
git tag phase3-complete # Production ready
# Emergency rollback
./scripts/rollback_phase3.sh [checkpoint-number]
Deliverables Checklist
Code Deliverables
- SafeObjectReference.h/cpp (550 lines)
- ReferenceValidator.h/cpp (450 lines)
- ReferenceCache.h/cpp (600 lines)
- ReferenceTracking.h/cpp (400 lines)
- WeakReference.h/cpp (300 lines)
- ReferencePool.h/cpp (350 lines)
- ReferenceDebugger.h/cpp (250 lines)
Test Deliverables
- Unit tests (2000+ lines)
- Integration tests (1000+ lines)
- Stress tests
- Performance benchmarks
Documentation Deliverables
- API reference
- Migration guide
- Performance guide
- Troubleshooting guide
Phase 3 Complete Validation
Exit Criteria
- Issue #4 completely resolved
- Zero dangling pointer crashes
- Performance targets met
- All pointers migrated in bot module
- Full test coverage achieved
Estimated Completion: 90 hours (mid-range of 80-100 hour estimate) Confidence Level: 90% (complex but well-understood patterns)