#pragma once
#include "Loop.h"
#include <panda/CallbackDispatcher.h>
namespace panda { namespace unievent {
struct Streamer : Refcnt {
struct IInput : Refcnt {
virtual ErrorCode start_reading () = 0;
virtual void stop_reading () = 0;
virtual ErrorCode start (const LoopSP&) = 0;
virtual void stop () = 0;
protected:
void handle_read (const string& data, const ErrorCode& err) { streamer->handle_read(data, err); }
void handle_eof () { streamer->handle_eof(); }
private:
friend Streamer;
Streamer* streamer = nullptr;
};
using IInputSP = iptr<IInput>;
struct IOutput : Refcnt {
virtual ErrorCode start (const LoopSP&) = 0;
virtual void stop () = 0;
virtual ErrorCode write (const string& data) = 0;
virtual size_t write_queue_size () const = 0;
protected:
void handle_write (const ErrorCode& err) { streamer->handle_write(err); }
private:
friend Streamer;
Streamer* streamer = nullptr;
};
using IOutputSP = iptr<IOutput>;
using finish_fptr = void(const ErrorCode& err);
using finish_fn = function<finish_fptr>;
CallbackDispatcher<finish_fptr> finish_event;
Streamer (const IInputSP& input, const IOutputSP& output, size_t max_buf = 10000000, const LoopSP& loop = Loop::default_loop());
void start ();
void stop ();
virtual ~Streamer () {}
private:
friend IInput; friend IOutput;
LoopSP loop;
IInputSP input;
IOutputSP output;
size_t max_buf;
size_t thr_buf;
size_t nread = 0;
size_t nwrite = 0;
bool started = false;
bool inread = true;
bool eof = false;
void handle_read (const string&, const ErrorCode&);
void handle_write (const ErrorCode&);
void handle_eof ();
void finish (const ErrorCode& = {});
};
using StreamerSP = iptr<Streamer>;
}}