Solved

Using CRITICAL_SECTION for different class instances

Posted on 2001-06-09
8
525 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
Netscaler Common Configuration How To guides

If you use NetScaler you will want to see these guides. The NetScaler How To Guides show administrators how to get NetScaler up and configured by providing instructions for common scenarios and some not so common ones.

 
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

Does Powershell have you tied up in knots?

Managing Active Directory does not always have to be complicated.  If you are spending more time trying instead of doing, then it's time to look at something else. For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Event ID 10010 3 60
Run Program using VBScript 3 65
Importing Special Characters in Dynamics GP Through Integration Manager 3 76
Need to create an object factory 2 46
This article shows how to make a Windows 7 gadget that accepts files dropped from the Windows Explorer.  It also illustrates how to give your gadget a non-rectangular shape and how to add some nifty visual effects to text displayed in a your gadget.…
This article shows how to make a Windows 7 gadget that extends its U/I with a flyout panel -- a window that pops out next to the gadget.  The example gadget shows several additional techniques:  How to automatically resize a gadget or flyout panel t…
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…
Although Jacob Bernoulli (1654-1705) has been credited as the creator of "Binomial Distribution Table", Gottfried Leibniz (1646-1716) did his dissertation on the subject in 1666; Leibniz you may recall is the co-inventor of "Calculus" and beat Isaac…

777 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