<commit_before>package clock

import (
	"fmt"
	"sync"
	"time"
)

// MockClock provides a Clock whose time only changes or advances when
// manually specified to do so. This is useful for unit tests.
type MockClock struct {
	// Mutex is used to guard the current time, and the cond is used to
	// broadcast changes to things waiting for the time to change.
	cond *sync.Cond
	now  time.Time
}

var _ Clock = new(MockClock)

// Now returns the current local time.
func (m *MockClock) Now() time.Time {
	m.cond.L.Lock()
	defer m.cond.L.Unlock()

	return m.now
}

// After waits for the duration to elapse and then sends the current time on the returned channel.
func (m *MockClock) After(d time.Duration) <-chan time.Time {
	ch := make(chan time.Time, 1)
	target := m.Now().Add(d)

	go func() {
		for {
			m.cond.L.Lock()
			if target.After(m.now) {
				m.cond.Wait()
			} else {
				m.cond.L.Unlock()
				ch <- m.now
				return
			}

			m.cond.L.Unlock()
		}
	}()

	return ch
}

// Sleep pauses the current goroutine for at least the duration d. A negative or zero duration causes Sleep to return immediately.
func (m *MockClock) Sleep(d time.Duration) {
	<-m.After(d)
}

// Tick is a convenience wrapper for NewTicker providing access to the ticking channel only. While Tick is useful for clients that have no need to shut down the Ticker, be aware that without a way to shut it down the underlying Ticker cannot be recovered by the garbage collector; it "leaks".
func (m *MockClock) Tick(d time.Duration) <-chan time.Time {
	return m.NewTicker(d).Chan()<commit_msg>mock: fix a data race in After()<commit_after>package clock

import (
	"fmt"
	"sync"
	"time"
)

// MockClock provides a Clock whose time only changes or advances when
// manually specified to do so. This is useful for unit tests.
type MockClock struct {
	// Mutex is used to guard the current time, and the cond is used to
	// broadcast changes to things waiting for the time to change.
	cond *sync.Cond
	now  time.Time
}

var _ Clock = new(MockClock)

// Now returns the current local time.
func (m *MockClock) Now() time.Time {
	m.cond.L.Lock()
	defer m.cond.L.Unlock()

	return m.now
}

// After waits for the duration to elapse and then sends the current time on the returned channel.
func (m *MockClock) After(d time.Duration) <-chan time.Time {
	ch := make(chan time.Time, 1)
	target := m.Now().Add(d)

	go func() {
		for {
			m.cond.L.Lock()
			if target.After(m.now) {
				m.cond.Wait()
			} else {
				now := m.now
				m.cond.L.Unlock()
				ch <- now
				return
			}

			m.cond.L.Unlock()
		}
	}()

	return ch
}

// Sleep pauses the current goroutine for at least the duration d. A negative or zero duration causes Sleep to return immediately.
func (m *MockClock) Sleep(d time.Duration) {
	<-m.After(d)
}

// Tick is a convenience wrapper for NewTicker providing access to the ticking channel only. While Tick is useful for clients that have no need to shut down the Ticker, be aware that without a way to shut it down the underlying Ticker cannot be recovered by the garbage collector; it "leaks".
func (m *MockClock) Tick(d time.Duration) <-chan time.Time {
	return m.NewTicker(d).Chan()
{'fraction_non_alphanumeric': 0.10278304870335231, 'fraction_numerical': 0.0006325110689437065, 'mean_word_length': 3.206117021276596, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 3, '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': '6353051', 'n_tokens_mistral': 1087, 'n_tokens_neox': 1007, 'n_words': 429}