Upgrading dependencies to gorealis v2 and thrift 0.12.0
This commit is contained in:
parent
7cbbea498b
commit
54b8d7942a
1327 changed files with 137391 additions and 61476 deletions
123
vendor/git.apache.org/thrift.git/lib/cpp/test/concurrency/MutexTest.cpp
generated
vendored
Normal file
123
vendor/git.apache.org/thrift.git/lib/cpp/test/concurrency/MutexTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
// This is linked into the UnitTests test executable
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include "thrift/concurrency/Exception.h"
|
||||
#include "thrift/concurrency/Mutex.h"
|
||||
|
||||
using boost::unit_test::test_suite;
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
using namespace apache::thrift::concurrency;
|
||||
|
||||
struct LFAT
|
||||
{
|
||||
LFAT()
|
||||
: uut(Mutex::ERRORCHECK_INITIALIZER)
|
||||
{
|
||||
BOOST_CHECK_EQUAL(0, pthread_mutex_init(&mx, 0));
|
||||
BOOST_CHECK_EQUAL(0, pthread_cond_init(&cv, 0));
|
||||
}
|
||||
|
||||
Mutex uut;
|
||||
pthread_mutex_t mx;
|
||||
pthread_cond_t cv;
|
||||
};
|
||||
|
||||
// Helper for testing mutex behavior when locked by another thread
|
||||
void * lockFromAnotherThread(void *ptr)
|
||||
{
|
||||
struct LFAT *lfat = (LFAT *)ptr;
|
||||
BOOST_CHECK_EQUAL (0, pthread_mutex_lock(&lfat->mx)); // synchronize with testing thread
|
||||
BOOST_CHECK_NO_THROW( lfat->uut.lock());
|
||||
BOOST_CHECK_EQUAL (0, pthread_cond_signal(&lfat->cv)); // tell testing thread we have locked the mutex
|
||||
BOOST_CHECK_EQUAL (0, pthread_cond_wait(&lfat->cv, &lfat->mx)); // wait for testing thread to signal condition variable telling us to unlock
|
||||
BOOST_CHECK_NO_THROW( lfat->uut.unlock());
|
||||
return ptr; // testing thread should join to ensure completeness
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(MutexTest)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(happy_path)
|
||||
{
|
||||
Mutex uut(Mutex::ERRORCHECK_INITIALIZER); // needed to test unlocking twice without undefined behavior
|
||||
|
||||
BOOST_CHECK_NO_THROW( uut.lock());
|
||||
BOOST_CHECK_THROW ( uut.lock(), SystemResourceException); // EDEADLK (this thread owns it)
|
||||
BOOST_CHECK_NO_THROW( uut.unlock());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(recursive_happy_path)
|
||||
{
|
||||
Mutex uut(Mutex::RECURSIVE_INITIALIZER);
|
||||
|
||||
BOOST_CHECK_NO_THROW( uut.lock());
|
||||
BOOST_CHECK_NO_THROW( uut.lock());
|
||||
BOOST_CHECK_NO_THROW( uut.unlock());
|
||||
BOOST_CHECK_NO_THROW( uut.lock());
|
||||
BOOST_CHECK_NO_THROW( uut.lock());
|
||||
BOOST_CHECK_NO_THROW( uut.unlock());
|
||||
BOOST_CHECK_NO_THROW( uut.lock());
|
||||
BOOST_CHECK_NO_THROW( uut.unlock());
|
||||
BOOST_CHECK_NO_THROW( uut.unlock());
|
||||
BOOST_CHECK_NO_THROW( uut.unlock());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(trylock)
|
||||
{
|
||||
Mutex uut(Mutex::ADAPTIVE_INITIALIZER); // just using another initializer for coverage
|
||||
|
||||
BOOST_CHECK ( uut.trylock());
|
||||
BOOST_CHECK (!uut.trylock());
|
||||
BOOST_CHECK_NO_THROW( uut.unlock());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(timedlock)
|
||||
{
|
||||
pthread_t th;
|
||||
struct LFAT lfat;
|
||||
|
||||
BOOST_CHECK ( lfat.uut.timedlock(100));
|
||||
BOOST_CHECK_THROW ( lfat.uut.timedlock(100),
|
||||
SystemResourceException); // EDEADLK (current thread owns mutex - logic error)
|
||||
BOOST_CHECK_NO_THROW( lfat.uut.unlock());
|
||||
|
||||
BOOST_CHECK_EQUAL (0, pthread_mutex_lock(&lfat.mx)); // synchronize with helper thread
|
||||
BOOST_CHECK_EQUAL (0, pthread_create(&th, NULL,
|
||||
lockFromAnotherThread, &lfat)); // create helper thread
|
||||
BOOST_CHECK_EQUAL (0, pthread_cond_wait(&lfat.cv, &lfat.mx)); // wait for helper thread to lock mutex
|
||||
|
||||
BOOST_CHECK (!lfat.uut.timedlock(100)); // false: another thread owns the lock
|
||||
|
||||
BOOST_CHECK_EQUAL (0, pthread_cond_signal(&lfat.cv)); // tell helper thread we are done
|
||||
BOOST_CHECK_EQUAL (0, pthread_mutex_unlock(&lfat.mx)); // let helper thread clean up
|
||||
BOOST_CHECK_EQUAL (0, pthread_join(th, 0)); // wait for testing thread to unlock and be done
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(underlying)
|
||||
{
|
||||
Mutex uut;
|
||||
|
||||
BOOST_CHECK ( uut.getUnderlyingImpl());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
157
vendor/git.apache.org/thrift.git/lib/cpp/test/concurrency/RWMutexStarveTest.cpp
generated
vendored
Normal file
157
vendor/git.apache.org/thrift.git/lib/cpp/test/concurrency/RWMutexStarveTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
// This is linked into the UnitTests test executable
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include "thrift/concurrency/Mutex.h"
|
||||
#include "thrift/concurrency/PosixThreadFactory.h"
|
||||
#include <thrift/stdcxx.h>
|
||||
|
||||
using apache::thrift::stdcxx::shared_ptr;
|
||||
using boost::unit_test::test_suite;
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
using namespace apache::thrift::concurrency;
|
||||
|
||||
class Locker : public Runnable {
|
||||
protected:
|
||||
Locker(shared_ptr<ReadWriteMutex> rwlock, bool writer)
|
||||
: rwlock_(rwlock), writer_(writer), started_(false), gotLock_(false), signaled_(false) {}
|
||||
|
||||
public:
|
||||
virtual void run() {
|
||||
started_ = true;
|
||||
if (writer_) {
|
||||
rwlock_->acquireWrite();
|
||||
} else {
|
||||
rwlock_->acquireRead();
|
||||
}
|
||||
gotLock_ = true;
|
||||
while (!signaled_) {
|
||||
usleep(5000);
|
||||
}
|
||||
rwlock_->release();
|
||||
}
|
||||
|
||||
bool started() const { return started_; }
|
||||
bool gotLock() const { return gotLock_; }
|
||||
void signal() { signaled_ = true; }
|
||||
|
||||
protected:
|
||||
shared_ptr<ReadWriteMutex> rwlock_;
|
||||
bool writer_;
|
||||
volatile bool started_;
|
||||
volatile bool gotLock_;
|
||||
volatile bool signaled_;
|
||||
};
|
||||
|
||||
class Reader : public Locker {
|
||||
public:
|
||||
Reader(shared_ptr<ReadWriteMutex> rwlock) : Locker(rwlock, false) {}
|
||||
};
|
||||
|
||||
class Writer : public Locker {
|
||||
public:
|
||||
Writer(shared_ptr<ReadWriteMutex> rwlock) : Locker(rwlock, true) {}
|
||||
};
|
||||
|
||||
void test_starve(PosixThreadFactory::POLICY policy) {
|
||||
// the man pages for pthread_wrlock_rdlock suggest that any OS guarantee about
|
||||
// writer starvation may be influenced by the scheduling policy, so let's try
|
||||
// all 3 policies to see if any of them work.
|
||||
PosixThreadFactory factory(policy);
|
||||
factory.setDetached(false);
|
||||
|
||||
shared_ptr<ReadWriteMutex> rwlock(new NoStarveReadWriteMutex());
|
||||
|
||||
shared_ptr<Reader> reader1(new Reader(rwlock));
|
||||
shared_ptr<Reader> reader2(new Reader(rwlock));
|
||||
shared_ptr<Writer> writer(new Writer(rwlock));
|
||||
|
||||
shared_ptr<Thread> treader1 = factory.newThread(reader1);
|
||||
shared_ptr<Thread> treader2 = factory.newThread(reader2);
|
||||
shared_ptr<Thread> twriter = factory.newThread(writer);
|
||||
|
||||
// launch a reader and make sure he has the lock
|
||||
treader1->start();
|
||||
while (!reader1->gotLock()) {
|
||||
usleep(2000);
|
||||
}
|
||||
|
||||
// launch a writer and make sure he's blocked on the lock
|
||||
twriter->start();
|
||||
while (!writer->started()) {
|
||||
usleep(2000);
|
||||
}
|
||||
// tricky part... we can never be 100% sure that the writer is actually
|
||||
// blocked on the lock, but we can pretty reasonably sure because we know
|
||||
// he just executed the line immediately before getting the lock, and
|
||||
// we'll wait a full second for him to get on it.
|
||||
sleep(1);
|
||||
|
||||
// launch a second reader... if the RWMutex guarantees that writers won't
|
||||
// starve, this reader should not be able to acquire the lock until the writer
|
||||
// has acquired and released it.
|
||||
treader2->start();
|
||||
while (!reader2->started()) {
|
||||
usleep(2000);
|
||||
}
|
||||
// again... can't be 100% sure the reader is waiting on (or has) the lock
|
||||
// but we can be close.
|
||||
sleep(1);
|
||||
|
||||
// tell reader 1 to let go of the lock
|
||||
reader1->signal();
|
||||
|
||||
// wait for someone to get the lock
|
||||
while (!reader2->gotLock() && !writer->gotLock()) {
|
||||
usleep(2000);
|
||||
}
|
||||
|
||||
// the test succeeded if the WRITER got the lock.
|
||||
bool success = writer->gotLock();
|
||||
|
||||
// tell everyone we're done and wait for them to finish
|
||||
reader2->signal();
|
||||
writer->signal();
|
||||
treader1->join();
|
||||
treader2->join();
|
||||
twriter->join();
|
||||
|
||||
// make sure it worked.
|
||||
BOOST_CHECK_MESSAGE(success, "writer is starving");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(RWMutexStarveTest)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_starve_other) {
|
||||
test_starve(PosixThreadFactory::OTHER);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_starve_rr) {
|
||||
test_starve(PosixThreadFactory::ROUND_ROBIN);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_starve_fifo) {
|
||||
test_starve(PosixThreadFactory::FIFO);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
53
vendor/git.apache.org/thrift.git/lib/cpp/test/concurrency/Tests.cpp
generated
vendored
53
vendor/git.apache.org/thrift.git/lib/cpp/test/concurrency/Tests.cpp
generated
vendored
|
@ -25,6 +25,10 @@
|
|||
#include "TimerManagerTests.h"
|
||||
#include "ThreadManagerTests.h"
|
||||
|
||||
// The test weight, where 10 is 10 times more threads than baseline
|
||||
// and the baseline is optimized for running in valgrind
|
||||
static int WEIGHT = 10;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
std::string arg;
|
||||
|
@ -37,6 +41,11 @@ int main(int argc, char** argv) {
|
|||
args[ix - 1] = std::string(argv[ix]);
|
||||
}
|
||||
|
||||
if (getenv("VALGRIND") != 0) {
|
||||
// lower the scale of every test
|
||||
WEIGHT = 1;
|
||||
}
|
||||
|
||||
bool runAll = args[0].compare("all") == 0;
|
||||
|
||||
if (runAll || args[0].compare("thread-factory") == 0) {
|
||||
|
@ -45,10 +54,10 @@ int main(int argc, char** argv) {
|
|||
|
||||
std::cout << "ThreadFactory tests..." << std::endl;
|
||||
|
||||
int reapLoops = 20;
|
||||
int reapCount = 1000;
|
||||
int reapLoops = 2 * WEIGHT;
|
||||
int reapCount = 100 * WEIGHT;
|
||||
size_t floodLoops = 3;
|
||||
size_t floodCount = 20000;
|
||||
size_t floodCount = 500 * WEIGHT;
|
||||
|
||||
std::cout << "\t\tThreadFactory reap N threads test: N = " << reapLoops << "x" << reapCount << std::endl;
|
||||
|
||||
|
@ -114,6 +123,34 @@ int main(int argc, char** argv) {
|
|||
std::cerr << "\t\tTimerManager tests FAILED" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "\t\tTimerManager test01" << std::endl;
|
||||
|
||||
if (!timerManagerTests.test01()) {
|
||||
std::cerr << "\t\tTimerManager tests FAILED" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "\t\tTimerManager test02" << std::endl;
|
||||
|
||||
if (!timerManagerTests.test02()) {
|
||||
std::cerr << "\t\tTimerManager tests FAILED" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "\t\tTimerManager test03" << std::endl;
|
||||
|
||||
if (!timerManagerTests.test03()) {
|
||||
std::cerr << "\t\tTimerManager tests FAILED" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "\t\tTimerManager test04" << std::endl;
|
||||
|
||||
if (!timerManagerTests.test04()) {
|
||||
std::cerr << "\t\tTimerManager tests FAILED" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (runAll || args[0].compare("thread-manager") == 0) {
|
||||
|
@ -121,8 +158,8 @@ int main(int argc, char** argv) {
|
|||
std::cout << "ThreadManager tests..." << std::endl;
|
||||
|
||||
{
|
||||
size_t workerCount = 100;
|
||||
size_t taskCount = 50000;
|
||||
size_t workerCount = 10 * WEIGHT;
|
||||
size_t taskCount = 500 * WEIGHT;
|
||||
int64_t delay = 10LL;
|
||||
|
||||
ThreadManagerTests threadManagerTests;
|
||||
|
@ -160,13 +197,13 @@ int main(int argc, char** argv) {
|
|||
|
||||
size_t minWorkerCount = 2;
|
||||
|
||||
size_t maxWorkerCount = 64;
|
||||
size_t maxWorkerCount = 8;
|
||||
|
||||
size_t tasksPerWorker = 1000;
|
||||
size_t tasksPerWorker = 100 * WEIGHT;
|
||||
|
||||
int64_t delay = 5LL;
|
||||
|
||||
for (size_t workerCount = minWorkerCount; workerCount < maxWorkerCount; workerCount *= 4) {
|
||||
for (size_t workerCount = minWorkerCount; workerCount <= maxWorkerCount; workerCount *= 4) {
|
||||
|
||||
size_t taskCount = workerCount * tasksPerWorker;
|
||||
|
||||
|
|
46
vendor/git.apache.org/thrift.git/lib/cpp/test/concurrency/ThreadFactoryTests.h
generated
vendored
46
vendor/git.apache.org/thrift.git/lib/cpp/test/concurrency/ThreadFactoryTests.h
generated
vendored
|
@ -21,18 +21,19 @@
|
|||
#include <thrift/concurrency/Thread.h>
|
||||
#include <thrift/concurrency/PlatformThreadFactory.h>
|
||||
#include <thrift/concurrency/Monitor.h>
|
||||
#include <thrift/concurrency/Mutex.h>
|
||||
#include <thrift/concurrency/Util.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace concurrency {
|
||||
namespace test {
|
||||
|
||||
using boost::shared_ptr;
|
||||
using stdcxx::shared_ptr;
|
||||
using namespace apache::thrift::concurrency;
|
||||
|
||||
/**
|
||||
|
@ -53,39 +54,33 @@ public:
|
|||
|
||||
void run() {
|
||||
Synchronized s(_monitor);
|
||||
|
||||
_count--;
|
||||
|
||||
// std::cout << "\t\t\tthread count: " << _count << std::endl;
|
||||
|
||||
if (_count == 0) {
|
||||
|
||||
if (--_count == 0) {
|
||||
_monitor.notify();
|
||||
}
|
||||
}
|
||||
|
||||
Monitor& _monitor;
|
||||
|
||||
int& _count;
|
||||
};
|
||||
|
||||
bool reapNThreads(int loop = 1, int count = 10) {
|
||||
|
||||
PlatformThreadFactory threadFactory = PlatformThreadFactory();
|
||||
|
||||
shared_ptr<Monitor> monitor(new Monitor);
|
||||
|
||||
for (int lix = 0; lix < loop; lix++) {
|
||||
|
||||
int* activeCount = new int(count);
|
||||
|
||||
std::set<shared_ptr<Thread> > threads;
|
||||
int activeCount = 0;
|
||||
|
||||
std::vector<shared_ptr<Thread> > threads;
|
||||
int tix;
|
||||
|
||||
for (tix = 0; tix < count; tix++) {
|
||||
try {
|
||||
threads.insert(
|
||||
threadFactory.newThread(shared_ptr<Runnable>(new ReapNTask(*monitor, *activeCount))));
|
||||
++activeCount;
|
||||
threads.push_back(
|
||||
threadFactory.newThread(shared_ptr<Runnable>(new ReapNTask(*monitor, activeCount))));
|
||||
} catch (SystemResourceException& e) {
|
||||
std::cout << "\t\t\tfailed to create " << lix* count + tix << " thread " << e.what()
|
||||
<< std::endl;
|
||||
|
@ -94,7 +89,7 @@ public:
|
|||
}
|
||||
|
||||
tix = 0;
|
||||
for (std::set<shared_ptr<Thread> >::const_iterator thread = threads.begin();
|
||||
for (std::vector<shared_ptr<Thread> >::const_iterator thread = threads.begin();
|
||||
thread != threads.end();
|
||||
tix++, ++thread) {
|
||||
|
||||
|
@ -109,16 +104,15 @@ public:
|
|||
|
||||
{
|
||||
Synchronized s(*monitor);
|
||||
while (*activeCount > 0) {
|
||||
while (activeCount > 0) {
|
||||
monitor->wait(1000);
|
||||
}
|
||||
}
|
||||
delete activeCount;
|
||||
|
||||
std::cout << "\t\t\treaped " << lix* count << " threads" << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "\t\t\tSuccess!" << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -253,19 +247,22 @@ public:
|
|||
|
||||
class FloodTask : public Runnable {
|
||||
public:
|
||||
FloodTask(const size_t id) : _id(id) {}
|
||||
FloodTask(const size_t id, Monitor& mon) : _id(id), _mon(mon) {}
|
||||
~FloodTask() {
|
||||
if (_id % 10000 == 0) {
|
||||
Synchronized sync(_mon);
|
||||
std::cout << "\t\tthread " << _id << " done" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void run() {
|
||||
if (_id % 10000 == 0) {
|
||||
Synchronized sync(_mon);
|
||||
std::cout << "\t\tthread " << _id << " started" << std::endl;
|
||||
}
|
||||
}
|
||||
const size_t _id;
|
||||
Monitor& _mon;
|
||||
};
|
||||
|
||||
void foo(PlatformThreadFactory* tf) { (void)tf; }
|
||||
|
@ -273,7 +270,8 @@ public:
|
|||
bool floodNTest(size_t loop = 1, size_t count = 100000) {
|
||||
|
||||
bool success = false;
|
||||
|
||||
Monitor mon;
|
||||
|
||||
for (size_t lix = 0; lix < loop; lix++) {
|
||||
|
||||
PlatformThreadFactory threadFactory = PlatformThreadFactory();
|
||||
|
@ -283,10 +281,8 @@ public:
|
|||
|
||||
try {
|
||||
|
||||
shared_ptr<FloodTask> task(new FloodTask(lix * count + tix));
|
||||
|
||||
shared_ptr<FloodTask> task(new FloodTask(lix * count + tix, mon));
|
||||
shared_ptr<Thread> thread = threadFactory.newThread(task);
|
||||
|
||||
thread->start();
|
||||
|
||||
} catch (TException& e) {
|
||||
|
@ -298,8 +294,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
Synchronized sync(mon);
|
||||
std::cout << "\t\t\tflooded " << (lix + 1) * count << " threads" << std::endl;
|
||||
|
||||
success = true;
|
||||
}
|
||||
|
||||
|
|
6
vendor/git.apache.org/thrift.git/lib/cpp/test/concurrency/ThreadManagerTests.h
generated
vendored
6
vendor/git.apache.org/thrift.git/lib/cpp/test/concurrency/ThreadManagerTests.h
generated
vendored
|
@ -36,8 +36,8 @@ namespace test {
|
|||
|
||||
using namespace apache::thrift::concurrency;
|
||||
|
||||
static std::deque<boost::shared_ptr<Runnable> > m_expired;
|
||||
static void expiredNotifier(boost::shared_ptr<Runnable> runnable)
|
||||
static std::deque<stdcxx::shared_ptr<Runnable> > m_expired;
|
||||
static void expiredNotifier(stdcxx::shared_ptr<Runnable> runnable)
|
||||
{
|
||||
m_expired.push_back(runnable);
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ public:
|
|||
shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(workerCount);
|
||||
|
||||
shared_ptr<PlatformThreadFactory> threadFactory
|
||||
= shared_ptr<PlatformThreadFactory>(new PlatformThreadFactory());
|
||||
= shared_ptr<PlatformThreadFactory>(new PlatformThreadFactory(false));
|
||||
|
||||
#if !USE_BOOST_THREAD && !USE_STD_THREAD
|
||||
threadFactory->setPriority(PosixThreadFactory::HIGHEST);
|
||||
|
|
166
vendor/git.apache.org/thrift.git/lib/cpp/test/concurrency/TimerManagerTests.h
generated
vendored
166
vendor/git.apache.org/thrift.git/lib/cpp/test/concurrency/TimerManagerTests.h
generated
vendored
|
@ -79,14 +79,13 @@ public:
|
|||
= shared_ptr<TimerManagerTests::Task>(new TimerManagerTests::Task(_monitor, 10 * timeout));
|
||||
|
||||
{
|
||||
|
||||
TimerManager timerManager;
|
||||
|
||||
timerManager.threadFactory(shared_ptr<PlatformThreadFactory>(new PlatformThreadFactory()));
|
||||
|
||||
timerManager.start();
|
||||
|
||||
assert(timerManager.state() == TimerManager::STARTED);
|
||||
if (timerManager.state() != TimerManager::STARTED) {
|
||||
std::cerr << "timerManager is not in the STARTED state, but should be" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't create task yet, because its constructor sets the expected completion time, and we
|
||||
// need to delay between inserting the two tasks into the run queue.
|
||||
|
@ -94,34 +93,161 @@ public:
|
|||
|
||||
{
|
||||
Synchronized s(_monitor);
|
||||
|
||||
timerManager.add(orphanTask, 10 * timeout);
|
||||
|
||||
try {
|
||||
// Wait for 1 second in order to give timerManager a chance to start sleeping in response
|
||||
// to adding orphanTask. We need to do this so we can verify that adding the second task
|
||||
// kicks the dispatcher out of the current wait and starts the new 1 second wait.
|
||||
_monitor.wait(1000);
|
||||
assert(
|
||||
0 == "ERROR: This wait should time out. TimerManager dispatcher may have a problem.");
|
||||
} catch (TimedOutException&) {
|
||||
}
|
||||
THRIFT_SLEEP_USEC(timeout * 1000);
|
||||
|
||||
task.reset(new TimerManagerTests::Task(_monitor, timeout));
|
||||
|
||||
timerManager.add(task, timeout);
|
||||
|
||||
_monitor.wait();
|
||||
}
|
||||
|
||||
assert(task->_done);
|
||||
if (!task->_done) {
|
||||
std::cerr << "task is not done, but it should have executed" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::cout << "\t\t\t" << (task->_success ? "Success" : "Failure") << "!" << std::endl;
|
||||
}
|
||||
|
||||
// timerManager.stop(); This is where it happens via destructor
|
||||
if (orphanTask->_done) {
|
||||
std::cerr << "orphan task is done, but it should not have executed" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(!orphanTask->_done);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This test creates two tasks, removes the first one then waits for the second one. It then
|
||||
* verifies that the timer manager properly clean up itself and the remaining orphaned timeout
|
||||
* task when the manager goes out of scope and its destructor is called.
|
||||
*/
|
||||
bool test01(int64_t timeout = 1000LL) {
|
||||
TimerManager timerManager;
|
||||
timerManager.threadFactory(shared_ptr<PlatformThreadFactory>(new PlatformThreadFactory()));
|
||||
timerManager.start();
|
||||
assert(timerManager.state() == TimerManager::STARTED);
|
||||
|
||||
Synchronized s(_monitor);
|
||||
|
||||
// Setup the two tasks
|
||||
shared_ptr<TimerManagerTests::Task> taskToRemove
|
||||
= shared_ptr<TimerManagerTests::Task>(new TimerManagerTests::Task(_monitor, timeout / 2));
|
||||
timerManager.add(taskToRemove, taskToRemove->_timeout);
|
||||
|
||||
shared_ptr<TimerManagerTests::Task> task
|
||||
= shared_ptr<TimerManagerTests::Task>(new TimerManagerTests::Task(_monitor, timeout));
|
||||
timerManager.add(task, task->_timeout);
|
||||
|
||||
// Remove one task and wait until the other has completed
|
||||
timerManager.remove(taskToRemove);
|
||||
_monitor.wait(timeout * 2);
|
||||
|
||||
assert(!taskToRemove->_done);
|
||||
assert(task->_done);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This test creates two tasks with the same callback and another one, then removes the two
|
||||
* duplicated then waits for the last one. It then verifies that the timer manager properly
|
||||
* clean up itself and the remaining orphaned timeout task when the manager goes out of scope
|
||||
* and its destructor is called.
|
||||
*/
|
||||
bool test02(int64_t timeout = 1000LL) {
|
||||
TimerManager timerManager;
|
||||
timerManager.threadFactory(shared_ptr<PlatformThreadFactory>(new PlatformThreadFactory()));
|
||||
timerManager.start();
|
||||
assert(timerManager.state() == TimerManager::STARTED);
|
||||
|
||||
Synchronized s(_monitor);
|
||||
|
||||
// Setup the one tasks and add it twice
|
||||
shared_ptr<TimerManagerTests::Task> taskToRemove
|
||||
= shared_ptr<TimerManagerTests::Task>(new TimerManagerTests::Task(_monitor, timeout / 3));
|
||||
timerManager.add(taskToRemove, taskToRemove->_timeout);
|
||||
timerManager.add(taskToRemove, taskToRemove->_timeout * 2);
|
||||
|
||||
shared_ptr<TimerManagerTests::Task> task
|
||||
= shared_ptr<TimerManagerTests::Task>(new TimerManagerTests::Task(_monitor, timeout));
|
||||
timerManager.add(task, task->_timeout);
|
||||
|
||||
// Remove the first task (e.g. two timers) and wait until the other has completed
|
||||
timerManager.remove(taskToRemove);
|
||||
_monitor.wait(timeout * 2);
|
||||
|
||||
assert(!taskToRemove->_done);
|
||||
assert(task->_done);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This test creates two tasks, removes the first one then waits for the second one. It then
|
||||
* verifies that the timer manager properly clean up itself and the remaining orphaned timeout
|
||||
* task when the manager goes out of scope and its destructor is called.
|
||||
*/
|
||||
bool test03(int64_t timeout = 1000LL) {
|
||||
TimerManager timerManager;
|
||||
timerManager.threadFactory(shared_ptr<PlatformThreadFactory>(new PlatformThreadFactory()));
|
||||
timerManager.start();
|
||||
assert(timerManager.state() == TimerManager::STARTED);
|
||||
|
||||
Synchronized s(_monitor);
|
||||
|
||||
// Setup the two tasks
|
||||
shared_ptr<TimerManagerTests::Task> taskToRemove
|
||||
= shared_ptr<TimerManagerTests::Task>(new TimerManagerTests::Task(_monitor, timeout / 2));
|
||||
TimerManager::Timer timer = timerManager.add(taskToRemove, taskToRemove->_timeout);
|
||||
|
||||
shared_ptr<TimerManagerTests::Task> task
|
||||
= shared_ptr<TimerManagerTests::Task>(new TimerManagerTests::Task(_monitor, timeout));
|
||||
timerManager.add(task, task->_timeout);
|
||||
|
||||
// Remove one task and wait until the other has completed
|
||||
timerManager.remove(timer);
|
||||
_monitor.wait(timeout * 2);
|
||||
|
||||
assert(!taskToRemove->_done);
|
||||
assert(task->_done);
|
||||
|
||||
// Verify behavior when removing the removed task
|
||||
try {
|
||||
timerManager.remove(timer);
|
||||
assert(0 == "ERROR: This remove should send a NoSuchTaskException exception.");
|
||||
} catch (NoSuchTaskException&) {
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This test creates one tasks, and tries to remove it after it has expired.
|
||||
*/
|
||||
bool test04(int64_t timeout = 1000LL) {
|
||||
TimerManager timerManager;
|
||||
timerManager.threadFactory(shared_ptr<PlatformThreadFactory>(new PlatformThreadFactory()));
|
||||
timerManager.start();
|
||||
assert(timerManager.state() == TimerManager::STARTED);
|
||||
|
||||
Synchronized s(_monitor);
|
||||
|
||||
// Setup the task
|
||||
shared_ptr<TimerManagerTests::Task> task
|
||||
= shared_ptr<TimerManagerTests::Task>(new TimerManagerTests::Task(_monitor, timeout / 10));
|
||||
TimerManager::Timer timer = timerManager.add(task, task->_timeout);
|
||||
|
||||
// Wait until the task has completed
|
||||
_monitor.wait(timeout);
|
||||
|
||||
// Verify behavior when removing the expired task
|
||||
try {
|
||||
timerManager.remove(timer);
|
||||
assert(0 == "ERROR: This remove should send a NoSuchTaskException exception.");
|
||||
} catch (NoSuchTaskException&) {
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue