Skip to content

Commit

Permalink
Add ReferenceCountedDirectoryCloser
Browse files Browse the repository at this point in the history
Sometimes you run into situations where you want to traverse directory
hierarchies in parallel. In those cases it's useful to have reference
counting on the directory objects, so that directories don't need to be
opened redundantly.
  • Loading branch information
EdSchouten committed Jul 12, 2024
1 parent a2eab49 commit c56df61
Showing 1 changed file with 41 additions and 0 deletions.
41 changes: 41 additions & 0 deletions pkg/filesystem/directory.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package filesystem
import (
"io"
"os"
"sync/atomic"
"time"

"github.com/buildbarn/bb-storage/pkg/filesystem/path"
Expand Down Expand Up @@ -139,3 +140,43 @@ func NopDirectoryCloser(d Directory) DirectoryCloser {
func (d nopDirectoryCloser) Close() error {
return nil
}

// ReferenceCountedDirectoryCloser is a decorator for DirectoryCloser that
// adds reference counting. This makes it possible to duplicate it, and
// call Close() on it multiple times.
type ReferenceCountedDirectoryCloser struct {
DirectoryCloser
refcount atomic.Int32
}

// NewReferenceCountedDirectoryCloser creates a new
// ReferenceCountedDirectoryCloser against which Close() can be called
// exactly once.
func NewReferenceCountedDirectoryCloser(directory DirectoryCloser) *ReferenceCountedDirectoryCloser {
d := &ReferenceCountedDirectoryCloser{
DirectoryCloser: directory,
}
d.refcount.Store(1)
return d
}

// Duplicate the ReferenceCountedDirectoryCloser by increasing its
// reference count.
func (d *ReferenceCountedDirectoryCloser) Duplicate() *ReferenceCountedDirectoryCloser {
if newRefcount := d.refcount.Add(1); newRefcount <= 1 {
panic("Invalid reference count")
}
return d
}

// Close the ReferenceCountedDirectoryCloser by decreasing its reference
// count. If the reference count reaches zero, the underlying directory
// is closed.
func (d *ReferenceCountedDirectoryCloser) Close() error {
if newRefcount := d.refcount.Add(-1); newRefcount == 0 {
return d.DirectoryCloser.Close()
} else if newRefcount < 0 {
panic("Invalid reference count")
}
return nil
}

0 comments on commit c56df61

Please sign in to comment.