/* Filename: NonBlockingAtomicReferenceArray.java, * STUDENT must implement this class. ************************************************************ Author: Dr. Parson Student co-author: Major: Professor Creation Date: 2/23/2024 Due Date: 3/28/2024 after spring break Course: CSC543 spring 2024 Professor Name: D. Parson Assignment: #3 Interface INonBlockingTupleExchange for NonBlockingQueue, NonBlockingAtomicReference, and NonBlockingAtomicReferenceArray implementing classes. */ package CSC543s24NonBlockingDataflowAssn3 ; import net.jcip.annotations.* ; import java.util.concurrent.atomic.AtomicReferenceArray ; // https://docs.oracle.com/javase/8/docs/api/index.html?java/util/concurrent/atomic/AtomicReferenceArray.html public class NonBlockingAtomicReferenceArray implements INonBlockingTupleExchange { /* TupleType will be FiveTuple or TenTuple in this assignment. */ private volatile int nextPut = 0 ; private volatile int nextTake = 0 ; public NonBlockingAtomicReferenceArray(AtomicReferenceArray q) { // STUDENT 3 (15%): Tag class as @ThreadSafe, store constructor // parameter or parameters in thread-safe fields, // and implement spinUntilPut and spinUntilTake as // described in interface INonBlockingTupleExchange and below. } public void spinUntilPut(TupleType tuple) { /* * spinUntilPut spins until it succeeds in calling non-blocking * successful insertion into an AtomicReferenceArray * via compareAndSet(). * STUDENT IMPLENTATION NOTE: When running compareAndSet() on * the AtomicReferenceArray q at index nextPut * indicates failure because that q slot contains contents, * loop on nextPut = (nextPut+1) MODULO (%) the q.length() * repeatedly until finding an empty q slot. The MOD operator * treats the AtomicReferenceArray as a circular buffer. * COMMENT: In this particular pipeline there is no race * condition on the update to nextPut. Even if there were * multiple threads accessing the same nextPut variable * (there aren't), they would just keep looping until they find * a null slot. Note that atomics are NOT recommended when * there is a chance of high thread contention because * of lack of strong synchronization; in such cases blocking * locks and conditions variables work better. But in this * pipeline, there is no such contention. There may be much * idle spinning for a producer when the consumer is slow to * consume, or idle spinning for a consumer when the producer * is slow to produce. A lot of spinning on a volatile variable * may clutter memory buses, causing memory access contention. * This exercise is in part a test of effectiveness of atomics * in such a pipeline. */ } public TupleType spinUntilTake() { return null ; // STUDENT Delete this line when you code this class. /* * spinUntilTake spins until it succeeds in calling non-blocking * successful retrieval from an AtomicReferenceArray * via getAndSet(). * STUDENT IMPLENTATION NOTE: When running getAndSet() on * the AtomicReferenceArray q at index nextTake * indicates failure because that q slot contains no contents, * loop on nextTake = (nextTake+1) MODULO (%) the q.length() * repeatedly until finding a non-empty q slot. The MOD operator * treats the AtomicReferenceArray as a circular buffer. * See COMMENT in spinUntilPut above. */ } }