// -*- mode: c++; indent-tabs-mode: nil; -*- // // Copyright 2009 Illumina, Inc. // // This software is covered by the "Illumina Genome Analyzer Software // License Agreement" and the "Illumina Source Code License Agreement", // and certain third party copyright/licenses, and any user of this // source file is bound by the terms therein (see accompanying files // Illumina_Genome_Analyzer_Software_License_Agreement.pdf and // Illumina_Source_Code_License_Agreement.pdf and third party // copyright/license notices). // // /// \file /// /// \author Chris Saunders /// #include "blt_util/log.hh" #include "blt_util/multi_stage_circular_manager.hh" #include #include #include // stage_length specifies size of stages from front to back. multi_stage_circular_manager:: multi_stage_circular_manager(const std::vector& stage_size, const pos_range& report_range, pos_processor_base& ppb) : _n_stages(stage_size.size()), _is_head_pos(false), _is_first_pos_set(false), _report_range(report_range), _ppb(ppb) { assert(_n_stages>0); unsigned total(0); for(unsigned i(0);i<_n_stages;++i){ total += stage_size[i]; _stage_n_buffer_size.push_back(total); } _buffer_size=total; } void multi_stage_circular_manager:: reset() { if(_is_first_pos_set){ if(_report_range.is_end_pos) { pos_t final_pos(_report_range.end_pos); for(pos_t i(_max_pos+1);i _max_pos) { // process older positions: for(pos_t i(_max_pos+1);i<=pos;++i) process_pos(i); _max_pos = pos; } } // new positional information has to fit into the buffer for its // stage: // bool multi_stage_circular_manager:: is_new_pos_value_valid(const pos_t pos, const int stage){ assert(stage < static_cast(_n_stages)); if(not _is_first_pos_set) return true; int fshift(0); if(stage>=0) fshift=(_stage_n_buffer_size[stage]); return (pos > (_max_pos-fshift)); } void multi_stage_circular_manager:: validate_new_pos_value(const pos_t pos, const int stage){ if(not is_new_pos_value_valid(pos,stage)){ // \todo this should be a throw: log_os << "ERROR:: reference sequence position difference too high for multi_stage_circular_buffer\n" << "current position:\t" << (pos+1) << "\n" << "top position for stage:\t" << (_max_pos+1) << "\n" << "stage no:\t" << stage << "\n"; exit(EXIT_FAILURE); } } void multi_stage_circular_manager:: process_pos(const pos_t pos){ if(not _is_head_pos) { _head_pos = pos; _is_head_pos = true; } for(pos_t p(_head_pos);p<=pos;++p){ _ppb.process_pos(-1,p); // head_pos signal for(unsigned i(0);i<_n_stages;++i){ const pos_t stage_pos(p-_stage_n_buffer_size[i]); if(stage_pos<_min_pos) break; _ppb.process_pos(static_cast(i),stage_pos); } } _head_pos=pos+1; } void multi_stage_circular_manager:: finish_process_pos(){ assert(_is_head_pos); for(pos_t p(_head_pos);true;++p){ pos_t stage_pos(p); for(unsigned i(0);i<_n_stages;++i){ stage_pos=p-_stage_n_buffer_size[i]; if(stage_pos>=_head_pos) continue; if(stage_pos<_min_pos) break; _ppb.process_pos(static_cast(i),stage_pos); } if(stage_pos>=_head_pos) break; } }