#ifndef SRC_CALLBACK_QUEUE_H_ #define SRC_CALLBACK_QUEUE_H_ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include namespace node { namespace CallbackFlags { enum Flags { kUnrefed = 0, kRefed = 1, }; } // A queue of C++ functions that take Args... as arguments and return R // (this is similar to the signature of std::function). // New entries are added using `CreateCallback()`/`Push()`, and removed using // `Shift()`. // The `refed` flag is left for easier use in situations in which some of these // should be run even if nothing else is keeping the event loop alive. template class CallbackQueue { public: class Callback { public: explicit inline Callback(CallbackFlags::Flags flags); virtual ~Callback() = default; virtual R Call(Args... args) = 0; inline CallbackFlags::Flags flags() const; private: inline std::unique_ptr get_next(); inline void set_next(std::unique_ptr next); CallbackFlags::Flags flags_; std::unique_ptr next_; friend class CallbackQueue; }; template inline std::unique_ptr CreateCallback( Fn&& fn, CallbackFlags::Flags); inline std::unique_ptr Shift(); inline void Push(std::unique_ptr cb); // ConcatMove adds elements from 'other' to the end of this list, and clears // 'other' afterwards. inline void ConcatMove(CallbackQueue&& other); // size() is atomic and may be called from any thread. inline size_t size() const; private: template class CallbackImpl final : public Callback { public: CallbackImpl(Fn&& callback, CallbackFlags::Flags flags); R Call(Args... args) override; private: Fn callback_; }; std::atomic size_ {0}; std::unique_ptr head_; Callback* tail_ = nullptr; }; } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #endif // SRC_CALLBACK_QUEUE_H_