/*
- * Copyright 2015 Facebook, Inc.
+ * Copyright 2016 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
// avoid destroying the function object.
class DestroyTestConsumer : public IntQueue::Consumer {
public:
- DestroyTestConsumer() {}
-
void messageAvailable(int&& value) override {
+ DestructorGuard g(this);
if (fn && *fn) {
(*fn)(value);
}
}
std::function<void(int)> *fn;
+ protected:
+ virtual ~DestroyTestConsumer() = default;
};
EventBase eventBase;
// This way one consumer will be destroyed from inside its messageAvailable()
// callback, and one consume will be destroyed when it isn't inside
// messageAvailable().
- std::unique_ptr<DestroyTestConsumer> consumer1(new DestroyTestConsumer);
- std::unique_ptr<DestroyTestConsumer> consumer2(new DestroyTestConsumer);
+ std::unique_ptr<DestroyTestConsumer, DelayedDestruction::Destructor>
+ consumer1(new DestroyTestConsumer);
+ std::unique_ptr<DestroyTestConsumer, DelayedDestruction::Destructor>
+ consumer2(new DestroyTestConsumer);
std::function<void(int)> fn = [&](int) {
- consumer1.reset();
- consumer2.reset();
+ consumer1 = nullptr;
+ consumer2 = nullptr;
};
consumer1->fn = &fn;
consumer2->fn = &fn;
// Make sure there can only be one drainer at once
folly::Baton<> callbackBaton, threadStartBaton;
- consumer.fn = [&](int i) {
- callbackBaton.wait();
- };
+ consumer.fn = [&](int /* i */) { callbackBaton.wait(); };
QueueConsumer competingConsumer;
competingConsumer.startConsuming(&eventBase, &queue);
queue.putMessage(1);
// Make sure there can only be one drainer at once
folly::Baton<> callbackBaton, threadStartBaton;
- consumer.fn = [&](int i) {
- callbackBaton.wait();
- };
+ consumer.fn = [&](int /* i */) { callbackBaton.wait(); };
QueueConsumer competingConsumer;
competingConsumer.startConsuming(&eventBase, &queue);
queue.putMessage(1);
}
/*
- * Test code that creates a TNotificationQueue, then forks, and incorrectly
+ * Test code that creates a NotificationQueue, then forks, and incorrectly
* tries to send a message to the queue from the child process.
*
* The child process should crash in this scenario, since the child code has a
- * bug. (Older versions of TNotificationQueue didn't catch this in the child,
+ * bug. (Older versions of NotificationQueue didn't catch this in the child,
* resulting in a crash in the parent process.)
*/
TEST(NotificationQueueTest, UseAfterFork) {
// We shouldn't reach here.
_exit(0);
}
+ PCHECK(pid > 0);
// Parent. Wait for the child to exit.
auto waited = waitpid(pid, &childStatus, 0);
}
// The child process should have crashed when it tried to call putMessage()
- // on our TNotificationQueue.
+ // on our NotificationQueue.
EXPECT_TRUE(WIFSIGNALED(childStatus));
EXPECT_EQ(SIGABRT, WTERMSIG(childStatus));
EXPECT_EQ(5678, consumer.messages.front());
consumer.messages.pop_front();
}
+
+TEST(NotificationQueueConsumer, make) {
+ int value = 0;
+ EventBase evb;
+ NotificationQueue<int> 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);
+}