Unit Testing Refcounted Critical Section Class

Posted by BillyONeal on Stack Overflow See other posts from Stack Overflow or by BillyONeal
Published on 2010-03-11T05:18:21Z Indexed on 2010/03/11 5:23 UTC
Read the original article Hit count: 423

Hello all :)

I'm looking at a simple class I have to manage critical sections and locks, and I'd like to cover this with test cases. Does this make sense, and how would one go about doing it? It's difficult because the only way to verify the class works is to setup very complicated threading scenarios, and even then there's not a good way to test for a leak of a Critical Section in Win32. Is there a more direct way to make sure it's working correctly?

Here's the code:

CriticalSection.hpp:

#pragma once
#include <windows.h>

namespace WindowsAPI { namespace Threading {

 class CriticalSection;

 class CriticalLock
 {
  std::size_t *instanceCount;
  CRITICAL_SECTION * criticalStructure;
  bool lockValid;
  friend class CriticalSection;
  CriticalLock(std::size_t *, CRITICAL_SECTION *, bool);
 public:
  bool IsValid() { return lockValid; };
  void Unlock();
  ~CriticalLock() { Unlock(); };
 };

 class CriticalSection
 {
  std::size_t *instanceCount;
  CRITICAL_SECTION * criticalStructure;
 public:
  CriticalSection();
  CriticalSection(const CriticalSection&);
  CriticalSection& operator=(const CriticalSection&);
  CriticalSection& swap(CriticalSection&);
  ~CriticalSection();
  CriticalLock Enter();
  CriticalLock TryEnter();
 };

}}

CriticalSection.cpp:

#include "CriticalSection.hpp"

namespace WindowsAPI { namespace Threading {

CriticalSection::CriticalSection()
{
 criticalStructure = new CRITICAL_SECTION;
 instanceCount = new std::size_t;
 *instanceCount = 1;
 InitializeCriticalSection(criticalStructure);
}

CriticalSection::CriticalSection(const CriticalSection& other)
{
 criticalStructure = other.criticalStructure;
 instanceCount = other.instanceCount;
 instanceCount++;
}

CriticalSection& CriticalSection::operator=(const CriticalSection& other)
{
 CriticalSection copyOfOther(other);
 swap(copyOfOther);
 return *this;
}

CriticalSection& CriticalSection::swap(CriticalSection& other)
{
 std::swap(other.instanceCount, instanceCount);
 std::swap(other.criticalStructure, other.criticalStructure);
 return *this;
}

CriticalSection::~CriticalSection()
{
 if (!--(*instanceCount))
 {
  DeleteCriticalSection(criticalStructure);
  delete criticalStructure;
  delete instanceCount;
 }
}

CriticalLock CriticalSection::Enter()
{
 EnterCriticalSection(criticalStructure);
 (*instanceCount)++;
 return CriticalLock(instanceCount, criticalStructure, true);
}

CriticalLock CriticalSection::TryEnter()
{
 bool lockAquired;
 if (TryEnterCriticalSection(criticalStructure))
 {
  (*instanceCount)++;
  lockAquired = true;
 }
 else
  lockAquired = false;
 return CriticalLock(instanceCount, criticalStructure, lockAquired);
}

void CriticalLock::Unlock()
{
 if (!lockValid)
  return;
 LeaveCriticalSection(criticalStructure);
 lockValid = false;
 if (!--(*instanceCount))
 {
  DeleteCriticalSection(criticalStructure);
  delete criticalStructure;
  delete instanceCount;
 }
}

}}

© Stack Overflow or respective owner

Related posts about c++

Related posts about unit-testing