// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Tries to extract the top object of the stack. // If the stack is empty, the method returns nullptr. T* Pop() { T* node; int waitCount = 0; // Used for back off. time_ = ThreadUtils::GetSystemTime(); while(true) { HeadType oldHead = Memory::ReadValue(&head_); node = oldHead.GetFirst(); if(node == nullptr) { return nullptr; // The stack is empty; } // Is 'head' still the same? if(oldHead == Memory::ReadValue(&head_)) { HeadType newHead = HeadType(oldHead.GetCount() - 1, node->Next); if(CompareExchange(oldHead, newHead)) { return node; // The head was successfully updated. } } if((++waitCount % 50) == 0) { // Give threads with a lower priority a chance to run. ThreadUtils::SwitchToThread(); } else { // Backoff. for(int i = 0; i < waitCount; i++) { ThreadUtils::Wait(); } } } }
U32 Interlocked::Add(U32 * addr, U32 value) { volatile U32 addrValue,sum; do { addrValue = *addr; sum = addrValue + value; if(CompareExchange(addr,sum,addrValue) == addrValue) return sum; }while(true); }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Tries to insert an object in the stack. // If the maximum number of objects is reached, the object // isn't inserted anymore and the method returns the address of the object. // If the object could be inserted, the method returns nullptr. T* Push(T* node) { int waitCount = 0; // Used for back off. time_ = ThreadUtils::GetSystemTime(); while(true) { HeadType oldHead = Memory::ReadValue(&head_); if(oldHead.GetCount() >= maxObjects_) { return node; // The stack has reached the maximum number of objects. } // Set the new head of the stack and update the oldest location. HeadType newHead = HeadType(oldHead.GetCount() + 1, node); // Is 'head' still the same? if(oldHead == Memory::ReadValue(&head_)) { // Link the node to the current head of the stack. node->Next = oldHead.GetFirst(); if(CompareExchange(oldHead, newHead)) { T* temp = newHead.GetFirst(); temp->Next = temp->Next; return nullptr; // The head was successfully updated. } } if((++waitCount % 50) == 0) { // Give threads with a lower priority a chance to run. ThreadUtils::SwitchToThread(); } else { // Back off. for(int i = 0; i < waitCount; i++) { ThreadUtils::Wait(); } } } }