mirror of
https://github.com/metabarcoding/obitools4.git
synced 2025-06-29 16:20:46 +00:00
Add automatic garbage collection on ApatPattern
This commit is contained in:
@ -8,6 +8,7 @@ package obiapat
|
||||
import "C"
|
||||
import (
|
||||
"errors"
|
||||
"runtime"
|
||||
"unsafe"
|
||||
|
||||
"git.metabarcoding.org/lecasofts/go/obitools/pkg/obiseq"
|
||||
@ -17,10 +18,14 @@ var _MaxPatLen = int(C.MAX_PAT_LEN)
|
||||
|
||||
// ApatPattern stores a regular pattern usable by the
|
||||
// Apat algorithm functions and methods
|
||||
type ApatPattern struct {
|
||||
type _ApatPattern struct {
|
||||
pointer *C.Pattern
|
||||
}
|
||||
|
||||
type ApatPattern struct {
|
||||
pointer *_ApatPattern
|
||||
}
|
||||
|
||||
// ApatSequence stores sequence in structure usable by the
|
||||
// Apat algorithm functions and methods
|
||||
type ApatSequence struct {
|
||||
@ -58,15 +63,22 @@ func MakeApatPattern(pattern string, errormax int) (ApatPattern, error) {
|
||||
var errno C.int32_t
|
||||
var errmsg *C.char
|
||||
|
||||
ap := C.buildPattern(cpattern, cerrormax, &errno, &errmsg)
|
||||
apc := C.buildPattern(cpattern, cerrormax, &errno, &errmsg)
|
||||
|
||||
if ap == nil {
|
||||
if apc == nil {
|
||||
message := C.GoString(errmsg)
|
||||
C.free(unsafe.Pointer(errmsg))
|
||||
return NilApatPattern, errors.New(message)
|
||||
}
|
||||
|
||||
return ApatPattern{pointer: ap}, nil
|
||||
ap := _ApatPattern{apc}
|
||||
|
||||
runtime.SetFinalizer(&ap, func(p *_ApatPattern) {
|
||||
// log.Printf("Finaliser called on %s\n", C.GoString(p.pointer.cpat))
|
||||
C.free(unsafe.Pointer(p.pointer))
|
||||
})
|
||||
|
||||
return ApatPattern{pointer: &ap}, nil
|
||||
}
|
||||
|
||||
// ReverseComplement method builds a new ApatPattern
|
||||
@ -75,38 +87,56 @@ func MakeApatPattern(pattern string, errormax int) (ApatPattern, error) {
|
||||
func (pattern ApatPattern) ReverseComplement() (ApatPattern, error) {
|
||||
var errno C.int32_t
|
||||
var errmsg *C.char
|
||||
ap := C.complementPattern((*C.Pattern)(pattern.pointer), &errno, &errmsg)
|
||||
apc := C.complementPattern((*C.Pattern)(pattern.pointer.pointer), &errno, &errmsg)
|
||||
|
||||
if ap == nil {
|
||||
if apc == nil {
|
||||
message := C.GoString(errmsg)
|
||||
C.free(unsafe.Pointer(errmsg))
|
||||
return ApatPattern{nil}, errors.New(message)
|
||||
}
|
||||
|
||||
return ApatPattern{pointer: ap}, nil
|
||||
ap := _ApatPattern{apc}
|
||||
|
||||
runtime.SetFinalizer(&ap, func(p *_ApatPattern) {
|
||||
// log.Printf("Finaliser called on %s\n", C.GoString(p.pointer.cpat))
|
||||
C.free(unsafe.Pointer(p.pointer))
|
||||
})
|
||||
|
||||
return ApatPattern{pointer: &ap}, nil
|
||||
}
|
||||
|
||||
// String method casts the ApatPattern to a Go String.
|
||||
func (pattern ApatPattern) String() string {
|
||||
return C.GoString(pattern.pointer.cpat)
|
||||
return C.GoString(pattern.pointer.pointer.cpat)
|
||||
}
|
||||
|
||||
// Length method returns the length of the matched pattern.
|
||||
func (pattern ApatPattern) Length() int {
|
||||
return int(pattern.pointer.patlen)
|
||||
return int(pattern.pointer.pointer.patlen)
|
||||
}
|
||||
|
||||
// Free method ensure that the C structure wrapped is
|
||||
// desallocated
|
||||
// Release the C allocated memory of an ApatPattern instance.
|
||||
//
|
||||
// Thee method ensurse that the C structure wrapped in
|
||||
// an ApatPattern instance is released. Normally this
|
||||
// action is taken in charge by a finalizer and the call
|
||||
// to the Free meethod is not mandatory. Nevertheless,
|
||||
// If you choose to call this method, it will disconnect
|
||||
// the finalizer associated to the ApatPattern instance
|
||||
// to avoid double freeing.
|
||||
//
|
||||
func (pattern ApatPattern) Free() {
|
||||
C.free(unsafe.Pointer(pattern.pointer))
|
||||
// log.Printf("Free called on %s\n", C.GoString(pattern.pointer.pointer.cpat))
|
||||
C.free(unsafe.Pointer(pattern.pointer.pointer))
|
||||
runtime.SetFinalizer(pattern.pointer, nil)
|
||||
|
||||
pattern.pointer = nil
|
||||
}
|
||||
|
||||
// Print method prints the ApatPattern to the standard output.
|
||||
// This is mainly a debug method.
|
||||
func (pattern ApatPattern) Print() {
|
||||
C.PrintDebugPattern(C.PatternPtr(pattern.pointer))
|
||||
C.PrintDebugPattern(C.PatternPtr(pattern.pointer.pointer))
|
||||
}
|
||||
|
||||
// MakeApatSequence casts an obiseq.BioSequence to an ApatSequence.
|
||||
@ -197,7 +227,7 @@ func (pattern ApatPattern) FindAllIndex(sequence ApatSequence, limits ...int) (l
|
||||
}
|
||||
|
||||
nhits := int(C.ManberAll(sequence.pointer,
|
||||
pattern.pointer,
|
||||
pattern.pointer.pointer,
|
||||
0,
|
||||
C.int32_t(begin),
|
||||
C.int32_t(length+C.MAX_PAT_LEN)))
|
||||
@ -208,7 +238,7 @@ func (pattern ApatPattern) FindAllIndex(sequence ApatSequence, limits ...int) (l
|
||||
|
||||
stktmp := (*[1 << 30]int32)(unsafe.Pointer(sequence.pointer.hitpos[0].val))
|
||||
errtmp := (*[1 << 30]int32)(unsafe.Pointer(sequence.pointer.hiterr[0].val))
|
||||
patlen := int(pattern.pointer.patlen)
|
||||
patlen := int(pattern.pointer.pointer.patlen)
|
||||
|
||||
for i := 0; i < nhits; i++ {
|
||||
start := int(stktmp[i])
|
||||
|
@ -217,24 +217,6 @@ func OptionBatchSize(size int) WithOption {
|
||||
return f
|
||||
}
|
||||
|
||||
func (options Options) Free() {
|
||||
if options.pointer.forward.pointer != nil {
|
||||
options.pointer.forward.Free()
|
||||
}
|
||||
|
||||
if options.pointer.cfwd.pointer != nil {
|
||||
options.pointer.cfwd.Free()
|
||||
}
|
||||
|
||||
if options.pointer.reverse.pointer != nil {
|
||||
options.pointer.reverse.Free()
|
||||
}
|
||||
|
||||
if options.pointer.crev.pointer != nil {
|
||||
options.pointer.crev.Free()
|
||||
}
|
||||
}
|
||||
|
||||
func _Pcr(seq ApatSequence,
|
||||
sequence obiseq.BioSequence,
|
||||
opt Options) obiseq.BioSequenceSlice {
|
||||
@ -397,7 +379,6 @@ func _Pcr(seq ApatSequence,
|
||||
func PCR(sequence obiseq.BioSequence, options ...WithOption) obiseq.BioSequenceSlice {
|
||||
|
||||
opt := MakeOptions(options)
|
||||
defer opt.Free()
|
||||
|
||||
seq, _ := MakeApatSequence(sequence, opt.Circular())
|
||||
defer seq.Free()
|
||||
@ -407,6 +388,33 @@ func PCR(sequence obiseq.BioSequence, options ...WithOption) obiseq.BioSequenceS
|
||||
return results
|
||||
}
|
||||
|
||||
func _PCRSlice(sequences obiseq.BioSequenceSlice,
|
||||
options Options) obiseq.BioSequenceSlice {
|
||||
|
||||
results := make(obiseq.BioSequenceSlice, 0, len(sequences))
|
||||
|
||||
if len(sequences) > 0 {
|
||||
seq, _ := MakeApatSequence(sequences[0], options.Circular())
|
||||
amplicons := _Pcr(seq, sequences[0], options)
|
||||
|
||||
if len(amplicons) > 0 {
|
||||
results = append(results, amplicons...)
|
||||
}
|
||||
|
||||
for _, sequence := range sequences[1:] {
|
||||
seq, _ = MakeApatSequence(sequence, options.Circular(), seq)
|
||||
amplicons = _Pcr(seq, sequence, options)
|
||||
if len(amplicons) > 0 {
|
||||
results = append(results, amplicons...)
|
||||
}
|
||||
}
|
||||
|
||||
seq.Free()
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
// PCRSlice runs the PCR simulation algorithm on a set of
|
||||
// obiseq.BioSequence instances grouped in a obiseq.BioSequenceSlice.
|
||||
// PCR parameters are
|
||||
@ -415,39 +423,17 @@ func PCR(sequence obiseq.BioSequence, options ...WithOption) obiseq.BioSequenceS
|
||||
func PCRSlice(sequences obiseq.BioSequenceSlice,
|
||||
options ...WithOption) obiseq.BioSequenceSlice {
|
||||
|
||||
results := make(obiseq.BioSequenceSlice, 0, len(sequences))
|
||||
|
||||
opt := MakeOptions(options)
|
||||
defer opt.Free()
|
||||
|
||||
if len(sequences) > 0 {
|
||||
seq, _ := MakeApatSequence(sequences[0], opt.Circular())
|
||||
amplicons := _Pcr(seq, sequences[0], opt)
|
||||
|
||||
if len(amplicons) > 0 {
|
||||
results = append(results, amplicons...)
|
||||
}
|
||||
|
||||
for _, sequence := range sequences[1:] {
|
||||
seq, _ = MakeApatSequence(sequence, opt.Circular(), seq)
|
||||
amplicons = _Pcr(seq, sequence, opt)
|
||||
if len(amplicons) > 0 {
|
||||
results = append(results, amplicons...)
|
||||
}
|
||||
}
|
||||
|
||||
seq.Free()
|
||||
}
|
||||
|
||||
return results
|
||||
return _PCRSlice(sequences, opt)
|
||||
}
|
||||
|
||||
// PCRSliceWorker is a worker function builder which produce
|
||||
// job function usable by the obiseq.MakeISliceWorker function.
|
||||
func PCRSliceWorker(options ...WithOption) obiseq.SeqSliceWorker {
|
||||
|
||||
opt := MakeOptions(options)
|
||||
worker := func(sequences obiseq.BioSequenceSlice) obiseq.BioSequenceSlice {
|
||||
return PCRSlice(sequences, options...)
|
||||
return _PCRSlice(sequences, opt)
|
||||
}
|
||||
|
||||
return worker
|
||||
|
Reference in New Issue
Block a user