Skip to content

Commit beeeafa

Browse files
committed
unify check
1 parent fc75401 commit beeeafa

File tree

1 file changed

+196
-193
lines changed

1 file changed

+196
-193
lines changed

tier0/threadtools.cpp

Lines changed: 196 additions & 193 deletions
Original file line numberDiff line numberDiff line change
@@ -1635,200 +1635,203 @@ int ThreadWaitForEvents(int nEvents, CThreadEvent* const* pEvents, bool bWaitAll
16351635
}
16361636
ThreadPause();
16371637
}
1638-
// Second optimistic case: we can do an initial check to minimize contention
1639-
if (!bRet && lPredSignaledAnyCheck())
1638+
if (!bRet)
16401639
{
1641-
// Check handles auto reset
1642-
bRet = true;
1643-
}
1644-
else if (!bRet)
1645-
{
1646-
// Lock all at the same time, to prevent race conditions.
1647-
// Before, this was implemented by locking and checking for each one after the other, which caused a race condition.
1648-
switch (nEvents)
1649-
{
1650-
case 2:
1651-
{
1652-
CExtendedScopedLock<std::mutex, std::mutex> lock(pEvents[0]->m_Mutex, pEvents[1]->m_Mutex);
1653-
// If we're already signaled, skip adding listeners
1654-
if (lPredSignaledAny())
1655-
{
1656-
bRet = true;
1657-
}
1658-
else if (timeout != 0)
1659-
{
1660-
std::shared_ptr<std::condition_variable_any> condition = std::make_shared<std::condition_variable_any>();
1661-
for (int i = 0; i < nEvents; i++)
1662-
{
1663-
pEvents[i]->AddListenerNoLock(condition);
1664-
}
1665-
1666-
if (timeout == TT_INFINITE)
1667-
{
1668-
condition->wait(lock, lPredSignaledAny);
1669-
bRet = true;
1670-
}
1671-
else
1672-
{
1673-
bRet = condition->wait_for(lock, std::chrono::milliseconds(timeout), lPredSignaledAny);
1674-
}
1675-
1676-
// Clear out listeners
1677-
for (int i = 0; i < nEvents; i++)
1678-
{
1679-
pEvents[i]->RemoveListenerNoLock(condition);
1680-
}
1681-
condition.reset();
1682-
}
1683-
1684-
// Auto reset, since this function is a wait too!
1685-
if (bRet)
1686-
{
1687-
if (pEvents[iEventIndex]->m_bAutoReset)
1688-
{
1689-
pEvents[iEventIndex]->m_bSignaled = false;
1690-
}
1691-
}
1692-
break;
1693-
}
1694-
case 3:
1695-
{
1696-
CExtendedScopedLock<std::mutex, std::mutex, std::mutex> lock(pEvents[0]->m_Mutex, pEvents[1]->m_Mutex, pEvents[2]->m_Mutex);
1697-
// If we're already signaled, skip adding listeners
1698-
if (lPredSignaledAny())
1699-
{
1700-
bRet = true;
1701-
}
1702-
else if (timeout != 0)
1703-
{
1704-
std::shared_ptr<std::condition_variable_any> condition = std::make_shared<std::condition_variable_any>();
1705-
for (int i = 0; i < nEvents; i++)
1706-
{
1707-
pEvents[i]->AddListenerNoLock(condition);
1708-
}
1709-
1710-
if (timeout == TT_INFINITE)
1711-
{
1712-
condition->wait(lock, lPredSignaledAny);
1713-
bRet = true;
1714-
}
1715-
else
1716-
{
1717-
bRet = condition->wait_for(lock, std::chrono::milliseconds(timeout), lPredSignaledAny);
1718-
}
1719-
1720-
// Clear out listeners
1721-
for (int i = 0; i < nEvents; i++)
1722-
{
1723-
pEvents[i]->RemoveListenerNoLock(condition);
1724-
}
1725-
condition.reset();
1726-
}
1727-
1728-
// Auto reset, since this function is a wait too!
1729-
if (bRet)
1730-
{
1731-
if (pEvents[iEventIndex]->m_bAutoReset)
1732-
{
1733-
pEvents[iEventIndex]->m_bSignaled = false;
1734-
}
1735-
}
1736-
break;
1737-
}
1738-
case 4:
1739-
{
1740-
CExtendedScopedLock<std::mutex, std::mutex, std::mutex, std::mutex> lock(pEvents[0]->m_Mutex, pEvents[1]->m_Mutex, pEvents[2]->m_Mutex, pEvents[3]->m_Mutex);
1741-
// If we're already signaled, skip adding listeners
1742-
if (lPredSignaledAny())
1743-
{
1744-
bRet = true;
1745-
}
1746-
else if (timeout != 0)
1747-
{
1748-
std::shared_ptr<std::condition_variable_any> condition = std::make_shared<std::condition_variable_any>();
1749-
for (int i = 0; i < nEvents; i++)
1750-
{
1751-
pEvents[i]->AddListenerNoLock(condition);
1752-
}
1753-
1754-
if (timeout == TT_INFINITE)
1755-
{
1756-
condition->wait(lock, lPredSignaledAny);
1757-
bRet = true;
1758-
}
1759-
else
1760-
{
1761-
bRet = condition->wait_for(lock, std::chrono::milliseconds(timeout), lPredSignaledAny);
1762-
}
1763-
1764-
// Clear out listeners
1765-
for (int i = 0; i < nEvents; i++)
1766-
{
1767-
pEvents[i]->RemoveListenerNoLock(condition);
1768-
}
1769-
condition.reset();
1770-
}
1771-
1772-
// Auto reset, since this function is a wait too!
1773-
if (bRet)
1774-
{
1775-
if (pEvents[iEventIndex]->m_bAutoReset)
1776-
{
1777-
pEvents[iEventIndex]->m_bSignaled = false;
1778-
}
1779-
}
1780-
break;
1781-
}
1782-
case 5:
1783-
{
1784-
CExtendedScopedLock<std::mutex, std::mutex, std::mutex, std::mutex, std::mutex> lock(pEvents[0]->m_Mutex, pEvents[1]->m_Mutex, pEvents[2]->m_Mutex, pEvents[3]->m_Mutex, pEvents[4]->m_Mutex);
1785-
// If we're already signaled, skip adding listeners
1786-
if (lPredSignaledAny())
1787-
{
1788-
bRet = true;
1789-
}
1790-
else if (timeout != 0)
1791-
{
1792-
std::shared_ptr<std::condition_variable_any> condition = std::make_shared<std::condition_variable_any>();
1793-
for (int i = 0; i < nEvents; i++)
1794-
{
1795-
pEvents[i]->AddListenerNoLock(condition);
1796-
}
1797-
1798-
if (timeout == TT_INFINITE)
1799-
{
1800-
condition->wait(lock, lPredSignaledAny);
1801-
bRet = true;
1802-
}
1803-
else
1804-
{
1805-
bRet = condition->wait_for(lock, std::chrono::milliseconds(timeout), lPredSignaledAny);
1806-
}
1807-
1808-
// Clear out listeners
1809-
for (int i = 0; i < nEvents; i++)
1810-
{
1811-
pEvents[i]->RemoveListenerNoLock(condition);
1812-
}
1813-
condition.reset();
1814-
}
1815-
1816-
// Auto reset, since this function is a wait too!
1817-
if (bRet)
1818-
{
1819-
if (pEvents[iEventIndex]->m_bAutoReset)
1820-
{
1821-
pEvents[iEventIndex]->m_bSignaled = false;
1822-
}
1823-
}
1824-
break;
1825-
}
1826-
default:
1827-
{
1828-
Assert(0);
1829-
break;
1830-
}
1831-
}
1640+
// Second optimistic case: we can do an initial check to minimize contention
1641+
if (lPredSignaledAnyCheck())
1642+
{
1643+
// Check handles auto reset
1644+
bRet = true;
1645+
}
1646+
else
1647+
{
1648+
// Lock all at the same time, to prevent race conditions.
1649+
// Before, this was implemented by locking and checking for each one after the other, which caused a race condition.
1650+
switch (nEvents)
1651+
{
1652+
case 2:
1653+
{
1654+
CExtendedScopedLock<std::mutex, std::mutex> lock(pEvents[0]->m_Mutex, pEvents[1]->m_Mutex);
1655+
// If we're already signaled, skip adding listeners
1656+
if (lPredSignaledAny())
1657+
{
1658+
bRet = true;
1659+
}
1660+
else if (timeout != 0)
1661+
{
1662+
std::shared_ptr<std::condition_variable_any> condition = std::make_shared<std::condition_variable_any>();
1663+
for (int i = 0; i < nEvents; i++)
1664+
{
1665+
pEvents[i]->AddListenerNoLock(condition);
1666+
}
1667+
1668+
if (timeout == TT_INFINITE)
1669+
{
1670+
condition->wait(lock, lPredSignaledAny);
1671+
bRet = true;
1672+
}
1673+
else
1674+
{
1675+
bRet = condition->wait_for(lock, std::chrono::milliseconds(timeout), lPredSignaledAny);
1676+
}
1677+
1678+
// Clear out listeners
1679+
for (int i = 0; i < nEvents; i++)
1680+
{
1681+
pEvents[i]->RemoveListenerNoLock(condition);
1682+
}
1683+
condition.reset();
1684+
}
1685+
1686+
// Auto reset, since this function is a wait too!
1687+
if (bRet)
1688+
{
1689+
if (pEvents[iEventIndex]->m_bAutoReset)
1690+
{
1691+
pEvents[iEventIndex]->m_bSignaled = false;
1692+
}
1693+
}
1694+
break;
1695+
}
1696+
case 3:
1697+
{
1698+
CExtendedScopedLock<std::mutex, std::mutex, std::mutex> lock(pEvents[0]->m_Mutex, pEvents[1]->m_Mutex, pEvents[2]->m_Mutex);
1699+
// If we're already signaled, skip adding listeners
1700+
if (lPredSignaledAny())
1701+
{
1702+
bRet = true;
1703+
}
1704+
else if (timeout != 0)
1705+
{
1706+
std::shared_ptr<std::condition_variable_any> condition = std::make_shared<std::condition_variable_any>();
1707+
for (int i = 0; i < nEvents; i++)
1708+
{
1709+
pEvents[i]->AddListenerNoLock(condition);
1710+
}
1711+
1712+
if (timeout == TT_INFINITE)
1713+
{
1714+
condition->wait(lock, lPredSignaledAny);
1715+
bRet = true;
1716+
}
1717+
else
1718+
{
1719+
bRet = condition->wait_for(lock, std::chrono::milliseconds(timeout), lPredSignaledAny);
1720+
}
1721+
1722+
// Clear out listeners
1723+
for (int i = 0; i < nEvents; i++)
1724+
{
1725+
pEvents[i]->RemoveListenerNoLock(condition);
1726+
}
1727+
condition.reset();
1728+
}
1729+
1730+
// Auto reset, since this function is a wait too!
1731+
if (bRet)
1732+
{
1733+
if (pEvents[iEventIndex]->m_bAutoReset)
1734+
{
1735+
pEvents[iEventIndex]->m_bSignaled = false;
1736+
}
1737+
}
1738+
break;
1739+
}
1740+
case 4:
1741+
{
1742+
CExtendedScopedLock<std::mutex, std::mutex, std::mutex, std::mutex> lock(pEvents[0]->m_Mutex, pEvents[1]->m_Mutex, pEvents[2]->m_Mutex, pEvents[3]->m_Mutex);
1743+
// If we're already signaled, skip adding listeners
1744+
if (lPredSignaledAny())
1745+
{
1746+
bRet = true;
1747+
}
1748+
else if (timeout != 0)
1749+
{
1750+
std::shared_ptr<std::condition_variable_any> condition = std::make_shared<std::condition_variable_any>();
1751+
for (int i = 0; i < nEvents; i++)
1752+
{
1753+
pEvents[i]->AddListenerNoLock(condition);
1754+
}
1755+
1756+
if (timeout == TT_INFINITE)
1757+
{
1758+
condition->wait(lock, lPredSignaledAny);
1759+
bRet = true;
1760+
}
1761+
else
1762+
{
1763+
bRet = condition->wait_for(lock, std::chrono::milliseconds(timeout), lPredSignaledAny);
1764+
}
1765+
1766+
// Clear out listeners
1767+
for (int i = 0; i < nEvents; i++)
1768+
{
1769+
pEvents[i]->RemoveListenerNoLock(condition);
1770+
}
1771+
condition.reset();
1772+
}
1773+
1774+
// Auto reset, since this function is a wait too!
1775+
if (bRet)
1776+
{
1777+
if (pEvents[iEventIndex]->m_bAutoReset)
1778+
{
1779+
pEvents[iEventIndex]->m_bSignaled = false;
1780+
}
1781+
}
1782+
break;
1783+
}
1784+
case 5:
1785+
{
1786+
CExtendedScopedLock<std::mutex, std::mutex, std::mutex, std::mutex, std::mutex> lock(pEvents[0]->m_Mutex, pEvents[1]->m_Mutex, pEvents[2]->m_Mutex, pEvents[3]->m_Mutex, pEvents[4]->m_Mutex);
1787+
// If we're already signaled, skip adding listeners
1788+
if (lPredSignaledAny())
1789+
{
1790+
bRet = true;
1791+
}
1792+
else if (timeout != 0)
1793+
{
1794+
std::shared_ptr<std::condition_variable_any> condition = std::make_shared<std::condition_variable_any>();
1795+
for (int i = 0; i < nEvents; i++)
1796+
{
1797+
pEvents[i]->AddListenerNoLock(condition);
1798+
}
1799+
1800+
if (timeout == TT_INFINITE)
1801+
{
1802+
condition->wait(lock, lPredSignaledAny);
1803+
bRet = true;
1804+
}
1805+
else
1806+
{
1807+
bRet = condition->wait_for(lock, std::chrono::milliseconds(timeout), lPredSignaledAny);
1808+
}
1809+
1810+
// Clear out listeners
1811+
for (int i = 0; i < nEvents; i++)
1812+
{
1813+
pEvents[i]->RemoveListenerNoLock(condition);
1814+
}
1815+
condition.reset();
1816+
}
1817+
1818+
// Auto reset, since this function is a wait too!
1819+
if (bRet)
1820+
{
1821+
if (pEvents[iEventIndex]->m_bAutoReset)
1822+
{
1823+
pEvents[iEventIndex]->m_bSignaled = false;
1824+
}
1825+
}
1826+
break;
1827+
}
1828+
default:
1829+
{
1830+
Assert(0);
1831+
break;
1832+
}
1833+
}
1834+
}
18321835
}
18331836
}
18341837
if (bRet)

0 commit comments

Comments
 (0)