
                           Manual for csext
                     (c) 2000-2020 Jaroslav fojtik
======================================================================

CSext provides compatibility layer for Windows and Unix based systems.


How to use csext.h


Object CritSectionWrapper provides automatic initialisation of critical
section. When you use it, you do not need to care about destruction of 
critical section.


The simple ussage
=================


CritSectionWrapper MyCriticalSection;


void thread1(void)
{
.........


  MyCriticalSection.Lock();
    
  ... some stuff ...

  MyCriticalSection.Unlock();

.........
}


void thread2(void)
{
.........


  MyCriticalSection.Lock();
    
  ... some stuff ...

  MyCriticalSection.Unlock();

.........
}


This code works as expected, but there is a major hidden danger that arises from exceptions.
When exception occurs inside critical section, it is NEVER unlocked.
You can use this code only when you are absolutelly sure that no exception is emitted from inner
block e.g. access to some variable. Or that all possible exceptions are catched.


Exception-safe ussage:
======================

CritSectionWrapper MyCriticalSection;


void thread1(void)
{
.........

  {
    CritSectionLocker Lock(MyCriticalSection.cs);
    
    ... some stuff ...

  }   // The critical section is automatically unlocked at the end of block.

.........
}


void thread2(void)
{
.........


  {
    CritSectionLocker Lock(MyCriticalSection.cs);
    
    ... some stuff ...

  }   // The critical section is automatically unlocked at the end of block.

.........
}

This code is really exception safe. Any local object on the stack is automatically destroyed.
The "Lock" object causes to release critical section during its destruction.



Advanced usage
===============

Sometime you need critical section that allows either one exclusive Write access or many concurrent read only 
accesses. For this case you can use class 'CriticalSectionExt'.


The simple case
---------------


CriticalSectionExt MyCriticalSectionE;

void thread1(void)
{
.........


  MyCriticalSectionE.LockRW();
    
  ... some stuff ...

  MyCriticalSectionE.UnlockRW();

.........
}


void thread2(void)
{
.........


  MyCriticalSectionE.LockRO();
    
  ... some stuff ...

  MyCriticalSectionE.UnlockRO();

.........
}


void thread3(void)
{
.........


  MyCriticalSectionE.LockRO();
    
  ... some stuff ...

  MyCriticalSectionE.UnlockRO();

.........
}


This code allows simultaneous access from "thread2" and "thread3" or exclusive access
from "thread1". Of course there exists same danger as mentioned in previous text.
Code is not exception safe. Use it only when you are absolutelly sure, that no exception can occur.
Or in a case when a code is compiled without exception support.


For the case when exceptions are needed, two additiona objects are defined.
CriticalSectionExtROLocker and CriticalSectionExtRWLocker.



The exception safe case
-----------------------


CriticalSectionExt MyCriticalSectionE;

void thread1(void)
{
.........

  {
    CriticalSectionExtRWLocker(MyCriticalSectionE);
    
     ... some stuff ...

  }

.........
}


void thread2(void)
{
.........

  {
     CriticalSectionExtROLocker(MyCriticalSectionE);
    
  ... some stuff ...

  }

.........
}


void thread3(void)
{
.........


  {
     CriticalSectionExtROLocker(MyCriticalSectionE);
    
  ... some stuff ...

  }
.........
}


This is the most complex example that is really exception safe.

