38#ifndef DISPENSO_GRAPH_DEPENDENTS_INLINE_SIZE
39#define DISPENSO_GRAPH_DEPENDENTS_INLINE_SIZE 4
43 DISPENSO_GRAPH_DEPENDENTS_INLINE_SIZE >= 1 && DISPENSO_GRAPH_DEPENDENTS_INLINE_SIZE <= 64,
44 "DISPENSO_GRAPH_DEPENDENTS_INLINE_SIZE must be between 1 and 64");
230void callFunctor(
void* ptr) {
231 (*
static_cast<F*
>(ptr))();
235void destroyFunctor(
void* ptr) {
236 static_cast<F*
>(ptr)->~F();
237 constexpr size_t kFuncSize =
static_cast<size_t>(dispenso::detail::nextPow2(
sizeof(F)));
238 dispenso::deallocSmallBuffer<kFuncSize>(ptr);
256 Node& operator=(
const Node&) =
delete;
259 : numIncompletePredecessors_(other.numIncompletePredecessors_.load()),
260 numPredecessors_(other.numPredecessors_),
261 invoke_(other.invoke_),
262 destroy_(other.destroy_),
263 funcBuffer_(other.funcBuffer_),
264 dependents_(std::move(other.dependents_)) {
265 other.funcBuffer_ =
nullptr;
269 destroy_(funcBuffer_);
277 template <
typename... Ns>
279 ((void)std::initializer_list<int>{(dependsOnOneNode(nodes), 0)...});
286 invoke_(funcBuffer_);
287 numIncompletePredecessors_.store(kCompleted, std::memory_order_release);
296 for (
const Node* dependent : dependents_) {
307 for (
Node* dependent : dependents_) {
315 return numPredecessors_;
324 return numIncompletePredecessors_.load(std::memory_order_relaxed) == kCompleted;
334 if (numIncompletePredecessors_.load(std::memory_order_relaxed) == kCompleted) {
335 numIncompletePredecessors_.store(0, std::memory_order_relaxed);
347 numIncompletePredecessors_.store(kCompleted, std::memory_order_relaxed);
352#if DISPENSO_HAS_CONCEPTS
354 requires(!std::derived_from<std::remove_cvref_t<F>,
Node>)
355 Node(F&& f) : numIncompletePredecessors_(0) {
357 template <class F, class X = std::enable_if_t<!std::is_base_of<Node, F>::value,
void>>
358 Node(F&& f) : numIncompletePredecessors_(0) {
360 using FNoRef =
typename std::remove_reference<F>::type;
362 constexpr size_t kFuncSize =
static_cast<size_t>(detail::nextPow2(
sizeof(FNoRef)));
363 funcBuffer_ = allocSmallBuffer<kFuncSize>();
364 new (funcBuffer_) FNoRef(std::forward<F>(f));
365 invoke_ = ::detail::callFunctor<FNoRef>;
366 destroy_ = ::detail::destroyFunctor<FNoRef>;
369 void dependsOnOneNode(
Node& node) {
370 node.dependents_.emplace_back(
this);
374 static constexpr size_t kCompleted = std::numeric_limits<size_t>::max();
375 mutable std::atomic<size_t> numIncompletePredecessors_;
376 size_t numPredecessors_ = 0;
379 using InvokerType = void (*)(
void* ptr);
382 InvokerType destroy_;
385 SmallVector<Node*, DISPENSO_GRAPH_DEPENDENTS_INLINE_SIZE> dependents_;
388 friend class SubgraphT;
389 friend class detail::ExecutorBase;
390 template <
typename G>
391 friend void setAllNodesIncomplete(
const G& graph);
404 :
Node(std::move(other)), biPropSet_(std::move(other.biPropSet_)) {}
411 template <
class... Ns>
413 ((void)std::initializer_list<int>{(biPropDependsOnOneNode(nodes), 0)...});
422 return biPropSet_ && biPropSet_ == node.biPropSet_;
426#if DISPENSO_HAS_CONCEPTS
428 requires(!std::derived_from<std::remove_cvref_t<T>,
BiPropNode>)
431 template <class T, class X = std::enable_if_t<!std::is_base_of<BiPropNode, T>::value,
void>>
432 BiPropNode(T&& f) : Node(std::forward<T>(f)) {}
434 inline void removeFromBiPropSet() {
435 if (biPropSet_ !=
nullptr) {
436 auto it = std::find(biPropSet_->begin(), biPropSet_->end(),
this);
437 if (it != biPropSet_->end()) {
438 biPropSet_->erase(it);
443 DISPENSO_DLL_ACCESS
void biPropDependsOnOneNode(BiPropNode& node);
445 std::shared_ptr<std::vector<const BiPropNode*>> biPropSet_;
448 friend class SubgraphT;
449 friend class detail::ExecutorBase;
469 : graph_(other.graph_),
470 nodes_(std::move(other.nodes_)),
471 allocator_(std::move(other.allocator_)) {}
480 DISPENSO_REQUIRES(OnceCallableFunc<T>)
482 nodes_.push_back(
new (allocator_->alloc()) NodeType(std::forward<T>(f)));
483 return *nodes_.back();
489 return nodes_.size();
507 const N&
node(
size_t index)
const {
508 return *nodes_[index];
516 return *nodes_[index];
525 for (
const N* node : nodes_) {
537 for (N* node : nodes_) {
549 using PoolPtr = std::unique_ptr<NoLockPoolAllocator, DeallocFunc>;
551 static constexpr size_t kNodeSizeP2 =
static_cast<size_t>(detail::nextPow2(
sizeof(NodeType)));
553 explicit SubgraphT(
GraphT<N>* graph) : graph_(graph), nodes_(), allocator_(getAllocator()) {}
555 inline void removeNodeFromBiPropSet(
Node* ) {}
556 void removeNodeFromBiPropSet(BiPropNode* node) {
557 node->removeFromBiPropSet();
559 void decrementDependentCounters();
560 size_t markNodesWithPredicessors();
561 void removePredecessorDependencies(
size_t numGraphPredecessors);
565 static PoolPtr getAllocator();
566 static void releaseAllocator(NoLockPoolAllocator* ptr);
569#if defined(_WIN32) && !defined(__MINGW32__)
571#pragma warning(disable : 4251)
573 std::vector<N*> nodes_;
576#if defined(_WIN32) && !defined(__MINGW32__)
621 DISPENSO_REQUIRES(OnceCallableFunc<T>)
623 return subgraphs_[0].addNode(std::forward<T>(f));
629 return subgraphs_[0].numNodes();
635 subgraphs_[0].reserve(n);
642 const N&
node(
size_t index)
const {
643 return subgraphs_[0].node(index);
651 return subgraphs_[0].node(index);
661 return subgraphs_.size();
669 return subgraphs_[index];
677 return subgraphs_[index];
710 for (
const N* node : subgraph.nodes_) {
723 for (N* node : subgraph.nodes_) {
740 subgraph.destroyNodes();
745 static constexpr size_t kSubgraphSizeP2 =
746 static_cast<size_t>(detail::nextPow2(
sizeof(SubgraphType)));
748#if defined(_WIN32) && !defined(__MINGW32__)
750#pragma warning(disable : 4251)
752 std::deque<SubgraphT<N>> subgraphs_;
753#if defined(_WIN32) && !defined(__MINGW32__)
BiPropNode(BiPropNode &&other) noexcept
bool isSameSet(const BiPropNode &node) const
void biPropDependsOn(Ns &... nodes)
void forEachNode(F &&func) const
void forEachNode(F &&func)
void forEachSubgraph(F &&func) const
size_t numSubgraphs() const
void forEachSubgraph(F &&func)
const SubgraphT< N > & subgraph(size_t index) const
GraphT(GraphT< N > &&other)
const N & node(size_t index) const
SubgraphT< N > & subgraph(size_t index)
SubgraphT< N > & addSubgraph()
bool setIncomplete() const
void setCompleted() const
void forEachDependent(F &&func) const
void forEachDependent(F &&func)
void dependsOn(Ns &... nodes)
size_t numPredecessors() const
Node(Node &&other) noexcept
const N & node(size_t index) const
void forEachNode(F &&func) const
void forEachNode(F &&func)
SubgraphT(SubgraphT< N > &&other) noexcept