Bagikan melalui


Inisialisasi One-Time

Komponen sering dirancang untuk melakukan tugas inisialisasi ketika pertama kali dipanggil, bukan ketika dimuat. Fungsi inisialisasi satu kali memastikan bahwa inisialisasi ini hanya terjadi sekali, bahkan ketika beberapa utas dapat mencoba inisialisasi.

Windows Server 2003 dan Windows XP: Aplikasi harus menyediakan sinkronisasi mereka sendiri untuk inisialisasi satu kali dengan menggunakan fungsi yang saling diblokir atau mekanisme sinkronisasi lainnya. Fungsi inisialisasi satu kali tersedia dimulai dengan Windows Vista dan Windows Server 2008.

Fungsi inisialisasi satu kali memberikan keuntungan signifikan untuk memastikan bahwa hanya satu utas yang melakukan inisialisasi:

  • Mereka dioptimalkan untuk kecepatan.
  • Mereka menciptakan hambatan yang sesuai pada arsitektur prosesor yang membutuhkannya.
  • Mereka mendukung inisialisasi terkunci dan paralel.
  • Mereka menghindari penguncian internal sehingga kode dapat beroperasi secara asinkron atau sinkron.

Sistem mengelola proses inisialisasi melalui struktur INIT_ONCE buram yang berisi data dan informasi status. Pemanggil mengalokasikan struktur ini dan menginisialisasinya dengan memanggil InitOnceInitialize (untuk menginisialisasi struktur secara dinamis) atau menetapkan INIT_ONCE_STATIC_INIT konstanta ke variabel struktur (untuk menginisialisasi struktur secara statis). Awalnya, data yang disimpan dalam struktur inisialisasi satu kali adalah NULL dan statusnya tidak diinisialisasi.

Struktur inisialisasi satu kali tidak dapat dibagikan di seluruh proses.

Utas yang melakukan inisialisasi dapat secara opsional mengatur konteks yang tersedia untuk pemanggil setelah inisialisasi selesai. Konteksnya bisa menjadi objek sinkronisasi atau dapat berupa nilai atau struktur data. Jika konteksnya adalah nilai, INIT_ONCE_CTX_RESERVED_BITS berurutan rendah harus nol. Jika konteksnya adalah struktur data, struktur data harus selaras dengan DWORD. Konteks dikembalikan ke pemanggil dalam parameter output lpContext dari fungsi InitOnceBeginInitialize atau InitOnceExecuteOnce .

Inisialisasi satu kali dapat dilakukan secara sinkron atau asinkron. Fungsi panggilan balik opsional dapat digunakan untuk inisialisasi satu kali yang sinkron.

Inisialisasi Satu Kali Sinkron

Langkah-langkah berikut menjelaskan inisialisasi satu kali sinkron yang tidak menggunakan fungsi panggilan balik.

  1. Utas pertama yang memanggil fungsi InitOnceBeginInitialize berhasil menyebabkan inisialisasi satu kali dimulai. Untuk inisialisasi satu kali yang sinkron, InitOnceBeginInitialize harus dipanggil tanpa bendera INIT_ONCE_ASYNC .
  2. Utas berikutnya yang mencoba inisialisasi diblokir hingga utas pertama menyelesaikan inisialisasi atau gagal. Jika utas pertama gagal, utas berikutnya diizinkan untuk mencoba inisialisasi, dan sebagainya.
  3. Ketika inisialisasi selesai, utas memanggil fungsi InitOnceComplete . Utas dapat secara opsional membuat objek sinkronisasi (atau data konteks lainnya) dan menentukannya dalam parameter lpContext dari fungsi InitOnceComplete .
  4. Jika inisialisasi berhasil, status struktur inisialisasi satu kali diubah menjadi diinisialisasi dan handel lpContext (jika ada) disimpan dalam struktur inisialisasi. Upaya inisialisasi berikutnya mengembalikan data konteks ini. Jika inisialisasi gagal, datanya ADALAH NULL.

Langkah-langkah berikut menjelaskan inisialisasi satu kali sinkron yang menggunakan fungsi panggilan balik.

  1. Utas pertama yang berhasil memanggil fungsi InitOnceExecuteOnce meneruskan penunjuk ke fungsi panggilan balik InitOnceCallback yang ditentukan aplikasi dan data apa pun yang diperlukan oleh fungsi panggilan balik. Jika panggilan berhasil, fungsi panggilan balik InitOnceCallback akan dijalankan.
  2. Utas berikutnya yang mencoba inisialisasi diblokir hingga utas pertama menyelesaikan inisialisasi atau gagal. Jika utas pertama gagal, utas berikutnya diizinkan untuk mencoba inisialisasi, dan sebagainya.
  3. Ketika inisialisasi selesai, fungsi panggilan balik akan kembali. Fungsi panggilan balik dapat secara opsional membuat objek sinkronisasi (atau data konteks lainnya) dan menentukannya dalam parameter output Konteksnya .
  4. Jika inisialisasi berhasil, status struktur inisialisasi satu kali diubah menjadi diinisialisasi dan Handel konteks (jika ada) disimpan dalam struktur inisialisasi. Upaya inisialisasi berikutnya mengembalikan data konteks ini. Jika inisialisasi gagal, datanya ADALAH NULL.

Inisialisasi Satu Kali Asinkron

Langkah-langkah berikut menjelaskan inisialisasi satu kali asinkron.

  1. Jika beberapa utas secara bersamaan mencoba memulai inisialisasi dengan memanggil InitOnceBeginInitialize dengan INIT_ONCE_ASYNC, fungsi berhasil untuk semua utas dengan parameter fPending diatur ke TRUE. Hanya satu utas yang benar-benar akan berhasil pada inisialisasi; upaya bersamaan lainnya tidak mengubah status inisialisasi.
  2. Ketika InitOnceBeginInitialize kembali, parameter fPending menunjukkan status inisialisasi:
    • Jika fPendingFALSE, satu utas telah berhasil pada inisialisasi. Utas lain harus membersihkan data konteks apa pun yang telah mereka buat dan menggunakan data konteks dalam parameter output lpContext dari InitOnceBeginInitialize.
    • Jika fPendingTRUE, inisialisasi belum selesai dan utas lainnya harus dilanjutkan.
  3. Setiap utas memanggil fungsi InitOnceComplete . Utas dapat secara opsional membuat objek sinkronisasi (atau data konteks lainnya) dan menentukannya dalam parameter lpContextinitOnceComplete.
  4. Ketika InitOnceComplete kembali, nilai pengembaliannya menunjukkan apakah utas panggilan berhasil pada inisialisasi.
    • Jika InitOnceComplete berhasil, utas panggilan telah berhasil pada inisialisasi. Status struktur inisialisasi satu kali diubah menjadi diinisialisasi dan handel lpContext (jika ada) disimpan dalam struktur inisialisasi.
    • Jika InitOnceComplete gagal, utas lain telah berhasil pada inisialisasi. Utas panggilan harus membersihkan data konteks apa pun yang telah dibuatnya dan memanggil InitOnceBeginInitialize dengan INIT_ONCE_CHECK_ONLY untuk mengambil data konteks apa pun yang disimpan dalam struktur inisialisasi satu kali.

Memanggil inisialisasi One-Time dari beberapa situs

Inisialisasi satu kali yang dijaga oleh satu struktur INIT_ONCE dapat dilakukan dari situs mutiple; panggilan balik yang berbeda dapat diteruskan dari setiap situs, dan sinkronisasi dengan dan tanpa panggilan balik dapat dicampur. Inisialisasi masih dijamin untuk dilakukan hanya sekali.

Namun, inisialisasi asinkron dan sinkron tidak dapat dicampur: setelah inisialisasi asinkron dicoba, upaya untuk memulai inisialisasi sinkron akan gagal.

Menggunakan Inisialisasi One-Time