81 lines
1.4 KiB
C++
81 lines
1.4 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "UbaEvent.h"
|
|
#include "UbaPlatform.h"
|
|
#include "UbaSynchronization.h"
|
|
#include "UbaTimer.h"
|
|
|
|
namespace uba
|
|
{
|
|
struct BottleneckTicket
|
|
{
|
|
Event ev;
|
|
BottleneckTicket* next = nullptr;
|
|
};
|
|
|
|
struct Bottleneck
|
|
{
|
|
Bottleneck(u32 mc) : m_maxCount(mc) {}
|
|
|
|
void Enter(BottleneckTicket& ticket, Timer& timer)
|
|
{
|
|
SCOPED_FUTEX(m_lock, lock);
|
|
if (m_activeCount < m_maxCount)
|
|
{
|
|
UBA_ASSERT(!m_first);
|
|
++m_activeCount;
|
|
return;
|
|
}
|
|
|
|
if (!m_first)
|
|
m_first = &ticket;
|
|
else
|
|
m_last->next = &ticket;
|
|
m_last = &ticket;
|
|
|
|
if (!ticket.ev.IsCreated())
|
|
ticket.ev.Create(true);
|
|
|
|
lock.Leave();
|
|
|
|
TimerScope ts(timer);
|
|
ticket.ev.IsSet();
|
|
}
|
|
|
|
void Leave(BottleneckTicket& ticket)
|
|
{
|
|
SCOPED_FUTEX(m_lock, lock);
|
|
BottleneckTicket* first = m_first;
|
|
if (!first)
|
|
{
|
|
UBA_ASSERT(m_activeCount > 0);
|
|
--m_activeCount;
|
|
return;
|
|
}
|
|
m_first = first->next;
|
|
if (!m_first)
|
|
m_last = nullptr;
|
|
first->ev.Set();
|
|
}
|
|
|
|
private:
|
|
Futex m_lock;
|
|
BottleneckTicket* m_first = nullptr;
|
|
BottleneckTicket* m_last = nullptr;
|
|
u32 m_activeCount = 0;
|
|
u32 m_maxCount;
|
|
};
|
|
|
|
struct BottleneckScope
|
|
{
|
|
BottleneckScope(Bottleneck& b, Timer& timer) : bottleneck(b) { b.Enter(ticket, timer); }
|
|
~BottleneckScope() { bottleneck.Leave(ticket); }
|
|
|
|
Bottleneck& bottleneck;
|
|
BottleneckTicket ticket;
|
|
};
|
|
|
|
}
|