1#![allow(missing_docs)]
33
34pub mod io;
35pub mod memory_pool;
36pub mod net;
37pub mod runtime;
38pub mod window;
39
40use std::sync::Arc;
41
42use crate::memory_pool::BufferPool;
43
44pub struct Context {
48 runtime: tokio::runtime::Runtime,
50 buffer_pool: BufferPool,
52}
53
54impl Context {
55 pub fn new() -> Self {
57 let runtime = tokio::runtime::Builder::new_multi_thread()
58 .worker_threads(4)
59 .thread_name("iris-worker")
60 .enable_all()
61 .build()
62 .expect("Failed to create Tokio runtime");
63 Self {
64 runtime,
65 buffer_pool: BufferPool::default(),
66 }
67 }
68
69 pub fn buffer_pool(&self) -> &BufferPool {
71 &self.buffer_pool
72 }
73
74 pub fn handle(&self) -> &tokio::runtime::Handle {
76 self.runtime.handle()
77 }
78
79 pub fn spawn<F>(&self, future: F) -> tokio::task::JoinHandle<F::Output>
81 where
82 F: std::future::Future + Send + 'static,
83 F::Output: Send + 'static,
84 {
85 self.runtime.spawn(future)
86 }
87
88 pub fn block_on<F>(&self, future: F) -> F::Output
92 where
93 F: std::future::Future,
94 {
95 self.runtime.block_on(future)
96 }
97}
98
99impl Default for Context {
100 fn default() -> Self {
101 Self::new()
102 }
103}
104
105#[cfg(not(target_arch = "wasm32"))]
109pub trait Application: Send + 'static {
110 fn initialize(&mut self, ctx: &Context, event_loop: &winit::event_loop::ActiveEventLoop);
112
113 fn window_event(
115 &mut self,
116 ctx: &Context,
117 event_loop: &winit::event_loop::ActiveEventLoop,
118 window_id: winit::window::WindowId,
119 event: winit::event::WindowEvent,
120 );
121
122 #[allow(unused_variables)]
124 fn device_event(
125 &mut self,
126 ctx: &Context,
127 event_loop: &winit::event_loop::ActiveEventLoop,
128 device_id: winit::event::DeviceId,
129 event: winit::event::DeviceEvent,
130 ) {
131 }
132
133 #[allow(unused_variables)]
135 fn update(&mut self, ctx: &Context, event_loop: &winit::event_loop::ActiveEventLoop) {}
136
137 #[allow(unused_variables)]
139 fn exiting(&mut self, ctx: &Context) {}
140}
141
142#[cfg(not(target_arch = "wasm32"))]
146pub fn run_app<A: Application>(app: A) -> Result<(), Box<dyn std::error::Error>> {
147 use winit::application::ApplicationHandler;
148 use winit::event::{DeviceEvent, StartCause, WindowEvent};
149 use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
150
151 struct WinitApp<A> {
152 ctx: Arc<Context>,
153 app: A,
154 }
155
156 impl<A: Application> ApplicationHandler for WinitApp<A> {
157 fn resumed(&mut self, event_loop: &ActiveEventLoop) {
158 self.app.initialize(&self.ctx, event_loop);
159 }
160
161 fn window_event(
162 &mut self,
163 event_loop: &ActiveEventLoop,
164 window_id: winit::window::WindowId,
165 event: WindowEvent,
166 ) {
167 self.app
168 .window_event(&self.ctx, event_loop, window_id, event);
169 }
170
171 fn device_event(
172 &mut self,
173 event_loop: &ActiveEventLoop,
174 device_id: winit::event::DeviceId,
175 event: DeviceEvent,
176 ) {
177 self.app
178 .device_event(&self.ctx, event_loop, device_id, event);
179 }
180
181 fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) {
182 self.app.update(&self.ctx, event_loop);
183 }
184
185 fn new_events(&mut self, _event_loop: &ActiveEventLoop, _cause: StartCause) {}
186
187 fn suspended(&mut self, _event_loop: &ActiveEventLoop) {}
188
189 fn exiting(&mut self, _event_loop: &ActiveEventLoop) {
190 self.app.exiting(&self.ctx);
191 }
192 }
193
194 let ctx = Arc::new(Context::new());
195 let event_loop = EventLoop::new()?;
196 event_loop.set_control_flow(ControlFlow::Poll);
197
198 let mut winit_app = WinitApp { ctx, app };
199 event_loop.run_app(&mut winit_app)?;
200
201 Ok(())
202}
203
204pub fn init() {
206 println!("iris-core initialized");
207}