Click here to Skip to main content
15,900,254 members
Articles / Programming Languages / C++
Article

A TryEnterCriticalSection that works on Windows 9x

Rate me:
Please Sign up or sign in to vote.
2.50/5 (6 votes)
24 Sep 20022 min read 80.3K   1.2K   13   16
TryEnterCriticalSection is a useful tool to determine if some protected resource is busy, but it's only available on the NT Platform... until now.

Introduction

It wasn't too long ago that I needed to write an application where several threads were required. One of the threads in this application would be responsible for some shared resource, and the other threads would have to ask permission to gain temporary exclusive access to that shared resource. I knew that the resource did not need to be shared across multiple processes, so I wanted to avoid using expensive kernel objects. I decided to use a critical section to protect the resource where the several consuming threads would call the ::TryEnterCriticalSection() API to ask for permission and if so granted gain exclusive access to the shared resource. The only one problem with this solution was ::TryEnterCriticalSection() is only available on NT platforms, and I needed to support 9x.

The Solution

Several solutions to this problem ran through my mind. The first solution I considered was using a mutex object where the consuming threads would call the ::WaitForSingleObject() API passing 0 to the second parameter of the function (indicating that the function should try to get the mutex, but not wait for it), and checking against a return value of WAIT_OBJECT_0. The problem with this solution is it required use of the mutex kernel object, and it is a very expensive thing to switch from user to kernel mode. I decided to shelf that solution. After pondering a few other possibilities, I decided to write my own critical section class that allows for "try-enter" logic.

The CTryEnterCS class

CTryEnterCS is the fruit of that effort. It's actually quite simple to use as there are only two public methods in the class. It operates 100% in user mode, making use of the ::InterlockedExchange() and ::GetCurrentThreadId() API's. Below is a description of the public methods:

bool TryEnter()

This locks the critical section for the current thread if no other thread already owns the critical section. If the current thread already owns the critical section (reentry), the current thread is allowed to pass. Returns true if the critical section was entered; else false.
bool Leave()
This releases (leaves) ownership of the critical section if the current thread entered it (using TryEnter()). Returns true if this was successful; else false if this failed or the current thread did not own the critical section.

History

   
  •  
  • 21-Sept-2002 Initial revision.
       
  •  
  • 25-Sept-2002 TryEnter now reference counts multiple entry from the same thread; Leave decrements the count and when zero releases the lock.

    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


    Written By
    Web Developer
    United States United States
    Olan Patrick Barnes is a Senior Software Engineer at Open Text Corporation. He is currently working towards a Masters of Computer Science at Eastern Michigan University.

    Comments and Discussions

     
    GeneralQuestionable Implementation Pin
    Toby Opferman19-May-05 16:28
    Toby Opferman19-May-05 16:28 
    GeneralRe: Questionable Implementation Pin
    Toby Opferman19-May-05 16:38
    Toby Opferman19-May-05 16:38 
    GeneralRe: Questionable Implementation Pin
    Anonymous30-May-05 22:41
    Anonymous30-May-05 22:41 
    GeneralRe: Questionable Implementation Pin
    Toby Opferman31-May-05 16:09
    Toby Opferman31-May-05 16:09 
    GeneralRe: Questionable Implementation Pin
    Sreekanth Muralidharan31-May-05 20:58
    Sreekanth Muralidharan31-May-05 20:58 
    GeneralRe: Questionable Implementation Pin
    Toby Opferman1-Jun-05 5:21
    Toby Opferman1-Jun-05 5:21 
    This sounds more like a scheduling issue as when you minimize that application you just added it's GUI thread (and possibly others) to the READY List. The READY list is just the list of threads that are now ready to be run and the scheduler will simply walk through them. If your thread makes any calls into the kernel, certain APIs will cause a context switch to another thread. Interrupts that occur on the system, such as when you move your mouse or type will also cause an interruption on the current thread, which again may lead to a possible context switch as with most things, the scheduler is generally consulted on certain operations.

    Windows does not differentiate between user and kernel threads, so a user mode thread could be given a higher priority so that it would be less likely to be interrupted or not interrupted at all.

    ;  PUSH REALTIME_PRIORITY_CLASS
      PUSH HIGH_PRIORITY_CLASS
      PUSH EAX
      CALL SetPriorityClass
      
      CALL GetCurrentThread
      
    ;  PUSH THREAD_PRIORITY_TIME_CRITICAL
      PUSH THREAD_PRIORITY_ABOVE_NORMAL
      PUSH EAX
      CALL SetThreadPriority


    "Real Time" will make it impossible to interrupt your thread BTW. What you may want to consider is that you boost your thread priority while you are doing time critical work and when you are done you again lower your thread priority below normal. This is one way to help a user mode thread not become interrupted at all.

    This is just a high level view of what could be the possible problem. You could get out the kernel debugger and do some debugging though and attempt to find out what is going on with the thread. Perhaps another thread started hogging your time or its simply the fact that when you did the mouse click to minimize the application, that set off a series of events and context switches that just interrupted your thread. BTW, if you do set the thread to high priority and it takes a long time the system will either look hung or run sluggish.




    8bc7c0ec02c0e404c0cc0680f7018827ebee
    GeneralRe: Questionable Implementation Pin
    Sreekanth Muralidharan1-Jun-05 17:47
    Sreekanth Muralidharan1-Jun-05 17:47 
    GeneralRe: Questionable Implementation Pin
    Toby Opferman1-Jun-05 17:57
    Toby Opferman1-Jun-05 17:57 
    GeneralRe: Questionable Implementation Pin
    Sreekanth Muralidharan1-Jun-05 19:21
    Sreekanth Muralidharan1-Jun-05 19:21 
    QuestionWhat about EnterCriticalSection? Pin
    aufeuer22-Aug-04 18:09
    aufeuer22-Aug-04 18:09 
    AnswerRe: What about EnterCriticalSection? Pin
    Toby Opferman19-May-05 16:32
    Toby Opferman19-May-05 16:32 
    GeneralMetered Sections Pin
    Neville Franks21-Sep-02 12:04
    Neville Franks21-Sep-02 12:04 
    GeneralRe: Metered Sections Pin
    Olan Patrick Barnes21-Sep-02 12:52
    Olan Patrick Barnes21-Sep-02 12:52 
    GeneralRe: Metered Sections Pin
    mystro_AKA_kokie15-Jun-03 11:21
    mystro_AKA_kokie15-Jun-03 11:21 
    GeneralRe: Metered Sections Pin
    Neville Franks16-Jun-03 11:01
    Neville Franks16-Jun-03 11:01 

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

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