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");
232void callFunctor(
void* ptr) {
233 (*
static_cast<F*
>(ptr))();
237void destroyFunctor(
void* ptr) {
238 static_cast<F*
>(ptr)->~F();
239 constexpr size_t kFuncSize =
static_cast<size_t>(dispenso::detail::nextPow2(
sizeof(F)));
240 dispenso::deallocSmallBuffer<kFuncSize>(ptr);
251 Node& operator=(
const Node&) =
delete;
254 : numIncompletePredecessors_(other.numIncompletePredecessors_.load()),
255 numPredecessors_(other.numPredecessors_),
256 invoke_(other.invoke_),
257 destroy_(other.destroy_),
258 funcBuffer_(other.funcBuffer_),
259 dependents_(std::move(other.dependents_)) {
260 other.funcBuffer_ =
nullptr;
264 destroy_(funcBuffer_);
272 template <
typename... Ns>
274 ((void)std::initializer_list<int>{(dependsOnOneNode(nodes), 0)...});
281 invoke_(funcBuffer_);
282 numIncompletePredecessors_.store(kCompleted, std::memory_order_release);
291 for (
const Node* dependent : dependents_) {
302 for (
Node* dependent : dependents_) {
310 return numPredecessors_;
319 return numIncompletePredecessors_.load(std::memory_order_relaxed) == kCompleted;
329 if (numIncompletePredecessors_.load(std::memory_order_relaxed) == kCompleted) {
330 numIncompletePredecessors_.store(0, std::memory_order_relaxed);
342 numIncompletePredecessors_.store(kCompleted, std::memory_order_relaxed);
347#if DISPENSO_HAS_CONCEPTS
349 requires(!std::derived_from<std::remove_cvref_t<F>,
Node>)
350 Node(F&& f) : numIncompletePredecessors_(0) {
352 template <class F, class X = std::enable_if_t<!std::is_base_of<Node, F>::value,
void>>
353 Node(F&& f) : numIncompletePredecessors_(0) {
355 using FNoRef =
typename std::remove_reference<F>::type;
357 constexpr size_t kFuncSize =
static_cast<size_t>(detail::nextPow2(
sizeof(FNoRef)));
364 deallocSmallBuffer<kFuncSize>(buf);
367 } guard{allocSmallBuffer<kFuncSize>()};
368 new (guard.buf) FNoRef(std::forward<F>(f));
369 funcBuffer_ = guard.buf;
371 invoke_ = detail::callFunctor<FNoRef>;
372 destroy_ = detail::destroyFunctor<FNoRef>;
375 void dependsOnOneNode(
Node& node) {
376 node.dependents_.emplace_back(
this);
380 static constexpr size_t kCompleted = std::numeric_limits<size_t>::max();
381 mutable std::atomic<size_t> numIncompletePredecessors_;
382 size_t numPredecessors_ = 0;
385 using InvokerType = void (*)(
void* ptr);
388 InvokerType destroy_;
391 SmallVector<Node*, DISPENSO_GRAPH_DEPENDENTS_INLINE_SIZE> dependents_;
394 friend class SubgraphT;
395 friend class detail::ExecutorBase;
396 template <
typename G>
397 friend void setAllNodesIncomplete(
const G& graph);
410 :
Node(std::move(other)), biPropSet_(std::move(other.biPropSet_)) {}
417 template <
class... Ns>
419 ((void)std::initializer_list<int>{(biPropDependsOnOneNode(nodes), 0)...});
428 return biPropSet_ && biPropSet_ == node.biPropSet_;
432#if DISPENSO_HAS_CONCEPTS
434 requires(!std::derived_from<std::remove_cvref_t<T>,
BiPropNode>)
437 template <class T, class X = std::enable_if_t<!std::is_base_of<BiPropNode, T>::value,
void>>
438 BiPropNode(T&& f) : Node(std::forward<T>(f)) {}
440 inline void removeFromBiPropSet() {
441 if (biPropSet_ !=
nullptr) {
442 auto it = std::find(biPropSet_->begin(), biPropSet_->end(),
this);
443 if (it != biPropSet_->end()) {
444 biPropSet_->erase(it);
449 DISPENSO_DLL_ACCESS
void biPropDependsOnOneNode(BiPropNode& node);
451 std::shared_ptr<std::vector<const BiPropNode*>> biPropSet_;
454 friend class SubgraphT;
455 friend class detail::ExecutorBase;
475 : graph_(other.graph_),
476 nodes_(std::move(other.nodes_)),
477 allocator_(std::move(other.allocator_)) {}
486 DISPENSO_REQUIRES(OnceCallableFunc<T>)
488 nodes_.push_back(
new (allocator_->alloc()) NodeType(std::forward<T>(f)));
489 return *nodes_.back();
495 return nodes_.size();
513 const N&
node(
size_t index)
const {
514 return *nodes_[index];
522 return *nodes_[index];
531 for (
const N* node : nodes_) {
543 for (N* node : nodes_) {
555 using PoolPtr = std::unique_ptr<NoLockPoolAllocator, DeallocFunc>;
557 static constexpr size_t kNodeSizeP2 =
static_cast<size_t>(detail::nextPow2(
sizeof(NodeType)));
559 explicit SubgraphT(
GraphT<N>* graph) : graph_(graph), nodes_(), allocator_(getAllocator()) {}
561 inline void removeNodeFromBiPropSet(
Node* ) {}
562 void removeNodeFromBiPropSet(BiPropNode* node) {
563 node->removeFromBiPropSet();
565 void decrementDependentCounters();
566 size_t markNodesWithPredicessors();
567 void removePredecessorDependencies(
size_t numGraphPredecessors);
571 static PoolPtr getAllocator();
572 static void releaseAllocator(NoLockPoolAllocator* ptr);
575#if defined(_WIN32) && !defined(__MINGW32__)
577#pragma warning(disable : 4251)
579 std::vector<N*> nodes_;
582#if defined(_WIN32) && !defined(__MINGW32__)
627 DISPENSO_REQUIRES(OnceCallableFunc<T>)
629 return subgraphs_[0].addNode(std::forward<T>(f));
635 return subgraphs_[0].numNodes();
641 subgraphs_[0].reserve(n);
648 const N&
node(
size_t index)
const {
649 return subgraphs_[0].node(index);
657 return subgraphs_[0].node(index);
667 return subgraphs_.size();
675 return subgraphs_[index];
683 return subgraphs_[index];
716 for (
const N* node : subgraph.nodes_) {
729 for (N* node : subgraph.nodes_) {
746 subgraph.destroyNodes();
751 static constexpr size_t kSubgraphSizeP2 =
752 static_cast<size_t>(detail::nextPow2(
sizeof(SubgraphType)));
754#if defined(_WIN32) && !defined(__MINGW32__)
756#pragma warning(disable : 4251)
758 std::deque<SubgraphT<N>> subgraphs_;
759#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