GroveEngine/CLAUDE.md
StillHammer aefd7921b2 fix: Critical race conditions in ThreadedModuleSystem and logger
Fixed two critical race conditions that prevented multi-threaded module execution:

## Bug #1: ThreadedModuleSystem::registerModule() race condition

**Symptom:** Deadlock on first processModules() call
**Root Cause:** Worker thread started before being added to workers vector
**Fix:** Add worker to vector BEFORE spawning thread (src/ThreadedModuleSystem.cpp:102-108)

Before:
- Create worker → Start thread → Add to vector (RACE!)
- Thread accesses workers[index] before push_back completes

After:
- Create worker → Add to vector → Start thread (SAFE)
- Thread guaranteed to find worker in vector

## Bug #2: stillhammer::createLogger() race condition

**Symptom:** Deadlock when multiple threads create loggers simultaneously
**Root Cause:** Check-then-register pattern without mutex protection
**Fix:** Added static mutex around spdlog::get() + register_logger() (external/StillHammer/logger/src/Logger.cpp:94-96)

Before:
- Thread 1: check → create → register
- Thread 2: check → create → register (RACE on spdlog registry!)

After:
- Mutex protects entire check-then-register critical section

## Validation & Testing

Added comprehensive test suite:
- test_threaded_module_system.cpp (6 unit tests)
- test_threaded_stress.cpp (5 stress tests: 50 modules × 1000 frames)
- test_logger_threadsafe.cpp (concurrent logger creation)
- benchmark_threaded_vs_sequential.cpp (performance comparison)
- docs/THREADED_MODULE_SYSTEM_VALIDATION.md (full validation report)

All tests passing (100%):
- ThreadedModuleSystem:  0.15s
- ThreadedStress:  7.64s
- LoggerThreadSafe:  0.13s

## Impact

ThreadedModuleSystem now PRODUCTION READY:
- Thread-safe module registration
- Stable parallel execution (validated with 50,000+ operations)
- Hot-reload working (100 cycles tested)
- Logger thread-safe for concurrent module initialization

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-19 07:37:31 +07:00

6.2 KiB

GroveEngine - Claude Code Context

Project Overview

GroveEngine is a C++17 hot-reload module system for game engines. It supports dynamic loading/unloading of modules (.so) with state preservation during hot-reload.

Documentation

For developers using GroveEngine:

  • DEVELOPER_GUIDE.md - Complete guide to building applications with GroveEngine (modules, IIO topics, examples)
  • USER_GUIDE.md - Core module system, hot-reload, IIO communication basics

Module-specific:

UIModule Documentation (⚠️ READ BEFORE WORKING ON UI):

  • UI Widgets - Widget properties, JSON configuration, custom widgets
  • UI Topics - IIO topics reference and usage patterns
  • UI Architecture - Threading model, limitations, design principles
  • UI Rendering - Retained mode rendering architecture

Module Systems

System Status Description Use Case
SequentialModuleSystem Production Ready Single-threaded, one module at a time Debug, testing
ThreadedModuleSystem Phase 2 Complete One thread per module (parallel execution) 2-8 modules, ≤30 FPS
ThreadPoolModuleSystem 🚧 Planned (Phase 3) Shared worker pool, work stealing High performance (>30 FPS)
ClusterModuleSystem 🚧 Planned (Phase 4) Distributed across machines MMO scale

Available Modules

Module Status Description Build Flag
BgfxRenderer Phase 7-8 Complete 2D rendering (sprites, text, tilemap, particles) -DGROVE_BUILD_BGFX_RENDERER=ON
UIModule Phase 7 Complete UI widgets (buttons, panels, scrolling, tooltips) -DGROVE_BUILD_UI_MODULE=ON
InputModule Production Ready Input handling (mouse, keyboard, SDL backend) -DGROVE_BUILD_INPUT_MODULE=ON

Integration: All modules communicate via IIO topics. See DEVELOPER_GUIDE.md for complete IIO topics reference.

Build & Test

# Build core only
cmake -B build && cmake --build build -j4

# Build with all modules
cmake -B build -DGROVE_BUILD_BGFX_RENDERER=ON -DGROVE_BUILD_UI_MODULE=ON -DGROVE_BUILD_INPUT_MODULE=ON
cmake --build build -j4

# Run all tests (23+ tests)
cd build && ctest --output-on-failure

# Run visual tests (IMPORTANT: always run from project root for correct asset paths)
./build/tests/test_ui_showcase      # UI showcase with all widgets
./build/tests/test_renderer_showcase # Renderer showcase (sprites, text, particles)

# Build with ThreadSanitizer
cmake -DGROVE_ENABLE_TSAN=ON -B build-tsan
cmake --build build-tsan -j4

Architecture

Key Components

  • ModuleLoader: Handles dlopen/dlclose of .so modules with hot-reload support
  • SequentialModuleSystem: Single-threaded module execution for testing
  • IntraIOManager: Inter-module communication with pub/sub routing
  • TopicTree: O(k) topic matching with wildcard support

Thread Safety Patterns

See docs/coding_guidelines.md for detailed synchronization guidelines.

DO:

// Multiple mutexes - use scoped_lock (deadlock-free)
std::scoped_lock lock(mutex1, mutex2);

// Read-heavy data - use shared_mutex
std::shared_lock readLock(sharedMutex);   // concurrent reads
std::unique_lock writeLock(sharedMutex);  // exclusive write

DON'T:

// NEVER nest lock_guard - causes deadlock
std::lock_guard lock1(mutex1);
std::lock_guard lock2(mutex2);  // DEADLOCK RISK

ModuleLoader Usage

  • Each ModuleLoader instance manages ONE module lifecycle
  • Don't reuse loader for multiple independent modules (causes SEGFAULT)
  • reload() safely handles state extraction and library reload
  • load(path, name, isReload=true) for hot-reload with cache bypass

Known Issues

  • TankModule.h linter bug: A linter sometimes merges lines 35-36. If build fails with "logger not declared", check this file.

Test Categories

Test # Name Duration Description
1-10 scenario_* ~0.01s Basic scenarios
11 ProductionHotReload ~12s Full hot-reload cycle
12 ChaosMonkey ~41s Stress testing
13 StressTest ~180s Heavy load
15 MemoryLeakHunter ~135s 200 reload cycles
19 CrossSystemIntegration ~4s Multi-system test

Module Architecture Quick Reference

BgfxRenderer

  • RHI Layer: Abstracts bgfx calls (RHIDevice.h, BgfxDevice.cpp)
  • RenderGraph: Topological sort with Kahn's algorithm for pass ordering
  • CommandBuffer: Records commands, executed by device at frame end
  • IIO Topics: render:sprite, render:text, render:tilemap, render:particle, render:camera, render:clear, render:debug/*

UIModule

  • UIRenderer: Publishes render commands to BgfxRenderer via IIO (layer 1000+)
  • Widgets: UIButton, UIPanel, UILabel, UICheckbox, UISlider, UITextInput, UIProgressBar, UIImage, UIScrollPanel, UITooltip
  • IIO Topics: Consumes input:*, ui:set_text, ui:set_visible; publishes ui:click, ui:action, ui:value_changed, etc.
  • ⚠️ Before modifying UI code: Read UI Architecture for threading model, UI Widgets for widget properties, UI Topics for IIO patterns

InputModule

  • Backends: SDLBackend (mouse, keyboard, gamepad Phase 2)
  • Thread-safe: Event buffering with lock-free design
  • IIO Topics: input:mouse:*, input:keyboard:*, input:gamepad:*

Debugging Tools

# ThreadSanitizer (detects data races, deadlocks)
cmake -DGROVE_ENABLE_TSAN=ON -B build-tsan

# Helgrind (alternative deadlock detector)
cmake -DGROVE_ENABLE_HELGRIND=ON -B build
make helgrind