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
job_queue - When blocking wait is essential
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
Acceptance Criteria
Metrics
| Metric |
Before |
After |
| Public queue classes |
8 |
2 |
| Header files |
9 |
4 (2 public + 2 internal) |
| User decision points |
8 |
2 |
Related
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)
core/job_queue.hjob_queuecore/bounded_job_queue.hbounded_job_queuelockfree/lockfree_queue.hconcurrent_queuelockfree/lockfree_job_queue.hlockfree_job_queuequeue/adaptive_job_queue.hadaptive_job_queueimpl/typed_pool/typed_job_queue.htyped_job_queue_t<T>impl/typed_pool/typed_lockfree_job_queue.htyped_lockfree_job_queue_t<T>impl/typed_pool/adaptive_typed_job_queue.hadaptive_typed_job_queue_t<T>Directory Structure
Problem Analysis
YAGNI Analysis
Dependency Graph
Proposed Solution: 2 Queue Classes
Keep
job_queue- When blocking wait is essentialadaptive_job_queue- Default recommendation (wraps both modes)Consolidate/Remove
bounded_job_queuejob_queueconcurrent_queuedetail::namespacelockfree_job_queuetyped_*variantsNew Architecture
Usage Guidelines (to document)
Migration Path
Phase 1: Mark as internal
Phase 2: Deprecate typed_* variants
Phase 3: Merge bounded into job_queue
Phase 4: Remove deprecated (next major version)
Tasks
concurrent_queuetodetail::namespacelockfree_job_queuetodetail::namespacemax_sizeparameter tojob_queuebounded_job_queueenqueue<T>to base classestyped_job_queue_ttyped_lockfree_job_queue_tadaptive_typed_job_queue_tqueue_factory.hto recommend adaptiveAcceptance Criteria
detail::namespaceMetrics
Related