static MojErr MojThreadTestFn(void* arg) { static MojThreadLocalValue<int, MojThreadLocalValueZeroCtor<int> > s_localVal; MojThreadTestArgs* targs = (MojThreadTestArgs*) arg; MojTestAssert(targs); for (int i = 0; i < MojTestNumIterations; ++i) { targs->m_atomicCounter.increment(); MojThreadGuard guard(targs->m_mutex, false); if (!guard.tryLock()) guard.lock(); ++(targs->m_counter); if (targs->m_counter == (MojTestNumThreads * MojTestNumIterations)) { MojErr err = targs->m_countCond.signal(); MojTestErrCheck(err); } } MojErr err = MojThreadYield(); MojTestErrCheck(err); MojThreadGuard guard(targs->m_mutex); while (targs->m_wait) { err = targs->m_waitCond.wait(targs->m_mutex); MojTestErrCheck(err); } guard.unlock(); int* localVal = NULL; err = s_localVal.get(localVal); MojTestErrCheck(err); MojTestAssert(localVal && *localVal == 0); for (int i = 0; i < MojTestNumIterations; ++i) { ++(*localVal); targs->m_atomicCounter.decrement(); { MojThreadReadGuard readGuard(targs->m_rwlock); MojTestAssert(targs->m_counter > 0); } MojThreadReadGuard readGuard(targs->m_rwlock, false); if (!readGuard.tryLock()) readGuard.lock(); MojTestAssert(targs->m_counter > 0); readGuard.unlock(); { MojThreadWriteGuard writeGuard(targs->m_rwlock); ++(targs->m_counter); } MojThreadWriteGuard writeGuard(targs->m_rwlock, false); if (!writeGuard.tryLock()) writeGuard.lock(); targs->m_counter -= 2; } MojTestAssert(*localVal == MojTestNumIterations); return MojErrNone; }
void LinkAggregationManager::stateUpdated(const StateDelta& delta) { CHECK(sw_->getUpdateEvb()->inRunningEventBaseThread()); folly::SharedMutexWritePriority::WriteHolder writeGuard(&controllersLock_); if (!initialized_) { bool inserted; for (const auto& port : *(delta.newState()->getPorts())) { // TODO(samank): use try_emplace once OSS build uses boost >1.63.0 std::tie(std::ignore, inserted) = portToController_.insert(std::make_pair( port->getID(), std::make_shared<LacpController>( port->getID(), sw_->getLacpEvb(), this))); CHECK(inserted); } for (const auto& portAndController : portToController_) { portAndController.second->startMachines(); } initialized_ = true; } DeltaFunctions::forEachChanged( delta.getAggregatePortsDelta(), &LinkAggregationManager::aggregatePortChanged, &LinkAggregationManager::aggregatePortAdded, &LinkAggregationManager::aggregatePortRemoved, this); // Downgrade to a reader lock folly::SharedMutexWritePriority::ReadHolder readGuard(std::move(writeGuard)); DeltaFunctions::forEachChanged( delta.getPortsDelta(), &LinkAggregationManager::portChanged, this); }
const Signals::SemaphorePtr Signals::SignalTable::GetSemaphore(const ConnectionId & connection) { { boost::shared_lock<SignalsLock> guard(m_lock); Semaphores::iterator findIt = m_semaphores.find(connection.m_id); if (findIt != m_semaphores.end()) { return findIt->second; } } //Did not find the semaphore, we need to get write access. //first get an upgrade lock, which is only a read lock, but stops new //readers from getting in, so we will never be starved. boost::upgrade_lock<SignalsLock> readGuard(m_lock); //someone else may have gotten in and added the semaphore, so we check. Semaphores::iterator findIt = m_semaphores.find(connection.m_id); if (findIt != m_semaphores.end()) { return findIt->second; } //ok, now we upgrade and add. boost::upgrade_to_unique_lock<SignalsLock> writeGuard(readGuard); return AddSemaphore(connection); }