<commit_before>#![allow(dead_code)]
// Copyright 2012-2014 <NAME>. See the COPYRIGHT
// file at the top-level directory.
// 
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
//! A statically-sized ring buffer that acts as an MPMC queue.  Differs
//! from the ring buffer-backed VecDeque in that this structure
//! is lockless and threadsafe.  Threadsafety is achieved using only
//! CAS operations, making this queue ideal for high throughput.  This
//! queue is not ideal for situations where a long wait is expected
//! as any getter is blocked in a spinlock until an item is put.  Locks
//! due to resource starvation are avoided by yielding the spin lock to
//! the scheduler every few thousand iterations.  This queue is cache-aware
//! and performs best with cache line sizes of 64 bytes.
//!
//! Because this queue is threadsafe, it is safe to pass an Arc around
//! to spawned threads and call put, without wrapping the struct itself
//! in a mutex.

//! Benchmarks:
//! test ringbuffer::rbtest::bench_rb_batch     ... bench:    443876 ns/iter (+/- 19276)
//! ringbuffer::rbtest::bench_rb_get       ... bench:        42 ns/iter (+/- 2)
//! ringbuffer::rbtest::bench_rb_lifecycle ... bench:        24 ns/iter (+/- 0)
//! ringbuffer::rbtest::bench_rb_put       ... bench:        36 ns/iter (+/- 5)
//! ringbuffer::rbtest::bench_vecdeque     ... bench:      2934 ns/iter (+/- 394)
//!
//! The final benchmark is comparable to the bench_rb_lifecycle in terms
//! of functionality.

/// #Examples
///
/// ```
/// use marble::ringbuffer::RingBuffer;
/// 
/// use std::sync::Arc;
/// use std::thread;
/// 
/// let rb = Arc::new(RingBuffer::new(1));
///
/// let rbc = rb.clone();
/// let join = thread::spawn(move || {
/// 	loop {
/// 		let result = rbc.get();
/// 		match result {
/// 			Err(_) => break,
/// 			_ => ()
///			}	
///		}
/// });
///
/// rb.put(1);
/// rb.dispose();
/// join.join();
/// ```

use std::cell::UnsafeCell;
use std::default::Default;
use std::marker;
use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};
use std::thread::yield_now;
use std::vec::Vec;

// Node will wrap items in the buffer and keep track of enough
// meta data to know if queue and dequere are referencing the
// correct item.  This is achieved through the atomic position
// field.
struct Node<T> {
	item: 	  Option<T>,
	position: AtomicUsize,
}

impl<T> Node<T> {
	// new creates a new node with its atomic position set to
	// position.  No item by default.
	fn new(position: usize) -> Node<T> {
		Node {
			position: AtomicUsize::new(position),
			item: None,
		}
	}
}

/// RingBuffer is a threadsafe MPMC queue that's statically-sized.
/// Puts are blocked on a full queue and gets are blocked on an empty
/// queue.  In either case, calling dispose will free any blocked threads
/// and return an error.<commit_msg>Added repr(C) to ensure the padding is in the correct location in the struct.<commit_after>#![allow(dead_code)]
// Copyright 2012-2014 <NAME>. See the COPYRIGHT
// file at the top-level directory.
// 
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
//! A statically-sized ring buffer that acts as an MPMC queue.  Differs
//! from the ring buffer-backed VecDeque in that this structure
//! is lockless and threadsafe.  Threadsafety is achieved using only
//! CAS operations, making this queue ideal for high throughput.  This
//! queue is not ideal for situations where a long wait is expected
//! as any getter is blocked in a spinlock until an item is put.  Locks
//! due to resource starvation are avoided by yielding the spin lock to
//! the scheduler every few thousand iterations.  This queue is cache-aware
//! and performs best with cache line sizes of 64 bytes.
//!
//! Because this queue is threadsafe, it is safe to pass an Arc around
//! to spawned threads and call put, without wrapping the struct itself
//! in a mutex.

//! Benchmarks:
//! test ringbuffer::rbtest::bench_rb_batch     ... bench:    443876 ns/iter (+/- 19276)
//! ringbuffer::rbtest::bench_rb_get       ... bench:        42 ns/iter (+/- 2)
//! ringbuffer::rbtest::bench_rb_lifecycle ... bench:        24 ns/iter (+/- 0)
//! ringbuffer::rbtest::bench_rb_put       ... bench:        36 ns/iter (+/- 5)
//! ringbuffer::rbtest::bench_vecdeque     ... bench:      2934 ns/iter (+/- 394)
//!
//! The final benchmark is comparable to the bench_rb_lifecycle in terms
//! of functionality.

/// #Examples
///
/// ```
/// use marble::ringbuffer::RingBuffer;
/// 
/// use std::sync::Arc;
/// use std::thread;
/// 
/// let rb = Arc::new(RingBuffer::new(1));
///
/// let rbc = rb.clone();
/// let join = thread::spawn(move || {
/// 	loop {
/// 		let result = rbc.get();
/// 		match result {
/// 			Err(_) => break,
/// 			_ => ()
///			}	
///		}
/// });
///
/// rb.put(1);
/// rb.dispose();
/// join.join();
/// ```

use std::cell::UnsafeCell;
use std::default::Default;
use std::marker;
use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};
use std::thread::yield_now;
use std::vec::Vec;

// Node will wrap items in the buffer and keep track of enough
// meta data to know if queue and dequere are referencing the
// correct item.  This is achieved through the atomic position
// field.
struct Node<T> {
	item: 	  Option<T>,
	position: AtomicUsize,
}

impl<T> Node<T> {
	// new creates a new node with its atomic position set to
	// position.  No item by default.
	fn new(position: usize) -> Node<T> {
		Node {
			position: AtomicUsize::new(position),
			item: None,
		}
	}
}

/// RingBuffer is a threadsafe MPMC queue that's statically-sized.
/// Puts are blocked on a full queue and gets are blocked on an empty
/// queue.  In either case, calling dispose will free any blocked threads
/// and return an error.
#[repr(C)]
{'fraction_non_alphanumeric': 0.15029642685467073, 'fraction_numerical': 0.01377984297388239, 'mean_word_length': 2.90125, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '315899', 'n_tokens_mistral': 2058, 'n_tokens_neox': 1887, 'n_words': 719}