Apparently I've been using WaitGroups wrong all along.
func (me *Client) sendChunk(t *torrent, c *connection, r request) error {
b := make([]byte, r.Length)
- t.Pieces[r.Index].pendingWrites.Wait()
+ tp := t.Pieces[r.Index]
+ tp.pendingWritesMutex.Lock()
+ for tp.pendingWrites != 0 {
+ tp.noPendingWrites.Wait()
+ }
+ tp.pendingWritesMutex.Unlock()
p := t.Info.Piece(int(r.Index))
n, err := dataReadAt(t.data, b, p.Offset()+int64(r.Begin))
if err != nil {
me.upload(t, c)
- piece.pendingWrites.Add(1)
+ piece.pendingWritesMutex.Lock()
+ piece.pendingWrites++
+ piece.pendingWritesMutex.Unlock()
go func() {
- defer piece.pendingWrites.Done()
+ defer func() {
+ piece.pendingWritesMutex.Lock()
+ piece.pendingWrites--
+ if piece.pendingWrites == 0 {
+ piece.noPendingWrites.Broadcast()
+ }
+ piece.pendingWritesMutex.Unlock()
+ }()
// Write the chunk out.
tr := perf.NewTimer()
err := t.writeChunk(int(msg.Index), int64(msg.Begin), msg.Piece)
EverHashed bool
Event sync.Cond
Priority piecePriority
- pendingWrites sync.WaitGroup
+
+ pendingWritesMutex sync.Mutex
+ pendingWrites int
+ noPendingWrites sync.Cond
}
func (p *piece) pendingChunk(cs chunkSpec, chunkSize pp.Integer) bool {
if int64(len(b1)) > ip.Length()-po {
b1 = b1[:ip.Length()-po]
}
- tp.pendingWrites.Wait()
+ tp.pendingWritesMutex.Lock()
+ for tp.pendingWrites != 0 {
+ tp.noPendingWrites.Wait()
+ }
+ tp.pendingWritesMutex.Unlock()
n, err = dataReadAt(r.t.data, b1, pos)
if n != 0 {
err = nil
for _, hash := range infoPieceHashes(md) {
piece := &piece{}
piece.Event.L = eventLocker
+ piece.noPendingWrites.L = &piece.pendingWritesMutex
missinggo.CopyExact(piece.Hash[:], hash)
t.Pieces = append(t.Pieces, piece)
}
func (t *torrent) hashPiece(piece pp.Integer) (ps pieceSum) {
hash := pieceHash.New()
p := t.Pieces[piece]
- p.pendingWrites.Wait()
+ p.pendingWritesMutex.Lock()
+ for p.pendingWrites != 0 {
+ p.noPendingWrites.Wait()
+ }
+ p.pendingWritesMutex.Unlock()
t.data.WriteSectionTo(hash, int64(piece)*t.Info.PieceLength, t.Info.PieceLength)
missinggo.CopyExact(ps[:], hash.Sum(nil))
return