vgl 1.0.0
Virtual Globe Library: API reference
Loading...
Searching...
No Matches
foundation.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: MIT
2// Copyright (c) 2026 Jeremiah van Oosten
3//
4// C++ wrapper for vgl/foundation.h. Allocators, I/O and task scheduling written as C++ classes
5// are adapted onto the C interface tables (docs/c-api.md, sections 9.2 and 16).
6
7#ifndef VGL_FOUNDATION_HPP
8#define VGL_FOUNDATION_HPP
9
10#include <vgl/base.hpp>
11#include <vgl/foundation.h>
12
13#include <cstddef>
14#include <cstdint>
15#include <span>
16
17namespace vgl
18{
19
28
29// Base class for host allocators. Derive from it and pass c_interface() wherever the C API
30// takes a vgl_allocator_interface. The object must outlive every use of the interface.
32{
33public:
34 allocator() = default;
35 allocator(const allocator&) = delete;
36 allocator& operator=(const allocator&) = delete;
37 allocator(allocator&&) = delete;
39 virtual ~allocator() = default;
40
41 // Allocates size bytes (never 0) aligned to alignment, a power of two. Returns null on
42 // failure. Must not throw.
43 virtual void* allocate(std::size_t size, std::size_t alignment) noexcept = 0;
44
45 // Frees memory from allocate, with the same size and alignment. memory is never null.
46 virtual void deallocate(void* memory, std::size_t size, std::size_t alignment) noexcept = 0;
47
48 // C table whose entries forward to this object.
50 {
53 table.user_data = this;
54 table.allocate = &allocate_thunk;
55 table.deallocate = &deallocate_thunk;
56 return table;
57 }
58
59private:
60 static void* allocate_thunk(void* user_data, std::size_t size, std::size_t alignment)
61 {
62 return static_cast<allocator*>(user_data)->allocate(size, alignment);
63 }
64
65 static void
66 deallocate_thunk(void* user_data, void* memory, std::size_t size, std::size_t alignment)
67 {
68 static_cast<allocator*>(user_data)->deallocate(memory, size, alignment);
69 }
70};
71
74
75inline constexpr std::uint64_t io_size_to_end = VGL_IO_SIZE_TO_END;
76
77// Completes an I/O request with the bytes read, which are copied. Free-threaded.
78[[nodiscard]] inline result
79io_request_complete(io_request* request, result r, std::span<const std::byte> data = {}) noexcept
80{
81 return static_cast<result>(
82 vgl_io_request_complete(request, static_cast<vgl_result>(r), data.data(), data.size()));
83}
84
86
87// Creates a request whose completion calls complete(user_data, result, data, size), for passing
88// a read on to another I/O interface. alloc may be null for the C heap.
91 void* user_data,
92 const vgl_allocator_interface* alloc = nullptr) noexcept
93{
95 info.complete = complete;
96 info.user_data = user_data;
97 info.allocator = alloc;
98 io_request* request = nullptr;
99 const auto r = static_cast<result>(vgl_io_request_create(&info, &request));
100 if (failed(r))
101 {
102 return unexpected(r);
103 }
104 return request;
105}
106
107// Base class for host I/O. Derive from it and pass c_interface() as
108// vgl_context_create_info::io. The object must outlive every context that uses it.
110{
111public:
112 io_interface() = default;
113 io_interface(const io_interface&) = delete;
117 virtual ~io_interface() = default;
118
119 // Starts a read, which must be completed exactly once with io_request_complete. Called on
120 // the thread that calls into the context. Must not throw.
121 virtual void read(io_request* request, const io_read& read) noexcept = 0;
122
123 // Asks to give up a read; it must still be completed. Called on the context's thread.
124 virtual void cancel(io_request* /*request*/) noexcept {}
125
126 // Called once while a context that uses this object is destroyed, on the thread that
127 // destroys it. Reads may still be outstanding; they must still be completed.
128 virtual void on_destroy() noexcept {}
129
130 // C table whose entries forward to this object.
132 {
135 table.user_data = this;
136 table.read = &read_thunk;
137 table.cancel = &cancel_thunk;
138 table.destroy = &destroy_thunk;
139 return table;
140 }
141
142private:
143 static void read_thunk(void* user_data, vgl_io_request* request, const vgl_io_read* read)
144 {
145 static_cast<io_interface*>(user_data)->read(request, *read);
146 }
147
148 static void cancel_thunk(void* user_data, vgl_io_request* request)
149 {
150 static_cast<io_interface*>(user_data)->cancel(request);
151 }
152
153 static void destroy_thunk(void* user_data)
154 {
155 static_cast<io_interface*>(user_data)->on_destroy();
156 }
157};
158
160
161// Base class for host task scheduling. Derive from it and pass c_interface() as
162// vgl_context_create_info::tasks. The object must outlive every context that uses it.
164{
165public:
166 task_interface() = default;
171 virtual ~task_interface() = default;
172
173 // Runs function(task_data) exactly once, on any thread, and returns result::success; or
174 // returns another result and never calls it. Called on the context's thread. Must not
175 // throw.
176 virtual result submit(task_fn function, void* task_data) noexcept = 0;
177
178 // Called once while a context that uses this object is destroyed, on the thread that
179 // destroys it. Submitted tasks may still be queued; they must still run.
180 virtual void on_destroy() noexcept {}
181
182 // C table whose entries forward to this object.
184 {
187 table.user_data = this;
188 table.submit = &submit_thunk;
189 table.destroy = &destroy_thunk;
190 return table;
191 }
192
193private:
194 static vgl_result submit_thunk(void* user_data, vgl_task_fn function, void* task_data)
195 {
196 return static_cast<vgl_result>(
197 static_cast<task_interface*>(user_data)->submit(function, task_data));
198 }
199
200 static void destroy_thunk(void* user_data)
201 {
202 static_cast<task_interface*>(user_data)->on_destroy();
203 }
204};
205
206} // namespace vgl
207
208#endif // VGL_FOUNDATION_HPP
vgl_result
Definition base.h:98
Definition foundation.hpp:32
allocator(const allocator &)=delete
virtual void deallocate(void *memory, std::size_t size, std::size_t alignment) noexcept=0
allocator & operator=(const allocator &)=delete
virtual ~allocator()=default
allocator()=default
allocator(allocator &&)=delete
virtual void * allocate(std::size_t size, std::size_t alignment) noexcept=0
allocator & operator=(allocator &&)=delete
vgl_allocator_interface c_interface() noexcept
Definition foundation.hpp:49
Definition base.hpp:87
Definition foundation.hpp:110
virtual ~io_interface()=default
io_interface & operator=(io_interface &&)=delete
io_interface(io_interface &&)=delete
io_interface()=default
vgl_io_interface c_interface() noexcept
Definition foundation.hpp:131
virtual void read(io_request *request, const io_read &read) noexcept=0
io_interface(const io_interface &)=delete
io_interface & operator=(const io_interface &)=delete
virtual void on_destroy() noexcept
Definition foundation.hpp:128
virtual void cancel(io_request *) noexcept
Definition foundation.hpp:124
Definition foundation.hpp:164
task_interface()=default
task_interface(task_interface &&)=delete
virtual result submit(task_fn function, void *task_data) noexcept=0
task_interface & operator=(task_interface &&)=delete
task_interface(const task_interface &)=delete
virtual void on_destroy() noexcept
Definition foundation.hpp:180
virtual ~task_interface()=default
task_interface & operator=(const task_interface &)=delete
vgl_task_interface c_interface() noexcept
Definition foundation.hpp:183
Definition base.hpp:72
vgl_result vgl_io_request_complete(vgl_io_request *request, vgl_result result, const void *data, size_t size)
#define VGL_TASK_INTERFACE_VERSION
Definition foundation.h:224
struct vgl_io_request vgl_io_request
Definition foundation.h:76
#define VGL_IO_INTERFACE_VERSION
Definition foundation.h:94
#define VGL_IO_SIZE_TO_END
Definition foundation.h:79
vgl_result vgl_io_request_create(const vgl_io_request_create_info *info, vgl_io_request **out_request)
void(* vgl_task_fn)(void *user_data)
Definition foundation.h:222
#define VGL_ALLOCATOR_INTERFACE_VERSION
Definition foundation.h:41
@ VGL_LOG_LEVEL_DEFAULT
Definition foundation.h:21
@ VGL_LOG_LEVEL_ERROR
Definition foundation.h:22
@ VGL_LOG_LEVEL_DEBUG
Definition foundation.h:25
@ VGL_LOG_LEVEL_WARNING
Definition foundation.h:23
@ VGL_LOG_LEVEL_INFO
Definition foundation.h:24
void(* vgl_io_complete_fn)(void *user_data, vgl_result result, const void *data, size_t size)
Definition foundation.h:169
Definition base.hpp:22
vgl_task_fn task_fn
Definition foundation.hpp:159
expected< io_request * > io_request_create(io_complete_fn complete, void *user_data, const vgl_allocator_interface *alloc=nullptr) noexcept
Definition foundation.hpp:90
log_level
Definition foundation.hpp:21
result
Definition base.hpp:25
vgl_io_complete_fn io_complete_fn
Definition foundation.hpp:85
vgl_io_request io_request
Definition foundation.hpp:72
result io_request_complete(io_request *request, result r, std::span< const std::byte > data={}) noexcept
Definition foundation.hpp:79
constexpr std::uint64_t io_size_to_end
Definition foundation.hpp:75
Definition foundation.h:49
Definition foundation.h:102
Definition foundation.h:83
Definition foundation.h:232