348 lines
5.6 KiB
Plaintext
348 lines
5.6 KiB
Plaintext
# Projet : Runtime de Signaux/Slots Haute Performance en Rust
|
||
|
||
## Objectif
|
||
|
||
Créer un runtime événementiel inspiré de Qt Signals/Slots mais pensé pour :
|
||
|
||
- haute fréquence,
|
||
- multi-thread,
|
||
- audio temps réel,
|
||
- architecture modulaire,
|
||
- runtime distribué par workers,
|
||
- typage fort compile-time,
|
||
- signaux async/sync,
|
||
- performance extrême.
|
||
|
||
Le runtime doit pouvoir servir de base à :
|
||
- moteur événementiel,
|
||
- runtime applicatif,
|
||
- scheduler coopératif,
|
||
- actor system,
|
||
- infrastructure temps réel.
|
||
|
||
IMPORTANT :
|
||
Le runtime doit rester générique et indépendant du réseau.
|
||
Aucune logique UDP/TCP/socket ne doit être implémentée automatiquement.
|
||
L’intégration réseau sera réalisée manuellement plus tard par le développeur.
|
||
|
||
---
|
||
|
||
# Vision Architecture
|
||
|
||
```text
|
||
Application
|
||
↓
|
||
Signal Runtime
|
||
├── Worker 0
|
||
│ ├── Event Loop
|
||
│ ├── Audio Systems
|
||
│ ├── Metrics
|
||
│ └── Channels
|
||
│
|
||
├── Worker 1
|
||
│ ├── Auth
|
||
│ ├── Sessions
|
||
│ └── Runtime Tasks
|
||
│
|
||
└── Worker N
|
||
PHASE 1 — Runtime Minimal
|
||
Objectif
|
||
|
||
Créer :
|
||
|
||
runtime global,
|
||
workers,
|
||
queues,
|
||
event loop,
|
||
dispatch d’événements.
|
||
A implémenter
|
||
Runtime
|
||
struct Runtime {
|
||
workers: Vec<Worker>,
|
||
}
|
||
Worker
|
||
struct Worker {
|
||
id: usize,
|
||
sender: Sender<Event>,
|
||
}
|
||
Event Loop
|
||
|
||
Boucle infinie :
|
||
|
||
loop {
|
||
let event = rx.recv().unwrap();
|
||
event.execute();
|
||
}
|
||
Event Trait
|
||
trait ExecutableEvent {
|
||
fn execute(self: Box<Self>);
|
||
}
|
||
PHASE 2 — Système de Signaux
|
||
Objectif
|
||
|
||
Créer :
|
||
|
||
Signal<T>,
|
||
connect(),
|
||
emit(),
|
||
subscribers,
|
||
callbacks dynamiques.
|
||
A implémenter
|
||
Signal générique
|
||
struct Signal<T> {
|
||
subscribers: Vec<Subscriber<T>>,
|
||
}
|
||
Subscriber
|
||
|
||
Contient :
|
||
|
||
callback,
|
||
target_worker,
|
||
connection_type.
|
||
Connection Types
|
||
enum ConnectionType {
|
||
Direct,
|
||
Queued,
|
||
}
|
||
Emit
|
||
|
||
Le signal :
|
||
|
||
ne doit jamais exécuter directement un callback queued,
|
||
doit créer un Event,
|
||
envoyer vers le worker cible.
|
||
PHASE 3 — Runtime Global
|
||
Objectif
|
||
|
||
Créer :
|
||
|
||
runtime singleton,
|
||
accès global,
|
||
routing automatique.
|
||
A implémenter
|
||
OnceLock
|
||
static RUNTIME: OnceLock<Runtime>;
|
||
Dispatch global
|
||
runtime.dispatch(worker_id, event);
|
||
Routing intelligent
|
||
|
||
Le runtime doit :
|
||
|
||
choisir le bon worker,
|
||
envoyer dans la bonne queue,
|
||
éviter les locks globaux.
|
||
PHASE 4 — Proc Macros
|
||
Objectif
|
||
|
||
Créer :
|
||
|
||
#[derive(Signals)],
|
||
auto-enregistrement,
|
||
génération automatique de metadata.
|
||
Crate séparée
|
||
signals_derive/
|
||
Technologies
|
||
syn
|
||
quote
|
||
proc_macro2
|
||
Features
|
||
Détection automatique
|
||
|
||
Détecter :
|
||
|
||
Signal<T>
|
||
|
||
dans une struct.
|
||
|
||
Génération
|
||
|
||
Générer :
|
||
|
||
impl AudioEngine {
|
||
pub fn register_signals(...)
|
||
}
|
||
Support futur
|
||
|
||
Prévoir :
|
||
|
||
#[signal]
|
||
metadata runtime,
|
||
introspection légère.
|
||
PHASE 5 — Thread Affinity
|
||
Objectif
|
||
|
||
Chaque objet appartient à un worker.
|
||
|
||
A implémenter
|
||
RuntimeObject
|
||
struct RuntimeObject {
|
||
worker_id: usize,
|
||
}
|
||
Règles
|
||
les signaux queued doivent s’exécuter sur le worker cible,
|
||
éviter les accès cross-thread directs.
|
||
PHASE 6 — Weak References
|
||
Objectif
|
||
|
||
Reproduire l’auto-cleanup de Qt.
|
||
|
||
A implémenter
|
||
|
||
Utiliser :
|
||
|
||
Arc<T>
|
||
Weak<T>
|
||
Comportement
|
||
|
||
Si le receiver est détruit :
|
||
|
||
la connexion devient invalide,
|
||
le runtime l’ignore automatiquement.
|
||
PHASE 7 — Event Bus Typé
|
||
Objectif
|
||
|
||
Permettre :
|
||
|
||
runtime.emit(EventType)
|
||
runtime.subscribe::<EventType>()
|
||
Contraintes
|
||
typage compile-time,
|
||
pas de string routing obligatoire,
|
||
support Any/TypeId.
|
||
PHASE 8 — Optimisation Performance
|
||
Objectif
|
||
|
||
Préparer haute fréquence.
|
||
|
||
Optimisations attendues
|
||
Eviter
|
||
Mutex globaux,
|
||
allocations fréquentes,
|
||
Box inutiles,
|
||
contention CPU.
|
||
Ajouter
|
||
queues lock-free,
|
||
batching,
|
||
event pooling,
|
||
cache locality,
|
||
sharding runtime.
|
||
PHASE 9 — Runtime Sharding
|
||
Objectif
|
||
|
||
Eviter le bottleneck central.
|
||
|
||
Architecture
|
||
Shard 0
|
||
Shard 1
|
||
Shard 2
|
||
|
||
Chaque shard :
|
||
|
||
possède ses subscribers,
|
||
possède ses queues,
|
||
possède ses workers.
|
||
PHASE 10 — Intégration Applicative Générique
|
||
Objectif
|
||
|
||
Permettre à des systèmes externes de pousser des événements dans le runtime.
|
||
|
||
IMPORTANT :
|
||
Le runtime ne doit contenir aucune logique réseau native.
|
||
Il doit uniquement exposer des APIs génériques permettant :
|
||
|
||
d’émettre des événements,
|
||
de s’abonner à des événements,
|
||
de router les tâches.
|
||
|
||
Les couches réseau, audio, fichiers, protocoles ou IO seront branchées manuellement par le développeur.
|
||
|
||
Exemple attendu
|
||
runtime.emit(MyCustomEvent {
|
||
...
|
||
});
|
||
PHASE 11 — Scheduler Coopératif
|
||
Objectif
|
||
|
||
Fusionner :
|
||
|
||
signaux,
|
||
scheduler,
|
||
tâches coopératives.
|
||
Inspiré de
|
||
Go runtime,
|
||
Tokio,
|
||
Erlang.
|
||
Features
|
||
spawn()
|
||
spawn(async move {})
|
||
sleep()
|
||
wakeup()
|
||
channels()
|
||
PHASE 12 — Async Runtime Integration
|
||
Objectif
|
||
|
||
Compatibilité :
|
||
|
||
Tokio,
|
||
async/await,
|
||
futures.
|
||
Support
|
||
Async subscribers
|
||
signal.connect(async move |event| {
|
||
...
|
||
});
|
||
PHASE 13 — Monitoring & Introspection
|
||
Objectif
|
||
|
||
Observer :
|
||
|
||
workers,
|
||
queues,
|
||
charge CPU,
|
||
nombre d’événements,
|
||
latence.
|
||
Metrics
|
||
events/sec,
|
||
queue depth,
|
||
dropped events,
|
||
worker usage.
|
||
PHASE 14 — API Finale
|
||
Objectif
|
||
|
||
API élégante type Qt.
|
||
|
||
Exemple cible
|
||
#[derive(Signals)]
|
||
struct AudioEngine {
|
||
packet_received: Signal<AudioPacket>,
|
||
}
|
||
|
||
audio.packet_received.connect(&decoder, |d, p| {
|
||
d.decode(p);
|
||
});
|
||
|
||
audio.packet_received.emit(packet);
|
||
Contraintes Techniques
|
||
Langage
|
||
|
||
Rust stable uniquement au début.
|
||
|
||
Dépendances possibles
|
||
crossbeam
|
||
flume
|
||
parking_lot
|
||
dashmap (optionnel)
|
||
tokio (plus tard)
|
||
Eviter au début
|
||
async partout,
|
||
macros trop complexes,
|
||
ECS complet,
|
||
reflection lourde.
|
||
Objectif Long Terme
|
||
|
||
Créer un runtime capable de :
|
||
|
||
gérer des centaines de milliers/millions d’événements,
|
||
servir de cœur à des applications temps réel,
|
||
fournir un scheduler coopératif,
|
||
remplacer une architecture classique callbacks/mutex. |