mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 13:18:13 +00:00
Kernel: Introduce ThreadBlocker as a way to make unblocking neater :)
And port all the descriptor-based blocks over to it as a proof of concept.
This commit is contained in:
parent
a27c9e3e01
commit
0c8813e6d9
6 changed files with 154 additions and 67 deletions
|
@ -51,6 +51,88 @@ void Scheduler::beep()
|
|||
s_beep_timeout = g_uptime + 100;
|
||||
}
|
||||
|
||||
Thread::ThreadBlockerFileDescription::ThreadBlockerFileDescription(const RefPtr<FileDescription>& description)
|
||||
: m_blocked_description(description)
|
||||
{}
|
||||
|
||||
RefPtr<FileDescription> Thread::ThreadBlockerFileDescription::blocked_description() const
|
||||
{
|
||||
return m_blocked_description;
|
||||
}
|
||||
|
||||
Thread::ThreadBlockerAccept::ThreadBlockerAccept(const RefPtr<FileDescription>& description)
|
||||
: ThreadBlockerFileDescription(description)
|
||||
{
|
||||
}
|
||||
|
||||
bool Thread::ThreadBlockerAccept::should_unblock(time_t, long)
|
||||
{
|
||||
auto& description = *blocked_description();
|
||||
auto& socket = *description.socket();
|
||||
|
||||
return socket.can_accept();
|
||||
}
|
||||
|
||||
Thread::ThreadBlockerReceive::ThreadBlockerReceive(const RefPtr<FileDescription>& description)
|
||||
: ThreadBlockerFileDescription(description)
|
||||
{
|
||||
}
|
||||
|
||||
bool Thread::ThreadBlockerReceive::should_unblock(time_t now_sec, long now_usec)
|
||||
{
|
||||
auto& description = *blocked_description();
|
||||
auto& socket = *description.socket();
|
||||
// FIXME: Block until the amount of data wanted is available.
|
||||
bool timed_out = now_sec > socket.receive_deadline().tv_sec || (now_sec == socket.receive_deadline().tv_sec && now_usec >= socket.receive_deadline().tv_usec);
|
||||
if (timed_out || description.can_read())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
Thread::ThreadBlockerConnect::ThreadBlockerConnect(const RefPtr<FileDescription>& description)
|
||||
: ThreadBlockerFileDescription(description)
|
||||
{
|
||||
}
|
||||
|
||||
bool Thread::ThreadBlockerConnect::should_unblock(time_t, long)
|
||||
{
|
||||
auto& description = *blocked_description();
|
||||
auto& socket = *description.socket();
|
||||
return socket.is_connected();
|
||||
}
|
||||
|
||||
Thread::ThreadBlockerWrite::ThreadBlockerWrite(const RefPtr<FileDescription>& description)
|
||||
: ThreadBlockerFileDescription(description)
|
||||
{
|
||||
}
|
||||
|
||||
bool Thread::ThreadBlockerWrite::should_unblock(time_t, long)
|
||||
{
|
||||
return blocked_description()->can_write();
|
||||
}
|
||||
|
||||
Thread::ThreadBlockerRead::ThreadBlockerRead(const RefPtr<FileDescription>& description)
|
||||
: ThreadBlockerFileDescription(description)
|
||||
{
|
||||
}
|
||||
|
||||
bool Thread::ThreadBlockerRead::should_unblock(time_t, long)
|
||||
{
|
||||
// FIXME: Block until the amount of data wanted is available.
|
||||
return blocked_description()->can_read();
|
||||
}
|
||||
|
||||
Thread::ThreadBlockerCondition::ThreadBlockerCondition(Function<bool()> &condition)
|
||||
: m_block_until_condition(move(condition))
|
||||
{
|
||||
ASSERT(m_block_until_condition);
|
||||
}
|
||||
|
||||
bool Thread::ThreadBlockerCondition::should_unblock(time_t, long)
|
||||
{
|
||||
return m_block_until_condition();
|
||||
}
|
||||
|
||||
// Called by the scheduler on threads that are blocked for some reason.
|
||||
// Make a decision as to whether to unblock them or not.
|
||||
void Thread::consider_unblock(time_t now_sec, long now_usec)
|
||||
|
@ -93,41 +175,6 @@ void Thread::consider_unblock(time_t now_sec, long now_usec)
|
|||
return IterationDecision::Break;
|
||||
});
|
||||
return;
|
||||
case Thread::BlockedRead:
|
||||
ASSERT(m_blocked_description);
|
||||
// FIXME: Block until the amount of data wanted is available.
|
||||
if (m_blocked_description->can_read())
|
||||
unblock();
|
||||
return;
|
||||
case Thread::BlockedWrite:
|
||||
ASSERT(m_blocked_description != -1);
|
||||
if (m_blocked_description->can_write())
|
||||
unblock();
|
||||
return;
|
||||
case Thread::BlockedConnect: {
|
||||
auto& description = *m_blocked_description;
|
||||
auto& socket = *description.socket();
|
||||
if (socket.is_connected())
|
||||
unblock();
|
||||
return;
|
||||
}
|
||||
case Thread::BlockedReceive: {
|
||||
auto& description = *m_blocked_description;
|
||||
auto& socket = *description.socket();
|
||||
// FIXME: Block until the amount of data wanted is available.
|
||||
bool timed_out = now_sec > socket.receive_deadline().tv_sec || (now_sec == socket.receive_deadline().tv_sec && now_usec >= socket.receive_deadline().tv_usec);
|
||||
if (timed_out || description.can_read())
|
||||
unblock();
|
||||
return;
|
||||
}
|
||||
case Thread::BlockedAccept: {
|
||||
auto& description = *m_blocked_description;
|
||||
auto& socket = *description.socket();
|
||||
|
||||
if (socket.can_accept())
|
||||
unblock();
|
||||
return;
|
||||
}
|
||||
case Thread::BlockedSelect:
|
||||
if (m_select_has_timeout) {
|
||||
if (now_sec > m_select_timeout.tv_sec || (now_sec == m_select_timeout.tv_sec && now_usec >= m_select_timeout.tv_usec)) {
|
||||
|
@ -149,9 +196,10 @@ void Thread::consider_unblock(time_t now_sec, long now_usec)
|
|||
}
|
||||
return;
|
||||
case Thread::BlockedCondition:
|
||||
if (m_block_until_condition()) {
|
||||
m_block_until_condition = nullptr;
|
||||
ASSERT(m_blocker);
|
||||
if (m_blocker->should_unblock(now_sec, now_usec)) {
|
||||
unblock();
|
||||
m_blocker = nullptr;
|
||||
}
|
||||
return;
|
||||
case Thread::Skip1SchedulerPass:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue