using Invercargill; using Invercargill.DataStructures; namespace Astralis { internal class ServerOutput : Object, AsyncOutput { const int MAX_CHUNKS = 5; private BinaryData current_chunk = null; private Series chunks = new Series(); internal signal void on_new_chunk(); internal signal void on_chunk_poped(); private delegate void Handler(); private bool _connected = true; public bool connected { get { return _connected; } } public bool write_would_block { get { return chunks.length > MAX_CHUNKS; } } internal void close_connection() { _connected = false; } public async void write (Invercargill.BinaryData data) throws Error { if (!_connected) { throw new IOError.CLOSED("Cannot write to disconnected client"); } while(chunks.length > MAX_CHUNKS) { ulong handler_id = 0; handler_id = on_chunk_poped.connect(() => { SignalHandler.disconnect(this, handler_id); Idle.add(write.callback); }); yield; } var buffer = data.to_byte_buffer(); if(buffer.length > 0) { chunks.add(buffer); on_new_chunk(); } } internal size_t read_chunk(void* buffer, size_t max_size) { if(current_chunk != null && current_chunk.peek_count() == 0) { current_chunk = null; } if(current_chunk == null && chunks.length == 0) { return 0; } if(current_chunk == null) { current_chunk = chunks.pop_start (); on_chunk_poped(); } var size = current_chunk.write_to (buffer, max_size); current_chunk = current_chunk.skip((uint)size); return size; } } }