@@ -39,13 +39,15 @@ struct SC::WebServerExampleModelState
3939 String interface = " 127.0.0.1" ;
4040 int32_t port = 8090 ;
4141 int32_t maxClients = 32 ;
42+ bool useStreams = false ;
4243};
4344
4445SC_REFLECT_STRUCT_VISIT (SC::WebServerExampleModelState)
4546SC_REFLECT_STRUCT_FIELD(0 , directory)
4647SC_REFLECT_STRUCT_FIELD(1 , interface)
4748SC_REFLECT_STRUCT_FIELD(2 , port)
4849SC_REFLECT_STRUCT_FIELD(3 , maxClients)
50+ SC_REFLECT_STRUCT_FIELD(4 , useStreams)
4951SC_REFLECT_STRUCT_LEAVE()
5052
5153struct SC::WebServerExampleViewState
@@ -67,20 +69,55 @@ struct SC::WebServerExampleModel
6769 HttpAsyncServer httpServer;
6870 HttpWebServer httpWebServer;
6971
70- Buffer headerBuffer;
72+ Buffer requestsMemory;
73+ Buffer headerBuffer;
74+
7175 GrowableBuffer<Buffer> gb = {headerBuffer};
7276 Span<HttpServerClient> clients;
7377
78+ Span<ReadableFileStream::Request> readRequests;
79+ Span<WritableFileStream::Request> writeRequests;
80+
81+ Span<AsyncBufferView> buffers;
82+
7483 Result start ()
7584 {
85+ constexpr int REQUEST_SLICES = 2 ;
86+ constexpr int CLIENT_REQUEST = 1024 ;
87+ constexpr int HEADER_SIZE = 1024 * 8 ;
88+
7689 const size_t numClients = static_cast <size_t >(modelState.maxClients );
7790
78- clients = {new HttpServerClient[numClients], numClients};
79- SC_TRY (gb.resizeWithoutInitializing (1024 * 8 * numClients));
91+ SC_TRY (requestsMemory.resize (numClients * CLIENT_REQUEST));
92+
93+ // TODO: Simplify this messy manual memory handling
94+ clients = {new HttpServerClient[numClients], numClients};
95+ readRequests = {new ReadableFileStream::Request[numClients * REQUEST_SLICES], numClients* REQUEST_SLICES};
96+ writeRequests = {new WritableFileStream::Request[numClients * REQUEST_SLICES], numClients* REQUEST_SLICES};
97+ buffers = {new AsyncBufferView[numClients * (REQUEST_SLICES + 1 )], numClients*(REQUEST_SLICES + 1 )};
98+
99+ Span<char > requestsSpan = requestsMemory.toSpan ();
100+ for (size_t idx = 0 ; idx < numClients; ++idx)
101+ {
102+ for (size_t slice = 0 ; slice < REQUEST_SLICES; ++slice)
103+ {
104+ Span<char > memory;
105+ const size_t offset = idx * CLIENT_REQUEST + slice * CLIENT_REQUEST / REQUEST_SLICES;
106+ (void )requestsSpan.sliceStartLength (offset, CLIENT_REQUEST / REQUEST_SLICES, memory);
107+ buffers[idx * REQUEST_SLICES + slice] = memory;
108+ }
109+ }
110+
111+ SC_TRY (gb.resizeWithoutInitializing (HEADER_SIZE * numClients));
80112 HttpServer::Memory memory = {gb, clients};
81113 httpServer.httpServer .onRequest .bind <HttpWebServer, &HttpWebServer::serveFile>(httpWebServer);
82- SC_TRY (
83- httpServer.start (*eventLoop, modelState.interface .view (), static_cast <uint16_t >(modelState.port ), memory));
114+ if (modelState.useStreams )
115+ {
116+ httpServer.setUseAsyncStreams (true , readRequests, writeRequests, buffers);
117+ }
118+
119+ const uint16_t port = static_cast <uint16_t >(modelState.port );
120+ SC_TRY (httpServer.start (*eventLoop, modelState.interface .view (), port, memory));
84121 SC_TRY (httpWebServer.init (modelState.directory .view ()));
85122 return Result (true );
86123 }
@@ -90,7 +127,13 @@ struct SC::WebServerExampleModel
90127 SC_TRY (httpWebServer.stopAsync ());
91128 SC_TRY (httpServer.stopSync ());
92129 delete[] clients.data ();
93- clients = {};
130+ delete[] readRequests.data ();
131+ delete[] writeRequests.data ();
132+ delete[] buffers.data ();
133+ clients = {};
134+ readRequests = {};
135+ writeRequests = {};
136+ buffers = {};
94137 return Result (true );
95138 }
96139
@@ -133,6 +176,7 @@ struct SC::WebServerExampleView
133176 SC_TRY (InputText (" Interface" , buffer, model.modelState .interface , viewState.needsRestart ));
134177 SC_TRY (InputText (" Directory" , buffer, model.modelState .directory , viewState.needsRestart ));
135178 viewState.needsRestart |= ImGui::InputInt (" Port" , &model.modelState .port );
179+ viewState.needsRestart |= ImGui::Checkbox (" Use Async Streams" , &model.modelState .useStreams );
136180
137181 if (not model.httpServer .isStarted ())
138182 {
0 commit comments