Click here to Skip to main content
Licence 
First Posted 29 Mar 2000
Views 66,393
Bookmarked 22 times

A smart critical section wrapper for COM objects

By | 29 Mar 2000 | Article
An extremely simple class that wraps the win32 CRITICAL_SECTION. Ideal for the COM STA or MTA.

Introduction

More and more COM objects are written to be 'Both' threaded because it enables creating the object in either a COM STA or MTA. If the thread that creates the 'Both' threaded COM object is initialized to be in an STA by using CoInitialize(), CoInitializeEx(NULL, COINIT_APARTMENTTHREADED) or OleInitialize(), the object will be created in the same STA. If the thread is instead initialized to be in the MTA by using CoInitializeEx(NULL, COINIT_MULTITHREADED), the object will be created in the process's one and only MTA.

The developer of the object is thus forced to code for simultaneous access by multiple threads, typically by using a Critical Section. Note that any global and static variables need to be protected anyway. What I am presenting here optimizes the code that protects the per object instance state. I also want to point out that if the object in question aggregates the Free Threaded Marshaller (FTM), this technique should not be used. The class CComSmartAutoCriticalSection is an extremely simple class that wraps a WIN32 CRITICAL_SECTION. The definition of this class is as follows:

//////////////////////////////////////////////////////////////////////////////// 
// CComSmartAutoCriticalSection 
// 
class CComSmartAutoCriticalSection 
{ 
public: 
	CComSmartAutoCriticalSection() 
	{ 
		if (SUCCEEDED(::CoInitialize(NULL))) 
		{ 
			::CoUninitialize(); 

			m_bInMTA = FALSE; 
		} 
		else 
		{ 
			m_bInMTA = TRUE; 
		} 

		if (m_bInMTA) 
			::InitializeCriticalSection(&m_csSafeAccess); 
	} 

	~CComSmartAutoCriticalSection() 
	{ 
		if (m_bInMTA) 
			::DeleteCriticalSection(&m_csSafeAccess); 
	} 

	void Lock() 
	{ 
		if (m_bInMTA) 
			::EnterCriticalSection(&m_csSafeAccess); 
	} 

	void Unlock() 
	{ 
		if (m_bInMTA) 
			::LeaveCriticalSection(&m_csSafeAccess); 
	} 

private: 
	BOOL              m_bInMTA; 
	CRITICAL_SECTION  m_csSafeAccess; 
}; 

The constructor detects whether the creating thread belongs to a COM STA or MTA and initializes the private member variable m_bInMTA. The CoInitialize() call will return S_FALSE if the calling thread belongs to an STA or RPC_E_CHANGED_MODE if the calling thread belongs to an MTA. If the object is being created in the MTA, the m_csSafeAccess critical section is initialized..

The destructor deletes the m_csSafeAccess critical section if the object is created in the MTA.

The Lock() and Unlock() methods invoke the WIN32 EnterCirticalSection() and LeaveCriticalSection() APIs respectively ONLY IF the object is created within the MTA.

Usage

Within the C++ class the implements your COM object, define a member variable of type CComSmartAutoCriticalSection.

class ATL_NO_VTABLE CSomeCOMClass : <inheritance list> 
{ 
private: 
	CComSmartAutoCriticalSection m_csSafeAccess; 
} 

The implementation functions for the interface properties and methods should be wrapped within the Lock() and Unlock() functions.

STDMETHODIMP CSomeCOMClass::SomeMethod() 
{ 
	HRESULT hResult = S_OK; 


	m_csSafeAccess.Lock(); 

	... // Code to do what the method does. 

	m_csSafeAccess.Unlock(); 

	return hResult; 
} 

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Jeremiah Talkar



United States United States

Member



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
Questionhaving a 'CRITICAL_SECTION' as a member of 'struct' PinmemberMember 39118430:41 15 Jul '08  
QuestionDoes/will this work in COM+? PinsussDave Hanlon8:15 18 May '00  
AnswerRe: Does/will this work in COM+? PinsussJeremiah S. Talkar4:33 3 Jun '00  
GeneralRe: Does/will this work in COM+? PinsussGevorg Ter-saakov10:33 7 Jun '00  
AnswerRe: Does/will this work in COM+? PinsussRobert Little20:15 13 Sep '00  
GeneralRe: Does/will this work in COM+? PinmemberJeremiah Talkar7:54 9 Apr '01  
GeneralTimeouts PinsussChris21:27 3 Apr '00  
GeneralRe: Timeouts PinmemberMarcin Zielinski3:15 14 Nov '01  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web03 | 2.5.120517.1 | Last Updated 30 Mar 2000
Article Copyright 2000 by Jeremiah Talkar
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid