Apa cara terbaik untuk membuat dan menggunakan struct dengan hanya satu contoh dalam sistem? Ya, ini perlu, ini adalah subsistem OpenGL, dan membuat banyak salinan dari ini dan menyebarkannya ke mana-mana akan menambah kebingungan, daripada menghilangkannya.
Singleton harus seefisien mungkin. Tampaknya tidak mungkin untuk menyimpan objek sewenang-wenang di area statis, karena berisi Vec
dengan destruktor. Opsi kedua adalah menyimpan pointer (tidak aman) di area statis, menunjuk ke singleton yang dialokasikan heap. Apa cara paling nyaman dan teraman untuk melakukan ini, sambil menjaga sintaks tetap singkat.
Jawaban:
Bukan jawaban
Hindari keadaan global pada umumnya. Sebagai gantinya, buat objek di suatu tempat lebih awal (mungkin di
main
), lalu teruskan referensi yang dapat diubah ke objek tersebut ke tempat-tempat yang membutuhkannya. Ini biasanya akan membuat kode Anda lebih mudah untuk dipikirkan dan tidak perlu terlalu banyak membungkuk ke belakang.Lihatlah diri Anda sendiri di cermin sebelum memutuskan bahwa Anda menginginkan variabel global yang bisa berubah. Ada kasus yang jarang terjadi di mana ini berguna, jadi itulah mengapa perlu diketahui bagaimana melakukannya.
Masih ingin membuatnya ...?
Menggunakan lazy-static
The malas-statis peti dapat mengambil beberapa kerepotan menciptakan tunggal secara manual. Berikut adalah vektor global yang bisa berubah:
Jika Anda menghapusnya
Mutex
maka Anda memiliki singleton global tanpa perubahan apa pun.Anda juga dapat menggunakan a,
RwLock
bukan aMutex
untuk mengizinkan beberapa pembaca secara bersamaan.Menggunakan once_cell
The once_cell crate dapat menghilangkan beberapa pekerjaan membosankan dalam membuat singleton secara manual. Berikut adalah vektor global yang bisa berubah:
Jika Anda menghapusnya
Mutex
maka Anda memiliki singleton global tanpa perubahan apa pun.Anda juga dapat menggunakan a,
RwLock
bukan aMutex
untuk mengizinkan beberapa pembaca secara bersamaan.Kasus khusus: atomics
Jika Anda hanya perlu melacak nilai integer, Anda dapat langsung menggunakan atomic :
Manual, implementasi bebas ketergantungan
Ini sangat diambil dari implementasi Rust 1.0
stdin
dengan beberapa penyesuaian untuk Rust modern. Anda juga harus melihat implementasi modern dariio::Lazy
. Saya telah berkomentar sesuai dengan apa yang dilakukan setiap baris.Ini mencetak:
Kode ini dikompilasi dengan Rust 1.42.0. Implementasi nyata
Stdin
menggunakan beberapa fitur yang tidak stabil untuk mencoba membebaskan memori yang dialokasikan, yang tidak dilakukan oleh kode ini.Benar-benar, Anda mungkin ingin membuat
SingletonReader
menerapkanDeref
danDerefMut
sehingga Anda tidak perlu menyodok ke objek dan menguncinya sendiri.Semua pekerjaan ini adalah apa yang dilakukan lazy-static atau once_cell untuk Anda.
Arti "global"
Harap dicatat bahwa Anda masih dapat menggunakan pelingkupan Rust normal dan privasi tingkat modul untuk mengontrol akses ke variabel
static
ataulazy_static
. Ini berarti Anda dapat mendeklarasikannya dalam modul atau bahkan di dalam fungsi dan tidak akan dapat diakses di luar modul / fungsi itu. Ini bagus untuk mengontrol akses:Namun, variabel tersebut masih global karena ada satu contoh variabel yang ada di seluruh program.
sumber
void *
yang kemudian diteruskan kembali ke metode setiap modul. Ini adalah pola ekstensi tipikal untuk kode C. Jika aplikasi tidak mengizinkan hal ini dan Anda tidak dapat mengubahnya, ya, singleton mungkin merupakan solusi yang baik.lazy_static
contoh di Rust 1.24.1 dan berfungsi dengan tepat. Tidak adaexternal static
tempat di sini. Mungkin Anda perlu memeriksa beberapa hal di pihak Anda untuk memastikan Anda telah memahami jawabannya sepenuhnya.Gunakan SpinLock untuk akses global.
Jika Anda menginginkan status yang bisa berubah (BUKAN Singleton), lihat Yang Tidak Dapat Dilakukan di Rust untuk penjelasan lebih lanjut.
Semoga bermanfaat.
sumber
Menjawab pertanyaan duplikat saya sendiri .
Cargo.toml:
Root peti (lib.rs):
Inisialisasi (tidak perlu blok yang tidak aman):
EDIT:
Berhasil menyelesaikannya dengan once_cell, yang tidak membutuhkan makro.
Cargo.toml:
square.rs:
sumber
lazy_static
maupun yang lebih baruonce_cell
. Titik menandai sesuatu sebagai duplikat pada SO adalah untuk menghindari informasi yang berlebihan.