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);
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 template <class F, class X = std::enable_if_t<!std::is_base_of<Node, F>::value,
void>>
348 Node(F&& f) : numIncompletePredecessors_(0) {
349 using FNoRef =
typename std::remove_reference<F>::type;
351 constexpr size_t kFuncSize =
static_cast<size_t>(detail::nextPow2(
sizeof(FNoRef)));
352 funcBuffer_ = allocSmallBuffer<kFuncSize>();
353 new (funcBuffer_) FNoRef(std::forward<F>(f));
354 invoke_ = ::detail::callFunctor<FNoRef>;
355 destroy_ = ::detail::destroyFunctor<FNoRef>;
358 void dependsOnOneNode(
Node& node) {
359 node.dependents_.emplace_back(
this);
363 static constexpr size_t kCompleted = std::numeric_limits<size_t>::max();
364 mutable std::atomic<size_t> numIncompletePredecessors_;
365 size_t numPredecessors_ = 0;
368 using InvokerType = void (*)(
void* ptr);
371 InvokerType destroy_;
374 SmallVector<Node*, DISPENSO_GRAPH_DEPENDENTS_INLINE_SIZE> dependents_;
377 friend class SubgraphT;
378 friend class ::detail::ExecutorBase;
379 template <
typename G>
380 friend void setAllNodesIncomplete(
const G& graph);
393 :
Node(std::move(other)), biPropSet_(std::move(other.biPropSet_)) {}
400 template <
class... Ns>
402 ((void)std::initializer_list<int>{(biPropDependsOnOneNode(nodes), 0)...});
411 return biPropSet_ && biPropSet_ == node.biPropSet_;
415 template <class T, class X = std::enable_if_t<!std::is_base_of<BiPropNode, T>::value,
void>>
417 inline void removeFromBiPropSet() {
418 if (biPropSet_ !=
nullptr) {
419 auto it = std::find(biPropSet_->begin(), biPropSet_->end(),
this);
420 if (it != biPropSet_->end()) {
421 biPropSet_->erase(it);
426 DISPENSO_DLL_ACCESS
void biPropDependsOnOneNode(BiPropNode& node);
428 std::shared_ptr<std::vector<const BiPropNode*>> biPropSet_;
431 friend class SubgraphT;
432 friend class ::detail::ExecutorBase;
452 : graph_(other.graph_),
453 nodes_(std::move(other.nodes_)),
454 allocator_(std::move(other.allocator_)) {}
463 DISPENSO_REQUIRES(OnceCallableFunc<T>)
465 nodes_.push_back(
new (allocator_->alloc()) NodeType(std::forward<T>(f)));
466 return *nodes_.back();
472 return nodes_.size();
490 const N&
node(
size_t index)
const {
491 return *nodes_[index];
499 return *nodes_[index];
508 for (
const N* node : nodes_) {
520 for (N* node : nodes_) {
532 using PoolPtr = std::unique_ptr<NoLockPoolAllocator, DeallocFunc>;
534 static constexpr size_t kNodeSizeP2 =
static_cast<size_t>(detail::nextPow2(
sizeof(NodeType)));
536 explicit SubgraphT(
GraphT<N>* graph) : graph_(graph), nodes_(), allocator_(getAllocator()) {}
538 inline void removeNodeFromBiPropSet(
Node* ) {}
539 void removeNodeFromBiPropSet(BiPropNode* node) {
540 node->removeFromBiPropSet();
542 void decrementDependentCounters();
543 size_t markNodesWithPredicessors();
544 void removePredecessorDependencies(
size_t numGraphPredecessors);
548 static PoolPtr getAllocator();
549 static void releaseAllocator(NoLockPoolAllocator* ptr);
552#if defined(_WIN32) && !defined(__MINGW32__)
554#pragma warning(disable : 4251)
556 std::vector<N*> nodes_;
559#if defined(_WIN32) && !defined(__MINGW32__)
604 DISPENSO_REQUIRES(OnceCallableFunc<T>)
606 return subgraphs_[0].addNode(std::forward<T>(f));
612 return subgraphs_[0].numNodes();
619 const N&
node(
size_t index)
const {
620 return subgraphs_[0].node(index);
628 return subgraphs_[0].node(index);
638 return subgraphs_.size();
646 return subgraphs_[index];
654 return subgraphs_[index];
687 for (
const N* node : subgraph.nodes_) {
700 for (N* node : subgraph.nodes_) {
717 subgraph.destroyNodes();
722 static constexpr size_t kSubgraphSizeP2 =
723 static_cast<size_t>(detail::nextPow2(
sizeof(SubgraphType)));
725#if defined(_WIN32) && !defined(__MINGW32__)
727#pragma warning(disable : 4251)
729 std::deque<SubgraphT<N>> subgraphs_;
730#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