Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

Using CRITICAL_SECTION for different class instances

Posted on 2001-06-09
8
526 Views
Last Modified: 2013-12-03
I have some
class ResourceUser
{
?
     // Pointer to some data used by this class instance
     void* m_pResourcePointer;    

     // Attach data pointer to the class instance
     void AttachResourcePointer(void* p)
     {
       if(!p) m_pResourcePointer = p;
     }

     // Do some resource processing
     void ProcessResource()
     {
      ::EnterCriticalSection(&m_CS);
      // Do something with m_pResourcePointer
      ::LeaveCriticalSection(&m_CS);
     }

     // Critical Section
     static CRITICAL_SECTION m_CS;

?
}
and I use several instances of this class in my program:
     ResourceUser RU1, RU2;
     RU1. AttachResourcePointer(p1);
     RU2. AttachResourcePointer(p2);
Here p1 and p2 are some resource pointers (FILE*, for example), used by the two instances of ResourceUser. The problem is that both RU1 and RU2 are accessed by several threads in my program, and to make it safe, I use critical section m_CS in methods like ProcessResource() as shown above. However, RU1 And RU2 are using different resources ? so, if I declare m_CS as static to make it globally unique, any thread access to RU1 resource will also block the RU2 resource ? I do not want this to happen. How can I fix that? What happens, for instance, if I remove ?static? from the m_CS declaration ? will this contradict the usage of CRITICAL_SECTION ? In other words, how do I declare/use the critical section in my class so that using it in one class instance will not block another class instance ?
I certainly do not want to declare several static m_CS1, m_CS2 etc. just to use each particular m_CSn for its instance only ? the number of class instances in use changes dynamically.
0
Comment
Question by:olegsp
  • 3
  • 2
  • 2
  • +1
8 Comments
 
LVL 9

Accepted Solution

by:
ShaunWilde earned 200 total points
ID: 6171928
for global resources use the static keyword - however for the situation you are describing where you are protecting a class level resource then you can remove the static keyword.

you might make it easier to manage by binding the CS to the resource object rather than the class that is using the resource


void ProcessResource();
{
  ::EnterCriticalSection(m_pResourcePointer->m_CS)
  // work on m_pResourcePointer
  ::LeaveCriticalSection(m_pResourcePointer->m_CS)
}
0
 
LVL 5

Expert Comment

by:robpitt
ID: 6172242
It sounds to me like you would benifit from two critical sections.

The first for synchronised access to the shared data that m_pResourcePointer might point to.
And the second for synchronised access to an actual objects member data.

The second should be a normal class member. Arguably the first is actually a property of the shared data though this could be implemented as a static class member.

Rob
0
 
LVL 1

Author Comment

by:olegsp
ID: 6172459
>you can remove the static keyword
But if my critical section m_CS variable is not static (global), wouldn't every thread allocate its own copy of m_CS, making it thus useless ? This is something I do not know, please explain.


>you might make it easier to manage by binding the CS to >the resource object rather than the class that
>is using the resource
I thought about that, but I do not want to take this approach. My critical section code is a little bit more complex than just access to the resource pointer, so I need to keep the critical section variable in my ResourceUser class
0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 9

Expert Comment

by:ShaunWilde
ID: 6172847
> But if my critical section m_CS variable is not static
> (global), wouldn't every thread allocate its
> own copy of m_CS, making it thus useless ?

no if you made it a member of the class then you would have 1 CS per class - unless it was static then you would have 1 CS for all instances of the class

what scope you use for your critical section depends on the resource you are protecting

if the resource is 1 per class then you can use 1 CS per resource - if you use a resource between classes then you will need 1 CS per resource - so really it is 1 CS per resource

by resource I mean a collection of data (eg structure) or some other data that can only be accessed by 1 thread at a time
0
 
LVL 1

Author Comment

by:olegsp
ID: 6173647
Last question: is there a way to set a timeout value for the thread blocking ? I.e., when a thread is blocked at
     ::EnterCriticalSection(&m_CS);
it won't wait infinitely, and if the resource does not become available in some nTimeout seconds, the thread will exit without attempting to access the blocked resource?
I know one can do something like that with TryEnterCriticalSection(), but it is supported only on Win NT and 2000, I guess.
0
 
LVL 1

Expert Comment

by:Ziv
ID: 6189700
If you want to do this you can use Event object, ie CreateEvent(),
And then use WaitForSingleObject() with timeout and SetEvent() and ResetEvent() to change it's flag.
This would work on all OS's.
0
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 6189877
> TryEnterCriticalSection
the docs say it is unsupported but it does surprise me that this 1 CS related function isn't supported - even CE supports it. (the docs may be wrong - it wouldn't be the first time)

have a look at the exports of kernel32.dll on your 95/98/me machine and see if it is in there (use quick view and it might be ordinal 252)
0
 
LVL 1

Expert Comment

by:Ziv
ID: 6189940
It dosen't exist on the 95/8/me kernel32.dll (checked it).
I'd sugest you'd use the WaitForSingleObject() with Event Object, it's well documented, and works for me just fine!

Peeping again at your question.. even though you didn't mention what you want to do! using "Thread Local Storage" API might solve your problem in a more elegant way: Use TlsAlloc() and TlsSetValue(), TlsGetValue() to manage each thread private resource, and keep using the static CS to protect the global resource.
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

With most software applications trying to cater to multiple user needs nowadays, the focus is to make them as configurable as possible. For e.g., when creating Silverlight applications which will connect to WCF services, the service end point usuall…
After several hours of googling I could not gather any information on this topic. There are several ways of controlling the USB port connected to any storage device. The best example of that is by changing the registry value of "HKEY_LOCAL_MACHINE\S…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
Two types of users will appreciate AOMEI Backupper Pro: 1 - Those with PCIe drives (and haven't found cloning software that works on them). 2 - Those who want a fast clone of their boot drive (no re-boots needed) and it can clone your drive wh…

860 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question