5,699,997 members and growing! (12,040 online)
Email Password   helpLost your password?
Languages » C / C++ Language » Templates     Beginner License: The Code Project Open License (CPOL)

Lock Free Queue implementation in C++ and C#

By Idaho Edokpayi

Lock Free Queue implementation in C++ and C#
C++, C#, Windows, Dev

Posted: 30 Jan 2008
Updated: 23 Feb 2008
Views: 21,502
Bookmarked: 41 times
Announcements
Loading...



Search    
Advanced Search
Sitemap
11 votes for this Article.
Popularity: 3.47 Rating: 3.33 out of 5
3 votes, 27.3%
1
1 vote, 9.1%
2
1 vote, 9.1%
3
3 votes, 27.3%
4
3 votes, 27.3%
5
Note: This is an unedited contribution. If this article is inappropriate, needs attention or copies someone else's work without reference then please Report This Article

Introduction

This article demonstrates implementation of a "lock free" queue in C# and C++. Lock free queues are typically used in multi-threaded architectures to communicate between threads without fear of data corruption or performance loss due to threads waiting to use shared memory. The goal of the article is to familiarize readers with lock free queues and provide a starting point to writing wait-free production architectures. It should be noted that using lock-free queues is only the beginning - a true lock free architecture use a lock free memory allocator. Implementing lock free memory allocators is beyond the scope of this article however.

Background

Recent developments in CPU architecture has necessitated a change in thinking in high performance software architecture - multithreaded software. Communication between threads in multithreaded architecture has traditionally been accomplished using mutexes, critical sections, and locks. Recent research in algorithms and changes in computer architecture has led to the introduction of "wait free", "lock free", or "non-blocking" data structures. The most popular and possibly the most important is the queue, a First In First Out (FIFO) data structure.

The key to the majority of lock free data structures is an instruction known as Compare and Swap (CAS). The flow chart below describes what Compare and Swap does. For the assembler coders out there the instruction is named CMPXCHG on X86 and Itanium architectures. The special thing about this instruction is that it is atomic- meaning that other threads\processes cannot interrupt until it is finished. Operating Systems use atomic operations to implement sychronization - locks, mutexes, semaphores, and critical sections.

My code draws on research by Maged M. Michael and Michael L. Scott on non-blocking and blocking concurrent queue algorithms. In fact, an implementation of their queue is now part of the Java concurrency library. Their paper demonstrates why the queue is "linearizable" and "lock free". An implementation of the code in C is available here in tar.gz format. The idea is that pointers are reference counted and checked for consistency in a loop. The reference count is meant to prevent what is referred to the "ABA problem" - if a process or threads reads a value 'A' then attempts a CAS operation, the CAS operation might succeed incorrectly if a second thread or process changes value 'A' to 'B' and then back again to 'A'. If the "ABA" problem never occurs the code is safe because:

  1. The linked list is always connected.
  2. Nodes are only inserted at the end of the linked list and only inserted to a node that has a NULL next pointer.
  3. Nodes are deleted from the beginning of the list because they are only deleted from the head pointer and head always points to the first element of the list.
  4. Head always points to the first element of the list and only changes it's value atomically.

If CAS or similar instructions are not available I suggest using the STL queue or a similar queue with traditional sychronization primitives. Michael and Scott also present a "two lock" queue data structure.

Using the code

UML Diagram of sourceLockFreeQueue.jpg

Using the code provided with this article is simple.

  • C++ class declaration template< class T > class MSQueue
    • Include the "lockfree.h" file. #include "LockFreeQ.h"
    • Declare C++ queues like this: MSQueue< int > Q;
    • Add items to the queue: Q.enqueue(i);
    • Remove items from the queue: bool bIsQEmpty = Q.dequeue(i); dequeue returns false if the queue is empty and the value of i would be undefined.
  • C# class declaration namespace Lockfreeq { public class MSQueue {
    • Include the Lock Free Queue DLL: using Lockfreeq;
    • Declare a C# queue: MSQueue< int > Q = new MSQueue< int >();
    • Add items to the queue: Q.enqueue(i);
    • Remove items from the queue: bool bIsQEmpty = Q.dequeue(ref i); dequeue returns false if the queue is empty and the value of i would be undefined.

Points of Interest

Did you know that Valve Software (makers of Half-Life computer game) have switched to a wait free architecture?

History

  • This is my first article! (30.1.2008)
  • Revised 21:00 30.1.2008 (Thanks to the early commenters for spotting those mistakes!)
  • Noted need for memory allocator. 31.1.2008
  • Revision to correct inaccuracy with regards to Java Concurrency library.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Idaho Edokpayi


Idaho Edokpayi is a Consultant working in EMC's Microsoft Practice specializing in WSS 3.0, MOSS 07, .NET, and ASP.NET technology. He also likes to write C++, Win32/64 API, and DirectX code in his spare time.
Occupation: Web Developer
Company: EMC Corporation
Location: United States United States

Other popular C / C++ Language articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 25 of 33 (Total in Forum: 33) (Refresh)FirstPrevNext
Generalstress test not workingmemberhagai_sela2:08 28 Jul '08  
GeneralHellomembernidal1020027:38 8 Apr '08  
GeneralStill a bug. [modified]memberPatrick Twohig15:25 7 Apr '08  
GeneralRe: Still a bug.memberIdaho Edokpayi16:36 5 May '08  
GeneralIs there still a chance of bug?memberMember 122023:00 26 Feb '08  
GeneralRe: Is there still a chance of bug?memberIdaho Edokpayi3:35 27 Feb '08  
GeneralRe: Is there still a chance of bug?memberLanceDiduck10:30 18 Apr '08  
GeneralJava Concurrency LibrarymemberMike O'Neill15:09 21 Feb '08  
GeneralRe: Java Concurrency LibrarymemberIdaho Edokpayi15:45 23 Feb '08  
GeneralCritical Section on the Stack? How Can It Provide Protection/Synchronization?memberMike O'Neill16:11 20 Feb '08  
GeneralRe: Critical Section on the Stack? How Can It Provide Protection/Synchronization?memberIdaho Edokpayi15:48 23 Feb '08  
GeneralRe: Critical Section on the Stack? How Can It Provide Protection/Synchronization?memberopflucker16:13 5 May '08  
GeneralRe: Critical Section on the Stack? How Can It Provide Protection/Synchronization?memberIdaho Edokpayi16:29 5 May '08  
GeneralPerformance problem...memberjahuh14:28 6 Feb '08  
GeneralRe: Performance problem...memberIdaho Edokpayi3:39 7 Feb '08  
GeneralPatents?memberThe Wizard of Doze6:58 3 Feb '08  
GeneralRe: Patents?memberIdaho Edokpayi9:26 3 Feb '08  
GeneralRe: Patents?memberThe Wizard of Doze13:18 5 Feb '08  
GeneralRe: Patents?membersupercat98:59 4 Jul '08  
GeneralHeap operation is blockingmemberRicky Lung18:34 30 Jan '08  
GeneralRe: Heap operation is blockingmemberIdaho Edokpayi14:52 31 Jan '08  
GeneralRe: Heap operation is blockingmemberdasblinkenlight10:08 25 Nov '08  
GeneralRe: Heap operation is blockingmembersupercat99:03 4 Jul '08  
GeneralWhere is the C# version?memberDewey16:05 30 Jan '08  
GeneralRe: Where is the C# version?memberDewey22:17 31 Jan '08