I'm working on a RS485 communication class and I'm trying to make a function that reads until a certain char is on the line, but with a time out. The problem is that my system timer immediately returns, doesn't matter which time out I enter. I tried changing the timer to be a member variable of the class, so it doesn't go out of scope, but that wasn't the problem. I tried different implementations of timers (deadline_timer mostly) but that didn't help. If I remove the timer from the code, then the read succeeds, but when I add it, even if I give it a timeout of 10 seconds (which should be waay more than enough), it will respond with an immediate timeout.
I tried making a simple version of the class here, but I guess that the options mostly depend on the type of machine you're talking to:
class RS485CommunicationLayer final {
public:
    RS485CommunicationLayer(
            const std::string& path,
            /* options */
    ): io(), port(io), timer(port.get_io_service()) {
        open(/* options */);
    };
    std::size_t write(const char* const buffer, const size_t size) {
        /*impl*/
    }
// THIS FUNCTION --v
    void readUntil(std::vector<char>& buffer, char delim,std::chrono::microseconds timeout) {
        boost::optional<boost::system::error_code> timer_result;
        boost::optional<boost::system::error_code> read_result;
        
        port.get_io_service().reset();
        
        timer.expires_from_now(timeout);
        boost::asio::async_read_until(port,  asio::dynamic_buffer(buffer), delim, [&read_result] (const boost::system::error_code& error, size_t) { read_result.reset(error); });
        timer.async_wait([&timer_result] (const boost::system::error_code& error) { timer_result.reset(error); });
    
        
        while (port.get_io_service().run_one())
        { 
            if (read_result)
                timer.cancel();
            else if (timer_result) {
                port.cancel();
            }
        }
    
        if (read_result)
            throw boost::system::system_error(*read_result);
    };
private:
    asio::io_context io;
    asio::serial_port port;
    boost::asio::system_timer timer;
    void open(/*args*/) {
       port.open(path);
       /*set options*/
    }
};
Edit:
I also tried the following implementation after finding out that run_for() exists. But then the buffer stays empty weirdly enough.
void RS485CommunicationLayer::readUntil(std::vector<char>& buffer, char delim, std::chrono::microseconds timeout) {
    boost::optional<boost::system::error_code> read_result;
    
    boost::asio::async_read_until(port,  asio::dynamic_buffer(buffer), delim, [&read_result] (const boost::system::error_code& error, size_t) { read_result.reset(error); });
    port.get_io_service().run_for(timeout);
    if (read_result)
        throw boost::system::system_error(*read_result);
}
