153 lines
4.2 KiB
C++
153 lines
4.2 KiB
C++
/*
|
||
* BufferedCommunicationLink.cpp
|
||
*
|
||
* Created on: 23 апр. 2020 г.
|
||
* Author: LeonidTitov
|
||
*/
|
||
|
||
#include "BufferedCommunicationLink.hh"
|
||
#include <climits>
|
||
|
||
communication::service::BufferedCommunicationLink::BufferedCommunicationLink(
|
||
driver::ISlipCommunication & isc, std::pmr::memory_resource * memory, systemic::time_t timeout ) :
|
||
communication(isc), free_counter(0), series(isc), subscribers( std::less<PacketId>(), memory ),
|
||
timeout_after_send(timeout) {
|
||
|
||
series_timeout.start(timeout_after_send);
|
||
|
||
}
|
||
|
||
bool communication::service::BufferedCommunicationLink::registerMessageHandler(
|
||
IMessageHandler * handler, std::size_t packet_id ) {
|
||
|
||
Subscribers::iterator subscriber = subscribers.find( packet_id );
|
||
if( subscriber == subscribers.end() ) {
|
||
|
||
subscribers.insert( subscriber, std::pair<const PacketId, IMessageHandler *>( packet_id, handler ) );
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
void communication::service::BufferedCommunicationLink::process() {
|
||
|
||
std::pair<bool, unsigned short> packet_info = communication.isPacketAvailable();
|
||
|
||
if( packet_info.first ) {
|
||
|
||
free_counter++;
|
||
|
||
PacketId packet_id = packet_info.second;
|
||
|
||
Subscribers::iterator subscriber = subscribers.find( packet_id );
|
||
|
||
if( subscriber != subscribers.end() ) {
|
||
MessageLink packet_handler( packet_id, communication, series );
|
||
subscriber->second->handler( &packet_handler );
|
||
}
|
||
|
||
communication.recieveReset();
|
||
|
||
}
|
||
|
||
if( communication.isPacketSent() and series_timeout.delayFinished() ) {
|
||
series.update();
|
||
series_timeout.start(timeout_after_send);
|
||
}
|
||
|
||
}
|
||
|
||
communication::IMessageSeriesLink::ostream & communication::service::BufferedCommunicationLink::Series::sendData(
|
||
std::size_t size ) {
|
||
|
||
data_sent = communication.sendHead( message_id | 0x8000u, size * ( CHAR_BIT / 8 ) );
|
||
return communication;
|
||
|
||
}
|
||
|
||
bool communication::service::BufferedCommunicationLink::Series::charge(
|
||
PacketId id, std::size_t num_messages, IMessageSeriesHandler * handler ) {
|
||
|
||
if( not message_remain ) {
|
||
|
||
message_id = id;
|
||
series_handler = handler;
|
||
message_remain = num_messages;
|
||
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
void communication::service::BufferedCommunicationLink::Series::update() {
|
||
|
||
if( series_handler and message_remain ) {
|
||
|
||
series_handler->handler( this );
|
||
|
||
if( data_sent ) {
|
||
communication.sendEnd();
|
||
--message_remain;
|
||
data_sent = false;
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
driver::IRxLink & communication::service::BufferedCommunicationLink::MessageLink::getData() {
|
||
|
||
return communication;
|
||
|
||
}
|
||
|
||
driver::ITxLink & communication::service::BufferedCommunicationLink::MessageLink::createMessage( std::size_t size ) {
|
||
//todo: x2???
|
||
message_answered = communication.sendHead( message_id | 0x8000u, size * ( CHAR_BIT / 8 ) );
|
||
return communication;
|
||
|
||
}
|
||
|
||
std::size_t communication::service::BufferedCommunicationLink::MessageLink::transmitBuffCapacity() const {
|
||
|
||
return communication.transmitBuffCapacity();
|
||
|
||
}
|
||
|
||
std::size_t communication::service::BufferedCommunicationLink::MessageLink::receiveBuffCapacity() const {
|
||
|
||
return communication.receiveBuffCapacity();
|
||
|
||
}
|
||
|
||
bool communication::service::BufferedCommunicationLink::MessageLink::createMessageSeries(
|
||
std::size_t num_messages, IMessageSeriesHandler * handler ) {
|
||
|
||
return series.charge(message_id, num_messages, handler);
|
||
|
||
}
|
||
|
||
communication::service::BufferedCommunicationLink::MessageLink::MessageLink(
|
||
PacketId id, driver::ISlipCommunication & com, Series & ser ) : message_id(id), communication(com), series(ser), message_answered(false) {}
|
||
|
||
communication::service::BufferedCommunicationLink::MessageLink::~MessageLink() noexcept {
|
||
|
||
if( not message_answered )
|
||
communication.sendHead( message_id | 0x8000u, 0 );
|
||
|
||
communication.sendEnd();
|
||
|
||
}
|
||
|
||
float communication::service::BufferedCommunicationLink::getPacketCounter() const {
|
||
|
||
return free_counter;
|
||
|
||
}
|
||
|
||
communication::service::BufferedCommunicationLink::Series::Series(
|
||
driver::ISlipCommunication & com ) :
|
||
communication(com), data_sent(false), message_id(), message_remain(0), series_handler(nullptr) {}
|