From: Petr Lapukhov Date: Tue, 20 Oct 2015 22:30:55 +0000 (-0700) Subject: Add support for in-place creation of NotificationQueue::Consumer X-Git-Tag: deprecate-dynamic-initializer~309 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=a40474b58a11974500180fc00d2ec42cf555a596;p=folly.git Add support for in-place creation of NotificationQueue::Consumer Summary: as title, this comes handy when multiple consumers are needed within the same class. Reviewed By: has Differential Revision: D2530249 fb-gh-sync-id: 942761782a100b2d3fe54d94a7c1b0e03b95a847 --- diff --git a/folly/io/async/NotificationQueue.h b/folly/io/async/NotificationQueue.h index 129096f6..9d76e431 100644 --- a/folly/io/async/NotificationQueue.h +++ b/folly/io/async/NotificationQueue.h @@ -77,6 +77,11 @@ class NotificationQueue { destroyedFlagPtr_(nullptr), maxReadAtOnce_(kDefaultMaxReadAtOnce) {} + // create a consumer in-place, without the need to build new class + template + static std::unique_ptr make( + TCallback&& callback); + /** * messageAvailable() will be invoked whenever a new * message is available from the pipe. @@ -798,4 +803,49 @@ bool NotificationQueue::Consumer::consumeUntilDrained( return true; } +/** + * Creates a NotificationQueue::Consumer wrapping a function object + * Modeled after AsyncTimeout::make + * + */ + +namespace detail { + +template +struct notification_queue_consumer_wrapper + : public NotificationQueue::Consumer { + + template + explicit notification_queue_consumer_wrapper(UCallback&& callback) + : callback_(std::forward(callback)) {} + + // we are being stricter here and requiring noexcept for callback + void messageAvailable(MessageT&& message) override { + static_assert( + noexcept(std::declval()(std::forward(message))), + "callback must be declared noexcept, e.g.: `[]() noexcept {}`" + ); + + callback_(std::forward(message)); + } + + private: + TCallback callback_; +}; + +} // namespace detail + +template +template +std::unique_ptr::Consumer, + DelayedDestruction::Destructor> +NotificationQueue::Consumer::make(TCallback&& callback) { + return std::unique_ptr::Consumer, + DelayedDestruction::Destructor>( + new detail::notification_queue_consumer_wrapper< + MessageT, + typename std::decay::type>( + std::forward(callback))); +} + } // folly diff --git a/folly/io/async/test/NotificationQueueTest.cpp b/folly/io/async/test/NotificationQueueTest.cpp index 1438ae88..5de62856 100644 --- a/folly/io/async/test/NotificationQueueTest.cpp +++ b/folly/io/async/test/NotificationQueueTest.cpp @@ -644,3 +644,21 @@ TEST(NotificationQueueTest, UseAfterFork) { EXPECT_EQ(5678, consumer.messages.front()); consumer.messages.pop_front(); } + +TEST(NotificationQueueConsumer, make) { + int value = 0; + EventBase evb; + NotificationQueue queue(32); + + auto consumer = decltype(queue)::Consumer::make([&]( + int&& msg) noexcept { value = msg; }); + + consumer->startConsuming(&evb, &queue); + + int const newValue = 10; + queue.tryPutMessage(newValue); + + evb.loopOnce(); + + EXPECT_EQ(newValue, value); +}