I want to know the actual usage of QueryInterface and IUnknown interface.
QueryInterface() is a COM version of C# as keyword - you call QueryInterface() and supply an interface id and you either get success code (S_OK) and a valid pointer to that interface of the object or error code E_NOINTERFACE and null pointer which means the object doesn't implement such interface. IUnknown is the interface containing QueryInterface() and also the reference counting methods (AddRef() and Release()) which are used for COM object lifetime management. Every COM object must implement at least IUnknown, otherwise you simply can't Release() objects when you no longer need them and calling Release() is the only way to tell you no longer need the object.
QueryInterface checks whether the object that implements this interface supports the interface specified by IID. If so, QueryInterface
Increments the reference count.
Sets the Obj parameter so that it
points to an instance of the specified interface.
Returns 0 to indicate success.
If the object does not support the interface, QueryInterface returns a nonzero error code, such as E_NoInterface.
IUnknown is the fundamental interface in COM-Lite, as in COM. All other COM-Lite interfaces must derive from it.
Used for Object lifetime management (when to free an object) and object self-description (how to determine object capabilities at runtime)
Related
Code in C#
string GetValue()
{
//m_IFC is RCW of a native COM object returns Variant marshalled as managed object
object value1 = m_IFC.GetValue();
string valueStr = (string) value1;
return valueStr;
}
The assembly having above code is hosted in COM out-of-proc server which returns the received string from the API to all clients.
Are there any any potential memory leaks here?
From the code you show there is no potential memory leak if m_IFC is indeed a standard runtime callable wrapper. From the MSDN documetation:
The standard wrapper enforces built-in marshaling rules. For example, when a .NET client passes a String type as part of an argument to an unmanaged object, the wrapper converts the string to a BSTR type. Should the COM object return a BSTR to its managed caller, the caller receives a String. Both the client and the server send and receive data that is familiar to them.
All objects shown in your code are managed types and will be garbage collected when all references to it go out of scope. Any unmanaged memory is already handled by the wrapper.
According to JavaDoc of Object.hashCode() this method returns internal address of the object converting it to integer value.
But Garbage Collector can move the object from one memory segment to another changing it internal address. For example the object can be moved from Young Generation to Old Generation.
See for example the following command line keys of java.exe:
-XX:+UseSerialGC
-XX:+UseParallelGC
-XX:+UseParallelOldGC
-XX:+UseConcMarkSweepGC
They determine different algorithms of Garbage Collection.
Does it mean that in this case Object.hashCode() will return different values?
Or it will always return value corresponding to initial address of the object?
Straight from the javadoc
The general contract of hashCode is:
•Whenever it is invoked on the same object more than once during an
execution of a Java application, the hashCode method must consistently
return the same integer, provided no information used in equals
comparisons on the object is modified. This integer need not remain
consistent from one execution of an application to another execution
of the same application.
I create a CwinThread::thread in my application in order to get access to the data in COM asynchronous CALLBACK function.the COM library is initialized by CoInitialize(NULL).
Then when the thread uses the COM object's function an error occurred:
Method call IOPCAsyncIO2::Write failed with error code 8001010e
I use Error Lookup for help:the application is calling an Interface which is organized by another thread
the thread is supposed to be the COM thread.
any ideas?
sorry for not giving you the specific codes few days ago. This time I want to describe my issue using the pseudo code:
first:
in class A,func1
r1 = CoInitialize(NULL);
then something for judgement
in class B(this class is created as a winthread and used for accessing the data from callback class take CallbackClass as example).
in class A,I initialize the thread by calling
m_pThread = AfxBeginThread(RUNTIME_CLASS(CTestThread), THREAD_PRIORITY_NORMAL,0,0,NULL);
calling the functions of Class B by
m_pThread->PostThreadMessage(WM_INITIALIZETHREAD, (WPARAM)this, 0);
one can be aware that the Class A is set for just coding and building the relationship between the dialog, Class B and the CallbackClass.
My question is: I have read many blogs about the MTA and STA, and I know my PC's HKEY_CLASSES_ROOT says the ThreadingModel is Apartment. When I use the Class B(Thread class) to get the pointer of the CallbackClass,there the issue happens.
I know there must be something I missed about my thread and I need some example of at least one COM initialization and one win32 thread and how the thread can get access COM's data.Thank you very much.
So, you're sending a "raw" COM interface ('this') to code in another thread. That's probably why you get the error.
COM interface pointers must be passed using COM methods (as arguments to the method so COM knows it has to marshal it to another thread/apartment), not by other means. When in apartment model, you think of it like every COM object lives in each own process (you can't use 'this' in another process, and that's the same rule for apartments).
You could use "COM Connection points" (see here + google for some explanations: An introduction to COM connection points) which are like events between COM objects. Note this can be complicated.
You could also use more low-level constructs and marshal interface pointers yourself (using the CoMarshalInterThreadInterfaceInStream function). See another article on this here: What are the rules for CoMarshalInterThreadInterfaceInStream and CoGetInterfaceAndReleaseStream?. I would try that first.
I need to take the proxy instance created by Proxy.newProxyInstance as the key of a HashMap. I am not sure if it overwrites the equals and hashcode method of the Object. I am not sure if Object is suitable for that.
I checked the doc for hashcode method:
As much as is reasonably practical, the hashCode method defined by
* class Object does return distinct integers for distinct
* objects. (This is typically implemented by converting the internal
* address of the object into an integer.
The hashcode of Object will change after the object instance is moved during GC. Is this right?
I got #NPE 's explanation:
The computation is performed the first time a hash code is required. To maintain consistency, the result is then stored in the object's header and is returned on subsequent calls to hashCode(). The caching is done outside this function.
So the hashcode of Object will not change.
I got this from Proxy Java Doc:
A method invocation on a proxy instance through one of its proxy interfaces will be dispatched to the invoke method of the instance's invocation handler, passing the proxy instance, a java.lang.reflect.Method object identifying the method that was invoked, and an array of type Object containing the arguments.
That's to say only those methods of its proxy interfaces will be involved for proxy action. equals and hashCode are reasonably excluded only if they are also in the interfaces.
So the proxy should not override Obeject's implementation.
Thanks
A portable thread specific storage reference/identity mechanism, of which boost/thread/tss.hpp is an instance, needs a way to generate a unique keys for itself. This key is unique in the scope of a thread, and is subsequently used to retrieve the object it references. This mechanism is used in code written in a thread neutral manner.
Since boost is a portable example of this concept, how specifically does such a mechanism work ?
Boost thread is portable to the pthread threading library (for unix) and the windows win32 low-level-API's. The library allows a reference to be created which is unique in each thread of execution. The global C API errno is presented as an example of this concept in Boost's documentation.
Ignore If you Want -- it's just a trace through the source code finding the function of interest
The crux of the matter begins in [boost]/boost/thread/tss.hpp with the get function of thread_specific_ptr and the reset function -- i.e., the aquisition and the destruction, respectively, of the object referenced. Note: the data object is not placed in the reference of thread_specific_ptr's ctor, or destroyed by the dtor. The get and reset function call set_tss_data and get_tss_data. Focusing just on the setting aspect of the functionality, the important function call, get_current_thread_data, indirects via the cpp file [boost]/libs/thread/src/[libname]/thread.cpp via a chain of function calls. In get_current_thread_data there is a function call create_current_thread_tls_key and this is the function that will create a unique identifier for the thread_specific_ptr object.
create_current_thread_tls_key calls TlsAlloc() on win32 (link) and pthread_key_create for pthread (link). These calls assure that upon initialization of the ptr, the ptr receives a unique identifier usable in an API-specific manner to retrieve the object's data. The specific threading API uses the thread-id (context specific and resolved by the library itself) and the object identifier to return the object specific to the context of a certain thread.