Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 3360980
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 18, 20262026-05-18T03:05:00+00:00 2026-05-18T03:05:00+00:00

Consider the following code which uses non-blocking semantics to pop a stack: T Stack<T>::pop(

  • 0

Consider the following code which uses non-blocking semantics to pop a stack:

T Stack<T>::pop( ) 
{ 
    while (1) { 
        if (top == NULL) 
           throw std::string(“Cannot pop from empty stack”);
        Node* result = top;
        if (top && __sync_bool_compare_and_swap(&top, result, top->next)) { 
            return result->data;
        }
    }
}

My concern is that if the thread doing the pop got descheduled just before the 2nd if statement and by the time got back its time slice the stack’s empty is my check in 2nd loop good enough to avert a crash? Of course, in the worst case just after the comparison of top with zero the thread could get de-scheduled.

Any opinions appreciated. I am aware of the ABA problem that may also occur.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-18T03:05:00+00:00Added an answer on May 18, 2026 at 3:05 am

    Firstly, assuming top is volatile and can be changed by another thread at any point, only take its value once per loop so you won’t get the rug pulled out from under you:

    T Stack<T>::pop( )
    {
        while ( 1 ) {
            Node* result = top;
            if ( result == NULL )
                throw std::string ( “Cannot pop from empty stack” );
            // you now know result isn't NULL here 
            if ( __sync_bool_compare_and_swap ( &top, result, result -> next ) ) {
                return result -> data;
            }
        }
    }
    

    This still doesn’t solve the problem of result having been deleted or otherwise modified between getting top‘s value and dereferencing it.

    You want to use a safe sentinel instead of result -> next, so the logic is:

    • If top is null then the queue is empty
    • If top is sentinel then something else is pulling off the stack, go do something else useful.
    • If top is neither, put sentinel in top, get value from result, put result -> next in top, delete result.

    Whether this still counts as wait-free† depends on whether you can find something useful to do in the intermediate state.

    There are plenty of papers to read for more efficient ways than using a sentinel – in effect you’re simulating a two word CAS with a single CAS, since you need to check something about the state of result as well as the state of top. These are much too complicated to reproduce here.

    Not tested in any way:

    bool Stack<T>::pop ( T&out )
    {
        static const Node* const empty ( 0 );
        static const Node* const sentinel ( empty + 1 );
    
        while ( true ) {
            Node* result = top;
    
            if ( result == empty )
                throw std::string ( “Cannot pop from empty stack” );
    
            if ( result == sentinel )
                // something else is popping, return false and allow 
                // current thread to do some work before retrying
                return false;
    
            if ( __sync_bool_compare_and_swap ( &top, result, sentinel ) ) {
                // only one thread can CAS from a given result to something, 
                // so we are the only thread which has this value of result
                // hence we can dereference it and delete it/return it to a pool
                //
                // no other thread will change top if top == sentinel, so this
                // CAS can't fail
                if ( !__sync_bool_compare_and_swap ( &top, sentinel, result -> next ))
                    throw std::string ( "nobody's perfect" );
    
                out = result -> data;
                delete result;
                return true;
            }
        }
    }
    

    As you only inspect or mutate the pointee of result in the one thread at a time, it should be safe (I haven’t used this exact pattern before, and normally I end up thinking of weird cases a couple of days after I design something). Whether this ends up being any better than wrapping a std::deque with pthread_mutex_trylock is worth measuring.

    Of course, neither this nor the original is non-blocking anyway – if one thread keeps pulling off the stack, any other thread will go round the loop indefinitely waiting for the CAS to succeed. Fairly unlikely, and easily removed by returning false if the CAS does fail, but you do have to work out what you want the thread to do if it shouldn’t wait. If spinning until something can be dequeued is OK, you don’t need the return code.

    † I mostly work on x86/x64, where there’s no such thing as lock free code, as CMPXCHG implicitly locks the bus and takes time proportional to the number of caches to sync. So you can have code which doesn’t spin and wait, but you can’t have code which doesn’t lock.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Consider the following sample code which uses a TrustManager to log whether an outgoing
Consider the following code: client.Send(data, data.Length, endpoint); byte[] response = client.Receive(ref endpoint); While, according
I have a relatively simple use case which is failing. Consider the following code:
Consider the following imperative code which finds the largest palindrome among products of 3-digit
Consider the following code: uint32_t x = ~uint8_t(0); std::cout << x << std::endl; Now,
Consider the following code: $(a).attr(disabled, disabled); In IE and FF, this will make anchors
Consider the following code: void Handler(object o, EventArgs e) { // I swear o
Consider the following code: abstract class SomeClassX<T> { // blah } class SomeClassY: SomeClassX<int>
Consider the following code in VB9: Dim text = Line1<br/>Line2 Dim markup = <span><%=
Consider the following code snippet private void ProcessFile(string fullPath) { XmlTextReader rdr = new

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.