/* * CircularBinaryRemoteBuffer.cpp * * Created on: 24 апр. 2020 г. * Author: LeonidTitov */ #include "CircularBinaryRemoteBuffer.hh" #include #include std::size_t driver::CircularBinaryRemoteBuffer::get_frame_size() const { return frame_size; } bool driver::CircularBinaryRemoteBuffer::put( const char * frame ) { if( memory.isWriteComplete() ) { if( put_cache_writed == put_cache_stored ) { std::size_t grow_up = ( put_cache_writed - put_cache_begin ) / frame_size; index_in_memory = wrap_index( index_in_memory + grow_up ); put_cache_writed = put_cache_stored = put_cache_begin; } } if( put_cache_stored + frame_size <= put_cache_end ) { index = wrap_index( index + 1 ); loaded_frames = loaded_frames + 1 < number_of_frames ? loaded_frames + 1 : number_of_frames; std::memcpy( put_cache_stored, frame, frame_size ); put_cache_stored += frame_size; } else return false; std::size_t part_size = cut_part( put_cache_stored - put_cache_writed ); if( memory.write( put_cache_writed, position_in_memory, part_size ) ) { put_cache_writed += part_size; position_in_memory = wrap_position( position_in_memory + part_size ); } return true; } void driver::CircularBinaryRemoteBuffer::clear() { std::size_t current_index = index; //todo: Безопасный сброс. do { index_in_memory = 0; put_cache_writed = put_cache_stored = put_cache_begin; index = 0; loaded_frames = 0; position_in_memory = 0; cached_index_begin = 0; cached_index_end = 0; } while( current_index != index ); } std::pair driver::CircularBinaryRemoteBuffer::fixate( std::size_t desired_pretrigger_frames ) { std::size_t current_index = index; std::size_t pretrigger_frames = desired_pretrigger_frames < loaded_frames ? desired_pretrigger_frames : loaded_frames; loaded_frames = pretrigger_frames; return { Index( current_index < pretrigger_frames ? number_of_frames - pretrigger_frames + current_index : current_index - pretrigger_frames, number_of_frames ), pretrigger_frames }; } driver::CircularBinaryRemoteBuffer::CircularBinaryRemoteBuffer( peripheral::IMemoryAccess & memory, std::size_t frame_size, char * put_cache, std::size_t put_cache_size, char * get_cache, std::size_t get_cache_size ) : memory(memory), frame_size(frame_size), put_cache_begin(put_cache), put_cache_end(put_cache + put_cache_size), put_cache_stored(put_cache), put_cache_writed(put_cache), get_cache_begin(get_cache), get_cache_capacity( get_cache_size / frame_size ), index(0), index_in_memory(0), loaded_frames(0), position_in_memory(0), number_of_frames(memory.getCapacity() / frame_size), useful_capacity((memory.getCapacity() / frame_size)*frame_size), cached_index_begin(0), cached_index_end(0) {} std::size_t driver::CircularBinaryRemoteBuffer::wrap_index( std::size_t next_index ) { return next_index < number_of_frames ? next_index : next_index - number_of_frames; } std::size_t driver::CircularBinaryRemoteBuffer::wrap_position( std::size_t next_position ) { return next_position < useful_capacity ? next_position : next_position - useful_capacity; } void driver::CircularBinaryRemoteBuffer::restart( const Index & frame_index ) { //todo: } std::size_t driver::CircularBinaryRemoteBuffer::fixed( const Index & frame_index ) const { std::size_t current_index = index; std::size_t temp = ( current_index < frame_index.position ? number_of_frames - frame_index.position + current_index : current_index - frame_index.position ); return temp > loaded_frames ? 0 : temp; } std::size_t driver::CircularBinaryRemoteBuffer::available_in_memory( const Index & frame_index ) { std::size_t temp = ( index_in_memory < frame_index.position ? number_of_frames - frame_index.position + index_in_memory : index_in_memory - frame_index.position ); return temp > loaded_frames ? 0 : temp; } const char * driver::CircularBinaryRemoteBuffer::get( const Index & frame_index ) { if( not fixed( frame_index ) ) return nullptr; if( cached_index_begin <= frame_index.position and frame_index.position < cached_index_end ) return get_cache_begin + frame_size * ( frame_index.position - cached_index_begin ); std::size_t current_index = index; std::size_t load_from_memory = std::min( available_in_memory( frame_index ), get_cache_capacity ); std::size_t available_frames = std::min( fixed( frame_index ), get_cache_capacity ); std::size_t load_from_cache = available_frames - load_from_memory; if( load_from_memory < get_cache_capacity ) do { current_index = index; load_from_memory = std::min( available_in_memory( frame_index ), get_cache_capacity ); available_frames = std::min( fixed( frame_index ), get_cache_capacity ); load_from_cache = available_frames - load_from_memory; std::memcpy( get_cache_begin + load_from_memory * frame_size, put_cache_begin, load_from_cache * frame_size ); } while( current_index != index ); std::size_t first_part = ( load_from_memory * frame_size + frame_index.position * frame_size ) < useful_capacity ? load_from_memory * frame_size : useful_capacity - frame_index.position * frame_size; //cut_part( load_from_memory * frame_size ); std::size_t second_part = load_from_memory * frame_size - first_part; if( first_part ) { while( not memory.read( get_cache_begin, frame_index.position * frame_size, first_part ) ); while( not memory.isReadComplete() ); } if( second_part ) { //todo: wrap position? while( not memory.read( get_cache_begin + first_part, 0, second_part ) ); while( not memory.isReadComplete() ); } cached_index_begin = frame_index.position; cached_index_end = frame_index.position + available_frames; return get( frame_index ); } std::size_t driver::CircularBinaryRemoteBuffer::capacity() const { return number_of_frames; } std::size_t driver::CircularBinaryRemoteBuffer::cut_part( std::size_t next_part ) { return ( next_part + position_in_memory ) < useful_capacity ? next_part : useful_capacity - position_in_memory; }