Revise connection abstractions
-
Eliminate buffer[512]
in TCPConnection -
Remove sleep (sleep is higher level function, that is unclear what is does here) -
Make DataSources more modular. Maybe introduce a callback with an argument object which can send data (like sendString(String&), sendFileDescriptor(FileDescriptorString&), flush(), etc). This way the queueing of items can be eliminated from the connection. These send operations can fail because of the buffer is full, so they should result in new information. -
...
Eventually:
ServerConnectionBuilder(port)
.wrap<BufferConnection>(16384 /*bytes*/)
.wrap<SaltConnection>(certificate)
.wrap<DeflateCompression>()
.build();
For now, focus on the async system:
-
read(buffer, size, isComplete, next)
, withnext
getting the number of received bytes and the error code send(buffer, size, next)
- for when a message is very large, use a huge buffer of 1 MiB and force a lazy allocation with mmap() (so the memory is only used when touched)
So a layer can receive those operations from the level above. If possible these operations are executed immediately, but if needed, those operations can be queued.
Memory management is rather easy: as long as a read is outstanding, the connection is kept referenced with a shared_connection, so remains active.
Open issues:
- keep-alive messages should be sent at the lowest level, but there is no way to communicate errors. Maybe install a default error function if an error needs to propagate?
- after a keep-alive is sent and no activity was recording in that slot between keep-alives, a 'sleepy' state can be entered at which all buffers not currently needed can be deallocated. This clears the 1 MiB mmap buffers, to keep the memory usage down. For HTTP request, an automatic 'sleepy' generator can be injected in the pipeline.
- how to handle sends if a send is already active? If a protocol uses pipelining, this is an issue. One can interchange between reading and writing for simple protocols like HTTP. Otherwise, a lightweight stream is needed. Source objects can be offered to the connection object, which knows how to combine two of them etc. If accepted, true is returned. With false, the same source object must be offered again.
Edited by Bernard van Gastel