<commit_before>package latch

import (
	"sync"
	"time"
)

// NewCountDownLatch creates a new CountDownLatch
func NewCountDownLatch() *CountDownLatch {
	// creates a closed channel
	c := make(chan struct{})
	close(c)
	return &CountDownLatch{
		done: c,
	}
}

// CountDownLatch is the same as sync.WaitGroup but with the ability to wait with timeout
type CountDownLatch struct {
	mu      sync.RWMutex
	counter int
	done    chan struct{}
	closed  bool
}

// Add increases/decreases the countdown
func (l *CountDownLatch) Add(delta int) {
	l.mu.Lock()
	defer l.mu.Unlock()

	if delta > 0 && l.counter == 0 {
		l.done = make(chan struct{})
	}

	l.counter += delta
	if l.counter <= 0 && !l.closed {
		l.closed = true
		close(l.done)
	}
}

// Done decreases the countdown by one
func (l *CountDownLatch) Done() {
	l.Add(-1)
}

// Wait to be unblocked
func (l *CountDownLatch) Wait() <-chan struct{} {
	return l.done
}

// WaitWithTimeout waits until the timeout runs out or until the countdown is zero
func (l *CountDownLatch) WaitWithTimeout(timeout time.Duration) bool {
	select {
	case <-l.done:
		return false // completed normally
	case <-time.After(timeout):
		l.Close()
		return true // timed out
	}
}

// Close closes the latch unblocking wait
func (l *CountDownLatch) Close() {
	l.mu.Lock()
	defer l.mu.Unlock()

	if !l.closed {
		l.closed = true
		close(l.done)
	}
}

// Counter returns the current count down number
func (l *CountDownLatch) Counter() int {
	l.mu.Lock()<commit_msg>latch up down and up again<commit_after>package latch

import (
	"sync"
	"time"
)

// NewCountDownLatch creates a new CountDownLatch
func NewCountDownLatch() *CountDownLatch {
	// creates a closed channel
	c := make(chan struct{})
	close(c)
	return &CountDownLatch{
		done:   c,
		closed: true,
	}
}

// CountDownLatch is the same as sync.WaitGroup but with the ability to wait with timeout
type CountDownLatch struct {
	mu      sync.RWMutex
	counter int
	done    chan struct{}
	closed  bool
}

// Add increases/decreases the countdown
func (l *CountDownLatch) Add(delta int) {
	l.mu.Lock()
	defer l.mu.Unlock()

	oldCount := l.counter
	l.counter += delta
	if oldCount <= 0 && l.counter > 0 {
		l.done = make(chan struct{})
		l.closed = false
	} else if oldCount > 0 && l.counter <= 0 {
		l.closed = true
		close(l.done)
	}
}

// Done decreases the countdown by one
func (l *CountDownLatch) Done() {
	l.Add(-1)
}

// Wait to be unblocked
func (l *CountDownLatch) Wait() <-chan struct{} {
	return l.done
}

// WaitWithTimeout waits until the timeout runs out or until the countdown is zero
func (l *CountDownLatch) WaitWithTimeout(timeout time.Duration) bool {
	select {
	case <-l.done:
		return false // completed normally
	case <-time.After(timeout):
		l.Close()
		return true // timed out
	}
}

// Close closes the latch unblocking wait
func (l *CountDownLatch) Close() {
	l.mu.Lock()
	defer l.mu.Unlock()

	l.counter = 0
	if !l.closed {
		l.closed = true
		close(l.done)
	}
}

// Counter returns the current count down number
func (l *CountDownLatch) Counter() int {
	l.mu.Lock()
{'fraction_non_alphanumeric': 0.12129116400391261, 'fraction_numerical': 0.0032605151613955006, 'mean_word_length': 3.382857142857143, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 6, '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': '1169241', 'n_tokens_mistral': 1141, 'n_tokens_neox': 1079, 'n_words': 348}