/*
  * Progress condition: lock-free
  *
  * The dequeue() marks the node that has the item as "logically removed"
  * by setting the "marked" bit in node.next
  * By default, the "head" is pointing to the first node that has not been
  * "logically removed", but if it's the last node (node.next is nullptr),
  * then the head will be pointing to the last "logically removed" node.
  */
 T* dequeue(const int tid) {
     HPGuard hpguard { hp, tid }; // RAII to call hp.clear(tid) when returning
     while (true) {
         Node* lhead = hp.protectPtr(kHpHead, head.load(), tid);
         if (lhead != head.load()) continue;
         Node* lcurr = lhead;
         for (int i = 0; ;) {
             Node* lnext = lcurr->next.load();
             if (lnext == getMarked(nullptr)) {
                 if (lhead != lcurr && casHead(lhead, lcurr)) retireSubList(lhead, lcurr, tid);
                 return nullptr; // Queue is empty
             }
             if (isMarked(lnext)) {
                 hp.protectPtr(kHpNext+(i&0x1), getUnmarked(lnext), tid); // Alternate hps during traversal
                 if (lhead != head.load()) break;
                 lcurr = getUnmarked(lnext);
                 i++;
                 continue;
             }
             if (!lcurr->next.compare_exchange_strong(lnext, getMarked(lnext))) continue;
             T* item = lcurr->item;
             if (lcurr != lhead && casHead(lhead, lcurr)) retireSubList(lhead, lcurr, tid);
             return item;
         }
     }
 }
 /*
  * Progress condition: lock-free
  *
  * If we don't know maxThreads, we can replace the for() loop with a
  * while(true) and it will still be correct.
  */
 void enqueue(T* item, const int tid) {
     if (item == nullptr) throw std::invalid_argument("item can not be nullptr");
     HPGuard hpguard { hp, tid }; // RAII to call hp.clear(tid) when returning
     Node* newNode = new Node(item);
     while (true) {
         Node* ltail = hp.protectPtr(kHpTail, tail.load(), tid);
         if (ltail != tail.load()) continue;
         Node* lnext = ltail->next.load();
         if (getUnmarked(lnext) != nullptr) {         // Advance the tail first
             casTail(ltail, getUnmarked(lnext));      // "tail" is always unmarked
         } else {
             for (int i=0; i < 2; i++) {
                 Node* newNodeMark = isMarked(lnext) ? getMarked(newNode) : newNode; // lnext here is either nullptr or nullptr|0x1
                 newNode->next.store(nullptr, std::memory_order_relaxed);
                 if (ltail->next.compare_exchange_strong(lnext, newNodeMark)) {
                     casTail(ltail, newNode);
                     return;
                 }
                 lnext = ltail->next.load();
                 if (getUnmarked(lnext) != nullptr) {
                     casTail(ltail, getUnmarked(lnext));      // "tail" is always unmarked
                     break;
                 }
             }
         }
         for (int i = 0; i < maxThreads-1; i++) {       // This loop will run at most maxThreads because the CAS can fail at most maxThreads
             lnext = ltail->next.load();
             if (isMarked(lnext)) break;    // This node has been dequeued, must re-read tail. It's ok to be marked as long as it's the first and therefore, nullptr
             newNode->next.store(lnext, std::memory_order_relaxed);
             if (ltail->next.compare_exchange_strong(lnext, newNode)) return;
         }
     }
 }
 BitNextLazyHeadQueue(int maxThreads=MAX_THREADS) : maxThreads{maxThreads} {
     Node* sentinelNode = new Node(nullptr);
     // The sentinel is already "logically removed"
     sentinelNode->next.store(getMarked(nullptr), std::memory_order_relaxed);
     head.store(sentinelNode, std::memory_order_relaxed);
     tail.store(sentinelNode, std::memory_order_relaxed);
 }
    /**
     * This method is named 'Delete()' in the original paper.
     * Taken from Figure 7 of the paper:
     * "High Performance Dynamic Lock-Free Hash Tables and List-Based Sets"
     */
    bool remove(T* key, const int tid)
    {
        Node *curr, *next;
        std::atomic<Node*> *prev;
        while (true) {
            /* Try to find the key in the list. */
            if (!find(key, &prev, &curr, &next, tid)) {
                return false;
            }
            /* Mark if needed. */
            Node *tmp = getUnmarked(next);
            if (!curr->next.compare_exchange_strong(tmp, getMarked(next))) {
                continue; /* Another thread interfered. */
            }

            tmp = getUnmarked(curr);
            prev->compare_exchange_strong(tmp, getUnmarked(next)); /* Unlink */
            /*
             * If we want to prevent the possibility of there being an
             * unbounded number of unmarked nodes, add "else _find(head,key)."
             * This is not necessary for correctness.
             */
            return true;
        }
    }
Пример #5
0
string Polynomial::toString(bool latex/*, bool mathMode*/)const
{
  stringstream s;
  /*
  if(latex && !mathMode)
    s << "$";
  */
  bool first=true;

  if(terms.empty())
    {
      s << "0";
      return s.str();
    }
  // If the polynomial has a marked term it is written first
  //   printString("_");
  IntegerVector e=getMarked().m.exponent;
  for(TermMap::const_iterator i=terms.begin();i!=terms.end();i++)
    if(e==i->first.exponent)
      {
	s << i->second.toString(i->first.exponent.isZero(),!first,latex);
	if((!i->first.exponent.isZero())&&(!i->second.isOne())&&(!(-(i->second)).isOne()))s<<"*";
	s << i->first.toString(false,false,latex);
	first=false;
      }
  //    printString("_");
  for(TermMap::const_iterator i=terms.begin();i!=terms.end();i++)
    if(e!=i->first.exponent)
      {
	s << i->second.toString(i->first.exponent.isZero(),!first,latex);
	if((!i->first.exponent.isZero())&&(!i->second.isOne())&&(!(-(i->second)).isOne()))s<<"*";
	s << i->first.toString(false,false,latex);
	/*	printFieldElement(i->second,i->first.exponent.isZero(),!first);
	if((!i->first.exponent.isZero())&&(!i->second.isOne())&&(!(-(i->second)).isOne()))printString("*");
	printMonomial(i->first,false,false);*/
	first=false;
      }
  /*  if(latex && !mathMode)
    s << "$";
  */
   return s.str();
}