|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionThere are situations when the server application creates a pool of objects, and the client has the possibility to bind to one specific object. If the pool size is one, than the server can create a singleton instance and all the clients will connect to the same object. In the case of a pool bigger than one object, a solution could be the use of monikers. My solution proposes the change of the class factory for an ATL project. The new class factory will manage the name space by creating a strong table to store references to running objects. Strong table means, that when the last client releases the object, the object is still running, expecting new clients. To shutdown the object, the application must specifically remove the object from the table. In a multithread environment at least two racing condition can appear:
To avoid this, the server application register itself into a STA by calling
To use the new factory class class ATL_NO_VTABLE CTheObject : ... ... { public: ... //here it is set the class factory for the object DECLARE_CLASSFACTORY_EX(CComClassFactoryMon) Details of usageThe server component has one interface HRESULT TheObjectID([out,retval]LONG* plID); The implementation class has a static member variable A client interested in a specific object will call: HRESULT hr = CoGetObject( OLESTR("clsid:4F408B03-404A-4E14-949F-686969AE21D8:!myObject"), NULL, __uuidof(ITheObject), (void**)&spITheObjectPtr); If the " A client who does not care which object will get, can call: HRESULT hr = ::CoCreateInstance(CLSID_TheObject, NULL, CLSCTX_ALL, __uuidof(ITheObject),(void**)&spITheObjectPtr); When you decide that you do not need the object anymore you must call: HRESULT hr = CoGetObject( OLESTR("clsid:4F408B03-404A-4E14-949F-686969AE21D8:"),NULL, __uuidof(ITheObjectsTable),(void**)&spITheObjectsTable); if(SUCCEEDED(hr)) { spITheObjectsTable->RemoveObject(OLESTR("myObject")); } There are two projects:
If you compile the MonikerServer project on your computer, the server will register itself. If you choose not to compile the project, then run /Release/MonikerServer.exe to allow the server to self-register. Start the MonikerClient application and enter a name into the edit box. Click connect, and the readonly text box will display the object ID. Start a second MonikerClient instance, enter the same name and you should get the same ID. Select the checkbox "On close remove the object from the table" and click OK. Click OK in the other MonikerClient instance. Now all the clients are gone, the object is removed from the table and the MonikerServer application will shutdown itself.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||