Skip to content

[REFACTOR] Consolidate queue implementations from 8 to 2 - Kent Beck Simple Design #358

Description

@kcenon

Summary

Reduce 8 queue implementations to 2, following Kent Beck's Simple Design principle of "Fewest Elements" and YAGNI.

Current State

Queue Implementation Inventory (8 total)

File Class Purpose
core/job_queue.h job_queue Mutex-based, blocking wait
core/bounded_job_queue.h bounded_job_queue Size-limited version
lockfree/lockfree_queue.h concurrent_queue Fine-grained locking MPMC
lockfree/lockfree_job_queue.h lockfree_job_queue Job-specific lock-free
queue/adaptive_job_queue.h adaptive_job_queue Wraps mutex + lock-free
impl/typed_pool/typed_job_queue.h typed_job_queue_t<T> Type-safe wrapper
impl/typed_pool/typed_lockfree_job_queue.h typed_lockfree_job_queue_t<T> Type-safe lock-free
impl/typed_pool/adaptive_typed_job_queue.h adaptive_typed_job_queue_t<T> Type-safe adaptive

Directory Structure

include/kcenon/thread/
├── core/
│   ├── job_queue.h              
│   └── bounded_job_queue.h      
├── lockfree/
│   ├── lockfree_queue.h         
│   └── lockfree_job_queue.h     
├── queue/
│   ├── adaptive_job_queue.h     
│   └── queue_factory.h          
└── impl/typed_pool/
    ├── typed_job_queue.h
    ├── typed_lockfree_job_queue.h
    └── adaptive_typed_job_queue.h

Problem Analysis

Issue Kent Beck Principle Violated
8 implementations for 1 concept Fewest Elements
User confusion on which to use Reveals Intention
Overlapping functionality No Duplication
typed_* duplicates base classes DRY

YAGNI Analysis

  • Most users need: 1 general-purpose queue
  • Power users need: 1 specialized option
  • Current: 8 options with unclear selection criteria

Dependency Graph

adaptive_job_queue
├── job_queue (mutex mode)
└── lockfree_job_queue (lock-free mode)
    └── concurrent_queue (internal)

Proposed Solution: 2 Queue Classes

Keep

  1. job_queue - When blocking wait is essential
  2. adaptive_job_queue - Default recommendation (wraps both modes)

Consolidate/Remove

Current Action Rationale
bounded_job_queue Merge into job_queue Add optional size limit parameter
concurrent_queue Internal only Move to detail:: namespace
lockfree_job_queue Internal only Used only by adaptive
typed_* variants Template parameter Add to base classes

New Architecture

namespace kcenon::thread {

// Primary API: General-purpose adaptive queue
class adaptive_job_queue : public scheduler_interface {
public:
    explicit adaptive_job_queue(policy p = policy::balanced);
    
    // Optional: Type-safe submission
    template<typename JobType>
    auto enqueue(JobType&& job) -> common::VoidResult;
    
    // ...existing API...
};

// Secondary API: When blocking is required
class job_queue : public scheduler_interface {
public:
    explicit job_queue(std::optional<size_t> max_size = std::nullopt);
    
    // Optional: Type-safe submission  
    template<typename JobType>
    auto enqueue(JobType&& job) -> common::VoidResult;
    
    // ...existing API with optional bounds...
};

// Internal implementations (hidden)
namespace detail {
    template<typename T>
    class concurrent_queue { ... };  // MPMC
    
    class lockfree_job_queue { ... }; // Lock-free job queue
}

} // namespace kcenon::thread

Usage Guidelines (to document)

// Recommended: Most use cases
auto queue = std::make_unique<adaptive_job_queue>();

// Only when blocking wait is required
auto blocking = std::make_shared<job_queue>();

// With size limit (optional)
auto bounded = std::make_shared<job_queue>(/*max_size=*/1000);

Migration Path

Phase 1: Mark as internal

namespace detail {
    // Move these here
    class lockfree_job_queue { ... };
    template<typename T> class concurrent_queue { ... };
}

Phase 2: Deprecate typed_* variants

template<typename T>
class [[deprecated("Use adaptive_job_queue with template enqueue")]] 
    typed_job_queue_t { ... };

Phase 3: Merge bounded into job_queue

class job_queue {
public:
    explicit job_queue(std::optional<size_t> max_size = std::nullopt);
    // If max_size is set, behaves like bounded_job_queue
};

Phase 4: Remove deprecated (next major version)

  • Remove typed_* files
  • Remove bounded_job_queue.h (merged)

Tasks

  • Move concurrent_queue to detail:: namespace
  • Move lockfree_job_queue to detail:: namespace
  • Add max_size parameter to job_queue
  • Deprecate bounded_job_queue
  • Add template enqueue<T> to base classes
  • Deprecate typed_job_queue_t
  • Deprecate typed_lockfree_job_queue_t
  • Deprecate adaptive_typed_job_queue_t
  • Update queue_factory.h to recommend adaptive
  • Update all documentation
  • Update examples

Acceptance Criteria

  • Public API reduced to 2 classes
  • Internal implementations in detail:: namespace
  • typed_* variants deprecated with migration path
  • bounded_job_queue merged into job_queue
  • All tests pass
  • Documentation updated with clear guidance

Metrics

Metric Before After
Public queue classes 8 2
Header files 9 4 (2 public + 2 internal)
User decision points 8 2

Related

Metadata

Metadata

Assignees

Labels

architectureArchitectural changes and designpriority:highHigh priority issuerefactoringCode refactoring and improvements

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions