/* * Copyright (C) 2018-2023 Intel Corporation * * SPDX-License-Identifier: MIT * */ #pragma once #include "shared/source/helpers/mt_helpers.h" #include #include #include namespace NEO { template struct PtrType { }; template struct PtrType { using type = std::atomic; }; template struct PtrType { using type = NodeObjectType *; }; template using PtrType_t = typename PtrType::type; template struct IFNode { IFNode() : next(nullptr) { } virtual ~IFNode() = default; void insertOneNext(NodeObjectType &nd) { nd.next = next; next = &nd; } NodeObjectType *slice() { NodeObjectType *rest = next; next = nullptr; return rest; } void insertAllNext(NodeObjectType &rhs) { NodeObjectType *rhsTail = rhs.getTail(); rhsTail->next = next; next = &rhs; } NodeObjectType *getTail() { NodeObjectType *curr = static_cast(this); while (curr->next != nullptr) { curr = curr->next; } return curr; } std::unique_ptr deleteThisAndAllNext() { NodeObjectType *curr = this->next; while (curr != nullptr) { auto n = curr->next; delete curr; curr = n; } this->next = nullptr; return std::unique_ptr(static_cast(this)); } size_t countSuccessors() const { const NodeObjectType *curr = static_cast(this); size_t successors = 0; while (curr->next != nullptr) { curr = curr->next; ++successors; } return successors; } NodeObjectType *next; }; template class IFList { public: IFList() : head(nullptr) { } IFList(NodeObjectType *node) { head = node; } ~IFList() { this->cleanup(); } IFList(const IFList &) = delete; IFList &operator=(const IFList &) = delete; template typename std::enable_if::type pushFrontOne(NodeObjectType &node) { node.next = head; compareExchangeHead(node.next, &node); } template typename std::enable_if::type detachNodes() { NodeObjectType *rest = head; compareExchangeHead(rest, nullptr); return rest; } template typename std::enable_if::type pushFrontOne(NodeObjectType &node) { node.next = head; head = &node; } template typename std::enable_if::type detachNodes() { NodeObjectType *rest = head; head = nullptr; return rest; } template typename std::enable_if::type splice(NodeObjectType &nodes) { if (head == nullptr) { head = &nodes; } else { head->getTail()->next = &nodes; } } void deleteAll() { NodeObjectType *nodes = detachNodes(); if (nodes != nullptr) { nodes->deleteThisAndAllNext(); } } NodeObjectType *peekHead() { return head; } bool peekIsEmpty() { return (peekHead() == nullptr); } protected: template typename std::enable_if::type cleanup() { deleteAll(); } template typename std::enable_if::type cleanup() { ; } template typename std::enable_if::type compareExchangeHead(NodeObjectType *&expected, NodeObjectType *desired) { while (!NEO::MultiThreadHelpers::atomicCompareExchangeWeakSpin(head, expected, desired)) { ; } } PtrType_t head; }; template struct IFNodeRef : IFNode> { IFNodeRef(NodeObjectType *ref) : ref(ref) { } NodeObjectType *ref; }; template class IFRefList : public IFList, threadSafe, ownsNodes> { public: void pushRefFrontOne(NodeObjectType &node) { auto up = std::unique_ptr>(new IFNodeRef(&node)); this->pushFrontOne(*up); up.release(); } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) }; } // namespace NEO