Skip to content

File linkIo.h

File List > features > util > linkIo.h

Go to the documentation of this file

#pragma once

#include <jac/link/communicator.h>
#include <jac/machine/machine.h>
#include <jac/features/types/streams.h>

#include <atomic>
#include <thread>


namespace jac {


class LinkWritable : public Writable {
    jac::OutputStreamCommunicator* _comm;
public:
    LinkWritable(jac::OutputStreamCommunicator* comm): _comm(std::move(comm)) {}

    void write(std::string data) override {
        _comm->write(std::span<const uint8_t>(reinterpret_cast<const uint8_t*>(data.data()), data.size()));
    }
};

template<class Machine>
class LinkReadable : public Readable {
    Machine* _machine;
    jac::InputStreamCommunicator* _comm;
    std::thread _thread;
    std::atomic<bool> _running = false;

    bool startRead(auto callback) {
        if (_running) {
            return false;
        }
        if (_thread.joinable()) {
            _thread.join();
        }
        _running = true;

        _thread = std::thread(std::move(callback));

        return true;
    }
public:
    LinkReadable(Machine* machine, jac::InputStreamCommunicator* comm): _machine(machine), _comm(std::move(comm)) {}
    LinkReadable(LinkReadable&) = delete;
    LinkReadable(LinkReadable&&) = delete;

    bool get(std::function<void(char)> callback) override {
        return startRead([this, callback = std::move(callback)]() mutable {
            int res = _comm->get();

            if (res != 0) {
                _machine->scheduleEvent([callback = std::move(callback), res]() mutable {
                    callback(static_cast<char>(res));
                });
            }

            _running = false;
        });
    }

    bool read(std::function<void(std::string)> callback) override {
        return startRead([this, callback = std::move(callback)]() mutable {
            std::string buffer;
            buffer.resize(256);

            auto count = _comm->read(std::span<uint8_t>(reinterpret_cast<uint8_t*>(buffer.data()), buffer.size()));

            buffer.resize(count);
            _machine->scheduleEvent([callback = std::move(callback), buffer = std::move(buffer)]() mutable {
                callback(std::move(buffer));
            });

            _running = false;
        });
    }

    ~LinkReadable() override {
        if (_running) {
            _comm->cancelRead();
        }
        if (_thread.joinable()) {
            _thread.join();
        }
    }
};


} // namespace jac