[ofw] [PATCH] winverbs: add framework for allocating device object

Sean Hefty sean.hefty at intel.com
Wed Mar 12 12:11:06 PDT 2008


>>Index: winverbs/core/winverbs/user/wv_device.cpp
>>===================================================================
>>--- winverbs/core/winverbs/user/wv_device.cpp   (revision 974)
>>+++ winverbs/core/winverbs/user/wv_device.cpp   (working copy)
>>@@ -33,22 +33,32 @@
>> STDMETHODIMP CWVDevice::
>> QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
>> {
>>-       UNREFERENCED_PARAMETER(riid);
>>-       UNREFERENCED_PARAMETER(ppvObj);
>>+       if (riid != IID_IUnknown && riid != IID_IWVDevice)
>>+       {
>>+               *ppvObj = NULL;
>
>Don't touch output params in case of error.

I need to look this up again, but I thought this was the standard behavior for
QueryInterface.  (It forces an application crash if it assumes that the call
worked and tries to invoke the interface.)

>>Index: winverbs/core/winverbs/user/wv_device.h
>>===================================================================
>>--- winverbs/core/winverbs/user/wv_device.h     (revision 974)
>>+++ winverbs/core/winverbs/user/wv_device.h     (working copy)
>>@@ -55,6 +55,23 @@
>>        STDMETHODIMP CreateCompletionQueue(SIZE_T *pEntries,
>IWVCompletionQueue** ppCq);
>>        STDMETHODIMP AllocateProtectionDomain(IWVProtectionDomain** ppPd);
>>        STDMETHODIMP Notify(OVERLAPPED* pOverlapped, WV_EVENT* pEvent);
>>+
>>+       CWVDevice(IWVProvider *pProvider)
>>+       {
>>+               pProvider->AddRef();
>>+               m_pProvider = pProvider;
>>+               m_nRef = 0;
>
>Object creation should result in an object with a ref count of 1.  You should
>never have a valid object with a ref count of zero.  Ref count should be 1
>here, and the destructor can be private to force that you never call it
>directly (destruction should always be through the Release method).

I need to change this everywhere then.


>>+       ~CWVDevice()
>>+       {
>>+               m_pProvider->Release();
>>+       }
>
>You should think about creating an auto-ref template class that calls Release
>automatically when it goes out of scope.  You'll find it quite useful in the
>code when handling error flow, and can use it as the m_pProvider member, and
>never have to explicitly call Release when you destroy the object.

I couldn't figure out how to get any of the template classes to work, so I gave
up for the sake of making _some_ sort of progress.

>> STDMETHODIMP CWVProvider::
>> QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
>>@@ -73,10 +74,17 @@
>> STDMETHODIMP CWVProvider::
>> QueryDevice(UINT64 Guid, WV_DEVICE_ATTRIBUTES* pAttributes)
>> {
>>-       UNREFERENCED_PARAMETER(Guid);
>>-       UNREFERENCED_PARAMETER(pAttributes);
>>+       IWVDevice *dev;
>>+       HRESULT hr;
>>
>>-       return E_NOTIMPL;
>>+       hr = OpenDevice(Guid, &dev);
>>+       if (hr != WV_SUCCESS)
>>+               goto out;
>>+
>>+       hr = dev->Query(pAttributes);
>>+       dev->Release();
>
>Auto-release class would eliminate this explicit Release.
>
>>+out:
>>+       return hr;
>> }
>>
>> STDMETHODIMP CWVProvider::
>>@@ -91,10 +99,29 @@
>> STDMETHODIMP CWVProvider::
>> OpenDevice(UINT64 Guid, IWVDevice** ppDevice)
>> {
>>-       UNREFERENCED_PARAMETER(Guid);
>>-       UNREFERENCED_PARAMETER(ppDevice);
>>+       HRESULT hr;
>>+       CWVDevice *dev;
>>
>>-       return E_NOTIMPL;
>>+       dev = new CWVDevice(this);
>>+       if (!dev)
>>+       {
>>+               hr = WV_NO_MEMORY;
>
>Just return.

This sets ppDevice to NULL on failure below.

>
>>+               goto err1;
>>+       }
>>+
>>+       dev->QueryInterface(IID_IWVDevice, (LPVOID*) ppDevice);
>
>You shouldn't need this call.  In fact, you're setting yourself up for trouble:
>object creation should give you an object with a ref count of 1, calling
>QueryInterface will bump the ref count to 2, and then you return the object
>(still with a ref count of 2!)
>
>Note also that QueryInterface sets ppDevice = this - the CWVDevice object
>implements the IWVDevice interface, so there's no reason to call
>QueryInterface.  Set ppDevice = this, and then when you return you get the
>proper ref count of 1.

I was just trying to follow the random documentation that is COM...  I'll update
this when initializing the ref count to 1.

>>+       hr = dev->Open(Guid);
>>+       if (hr != WV_SUCCESS)
>
>You can use the SUCCEEDED() and FAILED() macros alternatively.

I had actually taken all of these out and just used 'if (hr)'.  But if
'if(SUCCEEDED(hr))' is standard, I can switch to that.  The samples were
inconsistent on this.

>
>>+               goto err2;
>>+
>>+       return WV_SUCCESS;
>>+
>>+err2:
>>+       dev->Release();
>
>An auto-release class here would simplify your error flow - you would just
>return when you detect the error above.  Even without, move the Release call
>into the body of the if( hr != WV_SUCCESS ) statement above, and then return.
>Basically, eliminate the gotos if you can.

gotos in error handling cases are your friend.  :)


I have several changes since the last patch where I've started implementing the
IOCTL calls.  I'm still working on that piece.  Once I get at least the device
calls written, I'll post that portion.  I haven't been able to test yet, since
the kernel driver doesn't even load at this point...

- Sean




More information about the ofw mailing list