package pl.mkaczara.bch.decoder;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import pl.mkaczara.bch.BCH;
import pl.mkaczara.bch.math.BinPolynomial;
import pl.mkaczara.bch.code.CyclicCode;
import pl.mkaczara.bch.decoder.worker.AbstractBCHDecoderWorker;
import pl.mkaczara.bch.exception.UncorrectableErrorsException;
/**
* Klasa obiektow, reprezentujacych dekoder kodu BCH
*
* @author Michał
*/
public class BCHDecoder {
/**
* Kod
*/
private CyclicCode code;
/*
* Czy dekoder uproszczony?
*/
private boolean simpleMode;
/**
* "Złożoność" dekodera
*/
private Long complexity = 0L;
/**
* Liczba worker'ów
*/
private Long workerCount = 0L;
/**
* Liczba worker'ów, którym udało się odkodować ciąg
*/
private Long successWorkerCount = 0L;
/**
* ThreadPool dla workerow
*/
private ExecutorService workerExecutorSvc = Executors.newCachedThreadPool(); //Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1);
/**
* Tworzy nowy obiekt dekodera BCH
*
* @param code kod
* @param simpleMode tryb
*/
public BCHDecoder(CyclicCode code, boolean simpleMode) {
this.code = code;
this.simpleMode = simpleMode;
}
/**
* Dekoduje slowa kodu BCH
*
* @param input tablica bajow z zakodowanymi slowami kodu
* @return tablica bajtow z odkodowanymi slowami
*/
public byte[] decode(byte[] input) throws UncorrectableErrorsException{
if(workerExecutorSvc.isShutdown()){
workerExecutorSvc = Executors.newCachedThreadPool(); //Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1);
}
ArrayList<BinPolynomial> encoded = BCH.bytesToPolynomials(input, code.getN()-1);
ArrayList<BinPolynomial> notEncoded = new ArrayList<>();
ArrayList<AbstractBCHDecoderWorker> workers = new ArrayList<>();
List<Future<BinPolynomial>> futures = new ArrayList<>();
boolean permamentErrors = false;
for(BinPolynomial word : encoded){
AbstractBCHDecoderWorker tmp = BCHDecoderWorkerFactory.getBCHDecoderWorker(code, simpleMode);
tmp.setInput(word);
workers.add(tmp);
}
workerCount += workers.size();
try {
futures = workerExecutorSvc.invokeAll(workers);
workerExecutorSvc.shutdownNow();
} catch (InterruptedException ex) {
}
for(Future<BinPolynomial> future : futures){
try {
notEncoded.add(future.get());
} catch (InterruptedException | ExecutionException ex) {
if(ex.getMessage().equals("pl.mkaczara.bch.exception.UncorrectableErrorsException")){
permamentErrors = true;
continue;
}
}
successWorkerCount++;
}
for(AbstractBCHDecoderWorker worker : workers){
complexity += worker.getComplexity();
}
if(!permamentErrors){
return BCH.polynomialsToBytes(notEncoded, code.getK()-1);
}
throw new UncorrectableErrorsException();
}
public boolean isSimpleMode() {
return simpleMode;
}
public Long getComplexity(){
return complexity;
}
public Long getWorkerCount(){
return workerCount;
}
public Long getSuccessWorkerCount(){
return successWorkerCount;
}
} // end BCHDecoder