Checking in vendor folder for ease of using go get.
This commit is contained in:
parent
7a1251853b
commit
cdb4b5a1d0
3554 changed files with 1270116 additions and 0 deletions
159
vendor/git.apache.org/thrift.git/lib/cpp/test/RWMutexStarveTest.cpp
generated
vendored
Normal file
159
vendor/git.apache.org/thrift.git/lib/cpp/test/RWMutexStarveTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include "thrift/concurrency/Mutex.h"
|
||||
#include "thrift/concurrency/PosixThreadFactory.h"
|
||||
|
||||
using boost::shared_ptr;
|
||||
using boost::unit_test::test_suite;
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
using namespace apache::thrift::concurrency;
|
||||
using namespace std;
|
||||
|
||||
class Locker : public Runnable {
|
||||
protected:
|
||||
Locker(boost::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:
|
||||
boost::shared_ptr<ReadWriteMutex> rwlock_;
|
||||
bool writer_;
|
||||
volatile bool started_;
|
||||
volatile bool gotLock_;
|
||||
volatile bool signaled_;
|
||||
};
|
||||
|
||||
class Reader : public Locker {
|
||||
public:
|
||||
Reader(boost::shared_ptr<ReadWriteMutex> rwlock) : Locker(rwlock, false) {}
|
||||
};
|
||||
|
||||
class Writer : public Locker {
|
||||
public:
|
||||
Writer(boost::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);
|
||||
|
||||
boost::shared_ptr<ReadWriteMutex> rwlock(new NoStarveReadWriteMutex());
|
||||
|
||||
boost::shared_ptr<Reader> reader1(new Reader(rwlock));
|
||||
boost::shared_ptr<Reader> reader2(new Reader(rwlock));
|
||||
boost::shared_ptr<Writer> writer(new Writer(rwlock));
|
||||
|
||||
boost::shared_ptr<Thread> treader1 = factory.newThread(reader1);
|
||||
boost::shared_ptr<Thread> treader2 = factory.newThread(reader2);
|
||||
boost::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()
|
Loading…
Add table
Add a link
Reference in a new issue