| CodeGuru Home | VC++ / MFC / C++ | .NET / C# | Visual Basic | Newsletters | VB Forums | Developer.com |
|
|||||||
| Multithreading Discuss multithreading issues and related topics. |
![]() |
|
|
Thread Tools | Search this Thread | Rate Thread | Display Modes |
|
#1
|
|||
|
|||
|
Locking An Entire Class
Hi All,
I'm having a lot of trouble finding an answer to this - hopefully you can provide some guidance. I'm currently in the design phase of a project which is multi-threaded and it maintains an array of connected client objects (CClient). Each CClient object is specific to it's related connection storing information such as statistics, positioning, connection details, etc, etc. This list can be accessed by multiple threads at different times (for reading/writing) and I'm trying to come up with a good way to lock the list during thread accesses. At this point in time I've decided that a per-client lock system would be the best way to go. Now for implementation. There are two ways I see this being done but cannot seem to get either to work. The first would be to implement a "gateway" type of function where all calls to a CClient instance would be made through a single function: Code:
getClient().connection.setAddress(".....");
The second way would be to have specific Lock() and Unlock() member functions of each CClient instance. Then when a thread wants to manipulate the CClient it calls "client.Lock()", does what it needs to, then calls "client.Unlock()". The problem with this method is that I can make CMutex a member variable of the CClient class but can't get CSingleLock set up as a member variable since it needs a pointer to the CMutex object when it's constructed. I think I'd prefer using the first method as it internalizes the locking mechanism to the CClient object itself - I'm just not sure how to implement it. Can anyone point me in the proper direction? Or maybe someone has a better idea on how to handle this? Thanks! |
|
#2
|
||||
|
||||
|
Re: Locking An Entire Class
Here's what I would do:
1) You'll need to lock access to the list that tracks the clients. 2) Lock each client methods. Put a critical section object in each client and wrap the client operations with Getters/Setters. Inside the getters/setters lock and unlock the cs. See my signature line for more multi-threading articles and posts.
__________________
Arjay Need a little help with Win32 thread synchronization? Check out the following CG articles and posts: Sharing a thread safe std::queue between threads w/progress bar updating Simple Thread: Part I Simple Thread: Part II Win32 Thread Synchronization, Part I: Overview Win32 Thread Synchronization, Part 2: Helper Classes www.iridyn.com
|
|
#3
|
|||
|
|||
|
Re: Locking An Entire Class
Thanks for the suggestion Arjay. It looks as if that's the way I'm going to have to go. The only problem I see is that I need to check the status of the CClient object to determine if it is locked or not. CCriticalSection doesn't provide any provision to do that. The MSDN shows that CCriticalSection::Lock() can take a timeout as a parameter but then further down states that "Lock ignores this parameter value". I could use a boolean flag for the locking state status but why use an extra variable if I don't have to - one less thing to have to worry about. C[Single][Multi]Lock at least provide an IsLocked() method. Actually come to think of it now I could just derive a new class from CCriticalSection, encapsulate that boolean state flag in it and give it an IsLocked() method. That'll work.
Last edited by SquishyOleo; November 5th, 2009 at 10:36 AM. |
|
#4
|
||||
|
||||
|
Re: Locking An Entire Class
Why do you need to check the state? Just attempt to get a lock and if you can't get a lock, you'll know another thread has a lock and will release it soon.
I've written some synch classes that are lightweight wrappers around the critical section, mutex, and a readerwriter lock object. I also have an CAutoLock class that provides the RAII form of locking (which automatically unlocks the synch object as it goes out of scope). The following is an example of pushing an item onto a queue Code:
HRESULT PushItem( CItem* pItem )
{
HRESULT hr = S_OK;
CAutoLockT< CItemQueue > lock( &m_ItemQueue );
try
{
m_ItemQueue.push( pItem );
}
catch( std::bad_alloc )
{
hr = E_OUTOFMEMORY;
}
return hr;
}
The CAutoLockT line locks the CItemQueue lock object. You'll notice that I don't check to find out if the queue is locked before I attempt to lock it, because I don't care if it's locked. If it's already locked by another thread, my thread will block for a very short time. When the other thread has finished, my thread will obtain the lock. Because I'm using the RAII approach, I'm guaranteed that the lock will always get released even if the push operation throws some unexpected exception. With RAII, I don't have to ever worry about unlocking the object which makes my code cleaner. I'm posting the CAutoLockT snippet above, just to illustrate that you don't need to check if an object is locked first. I code all my threading with the same pattern and have yet to run into trouble.
__________________
Arjay Need a little help with Win32 thread synchronization? Check out the following CG articles and posts: Sharing a thread safe std::queue between threads w/progress bar updating Simple Thread: Part I Simple Thread: Part II Win32 Thread Synchronization, Part I: Overview Win32 Thread Synchronization, Part 2: Helper Classes www.iridyn.com
|
|
#5
|
|||
|
|||
|
Re: Locking An Entire Class
The original purpose of being able to check for whether or not a CClient is locked was to allow for a separate thread to be able to check to see if, for instance, a client was ready to be shut down or not without stopping it's own execution. But now that you mention the method of just trying to get the lock and waiting for "your turn" does make more sense. If I want to shut the thread down, I'm going to want to make sure I, and nobody else, has the client. Thanks for the suggestion.
|
|
#6
|
|||
|
|||
|
Re: Locking An Entire Class
See...Your threads must be running on some condition...
something like this.. Code:
void svc()
{
while(isRunning)
{
//do something.
}
}
Ooops...!! volatile, instead of transient.. Dont forget to declare isRunning a transient..
__________________
Dont forget to rate my post if you find it useful.
Last edited by code_carnage; November 16th, 2009 at 06:01 AM. |
![]() |
| Bookmarks |
|
||||||
| Thread Tools | Search this Thread |
| Display Modes | Rate This Thread |
|
|