Add automatic garbage collection on ApatPattern

This commit is contained in:
2022-01-24 17:26:30 +01:00
parent 703eb62819
commit 251d3be923
10 changed files with 119 additions and 92 deletions

View File

@@ -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])