func New(wd string, ss Strategizer, gro ...GrabberOption) (*Grabber, error) { if wd == "" { return nil, MissingWorkDirError } mx := new(sync.RWMutex) g := &Grabber{ wd: wd, s: ss, writeState: mx, readState: mx.RLocker(), qIn: make(chan Segmenter, 100), // TODO(negz): Determine best buffer len. qOut: make(chan Segmenter, 100), maxRetry: 3, doneMx: new(sync.Mutex), pp: make(chan bool), decoder: yenc.NewDecoder, // TODO(negz): Detect encoding. fileCreator: createSegmentFile, grabT: new(tomb.Tomb), enqueueT: new(tomb.Tomb), } for _, o := range gro { if err := o(g); err != nil { return nil, err } } if g.name == "" { return nil, MissingNameError } g.hash = util.HashString(g.name) return g, nil }
func NewSegment(ns *nzb.Segment, f Filer) Segmenter { mx := new(sync.RWMutex) return &Segment{ ns: ns, f: f, writeState: mx, readState: mx.RLocker(), failedServer: make(map[Serverer]bool), failedGroup: make(map[string]bool), } }
func BenchmarkMtxBlock(b *testing.B) { var primer int64 m := new(sync.RWMutex) c := sync.NewCond(m.RLocker()) die := make(chan struct{}) for i := 0; i < runtime.GOMAXPROCS(0); i++ { go func() { for { select { case <-die: return default: // Gosched doubles as our item of work, as above. runtime.Gosched() } m.Lock() atomic.AddInt64(&primer, 1) c.Broadcast() m.Unlock() } }() } b.RunParallel(func(pb *testing.PB) { for pb.Next() { myPrimer := atomic.LoadInt64(&primer) for { m.RLock() if myPrimer != primer { m.RUnlock() break } c.Wait() m.RUnlock() } } }) close(die) }
func NewFile(nf *nzb.File, g Grabberer, filter ...*regexp.Regexp) Filer { mx := new(sync.RWMutex) f := &File{ nf: nf, g: g, hash: util.HashString(nf.Subject), segments: make([]Segmenter, 0, len(nf.Segments)), writeState: mx, readState: mx.RLocker(), doneMx: new(sync.Mutex), required: true, } for _, ns := range nf.Segments { f.segments = append(f.segments, NewSegment(ns, f)) } if par2RE.MatchString(nf.Subject) { f.par2 = true f.required = false f.Pause() } for _, r := range filter { if r.MatchString(nf.Subject) { f.filtered = true f.required = false f.Pause() } } if f.required { f.g.FileRequired() } return f }