Solved

Using CRITICAL_SECTION for different class instances

Posted on 2001-06-09
8
521 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
Comment Utility
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
Comment Utility
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
Comment Utility
>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
 
LVL 9

Expert Comment

by:ShaunWilde
Comment Utility
> 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
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 
LVL 1

Author Comment

by:olegsp
Comment Utility
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
Comment Utility
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
Comment Utility
> 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
Comment Utility
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

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

For a while now I'v been searching for a circular progress control, much like the one you get when first starting your Silverlight application. I found a couple that were written in WPF and there were a few written in Silverlight, but all appeared o…
A theme is a collection of property settings that allow you to define the look of pages and controls, and then apply the look consistently across pages in an application. Themes can be made up of a set of elements: skins, style sheets, images, and o…
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…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…

728 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

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now