Pembantu Implementasi Server Di Luar Proses

Empat fungsi pembantu yang dapat dipanggil oleh server di luar proses tersedia untuk menyederhanakan pekerjaan penulisan kode server. Klien COM dan server dalam proses COM biasanya tidak akan memanggilnya. Fungsi-fungsi ini dirancang untuk membantu mencegah kondisi balapan dalam aktivasi server ketika server memiliki beberapa apartemen atau beberapa objek kelas. Namun, mereka juga dapat dengan mudah digunakan untuk server objek kelas tunggal dan satu utas. Fungsinya adalah sebagai berikut:

Untuk mematikan dengan benar, server COM harus melacak berapa banyak instans objek yang telah dibuat instansnya dan berapa kali metode IClassFactory::LockServer telah dipanggil. Hanya ketika kedua hitungan ini mencapai nol dapat dimatikan server. Di server COM berulir tunggal, keputusan untuk mematikan dikoordinasikan dengan permintaan aktivasi masuk, yang diserialisasikan oleh antrean pesan. Server, setelah menerima rilis pada instans objek akhirnya dan memutuskan untuk mematikan, akan mencabut objek kelasnya sebelum permintaan aktivasi lagi dikirim. Jika permintaan aktivasi masuk setelah titik ini, COM akan mengenali bahwa objek kelas dicabut dan akan mengembalikan kesalahan ke Service Control Manager (SCM), yang kemudian akan menyebabkan instans baru proses server lokal dijalankan.

Namun, di server model apartemen, di mana objek kelas yang berbeda terdaftar di apartemen yang berbeda, dan di semua server utas bebas, keputusan untuk mematikan ini harus dikoordinasikan dengan permintaan aktivasi di beberapa utas sehingga satu utas server tidak memutuskan untuk mematikan sementara utas server lain sibuk membagikan objek kelas atau instans objek. Salah satu pendekatan klasik tetapi rumit untuk memecahkan ini adalah memiliki server, setelah mencabut objek kelasnya, cek ulang jumlah instansnya dan tetap hidup sampai semua instans dirilis.

Untuk mempermudah penulis server menangani jenis kondisi balapan ini, COM menyediakan dua fungsi penghitungan referensi:

Ketika jumlah referensi per proses global mencapai nol, COM secara otomatis memanggil CoSuspendClassObjects, yang mencegah permintaan aktivasi baru masuk. Server kemudian dapat membatalkan pendaftaran berbagai objek kelasnya dari berbagai utasnya pada waktu luang tanpa khawatir bahwa permintaan aktivasi lain mungkin masuk. Semua permintaan aktivasi baru ditangani oleh SCM yang meluncurkan instans baru dari proses server lokal.

Cara paling sederhana bagi aplikasi server lokal untuk menggunakan fungsi-fungsi ini adalah dengan memanggil CoAddRefServerProcess di konstruktor untuk setiap objek instansnya dan di masing-masing metode IClassFactory::LockServer ketika parameter fLock TRUE. Aplikasi server juga harus memanggil CoReleaseServerProcess di destruktor setiap objek instansnya dan di setiap metode IClassFactory::LockServer ketika parameter fLock FALSE.

Akhirnya, aplikasi server harus memperhatikan kode pengembalian dari CoReleaseServerProcess, dan jika mengembalikan 0, aplikasi server harus memulai pembersihannya, yang, untuk server dengan beberapa utas, biasanya berarti bahwa ia harus menandakan berbagai utasnya untuk keluar dari perulangan pesan mereka dan memanggil CoAddRefServerProcess dan CoReleaseServerProcess. Jika fungsi manajemen seumur hidup proses server digunakan, fungsi tersebut harus digunakan dalam instans objek dan metode LockServer ; jika tidak, aplikasi server mungkin dimatikan sebelum waktunya.

Ketika permintaan CoGetClassObject dibuat, COM menghubungi server, marshal antarmuka IClassFactory objek kelas, kembali ke proses klien, membatalkan nama antarmuka IClassFactory, dan mengembalikan ini ke klien. Pada titik ini, klien biasanya memanggil LockServer dengan TRUE untuk mencegah proses server dimatikan. Namun, ada jendela waktu antara ketika objek kelas di-marshal dan ketika klien memanggil LockServer di mana klien lain dapat terhubung ke server yang sama, mendapatkan instans, dan merilis instans tersebut, sehingga menyebabkan server dimatikan dan meninggalkan klien pertama tinggi dan kering dengan pointer IClassFactory yang terputus. Untuk mencegah kondisi balapan ini, COM menambahkan panggilan implisit ke LockServer dengan TRUE ke objek kelas saat marshal antarmuka IClassFactory dan panggilan implisit ke LockServer dengan FALSE saat klien merilis antarmuka IClassFactory. Oleh karena itu, tidak perlu untuk panggilan LockServer jarak jauh kembali ke server, dan proksi untuk LockServer hanya mengembalikan S_OK tanpa benar-benar jarak jauh panggilan.

Ada kondisi balapan terkait aktivasi lain selama inisialisasi proses server di luar proses. Server COM yang mendaftarkan beberapa kelas biasanya memanggil CoRegisterClassObject dengan REGCLS_LOCAL_SERVER untuk setiap CLSID yang didukungnya. Setelah melakukan ini untuk semua kelas, server memasukkan perulangan pesannya. Untuk server COM satu utas, semua permintaan aktivasi diblokir hingga server memasuki perulangan pesan. Namun, untuk server model apartemen yang mendaftarkan objek kelas yang berbeda di apartemen yang berbeda dan untuk semua server utas gratis, permintaan aktivasi dapat tiba lebih awal dari ini. Dalam kasus server model apartemen, permintaan aktivasi dapat tiba segera setelah satu utas memasuki perulangan pesannya. Dalam kasus server utas bebas, permintaan aktivasi dapat tiba segera setelah objek kelas pertama didaftarkan. Karena aktivasi dapat terjadi ini lebih awal, mungkin juga rilis akhir terjadi (dan karena itu menyebabkan server mulai dimatikan) sebelum server lainnya memiliki kesempatan untuk menyelesaikan inisialisasi.

Untuk menghilangkan kondisi balapan ini dan menyederhanakan pekerjaan penulis server, server apa pun yang ingin mendaftarkan beberapa objek kelas dengan COM harus memanggil CoRegisterClassObject dengan REGCLS_LOCAL_SERVER | REGCLS_SUSPENDED untuk setiap CLSID yang berbeda yang didukung server. Setelah semua kelas terdaftar dan proses server siap untuk menerima permintaan aktivasi masuk, server harus melakukan satu panggilan ke CoResumeClassObjects. Fungsi ini memberi tahu COM untuk menginformasikan SCM tentang semua kelas terdaftar, dan mulai membiarkan permintaan aktivasi ke dalam proses server. Menggunakan fungsi-fungsi ini memberikan keuntungan berikut:

  • Hanya satu panggilan yang dilakukan ke SCM, terlepas dari berapa banyak CLSID yang terdaftar, sehingga mengurangi waktu pendaftaran keseluruhan (dan karenanya waktu mulai aplikasi server).
  • Jika server memiliki beberapa apartemen dan CLSID yang berbeda terdaftar di apartemen yang berbeda, atau jika server adalah server utas bebas, tidak ada permintaan aktivasi yang akan masuk sampai server memanggil CoResumeClassObjects, memberi server kesempatan untuk mendaftarkan semua CLSID-nya dan menyiapkan dengan benar sebelum harus menangani permintaan aktivasi dan mungkin mematikan permintaan.

Tanggung Jawab Server COM