Quelle est la meilleure façon de créer et d'utiliser une structure avec une seule instanciation dans le système? Oui, c'est nécessaire, c'est le sous-système OpenGL, et faire de multiples copies de celui-ci et le faire circuler partout ajouterait de la confusion, plutôt que de la soulager.
Le singleton doit être aussi efficace que possible. Il ne semble pas possible de stocker un objet arbitraire sur la zone statique, car il contient un Vec
avec un destructeur. La deuxième option consiste à stocker un pointeur (non sécurisé) sur la zone statique, pointant vers un singleton alloué au tas. Quelle est la façon la plus pratique et la plus sûre de le faire, tout en gardant une syntaxe laconique.
Réponses:
Réponse sans réponse
Évitez l'état global en général. Au lieu de cela, construisez l'objet quelque part tôt (peut-être dans
main
), puis transmettez les références mutables à cet objet aux endroits qui en ont besoin. Cela rendra généralement votre code plus facile à raisonner et ne nécessitera pas autant de flexion en arrière.Regardez-vous attentivement dans le miroir avant de décider que vous voulez des variables globales mutables. Il y a de rares cas où cela est utile, c'est pourquoi cela vaut la peine de savoir comment faire.
Vous voulez toujours en faire un ...?
Utiliser lazy-static
La caisse paresseuse-statique peut éliminer une partie de la corvée de la création manuelle d'un singleton. Voici un vecteur mutable global:
Si vous supprimez le,
Mutex
vous avez un singleton global sans aucune mutabilité.Vous pouvez également utiliser a
RwLock
au lieu de aMutex
pour autoriser plusieurs lecteurs simultanés.Utiliser once_cell
La caisse once_cell peut éliminer une partie de la corvée de la création manuelle d'un singleton. Voici un vecteur mutable global:
Si vous supprimez le,
Mutex
vous avez un singleton global sans aucune mutabilité.Vous pouvez également utiliser a
RwLock
au lieu de aMutex
pour autoriser plusieurs lecteurs simultanés.Un cas particulier: l'atomique
Si vous avez seulement besoin de suivre une valeur entière, vous pouvez directement utiliser un atomique :
Implémentation manuelle sans dépendance
Ceci est grandement lié à l'implémentation de Rust 1.0
stdin
avec quelques modifications pour Rust moderne. Vous devriez également examiner l'implémentation moderne deio::Lazy
. J'ai commenté en ligne avec ce que fait chaque ligne.Cela imprime:
Ce code compile avec Rust 1.42.0. Les vraies implémentations
Stdin
utilisent certaines fonctionnalités instables pour tenter de libérer la mémoire allouée, ce que ce code ne fait pas.Vraiment, vous voudriez probablement créer un
SingletonReader
implémentationDeref
etDerefMut
vous n'avez donc pas besoin de pousser l'objet et de le verrouiller vous-même.Tout ce travail est ce que lazy-static ou once_cell fait pour vous.
La signification de «global»
Veuillez noter que vous pouvez toujours utiliser l'étendue Rust normale et la confidentialité au niveau du module pour contrôler l'accès à une variable
static
oulazy_static
. Cela signifie que vous pouvez le déclarer dans un module ou même à l'intérieur d'une fonction et qu'il ne sera pas accessible en dehors de ce module / fonction. C'est bon pour contrôler l'accès:Cependant, la variable est toujours globale dans la mesure où une instance de celle-ci existe dans tout le programme.
la source
void *
qui est ensuite renvoyée dans les méthodes de chaque module. Il s'agit d'un modèle d'extension typique pour le code C. Si l'application ne le permet pas et que vous ne pouvez pas le modifier, alors oui, un singleton peut être une bonne solution.lazy_static
exemple dans Rust 1.24.1 et cela fonctionne exactement. Il n'y aexternal static
nulle part ici. Vous devez peut-être vérifier les choses de votre côté pour vous assurer que vous avez bien compris la réponse.Utilisez SpinLock pour un accès global.
Si vous voulez un état mutable (PAS Singleton), consultez Que ne pas faire dans Rust pour plus de descriptions.
J'espère que c'est utile.
la source
Répondre à ma propre question en double .
Cargo.toml:
Crate root (lib.rs):
Initialisation (pas besoin de bloc non sécurisé):
ÉDITER:
J'ai réussi à le résoudre avec once_cell, qui n'a pas besoin de macro.
Cargo.toml:
square.rs:
la source
lazy_static
et les plus récentesonce_cell
. Le point de marquer des choses comme des doublons sur SO est d'éviter d'avoir des informations redondantes.