ladybird/Kernel/DoubleBuffer.h
Brian Gianforcaro f816abcbad Kernel: Add DoubleBuffer::try_create() factory method for OOM hardening
We need to expose the ability for DoubleBuffer creation to expose
failure, as DoubleBuffer depends on KBuffer, which also has to be able
to expose failure during OOM.

We will remove the non OOM API once all users have been converted.
2021-08-03 18:54:23 +02:00

74 lines
2.1 KiB
C++

/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Types.h>
#include <Kernel/KBuffer.h>
#include <Kernel/Mutex.h>
#include <Kernel/Thread.h>
#include <Kernel/UserOrKernelBuffer.h>
namespace Kernel {
class DoubleBuffer {
public:
[[nodiscard]] static OwnPtr<DoubleBuffer> try_create(size_t capacity = 65536);
explicit DoubleBuffer(size_t capacity = 65536);
[[nodiscard]] KResultOr<size_t> write(const UserOrKernelBuffer&, size_t);
[[nodiscard]] KResultOr<size_t> write(const u8* data, size_t size)
{
return write(UserOrKernelBuffer::for_kernel_buffer(const_cast<u8*>(data)), size);
}
[[nodiscard]] KResultOr<size_t> read(UserOrKernelBuffer&, size_t);
[[nodiscard]] KResultOr<size_t> read(u8* data, size_t size)
{
auto buffer = UserOrKernelBuffer::for_kernel_buffer(data);
return read(buffer, size);
}
[[nodiscard]] KResultOr<size_t> peek(UserOrKernelBuffer&, size_t);
[[nodiscard]] KResultOr<size_t> peek(u8* data, size_t size)
{
auto buffer = UserOrKernelBuffer::for_kernel_buffer(data);
return peek(buffer, size);
}
bool is_empty() const { return m_empty; }
size_t space_for_writing() const { return m_space_for_writing; }
void set_unblock_callback(Function<void()> callback)
{
VERIFY(!m_unblock_callback);
m_unblock_callback = move(callback);
}
private:
explicit DoubleBuffer(size_t capacity, NonnullOwnPtr<KBuffer> storage);
void flip();
void compute_lockfree_metadata();
struct InnerBuffer {
u8* data { nullptr };
size_t size;
};
InnerBuffer* m_write_buffer { nullptr };
InnerBuffer* m_read_buffer { nullptr };
InnerBuffer m_buffer1;
InnerBuffer m_buffer2;
NonnullOwnPtr<KBuffer> m_storage;
Function<void()> m_unblock_callback;
size_t m_capacity { 0 };
size_t m_read_buffer_index { 0 };
size_t m_space_for_writing { 0 };
bool m_empty { true };
mutable Mutex m_lock { "DoubleBuffer" };
};
}