<commit_before>package rbuf

// AtomicFixedSizeRingBuf: Synchronized version of FixedSizeRingBuf,
// safe for concurrent access.
//
// copyright (c) 2014, <NAME>
// license: MIT
//
// Some text from the Golang standard library doc is adapted and
// reproduced in fragments below to document the expected behaviors
// of the interface functions Read()/Write()/ReadFrom()/WriteTo() that
// are implemented here. Those descriptions (see
// http://golang.org/pkg/io/#Reader for example) are
// copyright 2010 The Go Authors.

import (
	"io"
	"sync"
)

// AtomicFixedSizeRingBuf: see FixedSizeRingBuf for the full
// details; this is the same, just safe for current access
// (and thus paying the price of synchronization on each call
// as well.)
//
type AtomicFixedSizeRingBuf struct {
	A        [2][]byte // a pair of ping/pong buffers. Only one is active.
	Use      int       // which A buffer is in active use, 0 or 1
	N        int       // MaxViewInBytes, the size of A[0] and A[1] in bytes.
	Beg      int       // start of data in A[Use]
	Readable int       // number of bytes available to read in A[Use]
	tex      sync.Mutex
}

// get the length of the largest read that we can provide to a contiguous slice
// without an extra linearizing copy of all bytes internally.
func (b *AtomicFixedSizeRingBuf) ContigLen() int {
	b.tex.Lock()
	defer b.tex.Unlock()

	extent := b.Beg + b.Readable
	firstContigLen := intMin2(extent, b.N) - b.Beg
	return firstContigLen
}

// constructor. NewAtomicFixedSizeRingBuf will allocate internally
// two buffers of size maxViewInBytes.
func NewAtomicFixedSizeRingBuf(maxViewInBytes int) *AtomicFixedSizeRingBuf {
	n := maxViewInBytes
	r := &AtomicFixedSizeRingBuf{
		Use: 0, // 0 or 1, whichever is actually in use at the moment.
		// If we are asked for Bytes() and we wrap, linearize into the other.

		N:        n,
		Beg:      0,
		Readable: 0,
	}
	r.A[0] = make([]byte, n, n)
	r.A[1] = make([]byte, n, n)

	return r
}

// from the standard library description of Bytes():
// Bytes() returns a slice of the contents of the unread portion of the buffer.
// If the caller changes the contents of the
// returned slice, the contents of the buffer will change provided there
//  are no intervening method calls on the Buffer.
//
// The largest slice Bytes ever returns is bounded above by the maxViewInBytes
// value used when calling NewAtomicFixedSizeRingBuf().
func (b *AtomicFixedSizeRingBuf) Bytes() []byte {
	b.tex.Lock()
	defer b.tex.Unlock()

	extent := b.Beg + b.Readable
	if extent <= b.N {
		// we fit contiguously in this buffer without wrapping to the other
		return b.A[b.Use][b.Beg:(b.Beg + b.Readable)]
	}

	// wrap into the other buffer
	src := b.Use
	dest := 1 - b.Use

	n := copy(b.A[dest], b.A[src][b.Beg:])
	n += copy(b.A[dest][n:], b.A[src][0:(extent%b.N)])

	b.Use = dest
	b.Beg = 0

	return b.A[b.Use][:n]
}

// Read():
//
// From bytes.Buffer.Read(): Read reads the next len(p) bytes
// from the buffer or until the buffer is drained. The return
// value n is the number of bytes read. If the buffer has no data
// to return, err is io.EOF (unless len(p) is zero); otherwise it is nil.
//
//  from the description of the Reader interface,
//     http://golang.org/pkg/io/#Reader<commit_msg>atg. atomic rbuf Bytes() returns a copy<commit_after>package rbuf

// AtomicFixedSizeRingBuf: Synchronized version of FixedSizeRingBuf,
// safe for concurrent access.
//
// copyright (c) 2014, <NAME>
// license: MIT
//
// Some text from the Golang standard library doc is adapted and
// reproduced in fragments below to document the expected behaviors
// of the interface functions Read()/Write()/ReadFrom()/WriteTo() that
// are implemented here. Those descriptions (see
// http://golang.org/pkg/io/#Reader for example) are
// copyright 2010 The Go Authors.

import (
	"io"
	"sync"
)

// AtomicFixedSizeRingBuf: see FixedSizeRingBuf for the full
// details; this is the same, just safe for current access
// (and thus paying the price of synchronization on each call
// as well.)
//
type AtomicFixedSizeRingBuf struct {
	A        [2][]byte // a pair of ping/pong buffers. Only one is active.
	Use      int       // which A buffer is in active use, 0 or 1
	N        int       // MaxViewInBytes, the size of A[0] and A[1] in bytes.
	Beg      int       // start of data in A[Use]
	Readable int       // number of bytes available to read in A[Use]
	tex      sync.Mutex
}

// get the length of the largest read that we can provide to a contiguous slice
// without an extra linearizing copy of all bytes internally.
func (b *AtomicFixedSizeRingBuf) ContigLen() int {
	b.tex.Lock()
	defer b.tex.Unlock()

	extent := b.Beg + b.Readable
	firstContigLen := intMin2(extent, b.N) - b.Beg
	return firstContigLen
}

// constructor. NewAtomicFixedSizeRingBuf will allocate internally
// two buffers of size maxViewInBytes.
func NewAtomicFixedSizeRingBuf(maxViewInBytes int) *AtomicFixedSizeRingBuf {
	n := maxViewInBytes
	r := &AtomicFixedSizeRingBuf{
		Use: 0, // 0 or 1, whichever is actually in use at the moment.
		// If we are asked for Bytes() and we wrap, linearize into the other.

		N:        n,
		Beg:      0,
		Readable: 0,
	}
	r.A[0] = make([]byte, n, n)
	r.A[1] = make([]byte, n, n)

	return r
}

// Bytes() returns a slice of the contents of the unread portion of the buffer.
// Unlike the standard library Bytes() method (on bytes.Buffer for example),
// the result of the AtomicFixedSizeRingBuf::Bytes() is a completely new
// returned slice, so modifying that slice will have no impact on the contents
// of the internal ring.
//
// The largest slice Bytes ever returns is bounded above by the maxViewInBytes
// value used when calling NewAtomicFixedSizeRingBuf().
func (b *AtomicFixedSizeRingBuf) Bytes() []byte {
	b.tex.Lock()
	defer b.tex.Unlock()

	extent := b.Beg + b.Readable
	if extent <= b.N {
		// we fit contiguously in this buffer without wrapping to the other
		return b.A[b.Use][b.Beg:(b.Beg + b.Readable)]
	}

	// wrap into the other buffer
	src := b.Use
	dest := 1 - b.Use

	n := copy(b.A[dest], b.A[src][b.Beg:])
	n += copy(b.A[dest][n:], b.A[src][0:(extent%b.N)])

	b.Use = dest
	b.Beg = 0

	ret := make([]byte, n)
	copy(ret, b.A[b.Use][:n])
	return ret
}

// Read():
//
// From bytes.Buffer.Read(): Read reads the next len(p) bytes
// from the buffer or until the buffer is drained. The return
// value n is the number of bytes read. If the buffer has no data
// to return, err is io.EOF (unless len(p) is zero); otherwise it is nil.
//
//  from the description of the Reader interface,
//     http://golang.org/pkg/io/#Reader
{'fraction_non_alphanumeric': 0.11613098847786538, 'fraction_numerical': 0.0072771376591873865, 'mean_word_length': 3.1077210460772107, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4574746', 'n_tokens_mistral': 2251, 'n_tokens_neox': 2110, 'n_words': 844}