diff --git a/assignments/week-1-assignment-0/src/edu/vuum/mooca/SynchronizedQueue.java b/assignments/week-1-assignment-0/src/edu/vuum/mooca/SynchronizedQueue.java index c4ffb3c18..44ae66c3e 100644 --- a/assignments/week-1-assignment-0/src/edu/vuum/mooca/SynchronizedQueue.java +++ b/assignments/week-1-assignment-0/src/edu/vuum/mooca/SynchronizedQueue.java @@ -220,22 +220,25 @@ public static SynchronizedQueueResult testQueue(QueueAdapter queue) { // initialization below to create two Java Threads, one // that's passed the producerRunnable and the other that's // passed the consumerRunnable. - Thread consumer = null; - Thread producer = null; + Thread consumer = new Thread(consumerRunnable); + Thread producer = new Thread(producerRunnable); // TODO - you fill in here to start the threads. More // interesting results will occur if you start the // consumer first. - + consumer.start(); + producer.start(); // Give the Threads a chance to run before interrupting // them. Thread.sleep(100); // TODO - you fill in here to interrupt the threads. - + consumer.interrupt(); + producer.interrupt(); // TODO - you fill in here to wait for the threads to // exit. - + consumer.join(); + producer.join(); // Do some sanity checking to see if the Threads work as // expected. if (consumer == null diff --git a/assignments/week-2-assignment-1/src/edu/vuum/mocca/SimpleAtomicLong.java b/assignments/week-2-assignment-1/src/edu/vuum/mocca/SimpleAtomicLong.java index f57064f95..7fad00e77 100644 --- a/assignments/week-2-assignment-1/src/edu/vuum/mocca/SimpleAtomicLong.java +++ b/assignments/week-2-assignment-1/src/edu/vuum/mocca/SimpleAtomicLong.java @@ -1,5 +1,3 @@ -// Import the necessary Java synchronization and scheduling classes. - package edu.vuum.mocca; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -18,27 +16,41 @@ class SimpleAtomicLong * The value that's manipulated atomically via the methods. */ private long mValue; - - + /** * The ReentrantReadWriteLock used to serialize access to mValue. */ - // TODO - add the implementation + + // TODO -- you fill in here by replacing the null with an + // initialization of ReentrantReadWriteLock. + private ReentrantReadWriteLock mRWLock = new ReentrantReadWriteLock(); /** * Creates a new SimpleAtomicLong with the given initial value. */ - public SimpleAtomicLong(long initialValue) { - // TODO - you fill in here + public SimpleAtomicLong(long initialValue) + { + // TODO -- you fill in here + this.mValue = initialValue; } /** - * @brief Gets the current value + * @brief Gets the current value. * * @returns The current value */ - public long get() { - // TODO - you fill in here + public long get() + { + long value; + + // TODO -- you fill in here + mRWLock.readLock().lock(); + try{ + value = mValue; + }finally{ + mRWLock.readLock().unlock(); + } + return value; } /** @@ -46,8 +58,20 @@ public long get() { * * @returns the updated value */ - public long decrementAndGet() { - // TODO - you fill in here + public long decrementAndGet() + { + long value = 0; + + // TODO -- you fill in here + mRWLock.writeLock().lock(); + try{ + mValue = mValue - 1; + value = mValue; + }finally{ + mRWLock.writeLock().unlock(); + } + + return value; } /** @@ -55,8 +79,20 @@ public long decrementAndGet() { * * @returns the previous value */ - public long getAndIncrement() { - // TODO - you fill in here + public long getAndIncrement() + { + long value = 0; + + // TODO -- you fill in here + mRWLock.writeLock().lock(); + try{ + value = mValue; + mValue = mValue + 1; + }finally{ + mRWLock.writeLock().unlock(); + } + + return value; } /** @@ -64,8 +100,19 @@ public long getAndIncrement() { * * @returns the previous value */ - public long getAndDecrement() { - // TODO - you fill in here + public long getAndDecrement() + { + long value = 0; + + // TODO -- you fill in here + mRWLock.writeLock().lock(); + try{ + value = mValue; + mValue = mValue - 1; + }finally{ + mRWLock.writeLock().unlock(); + } + return value; } /** @@ -73,8 +120,20 @@ public long getAndDecrement() { * * @returns the updated value */ - public long incrementAndGet() { - // TODO - you fill in here + public long incrementAndGet() + { + long value = 0; + + // TODO -- you fill in here + mRWLock.writeLock().lock(); + try{ + mValue = mValue + 1; + value = mValue; + }finally{ + mRWLock.writeLock().unlock(); + } + + return value; } } diff --git a/assignments/week-3-assignment-2/src/edu/vuum/mocca/SimpleAtomicLong.java b/assignments/week-3-assignment-2/src/edu/vuum/mocca/SimpleAtomicLong.java index f57064f95..7fad00e77 100644 --- a/assignments/week-3-assignment-2/src/edu/vuum/mocca/SimpleAtomicLong.java +++ b/assignments/week-3-assignment-2/src/edu/vuum/mocca/SimpleAtomicLong.java @@ -1,5 +1,3 @@ -// Import the necessary Java synchronization and scheduling classes. - package edu.vuum.mocca; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -18,27 +16,41 @@ class SimpleAtomicLong * The value that's manipulated atomically via the methods. */ private long mValue; - - + /** * The ReentrantReadWriteLock used to serialize access to mValue. */ - // TODO - add the implementation + + // TODO -- you fill in here by replacing the null with an + // initialization of ReentrantReadWriteLock. + private ReentrantReadWriteLock mRWLock = new ReentrantReadWriteLock(); /** * Creates a new SimpleAtomicLong with the given initial value. */ - public SimpleAtomicLong(long initialValue) { - // TODO - you fill in here + public SimpleAtomicLong(long initialValue) + { + // TODO -- you fill in here + this.mValue = initialValue; } /** - * @brief Gets the current value + * @brief Gets the current value. * * @returns The current value */ - public long get() { - // TODO - you fill in here + public long get() + { + long value; + + // TODO -- you fill in here + mRWLock.readLock().lock(); + try{ + value = mValue; + }finally{ + mRWLock.readLock().unlock(); + } + return value; } /** @@ -46,8 +58,20 @@ public long get() { * * @returns the updated value */ - public long decrementAndGet() { - // TODO - you fill in here + public long decrementAndGet() + { + long value = 0; + + // TODO -- you fill in here + mRWLock.writeLock().lock(); + try{ + mValue = mValue - 1; + value = mValue; + }finally{ + mRWLock.writeLock().unlock(); + } + + return value; } /** @@ -55,8 +79,20 @@ public long decrementAndGet() { * * @returns the previous value */ - public long getAndIncrement() { - // TODO - you fill in here + public long getAndIncrement() + { + long value = 0; + + // TODO -- you fill in here + mRWLock.writeLock().lock(); + try{ + value = mValue; + mValue = mValue + 1; + }finally{ + mRWLock.writeLock().unlock(); + } + + return value; } /** @@ -64,8 +100,19 @@ public long getAndIncrement() { * * @returns the previous value */ - public long getAndDecrement() { - // TODO - you fill in here + public long getAndDecrement() + { + long value = 0; + + // TODO -- you fill in here + mRWLock.writeLock().lock(); + try{ + value = mValue; + mValue = mValue - 1; + }finally{ + mRWLock.writeLock().unlock(); + } + return value; } /** @@ -73,8 +120,20 @@ public long getAndDecrement() { * * @returns the updated value */ - public long incrementAndGet() { - // TODO - you fill in here + public long incrementAndGet() + { + long value = 0; + + // TODO -- you fill in here + mRWLock.writeLock().lock(); + try{ + mValue = mValue + 1; + value = mValue; + }finally{ + mRWLock.writeLock().unlock(); + } + + return value; } } diff --git a/assignments/week-3-assignment-2/src/edu/vuum/mocca/SimpleSemaphore.java b/assignments/week-3-assignment-2/src/edu/vuum/mocca/SimpleSemaphore.java index a867818ed..d11e28258 100644 --- a/assignments/week-3-assignment-2/src/edu/vuum/mocca/SimpleSemaphore.java +++ b/assignments/week-3-assignment-2/src/edu/vuum/mocca/SimpleSemaphore.java @@ -6,65 +6,103 @@ /** * @class SimpleSemaphore - * + * * @brief This class provides a simple counting semaphore * implementation using Java a ReentrantLock and a - * ConditionObject (which is accessed via a Condition). It must - * implement both "Fair" and "NonFair" semaphore semantics, - * just liked Java Semaphores. + * ConditionObject. It must implement both "Fair" and + * "NonFair" semaphore semantics, just liked Java Semaphores. */ public class SimpleSemaphore { /** - * Define a Lock to protect the critical section. + * Define a ReentrantLock to protect the critical section. */ // TODO - you fill in here - + private ReentrantLock lock; /** - * Define a Condition that waits while the number of permits is 0. + * Define a ConditionObject to wait while the number of + * permits is 0. */ // TODO - you fill in here - + private Condition condition; /** * Define a count of the number of available permits. */ // TODO - you fill in here. Make sure that this data member will // ensure its values aren't cached by multiple Threads.. - - public SimpleSemaphore(int permits, boolean fair) { - // TODO - you fill in here to initialize the SimpleSemaphore, - // making sure to allow both fair and non-fair Semaphore - // semantics. + private volatile int permits; + /** + * Constructor initialize the data members. + */ + public SimpleSemaphore (int permits, + boolean fair) + { + // TODO - you fill in here + this.permits = permits; + lock = new ReentrantLock(fair); + condition = lock.newCondition(); } /** - * Acquire one permit from the semaphore in a manner that can be - * interrupted. + * Acquire one permit from the semaphore in a manner that can + * be interrupted. */ public void acquire() throws InterruptedException { - // TODO - you fill in here. + // TODO - you fill in here + lock.lockInterruptibly(); + try{ + while(permits == 0){ + condition.await(); + } + permits = permits - 1; + }finally{ + lock.unlock(); + } } /** - * Acquire one permit from the semaphore in a manner that cannot be - * interrupted. + * Acquire one permit from the semaphore in a manner that + * cannot be interrupted. */ public void acquireUninterruptibly() { - // TODO - you fill in here. + // TODO - you fill in here + lock.lock(); + try{ + while(permits == 0){ + condition.awaitUninterruptibly(); + } + permits = permits - 1; + }finally{ + lock.unlock(); + } } /** * Return one permit to the semaphore. */ - public void release() { - // TODO - you fill in here. + void release() { + // TODO - you fill in here + lock.lock(); + try{ + permits = permits + 1; + condition.signalAll(); + }finally{ + lock.unlock(); + } } - + /** * Return the number of permits available. */ - public int availablePermits() { - // TODO - you fill in here by changing null to the appropriate - // return value. - return null; + public int availablePermits(){ + // TODO - you fill in here + int result = 0; + lock.lock(); + try{ + result = permits; + }finally{ + lock.unlock(); + } + return result; // You will change this value. } } + diff --git a/assignments/week-4-assignment-3/.classpath b/assignments/week-4-assignment-3/.classpath index b0e3db7ba..b8224469e 100644 --- a/assignments/week-4-assignment-3/.classpath +++ b/assignments/week-4-assignment-3/.classpath @@ -1,8 +1,10 @@ - - - - - - + + + + + + \ No newline at end of file diff --git a/assignments/week-4-assignment-3/.project b/assignments/week-4-assignment-3/.project index f5e4399a9..202df801d 100644 --- a/assignments/week-4-assignment-3/.project +++ b/assignments/week-4-assignment-3/.project @@ -14,4 +14,4 @@ org.eclipse.jdt.core.javanature - + \ No newline at end of file diff --git a/assignments/week-4-assignment-3/Assignment-Description.txt b/assignments/week-4-assignment-3/Assignment-Description.txt index 66cb926d8..add9d3d92 100644 --- a/assignments/week-4-assignment-3/Assignment-Description.txt +++ b/assignments/week-4-assignment-3/Assignment-Description.txt @@ -6,7 +6,7 @@ Due Monday, June 16th, 2014 In this assignment, you will implement a Java program that creates two instances of the PlayPingPongThread and then starts these thread instances to correctly alternate printing "Ping" and "Pong", -respectively, on the console display. This assignment also reuses the +respectively, on the console display. This assignment also reuses the SimpleSemaphore you implemented for the previous assignment, so please apply any fixes motivated by watching the Virtual Office Hours video of the instructor's solution(s). @@ -28,11 +28,11 @@ In particular, you'll need to do the following: and fix the problems with the earlier PingPongWrong solution, which is covered in this video: - Section 1: Module 2: Part 3: Motivating Java Synchronization and Scheduling Mechanisms + Section 1: Module 2: Part 3: Motivating Java Synchronization and Scheduling Mechanisms . Implement the PingPongRight class data members (including a Java CountDownLatch) and the main() function that uses the - SimpleSemaphore and CountDownLatch. The Java CountDownLatch class + SimpleSemaphore and CountDownLatch. The Java CountDownLatch class is covered in this video: Section 1: Module 2: Part 9: Java CountDownLatch @@ -40,7 +40,7 @@ In particular, you'll need to do the following: There are also relevant discussions about using Java CountDownLatches at these links: - http://javatechig.com/java/countdownlatch-and-java-concurrency-example + http://javatechig.com/java/countdownlatch-and-java-concurrency-example http://tutorials.jenkov.com/java-util-concurrent/countdownlatch.html . The PingPongRight.java program also uses various features of Java @@ -84,41 +84,40 @@ The correct solution when you run PingPongRight should look exactly like this: Ready...Set...Go! -Ping! (1) +Ping! (1) Pong! (1) -Ping! (2) +Ping! (2) Pong! (2) -Ping! (3) +Ping! (3) Pong! (3) -Ping! (4) +Ping! (4) Pong! (4) -Ping! (5) +Ping! (5) Pong! (5) -Ping! (6) +Ping! (6) Pong! (6) -Ping! (7) +Ping! (7) Pong! (7) -Ping! (8) +Ping! (8) Pong! (8) -Ping! (9) +Ping! (9) Pong! (9) -Ping! (10) +Ping! (10) Pong! (10) Done! There is also a Unit Test Suite that will run the PingPongRightTest -file included in the test/edu/vuum/mooca directory for you at. When +file included in the test/edu/vuum/mooca directory for you at. When you first open the project in Eclipse, you might see compile errors if -JUnit is not included in your build path. To fix these errors, open +JUnit is not included in your build path. To fix these errors, open SynchronizedQueueTest.java, hover over "org.junit," and click "Fix -project setup." Make sure "Add JUnit 4 library to the build path" is -selected and then click "OK." At this point, the compile errors +project setup." Make sure "Add JUnit 4 library to the build path" is +selected and then click "OK." At this point, the compile errors should disappear! Right click on the PingPongRightTest.java file in Eclipse and select 'Run As' -> 'JUnit Test'. When the assignment is complete, the test -should complete successfully. If the test passes a green-check mark -will appear next to the test in the JUnit view. As long as this JUnit +should complete successfully. If the test passes a green-check mark +will appear next to the test in the JUnit view. As long as this JUnit test "passes" successfully your program will be be consider "correct" -for the purposes of assessing this assignment. - +for the purposes of assessing this assignment. \ No newline at end of file diff --git a/assignments/week-4-assignment-3/src/PingPongRight.java b/assignments/week-4-assignment-3/src/PingPongRight.java new file mode 100644 index 000000000..aabd5082d --- /dev/null +++ b/assignments/week-4-assignment-3/src/PingPongRight.java @@ -0,0 +1,119 @@ +// Import the necessary Java synchronization and scheduling classes. + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Semaphore; + +/** + * @class PingPongRight + * + * @brief This class implements a Java program that creates two + * instances of the PlayPingPongThread and start these thread + * instances to correctly alternate printing "Ping" and "Pong", + * respectively, on the console display. + */ +public class PingPongRight { + /** + * Number of iterations to run the test program. + */ + public static int mMaxIterations = 10; + + /** + * Latch that will be decremented each time a thread exits. + */ + public static CountDownLatch latch = new CountDownLatch(2); // TODO - You fill in here + + /** + * @class PlayPingPongThread + * + * @brief This class implements the ping/pong processing algorithm + * using the SimpleSemaphore to alternate printing "ping" + * and "pong" to the console display. + */ + public static class PlayPingPongThread extends Thread + { + private final static int FIRST_SEMA = 0; + private final static int SECOND_SEMA = 1; + /** + * Constructor initializes the data member. + */ + public PlayPingPongThread (/* TODO - You fill in here */ + SimpleSemaphore firstSema, SimpleSemaphore secondSema, String mStringToPrint) + { + // TODO - You fill in here. + mSemaphores[FIRST_SEMA] = firstSema; + mSemaphores[SECOND_SEMA] = secondSema; + this.mStringToPrint = mStringToPrint; + } + + /** + * Main event loop that runs in a separate thread of control + * and performs the ping/pong algorithm using the + * SimpleSemaphores. + */ + public void run () + { + // TODO - You fill in here. + for (int loopsDone = 1; loopsDone <= mMaxIterations; ++loopsDone) { + mSemaphores[FIRST_SEMA].acquireUninterruptibly(); + System.out.println(mStringToPrint + "(" + loopsDone + ")"); + mSemaphores[SECOND_SEMA].release(); + } + latch.countDown(); + } + + /** + * String to print (either "ping!" or "pong"!) for each + * iteration. + */ + // TODO - You fill in here. + private String mStringToPrint; + + /** + * The two SimpleSemaphores use to alternate pings and pongs. + */ + // TODO - You fill in here. + private SimpleSemaphore mSemaphores[] = new SimpleSemaphore[2]; + } + + /** + * The main() entry point method into PingPongRight program. + */ + public static void main(String[] args) { + try { + // Create the ping and pong SimpleSemaphores that control + // alternation between threads. + + // TODO - You fill in here. + SimpleSemaphore pingSema = new SimpleSemaphore(1, true); + SimpleSemaphore pongSema = new SimpleSemaphore(0, true); + + System.out.println("Ready...Set...Go!"); + + // Create the ping and pong threads, passing in the string + // to print and the appropriate SimpleSemaphores. + PlayPingPongThread ping = + new PlayPingPongThread(/* TODO - You fill in here */ + pingSema, pongSema, "ping"); + PlayPingPongThread pong = + new PlayPingPongThread(/* TODO - You fill in here */ + pongSema, pingSema, "pong"); + + // Initiate the ping and pong threads, which will call the + // run() hook method. + ping.start(); + pong.start(); + + // Use barrier synchronization to wait for both threads to + // finish. + + // TODO - replace replace the following line with a + // CountDownLatch barrier synchronizer call that waits for + // both threads to finish. + latch.await(); + } + catch (java.lang.InterruptedException e) + {} + + System.out.println("Done!"); + } +} diff --git a/assignments/week-4-assignment-3/src/SimpleSemaphore.java b/assignments/week-4-assignment-3/src/SimpleSemaphore.java new file mode 100644 index 000000000..ebcbd51f9 --- /dev/null +++ b/assignments/week-4-assignment-3/src/SimpleSemaphore.java @@ -0,0 +1,106 @@ +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.Condition; + +/** + * @class SimpleSemaphore + * + * @brief This class provides a simple counting semaphore + * implementation using Java a ReentrantLock and a + * ConditionObject. It must implement both "Fair" and + * "NonFair" semaphore semantics, just liked Java Semaphores. + */ +public class SimpleSemaphore { + /** + * Define a ReentrantLock to protect the critical section. + */ + // TODO - you fill in here + private ReentrantLock lock; + /** + * Define a ConditionObject to wait while the number of + * permits is 0. + */ + // TODO - you fill in here + private Condition condition; + /** + * Define a count of the number of available permits. + */ + // TODO - you fill in here. Make sure that this data member will + // ensure its values aren't cached by multiple Threads.. + private volatile int permits; + /** + * Constructor initialize the data members. + */ + public SimpleSemaphore (int permits, + boolean fair) + { + // TODO - you fill in here + this.permits = permits; + lock = new ReentrantLock(fair); + condition = lock.newCondition(); + } + + /** + * Acquire one permit from the semaphore in a manner that can + * be interrupted. + */ + public void acquire() throws InterruptedException { + // TODO - you fill in here + lock.lockInterruptibly(); + try{ + while(permits == 0){ + condition.await(); + } + permits = permits - 1; + }finally{ + lock.unlock(); + } + } + + /** + * Acquire one permit from the semaphore in a manner that + * cannot be interrupted. + */ + public void acquireUninterruptibly() { + // TODO - you fill in here + lock.lock(); + try{ + while(permits == 0){ + condition.awaitUninterruptibly(); + } + permits = permits - 1; + }finally{ + lock.unlock(); + } + } + + /** + * Return one permit to the semaphore. + */ + void release() { + // TODO - you fill in here + lock.lock(); + try{ + permits = permits + 1; + condition.signalAll(); + }finally{ + lock.unlock(); + } + } + + /** + * Return the number of permits available. + */ + public int availablePermits(){ + // TODO - you fill in here + int result = 0; + lock.lock(); + try{ + result = permits; + }finally{ + lock.unlock(); + } + return result; // You will change this value. + } +} + diff --git a/assignments/week-4-assignment-3/src/edu/vuum/mocca/PingPongRight.java b/assignments/week-4-assignment-3/src/edu/vuum/mocca/PingPongRight.java index 4fd24024f..142b72ae4 100644 --- a/assignments/week-4-assignment-3/src/edu/vuum/mocca/PingPongRight.java +++ b/assignments/week-4-assignment-3/src/edu/vuum/mocca/PingPongRight.java @@ -1,157 +1,175 @@ package edu.vuum.mocca; + // Import the necessary Java synchronization and scheduling classes. import java.util.concurrent.CountDownLatch; /** * @class PingPongRight - * + * * @brief This class implements a Java program that creates two - * instances of the PlayPingPongThread and start these thread - * instances to correctly alternate printing "Ping" and "Pong", - * respectively, on the console display. + * instances of the PlayPingPongThread and start these thread + * instances to correctly alternate printing "Ping" and "Pong", + * respectively, on the console display. */ public class PingPongRight { - /** - * Number of iterations to run the test program. - */ - public final static int mMaxIterations = 10; - - /** - * Latch that will be decremented each time a thread exits. - */ - public static CountDownLatch mLatch = null; - - /** - * @class PlayPingPongThread - * - * @brief This class implements the ping/pong processing algorithm - * using the SimpleSemaphore to alternate printing "ping" - * and "pong" to the console display. - */ - public static class PlayPingPongThread extends Thread { - /** - * Constants to distinguish between ping and pong - * SimpleSemaphores, if you choose to use an array of - * SimpleSemaphores. If you don't use this implementation - * feel free to remove these constants. - */ - private final static int FIRST_SEMA = 0; - private final static int SECOND_SEMA = 1; - - /** - * Maximum number of loop iterations. - */ - private int mMaxLoopIterations = 0; - - /** - * String to print (either "ping!" or "pong"!) for each - * iteration. - */ - // TODO - You fill in here. - - /** - * Two SimpleSemaphores use to alternate pings and pongs. You - * can use an array of SimpleSemaphores or just define them as - * two data members. - */ - // TODO - You fill in here. - - /** - * Constructor initializes the data member(s). - */ - public PlayPingPongThread(String stringToPrint, - SimpleSemaphore semaphoreOne, - SimpleSemaphore semaphoreTwo, - int maxIterations) { - // TODO - You fill in here. - } - - /** - * Main event loop that runs in a separate thread of control - * and performs the ping/pong algorithm using the - * SimpleSemaphores. - */ - public void run() { - /** - * This method runs in a separate thread of control and - * implements the core ping/pong algorithm. - */ - - // TODO - You fill in here. - } - - /** - * Method for acquiring the appropriate SimpleSemaphore. - */ - private void acquire() { - // TODO fill in here - } - - /** - * Method for releasing the appropriate SimpleSemaphore. - */ - private void release() { - // TODO fill in here - } - } - - /** - * The method that actually runs the ping/pong program. - */ - public static void process(String startString, - String pingString, - String pongString, - String finishString, - int maxIterations) throws InterruptedException { - - // TODO initialize this by replacing null with the appropriate - // constructor call. - mLatch = null; - - // Create the ping and pong SimpleSemaphores that control - // alternation between threads. - - // TODO - You fill in here, make pingSema start out unlocked. - SimpleSemaphore pingSema = null; - // TODO - You fill in here, make pongSema start out locked. - SimpleSemaphore pongSema = null; - - System.out.println(startString); - - // Create the ping and pong threads, passing in the string to - // print and the appropriate SimpleSemaphores. - PlayPingPongThread ping = new PlayPingPongThread(/* - * TODO - You fill in - * here - */); - PlayPingPongThread pong = new PlayPingPongThread(/* - * TODO - You fill in - * here - */); - - // TODO - Initiate the ping and pong threads, which will call - // the run() hook method. - - // TODO - replace the following line with a barrier - // synchronizer call to mLatch that waits for both threads to - // finish. - throw new java.lang.InterruptedException(); - - System.out.println(finishString); - } - - /** - * The main() entry point method into PingPongRight program. - * - * @throws InterruptedException - */ - public static void main(String[] args) throws InterruptedException { - process("Ready...Set...Go!", - "Ping! ", - " Pong! ", - "Done!", - mMaxIterations); - } -} - + /** + * Number of iterations to run the test program. + */ + public final static int mMaxIterations = 10; + + /** + * Latch that will be decremented each time a thread exits. + */ + public static CountDownLatch mLatch = null; + + /** + * @class PlayPingPongThread + * + * @brief This class implements the ping/pong processing algorithm + * using the SimpleSemaphore to alternate printing "ping" + * and "pong" to the console display. + */ + public static class PlayPingPongThread extends Thread { + /** + * Constants to distinguish between ping and pong + * SimpleSemaphores, if you choose to use an array of + * SimpleSemaphores. If you don't use this implementation + * feel free to remove these constants. + */ + private final static int FIRST_SEMA = 0; + private final static int SECOND_SEMA = 1; + + /** + * Maximum number of loop iterations. + */ + private int mMaxLoopIterations = 0; + + /** + * String to print (either "ping!" or "pong"!) for each + * iteration. + */ + // TODO - You fill in here. + private String mStringToPrint; + + /** + * Two SimpleSemaphores use to alternate pings and pongs. You + * can use an array of SimpleSemaphores or just define them as + * two data members. + */ + // TODO - You fill in here. + private SimpleSemaphore mSemaphores[] = new SimpleSemaphore[2]; + + /** + * Constructor initializes the data member(s). + */ + public PlayPingPongThread(String stringToPrint, + SimpleSemaphore semaphoreOne, + SimpleSemaphore semaphoreTwo, + int maxIterations) { + // TODO - You fill in here. + mStringToPrint = stringToPrint; + mSemaphores[FIRST_SEMA] = semaphoreOne; + mSemaphores[SECOND_SEMA] = semaphoreTwo; + mMaxLoopIterations = maxIterations; + } + + /** + * Main event loop that runs in a separate thread of control + * and performs the ping/pong algorithm using the + * SimpleSemaphores. + */ + public void run() { + /** + * This method runs in a separate thread of control and + * implements the core ping/pong algorithm. + */ + + // TODO - You fill in here. + for (int loopsDone = 1; loopsDone <= mMaxLoopIterations; ++loopsDone) { + acquire(); + System.out.println(mStringToPrint + "(" + loopsDone + ")"); + release(); + } + mLatch.countDown(); + } + + /** + * Method for acquiring the appropriate SimpleSemaphore. + */ + private void acquire() { + // TODO fill in here + mSemaphores[FIRST_SEMA].acquireUninterruptibly(); + } + + /** + * Method for releasing the appropriate SimpleSemaphore. + */ + private void release() { + // TODO fill in here + mSemaphores[SECOND_SEMA].release(); + } + } + + /** + * The method that actually runs the ping/pong program. + */ + public static void process(String startString, + String pingString, + String pongString, + String finishString, + int maxIterations) throws InterruptedException { + + // TODO initialize this by replacing null with the appropriate + // constructor call. + mLatch = new CountDownLatch(2); + + // Create the ping and pong SimpleSemaphores that control + // alternation between threads. + + // TODO - You fill in here, make pingSema start out unlocked. + SimpleSemaphore pingSema = new SimpleSemaphore(1, true); + // TODO - You fill in here, make pongSema start out locked. + SimpleSemaphore pongSema = new SimpleSemaphore(0, true); + + System.out.println(startString); + + // Create the ping and pong threads, passing in the string to + // print and the appropriate SimpleSemaphores. + PlayPingPongThread ping = new PlayPingPongThread(/* + * TODO - You fill in + * here + */ + pingString, pingSema, pongSema, maxIterations); + PlayPingPongThread pong = new PlayPingPongThread(/* + * TODO - You fill in + * here + */ + pongString, pongSema, pingSema, maxIterations); + + // TODO - Initiate the ping and pong threads, which will call + // the run() hook method. + ping.start(); + pong.start(); + + // TODO - replace the following line with a barrier + // synchronizer call to mLatch that waits for both threads to + // finish. + mLatch.await(); + + System.out.println(finishString); + } + + /** + * The main() entry point method into PingPongRight program. + * + * @throws InterruptedException + */ + public static void main(String[] args) throws InterruptedException { + process("Ready...Set...Go!", + "Ping! ", + " Pong! ", + "Done!", + mMaxIterations); + } +} \ No newline at end of file diff --git a/assignments/week-4-assignment-3/src/edu/vuum/mocca/SimpleSemaphore.java b/assignments/week-4-assignment-3/src/edu/vuum/mocca/SimpleSemaphore.java index 5e473adf6..d11e28258 100644 --- a/assignments/week-4-assignment-3/src/edu/vuum/mocca/SimpleSemaphore.java +++ b/assignments/week-4-assignment-3/src/edu/vuum/mocca/SimpleSemaphore.java @@ -1,66 +1,108 @@ package edu.vuum.mocca; -import java.util.concurrent.locks.Condition; + import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.Condition; /** * @class SimpleSemaphore - * - * @brief This class provides a simple counting semaphore implementation using - * Java a ReentrantLock and a ConditionObject (which is accessed via a - * Condition). It must implement both "Fair" and "NonFair" semaphore - * semantics, just liked Java Semaphores. + * + * @brief This class provides a simple counting semaphore + * implementation using Java a ReentrantLock and a + * ConditionObject. It must implement both "Fair" and + * "NonFair" semaphore semantics, just liked Java Semaphores. */ public class SimpleSemaphore { /** * Define a ReentrantLock to protect the critical section. */ // TODO - you fill in here - + private ReentrantLock lock; /** - * Define a Condition that waits while the number of permits is 0. + * Define a ConditionObject to wait while the number of + * permits is 0. */ // TODO - you fill in here - + private Condition condition; /** * Define a count of the number of available permits. */ - // TODO - you fill in here. Make sure that this data member will + // TODO - you fill in here. Make sure that this data member will // ensure its values aren't cached by multiple Threads.. - - public SimpleSemaphore(int permits, boolean fair) { - // TODO - you fill in here to initialize the SimpleSemaphore, - // making sure to allow both fair and non-fair Semaphore - // semantics. + private volatile int permits; + /** + * Constructor initialize the data members. + */ + public SimpleSemaphore (int permits, + boolean fair) + { + // TODO - you fill in here + this.permits = permits; + lock = new ReentrantLock(fair); + condition = lock.newCondition(); } /** - * Acquire one permit from the semaphore in a manner that can be - * interrupted. + * Acquire one permit from the semaphore in a manner that can + * be interrupted. */ public void acquire() throws InterruptedException { - // TODO - you fill in here. + // TODO - you fill in here + lock.lockInterruptibly(); + try{ + while(permits == 0){ + condition.await(); + } + permits = permits - 1; + }finally{ + lock.unlock(); + } } /** - * Acquire one permit from the semaphore in a manner that cannot be - * interrupted. + * Acquire one permit from the semaphore in a manner that + * cannot be interrupted. */ public void acquireUninterruptibly() { - // TODO - you fill in here. + // TODO - you fill in here + lock.lock(); + try{ + while(permits == 0){ + condition.awaitUninterruptibly(); + } + permits = permits - 1; + }finally{ + lock.unlock(); + } } /** * Return one permit to the semaphore. */ void release() { - // TODO - you fill in here. + // TODO - you fill in here + lock.lock(); + try{ + permits = permits + 1; + condition.signalAll(); + }finally{ + lock.unlock(); + } } - + /** * Return the number of permits available. */ - public int availablePermits() { - // TODO - you fill in here to return the correct result - return 0; + public int availablePermits(){ + // TODO - you fill in here + int result = 0; + lock.lock(); + try{ + result = permits; + }finally{ + lock.unlock(); + } + return result; // You will change this value. } } + diff --git a/assignments/week-4-assignment-3/test/edu/vuum/mocca/PingPongRightTest.java b/assignments/week-4-assignment-3/test/edu/vuum/mocca/PingPongRightTest.java index 5148fba59..964fb0e37 100644 --- a/assignments/week-4-assignment-3/test/edu/vuum/mocca/PingPongRightTest.java +++ b/assignments/week-4-assignment-3/test/edu/vuum/mocca/PingPongRightTest.java @@ -12,89 +12,89 @@ /** * @class PingPongRightTest - * + * * @brief This JUnit test checks the PingPong program to make sure it's working - * properly. + * properly. */ public class PingPongRightTest { - /* - * These data members are used to capture [ - * System.out.println() ] for testing. - */ - private final ByteArrayOutputStream outContent = - new ByteArrayOutputStream(); - private final ByteArrayOutputStream errContent = - new ByteArrayOutputStream(); + /* + * These data members are used to capture [ + * System.out.println() ] for testing. + */ + private final ByteArrayOutputStream outContent = + new ByteArrayOutputStream(); + private final ByteArrayOutputStream errContent = + new ByteArrayOutputStream(); - /* - * Setup the output Capturing. - */ - @Before - public void setUpStreams() { - System.setOut(new PrintStream(outContent)); - System.setErr(new PrintStream(errContent)); - } + /* + * Setup the output Capturing. + */ + @Before + public void setUpStreams() { + System.setOut(new PrintStream(outContent)); + System.setErr(new PrintStream(errContent)); + } - /* - * Tear-down the output Capturing. - */ - @After - public void cleanUpStreams() { - System.setOut(null); - System.setErr(null); - } + /* + * Tear-down the output Capturing. + */ + @After + public void cleanUpStreams() { + System.setOut(null); + System.setErr(null); + } - /* - * Test the process(...) logic/accuracy - * - * Gives some helpful error outputs for some simple error states. - */ - @Test(timeout = 3000) - // This test will only run for 3000ms => 3 seconds, otherwise if fails - public void test() throws InterruptedException, IOException { - for (int i = 0; i < 10; i++) { - PingPongRight.process("start", "a", "b", "end", 10); - String outResults = outContent.toString(); + /* + * Test the process(...) logic/accuracy + * + * Gives some helpful error outputs for some simple error states. + */ + @Test(timeout = 3000) + // This test will only run for 3000ms => 3 seconds, otherwise if fails + public void test() throws InterruptedException, IOException { + for (int i = 0; i < 10; i++) { + PingPongRight.process("start", "a", "b", "end", 10); + String outResults = outContent.toString(); - if (outResults == null || outResults.length() == 0) { - fail("No output at all."); - } + if (outResults == null || outResults.length() == 0) { + fail("No output at all."); + } - //We need to split things up for Windows and UNIX due to - //differences in the way that newlines are handled. - boolean windowsTrue = outResults.equals(testResultWindows); - boolean unixTrue = outResults.equals(testResultUnix); - boolean pingAllFirstTrue = outResults.equals(pingAllFirst); - boolean pongAllFirstTrue = outResults.equals(pongAllFirst); + //We need to split things up for Windows and UNIX due to + //differences in the way that newlines are handled. + boolean windowsTrue = outResults.equals(testResultWindows); + boolean unixTrue = outResults.equals(testResultUnix); + boolean pingAllFirstTrue = outResults.equals(pingAllFirst); + boolean pongAllFirstTrue = outResults.equals(pongAllFirst); - if (errContent.toString().length() != 0) - fail("There was error text."); + if (errContent.toString().length() != 0) + fail("There was error text."); - if (pingAllFirstTrue) - fail("Ping Thread completed before Pong started."); + if (pingAllFirstTrue) + fail("Ping Thread completed before Pong started."); - if (pongAllFirstTrue) - fail("Pong Thread completed before Ping started."); + if (pongAllFirstTrue) + fail("Pong Thread completed before Ping started."); - if (!(windowsTrue || unixTrue)) - fail("Output was wrong.\n" - + "--- Received output ---\n" - + outResults - + "--- Expected output ---\n" - + testResultWindows); + if (!(windowsTrue || unixTrue)) + fail("Output was wrong.\n" + + "--- Received output ---\n" + + outResults + + "--- Expected output ---\n" + + testResultWindows); - outContent.reset(); - } - } + outContent.reset(); + } + } - // This is what should be output \n was replaced for visible - // endlines for inclusion into single line. - String testResultUnix = - "start\na(1)\nb(1)\na(2)\nb(2)\na(3)\nb(3)\na(4)\nb(4)\na(5)\nb(5)\na(6)\nb(6)\na(7)\nb(7)\na(8)\nb(8)\na(9)\nb(9)\na(10)\nb(10)\nend\n"; - String testResultWindows = - "start\r\na(1)\r\nb(1)\r\na(2)\r\nb(2)\r\na(3)\r\nb(3)\r\na(4)\r\nb(4)\r\na(5)\r\nb(5)\r\na(6)\r\nb(6)\r\na(7)\r\nb(7)\r\na(8)\r\nb(8)\r\na(9)\r\nb(9)\r\na(10)\r\nb(10)\r\nend\r\n"; - String pingAllFirst = - "start\r\na(1)\r\nb(1)\r\na(2)\r\na(3)\r\na(4)\r\na(5)\r\na(6)\r\na(7)\r\na(8)\r\na(9)\r\na(10)\r\nb(2)\r\nb(3)\r\nb(4)\r\nb(5)\r\nb(6)\r\nb(8)\r\nb(7)\r\nb(9)\r\nb(10)\r\nend\r\n"; - String pongAllFirst = - "start\r\nb(1)\r\nb(2)\r\nb(3)\r\nb(4)\r\nb(5)\r\nb(6)\r\nb(8)\r\nb(7)\r\nb(9)\r\nb(10)\r\na(1)\r\na(2)\r\na(3)\r\na(4)\r\na(5)\r\na(6)\r\na(7)\r\na(8)\r\na(9)\r\na(10)\r\nend\r\n"; -} + // This is what should be output \n was replaced for visible + // endlines for inclusion into single line. + String testResultUnix = + "start\na(1)\nb(1)\na(2)\nb(2)\na(3)\nb(3)\na(4)\nb(4)\na(5)\nb(5)\na(6)\nb(6)\na(7)\nb(7)\na(8)\nb(8)\na(9)\nb(9)\na(10)\nb(10)\nend\n"; + String testResultWindows = + "start\r\na(1)\r\nb(1)\r\na(2)\r\nb(2)\r\na(3)\r\nb(3)\r\na(4)\r\nb(4)\r\na(5)\r\nb(5)\r\na(6)\r\nb(6)\r\na(7)\r\nb(7)\r\na(8)\r\nb(8)\r\na(9)\r\nb(9)\r\na(10)\r\nb(10)\r\nend\r\n"; + String pingAllFirst = + "start\r\na(1)\r\nb(1)\r\na(2)\r\na(3)\r\na(4)\r\na(5)\r\na(6)\r\na(7)\r\na(8)\r\na(9)\r\na(10)\r\nb(2)\r\nb(3)\r\nb(4)\r\nb(5)\r\nb(6)\r\nb(8)\r\nb(7)\r\nb(9)\r\nb(10)\r\nend\r\n"; + String pongAllFirst = + "start\r\nb(1)\r\nb(2)\r\nb(3)\r\nb(4)\r\nb(5)\r\nb(6)\r\nb(8)\r\nb(7)\r\nb(9)\r\nb(10)\r\na(1)\r\na(2)\r\na(3)\r\na(4)\r\na(5)\r\na(6)\r\na(7)\r\na(8)\r\na(9)\r\na(10)\r\nend\r\n"; +} \ No newline at end of file diff --git a/ex/ThreadedDownload/.classpath b/ex/ThreadedDownload/.classpath index c06dfcb8e..d57ec0251 100644 --- a/ex/ThreadedDownload/.classpath +++ b/ex/ThreadedDownload/.classpath @@ -1,9 +1,9 @@ - - + +