Files
ThordekkCore/PHASE_3_SAFE_REFERENCES_SUBPLAN.md
T
2026-01-20 21:33:16 -03:00

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

  1. Performance Regression: Implement fast-path for valid references
  2. Memory Overhead: Use pooling and compression
  3. Validation Cost: Multi-level validation with caching
  4. Migration Complexity: Phased migration with adapters

Integration Risks

  1. Legacy Code Compatibility: Adapter pattern for gradual migration
  2. Third-party Addons: Compatibility layer maintained
  3. 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

  1. Pre-Reference: Before any reference implementation
  2. Core-Complete: After core reference system
  3. Migration-Ready: Before pointer migration
  4. 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

  1. Issue #4 completely resolved
  2. Zero dangling pointer crashes
  3. Performance targets met
  4. All pointers migrated in bot module
  5. Full test coverage achieved

Estimated Completion: 90 hours (mid-range of 80-100 hour estimate) Confidence Level: 90% (complex but well-understood patterns)