Re[6]: boost::serial_port и мозговой секс
От: HolyNick  
Дата: 26.10.14 16:08
Оценка:
Вот такой код позволяет повторно открыть COM порт:
boost::asio::io_service service;
boost::asio::serial_port port(service);
port.open(address);
if (port.is_open())
{
    port.close();
    try
    {
       port.open(address); //OK порт открывается повторно
    }
    catch (...)
    {

    }
}


А такой не позволяет:
boost::asio::io_service service;
boost::asio::serial_port port(service);
port.open(address);
if (port.is_open())
{
    std::uint8_t Buffer;
    boost::asio::async_read(port, boost::asio::buffer(&Buffer, 1),
        [this](const boost::system::error_code& error, std::size_t bytes_transferred)
    {
        int i = 0;
        i++;
        //сюдя в отладчике не попадаю
    });
    port.close();
    
    try
    {
       port.open(address); //access denied, бросает исключение
    }
    catch (...)
    {
       //access denied
    }
}
Re[4]: boost::serial_port и мозговой секс
От: HolyNick  
Дата: 26.10.14 16:46
Оценка:
EP>Этот код точно не работает? А если создать полностью новый serial_port, после деструкции старого? (можно использовать optional<serial_port>)

У меня получилось повторно открыть порт, только с новым объектом порта и (одновременно) новым объектом io_service для него.
При этом предыдущий объект порта И его объект io_service должны быть уничтожены(вызван деструктор для них).
Отредактировано 26.10.2014 16:49 HolyNick . Предыдущая версия .
Re[5]: boost::serial_port и мозговой секс
От: Evgeny.Panasyuk Россия  
Дата: 26.10.14 18:39
Оценка:
Здравствуйте, niXman, Вы писали:

EP>>.close() по идее должен завершать все хэндлеры с boost::asio::error::operation_aborted.

X>нет. при close(), хендлеры вызовутся с end_of_file, а при cancel() — operation_aborted

Я же ссылку привёл, а по ней:

This function is used to close the serial port. Any asynchronous read or write operations will be cancelled immediately, and will complete with the boost::asio::error::operation_aborted error.

Re[7]: boost::serial_port и мозговой секс
От: Evgeny.Panasyuk Россия  
Дата: 26.10.14 18:45
Оценка:
Здравствуйте, HolyNick, Вы писали:

HN>А такой не позволяет:

HN>
HN>boost::asio::io_service service;
HN>boost::asio::serial_port port(service);
HN>port.open(address);
HN>if (port.is_open())
HN>{
HN>    std::uint8_t Buffer;
HN>    boost::asio::async_read(port, boost::asio::buffer(&Buffer, 1),
HN>        [this](const boost::system::error_code& error, std::size_t bytes_transferred)
HN>    {
HN>        int i = 0;
HN>        i++;
HN>        //сюдя в отладчике не попадаю
HN>    });
HN>    port.close();
    
HN>    try
HN>    {
HN>       port.open(address); //access denied, бросает исключение
HN>    }
HN>    catch (...)
HN>    {
HN>       //access denied
HN>    }
HN>}
HN>


А если перед close() ещё добавить cancel()?
Re[8]: boost::serial_port и мозговой секс
От: HolyNick  
Дата: 26.10.14 19:41
Оценка:
cancel() тоже не помогает.
Насколько я видел код close() просто закрывает хендл порта. Но, опять же насколько я представляю, а представляю я пока слабо, внутри (всей кухни управления COM портом) используется механизм
портов завершения вводы\вывода и если какая-то из функций этого механизма "держит" хендл, то фактически закрытия не происходит при вызове close().
Те перед close() надо сделать еще какие-то правильные действия в правильной последовательности.
Отредактировано 26.10.2014 20:20 HolyNick . Предыдущая версия . Еще …
Отредактировано 26.10.2014 19:43 HolyNick . Предыдущая версия .
Re[9]: boost::serial_port и мозговой секс
От: Evgeny.Panasyuk Россия  
Дата: 26.10.14 19:51
Оценка:
Здравствуйте, HolyNick, Вы писали:

HN>cancel() тоже не помогает.

HN>Насколько я видел код close() просто закрывает хендл окна.

А хендлер ни cancel ни close точно не дёргают? (должны в соответствии с документацией)
Re[10]: boost::serial_port и мозговой секс
От: HolyNick  
Дата: 26.10.14 20:25
Оценка:
Точно не могу сказать, вроде, нет.
Ты можешь вызвать port.close(), а потом у сервиса service.poll() или service.run() и тогда он вызовет хендлер с какой-то ошибкой(типа порт закрыт) соответственно.
Но это не значит, что Windows HANDLE порта правильно закрылся после этого...хотя — ...надо разбираться)))
Отредактировано 26.10.2014 20:28 HolyNick . Предыдущая версия .
Re[10]: boost::serial_port и мозговой секс
От: HolyNick  
Дата: 26.10.14 20:43
Оценка:
В принципе такой вариант работает:
    boost::asio::io_service service;
    std::shared_ptr<boost::asio::serial_port> port(new boost::asio::serial_port(service));
    port->open("COM3"); //OK 

    char buffer;
    boost::asio::async_read(*port, boost::asio::buffer(&buffer, 1),
        [port](boost::system::error_code error, std::size_t bytes_transferred)
    {
    });

    char buffer2;
    boost::asio::async_read(*port, boost::asio::buffer(&buffer2, 1),
        [port](boost::system::error_code error, std::size_t bytes_transferred)
    {
    });

    port->close();
    service.poll(); //оба обработчика вызываются с некоторой ошибкой

    try
    {
         port->open("COM3"); //OK, порт открывается повторно
    }
    catch (...)
    {
    }
Отредактировано 26.10.2014 20:53 HolyNick . Предыдущая версия .
Re[11]: boost::serial_port и мозговой секс
От: Evgeny.Panasyuk Россия  
Дата: 26.10.14 21:15
Оценка:
Здравствуйте, HolyNick, Вы писали:

HN>Точно не могу сказать, вроде, нет.

HN>Ты можешь вызвать port.close(), а потом у сервиса service.poll() или service.run() и тогда он вызовет хендлер с какой-то ошибкой(типа порт закрыт) соответственно.

Если .close() не вызывает, хотя документация говорит что должен — то по всей видимости там баг, и нужно открывать ticket.
Какая версия boost? И можешь привести минимальный пример однозначно воспроизводящий проблему (можно добавить вывод в cout внутри хэндлера, до и после вызова close/cancel).
Re[11]: boost::serial_port и мозговой секс
От: PM  
Дата: 26.10.14 21:50
Оценка:
Здравствуйте, HolyNick, Вы писали:

HN>В принципе такой вариант работает:

HN>
...
HN>    service.poll(); //оба обработчика вызываются с некоторой ошибкой

HN>


Телепатически предполагаю что все дело в выделенном — для нормальной работы асинхронного I/O у io_service нужно вызывать run(), run_once() или poll().
Re[12]: boost::serial_port и мозговой секс
От: HolyNick  
Дата: 26.10.14 21:52
Оценка:
Бага там нет, если ты запустил где-то service.run(), а потом вызвал port.close(), то он все обработчики вызовет.
Я-то service.run() вообще никогда не вызываю(не использую), только service.poll(), поэтому и после закрытия(port.close()) порта мне нужно вызвать service.poll(), как я указал в предыдущем примере.
Re[12]: boost::serial_port и мозговой секс
От: HolyNick  
Дата: 26.10.14 21:59
Оценка:
PM>Телепатически предполагаю что все дело в выделенном — для нормальной работы асинхронного I/O у io_service нужно вызывать run(), run_once() или poll().
Да. И еще похоже, что нужно делать вызов reset(), о чем в общем-то написано в исходниках :

    boost::asio::io_service service;
    std::shared_ptr<boost::asio::serial_port> port(new boost::asio::serial_port(service));
    port->open("COM3"); //OK

    char buffer;
    boost::asio::async_read(*port, boost::asio::buffer(&buffer, 1),
        [port](boost::system::error_code error, std::size_t bytes_transferred)
    {
        int i = 0;
        i++;
    });

    port->close();
    service.poll();Вызовется обработчик из предыдущего async_read

    service.reset();если не вызвать, то следующая команда poll не вызовет обработчик

    port->open("COM3");//OK
    char buffer2;
    boost::asio::async_read(*port, boost::asio::buffer(&buffer2, 1),
        [port](boost::system::error_code error, std::size_t bytes_transferred)
    {
        int i = 0;
        i++;
    });
    port->close();
    service.poll();Вызывает обработчик, только если был вызов reset()

    port->open("COM3");//OK, только если был вызов reset(), в противно случае ACCESS DENIED и исключение
Отредактировано 26.10.2014 21:59 HolyNick . Предыдущая версия .
Re[13]: boost::serial_port и мозговой секс
От: HolyNick  
Дата: 26.10.14 22:11
Оценка:
Все — пошел я спать)
Спасибо за внимание и извините за беспокойство
Re: boost::serial_port и мозговой секс
От: HolyNick  
Дата: 28.10.14 08:18
Оценка:
Если я использую в программе два COM(boost::asio::serial_port) порта каждый из которых использует свой отдельный объект io_service, могу ли я работать(делать вызовы poll()) с портами(и соответстсвенно сервисами) в разных потоках? Какие там подводные камни? Или надо для каждого порта запускать свой поток и опрашивать порт только в нем?
Спасибо.
Re[2]: boost::serial_port и мозговой секс
От: niXman Ниоткуда https://github.com/niXman
Дата: 28.10.14 08:43
Оценка:
а зачем тебе два io_service`а? или ты все еще продолжаешь писать "лишь бы работало"?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[3]: boost::serial_port и мозговой секс
От: HolyNick  
Дата: 28.10.14 09:58
Оценка:
X>а зачем тебе два io_service`а? или ты все еще продолжаешь писать "лишь бы работало"?
Пока разбираюсь. Но вопрос актуален даже если один и тот же сервис на оба порта.
Re[4]: boost::serial_port и мозговой секс
От: niXman Ниоткуда https://github.com/niXman
Дата: 28.10.14 13:21
Оценка:
а зачем тебе дополнительные потоки(threads)? чем асинхронный IO не угодил?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Отредактировано 28.10.2014 13:41 niXman . Предыдущая версия .
Re[5]: boost::serial_port и мозговой секс
От: HolyNick  
Дата: 28.10.14 18:17
Оценка:
X>а зачем тебе дополнительные потоки(threads)? чем асинхронный IO не угодил?
Основной поток реагирует на нажатия кнопочек окошка, второй пишет\читает(выполняет задачу) из порта.
Re[6]: boost::serial_port и мозговой секс
От: niXman Ниоткуда https://github.com/niXman
Дата: 28.10.14 18:22
Оценка:
Здравствуйте, HolyNick, Вы писали:

HN>Основной поток реагирует на нажатия кнопочек окошка, второй пишет\читает(выполняет задачу) из порта.

так интегрируй io_service::poll_one() в event loop твоей апликухи. и не нужно никаких дополнительных потоков.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[7]: boost::serial_port и мозговой секс
От: HolyNick  
Дата: 28.10.14 18:45
Оценка:
Здравствуйте, niXman, Вы писали:

X>Здравствуйте, HolyNick, Вы писали:


HN>>Основной поток реагирует на нажатия кнопочек окошка, второй пишет\читает(выполняет задачу) из порта.

X>так интегрируй io_service::poll_one() в event loop твоей апликухи. и не нужно никаких дополнительных потоков.

Да, согласен. (спасибо за подсказку)
ps: просто с парой потоков, при некотором условии, переставали вызываться обработчики(handler'ы) порта — хотелось понять почему (на будущее)
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.