CP — Concurrent Programming 9. Condition Objects Prof. O. Nierstrasz Wintersemester 2005 / 2006.

Slides:



Advertisements
Similar presentations
Operating Systems Semaphores II
Advertisements

Operating Systems: Monitors 1 Monitors (C.A.R. Hoare) higher level construct than semaphores a package of grouped procedures, variables and data i.e. object.
– R 7 :: 1 – 0024 Spring 2010 Parallel Programming 0024 Recitation Week 7 Spring Semester 2010.
Concurrency (p2) synchronized (this) { doLecture(part2); } synchronized (this) { doLecture(part2); }
Ch 7 B.
50.003: Elements of Software Construction Week 10 Thread Pool.
Ch. 7 Process Synchronization (1/2) I Background F Producer - Consumer process :  Compiler, Assembler, Loader, · · · · · · F Bounded buffer.
Silberschatz, Galvin and Gagne ©2009 Operating System Concepts – 8 th Edition, Chapter 6: Process Synchronization.
Process Synchronization. Module 6: Process Synchronization Background The Critical-Section Problem Peterson’s Solution Synchronization Hardware Semaphores.
5. Liveness and Guarded Methods Prof. O. Nierstrasz Selected material © Magee and Kramer.
Multithreaded Programs in Java. Tasks and Threads A task is an abstraction of a series of steps – Might be done in a separate thread – Java libraries.
Concurrency 101 Shared state. Part 1: General Concepts 2.
CS 5704 Fall 00 1 Monitors in Java Model and Examples.
CSC Multiprocessor Programming, Spring, 2011 Outline for Chapter 5 – Building Blocks – Library Classes, Dr. Dale E. Parson, week 5.
8. Condition Objects Prof. O. Nierstrasz Selected material © 2005 Bowbeer, Goetz, Holmes, Lea and Peierls.
CP — Concurrent Programming 8. Liveness and Asynchrony Prof. O. Nierstrasz Wintersemester 2005 / 2006.
7. Liveness and Asynchrony Prof. O. Nierstrasz. Roadmap  Asynchronous invocations  Simple Relays —Direct invocations —Thread-based messages —Command-based.
Threading Part 4 CS221 – 4/27/09. The Final Date: 5/7 Time: 6pm Duration: 1hr 50mins Location: EPS 103 Bring: 1 sheet of paper, filled both sides with.
10. Petri Nets Prof. O. Nierstrasz. Roadmap  Definition: —places, transitions, inputs, outputs —firing enabled transitions  Modelling: —concurrency.
ESE Einführung in Software Engineering N. XXX Prof. O. Nierstrasz Fall Semester 2009.
5.6 Semaphores Semaphores –Software construct that can be used to enforce mutual exclusion –Contains a protected variable Can be accessed only via wait.
CP — Concurrent Programming 12. Petri Nets Prof. O. Nierstrasz Wintersemester 2005 / 2006.
Metamodeling Seminar X. CHAPTER Prof. O. Nierstrasz Spring Semester 2008.
8. Condition Objects Prof. O. Nierstrasz Selected material © 2005 Bowbeer, Goetz, Holmes, Lea and Peierls.
ESE Einführung in Software Engineering X. CHAPTER Prof. O. Nierstrasz Wintersemester 2005 / 2006.
N. XXX Prof. O. Nierstrasz Thanks to Jens Palsberg and Tony Hosking for their kind permission to reuse and adapt the CS132 and CS502 lecture notes.
Semaphores CSCI 444/544 Operating Systems Fall 2008.
CP — Concurrent Programming 3. Safety and Synchronization Prof. O. Nierstrasz Wintersemester 2005 / 2006.
7. Liveness and Asynchrony Prof. O. Nierstrasz. Roadmap  Asynchronous invocations  Simple Relays —Direct invocations —Thread-based messages —Command-based.
Java 5 Threading CSE301 University of Sunderland Harry Erwin, PhD.
OORPT Object-Oriented Reengineering Patterns and Techniques X. CHAPTER Prof. O. Nierstrasz.
CP — Concurrent Programming X. CHAPTER Prof. O. Nierstrasz Wintersemester 2005 / 2006.
1 Thread Pools. 2 What’s A Thread Pool? A programming technique which we will use. A collection of threads that are created once (e.g. when server starts).
12. eToys. © O. Nierstrasz PS — eToys 12.2 Denotational Semantics Overview:  … References:  …
Threads in Java1 Concurrency Synchronizing threads, thread pools, etc.
1 CSCI 6900: Design, Implementation, and Verification of Concurrent Software Eileen Kraemer August 19 th, 2010 The University of Georgia.
Week 9 Building blocks.
Parallel Processing (CS526) Spring 2012(Week 8).  Thread Status.  Synchronization in Shared Memory Programming(Java threads ) ◦ Locks ◦ Barriars.
Threads some important concepts Simon Lynch
Threads in Java. History  Process is a program in execution  Has stack/heap memory  Has a program counter  Multiuser operating systems since the sixties.
Semaphores, Locks and Monitors By Samah Ibrahim And Dena Missak.
1 (Worker Queues) cs What is a Thread Pool? A collection of threads that are created once (e.g. when a server starts) That is, no need to create.
1 Threads  Sequential Execution: Here statements are executed one after the other.They consider only a single thread of execution, where thread is an.
Java Threads 1 1 Threading and Concurrent Programming in Java Queues D.W. Denbo.
Practice Session 8 Blocking queues Producers-Consumers pattern Semaphore Futures and Callables Advanced Thread Synchronization Methods CountDownLatch Thread.
CSC321 Concurrent Programming: §5 Monitors 1 Section 5 Monitors.
Synchronizing threads, thread pools, etc.
Concurrency in Java Brad Vander Zanden. Processes and Threads Process: A self-contained execution environment Thread: Exists within a process and shares.
1 CSCI 6900: Design, Implementation, and Verification of Concurrent Software Eileen Kraemer August 24 th, 2010 The University of Georgia.
Multithreading Chapter Introduction Consider ability of human body to ___________ –Breathing, heartbeat, chew gum, walk … In many situations we.
Advanced Concurrency Topics Nelson Padua-Perez Bill Pugh Department of Computer Science University of Maryland, College Park.
SPL/2010 Guarded Methods and Waiting 1. SPL/2010 Reminder! ● Concurrency problem: asynchronous modifications to object states lead to failure of thread.
Threads in Java1 Concurrency Synchronizing threads, thread pools, etc.
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display. Concurrency & Dynamic Programming.
Monitors and Blocking Synchronization Dalia Cohn Alperovich Based on “The Art of Multiprocessor Programming” by Herlihy & Shavit, chapter 8.
1 Condition Variables CS 241 Prof. Brighten Godfrey March 16, 2012 University of Illinois.
CP — Concurrent Programming 6. Liveness and Guarded Methods Prof. O. Nierstrasz Wintersemester 2005 / 2006.
Advanced Tools for Multi- Threads Programming Avshalom Elmalech Eliahu Khalastchi 2010.
…in java DThread Pools x. Thread Pools: Why? Source code updates – copy/paste of run/runnable method for each thread is exhausting There is overhead to.
Java.util.concurrent package. concurrency utilities packages provide a powerful, extensible framework of high-performance threading utilities such as.
Thread Pools (Worker Queues) cs
Background on the need for Synchronization
Practice Session 8 Lockfree LinkedList Blocking queues
Lecture 25 More Synchronized Data and Producer/Consumer Relationship
Condition Variables and Producer/Consumer
Condition Variables and Producer/Consumer
CSE 153 Design of Operating Systems Winter 19
Software Engineering and Architecture
CSE 542: Operating Systems
some important concepts
Presentation transcript:

CP — Concurrent Programming 9. Condition Objects Prof. O. Nierstrasz Wintersemester 2005 / 2006

© Oscar Nierstrasz CP — Condition Objects CP 9.2 Condition Objects Overview  Condition Objects —Simple Condition Objects —The “Nested Monitor Problem” —Permits and Semaphores —Using Semaphores  JUC (java.util.concurrent) Selected material © 2005 Bowbeer, Goetz, Holmes, Lea and Peierls

© Oscar Nierstrasz CP — Condition Objects CP 9.3 Pattern: Condition Objects Intent: Condition objects encapsulate the waits and notifications used in guarded methods. Applicability  To simplify class design by off-loading waiting and notification mechanics. —Because of the limitations surrounding the use of condition objects in Java, in some cases the use of condition objects will increase rather than decrease design complexity!  As an efficiency manoeuvre. —By isolating conditions, you can often avoid notifying waiting threads that could not possibly proceed given a particular state change.  As a means of encapsulating special scheduling policies surrounding notifications, for example to impose fairness or prioritization policies.  In the particular cases where conditions take the form of “permits” or “latches”.

© Oscar Nierstrasz CP — Condition Objects CP 9.4 Condition Objects A client that awaits a condition blocks until another object signals that the condition now may hold. public interface Condition { public void await ();// wait for some condition public void signal ();// signal that condition } public interface Condition { public void await ();// wait for some condition public void signal ();// signal that condition } Cf. java.util.concurrent.locks.Condition

© Oscar Nierstrasz CP — Condition Objects CP 9.5 A Simple Condition Object We can encapsulate guard conditions with this class: public class SimpleConditionObject implements Condition { public synchronized void await () { try { wait(); } catch (InterruptedException ex) {} } public synchronized void signal () { notifyAll (); } public class SimpleConditionObject implements Condition { public synchronized void await () { try { wait(); } catch (InterruptedException ex) {} } public synchronized void signal () { notifyAll (); } NB: Careless use can lead to the “Nested Monitor Problem”

© Oscar Nierstrasz CP — Condition Objects CP 9.6 The Nested Monitor problem We want to avoid waking up the wrong threads by separately notifying the conditions notMin and notMax: public class BoundedCounterVBAD implements BoundedCounter { protected long count_ = MIN; protected Condition notMin_ = new SimpleConditionObject(); protected Condition notMax_ = new SimpleConditionObject(); public synchronized long value() { return count_; }... public class BoundedCounterVBAD implements BoundedCounter { protected long count_ = MIN; protected Condition notMin_ = new SimpleConditionObject(); protected Condition notMax_ = new SimpleConditionObject(); public synchronized long value() { return count_; }...

© Oscar Nierstrasz CP — Condition Objects CP 9.7 public synchronized void dec() { while (count_ == MIN) notMin_.await();// wait till count not MIN if (count_-- == MAX) notMax_.signal(); } public synchronized void inc() {// can’t get in! while (count_ == MAX) notMax_.await(); if (count_++ == MIN) notMin_.signal();// we never get here! } public synchronized void dec() { while (count_ == MIN) notMin_.await();// wait till count not MIN if (count_-- == MAX) notMax_.signal(); } public synchronized void inc() {// can’t get in! while (count_ == MAX) notMax_.await(); if (count_++ == MIN) notMin_.signal();// we never get here! }

© Oscar Nierstrasz CP — Condition Objects CP 9.8 The Nested Monitor problem... Nested monitor lockouts occur whenever a blocked thread holds the lock for an object containing the method that would otherwise provide a notification to unblock the wait.

© Oscar Nierstrasz CP — Condition Objects CP 9.9 Nested Monitors in FSP Nested Monitors typically arise when one synchronized object is implemented using another. Recall our one Slot buffer in FSP: Suppose we try to implement a call/reply protocol using a private instance of Slot: const N = 2 Slot = (put[v:0..N] -> get[v] -> Slot). const N = 2 Slot = (put[v:0..N] -> get[v] -> Slot). ReplySlot=( put[v:0..N] -> my.put[v] -> ack -> ReplySlot | get -> my.get[v:0..N] -> ret[v] -> ReplySlot ). ReplySlot=( put[v:0..N] -> my.put[v] -> ack -> ReplySlot | get -> my.get[v:0..N] -> ret[v] -> ReplySlot ). 01

© Oscar Nierstrasz CP — Condition Objects CP 9.10 Nested Monitors in FSP... Our producer/consumer chain obeys the new protocol: 01 Producer = (put[0] -> ack ->put[1] -> ack ->put[2] -> ack -> Producer ). Consumer = ( get-> ret[x:0..N]->Consumer ). ||Chain = (Producer||ReplySlot||my:Slot||Consumer). Producer = (put[0] -> ack ->put[1] -> ack ->put[2] -> ack -> Producer ). Consumer = ( get-> ret[x:0..N]->Consumer ). ||Chain = (Producer||ReplySlot||my:Slot||Consumer).

© Oscar Nierstrasz CP — Condition Objects CP 9.11 Nested Monitors in FSP... But now the chain may deadlock: Progress violation for actions: {{ack, get}, my.{get, put}[0..2], {put, ret}[0..2]} Trace to terminal set of states: get Actions in terminal set: {} Progress violation for actions: {{ack, get}, my.{get, put}[0..2], {put, ret}[0..2]} Trace to terminal set of states: get Actions in terminal set: {} 01

© Oscar Nierstrasz CP — Condition Objects CP 9.12 Solving the Nested Monitors problem You must ensure that:  Waits do not occur while synchronization is held on the host object. —This leads to a guard loop that reverses the synchronization seen in the faulty version.  Notifications are never missed. —The entire guard wait loop should be enclosed within synchronized blocks on the condition object.  Notifications do not deadlock. —All notifications should be performed only upon release of all synchronization (except for the notified condition object).  Helper and host state must be consistent. —If the helper object maintains any state, it must always be consistent with that of the host, and if it shares any state with the host, that access is properly synchronized.

© Oscar Nierstrasz CP — Condition Objects CP 9.13 Example solution public class BoundedCounterVCV implements BoundedCounter { … public void dec() {// not synched! boolean wasMax = false;// record notification condition synchronized(notMin_) {// synch on condition object while (true) {// new guard loop synchronized(this) { if (count_ > MIN) {// check and act wasMax = (count_ == MAX); count_--; break; } notMin_.await();// release host synch before wait } if (wasMax) notMax_.signal();// release all synchs! } … } public class BoundedCounterVCV implements BoundedCounter { … public void dec() {// not synched! boolean wasMax = false;// record notification condition synchronized(notMin_) {// synch on condition object while (true) {// new guard loop synchronized(this) { if (count_ > MIN) {// check and act wasMax = (count_ == MAX); count_--; break; } notMin_.await();// release host synch before wait } if (wasMax) notMax_.signal();// release all synchs! } … }

© Oscar Nierstrasz CP — Condition Objects CP 9.14 Pattern: Permits and Semaphores Intent: Bundle synchronization in a condition object when synchronization depends on the value of a counter. Applicability  When any given await may proceed only if there have been more signals than awaits. —I.e., when await decrements and signal increments the number of available “permits”.  You need to guarantee the absence of missed signals. —Unlike simple condition objects, semaphores work even if one thread enters its await after another thread has signalled that it may proceed (!)  The host classes can arrange to invoke Condition methods outside of synchronized code.

© Oscar Nierstrasz CP — Condition Objects CP 9.15 Permits and Semaphores — design steps  Define a class implementing Condition that maintains a permit count, and immediately releases await if there are already enough permits. —e.g., BoundedCounter public class CountCondition implements Condition { protected BoundedCounter counter_ = new BoundedCounterV0(); public void await() { counter_.dec(); } public void signal() { counter_.inc(); } } public class CountCondition implements Condition { protected BoundedCounter counter_ = new BoundedCounterV0(); public void await() { counter_.dec(); } public void signal() { counter_.inc(); } }

© Oscar Nierstrasz CP — Condition Objects CP 9.16 Design steps...  As with all kinds of condition objects, their clients must avoid invoking await inside of synchronized code. —You can use a before/after design of the form: class Host { Condition aCondition_;... public method m1() { aCondition_.await();// not synched doM1();// synched for each Condition c enabled by m1() c.signal();// not synched } protected synchronized doM1() {... } } class Host { Condition aCondition_;... public method m1() { aCondition_.await();// not synched doM1();// synched for each Condition c enabled by m1() c.signal();// not synched } protected synchronized doM1() {... } }

© Oscar Nierstrasz CP — Condition Objects CP 9.17 Variants Permit Counters: (Counting Semaphores)  Just keep track of the number of “permits”  Can use notify instead of notifyAll if class is final Fair Semaphores:  Maintain FIFO queue of threads waiting on a SimpleCondition Locks and Latches:  Locks can be acquired and released in separate methods  Keep track of thread holding the lock so locks can be reentrant!  A latch is set to true by signal, and always stays true

© Oscar Nierstrasz CP — Condition Objects CP 9.18 Semaphores in Java public class Semaphore {// simple version private int value; public Semaphore (int initial) { value = initial; } synchronized public void up() {// AKA V ++value; notify();// wake up just one thread! } synchronized public void down() {// AKA P while (value==0) try { wait(); } catch(InterruptedException ex) { }; --value; } public class Semaphore {// simple version private int value; public Semaphore (int initial) { value = initial; } synchronized public void up() {// AKA V ++value; notify();// wake up just one thread! } synchronized public void down() {// AKA P while (value==0) try { wait(); } catch(InterruptedException ex) { }; --value; } Cf. java.util.concurrent.Semaphore

© Oscar Nierstrasz CP — Condition Objects CP 9.19 Using Semaphores public class BoundedCounterVSem implements BoundedCounter { … protected Semaphore mutex, full, empty; BoundedCounterVSem() { mutex = new Semaphore(1); full = new Semaphore(0);// number of items empty = new Semaphore(MAX-MIN); // number of slots } public long value() { mutex.down(); // grab the resource long val = count_; mutex.up(); // release it return val; } public void inc() { empty.down(); // grab a slot mutex.down(); count_ ++; mutex.up(); full.up(); // release an item } … public class BoundedCounterVSem implements BoundedCounter { … protected Semaphore mutex, full, empty; BoundedCounterVSem() { mutex = new Semaphore(1); full = new Semaphore(0);// number of items empty = new Semaphore(MAX-MIN); // number of slots } public long value() { mutex.down(); // grab the resource long val = count_; mutex.up(); // release it return val; } public void inc() { empty.down(); // grab a slot mutex.down(); count_ ++; mutex.up(); full.up(); // release an item } …

© Oscar Nierstrasz CP — Condition Objects CP 9.20 Using Semaphores... These would cause a nested monitor problem! … public void BADinc() { mutex.down(); empty.down(); // locks out BADdec! count_ ++; full.up(); mutex.up(); } public void BADdec() { mutex.down(); full.down(); // locks out BADinc! count_ --; empty.up(); mutex.up(); } … public void BADinc() { mutex.down(); empty.down(); // locks out BADdec! count_ ++; full.up(); mutex.up(); } public void BADdec() { mutex.down(); full.down(); // locks out BADinc! count_ --; empty.up(); mutex.up(); }

© Oscar Nierstrasz CP — Condition Objects CP 9.21 java.util.concurrent Executors —Executor —ExecutorService —ScheduledExecutorService —Callable —Future —ScheduledFuture —Delayed —CompletionService —ThreadPoolExecutor —ScheduledThreadPoolExecutor —AbstractExecutorService —Executors —FutureTask —ExecutorCompletionService Queues —BlockingQueue —ConcurrentLinkedQueue —LinkedBlockingQueue —ArrayBlockingQueue —SynchronousQueue —PriorityBlockingQueue —DelayQueue Concurrent Collections —ConcurrentMap —ConcurrentHashMap —CopyOnWriteArray{List,Set} Synchronizers —CountDownLatch —Semaphore —Exchanger —CyclicBarrier Locks: java.util.concurrent.locks —Lock —Condition —ReadWriteLock —AbstractQueuedSynchronizer —LockSupport —ReentrantLock —ReentrantReadWriteLock Atomics: java.util.concurrent.atomic —Atomic[Type] —Atomic[Type]Array —Atomic[Type]FieldUpdater —Atomic{Markable,Stampable}Reference © 2005 Bowbeer, Goetz, Holmes, Lea and Peierls

© Oscar Nierstrasz CP — Condition Objects CP 9.22 © 2005 Bowbeer, Goetz, Holmes, Lea and Peierls Key Functional Groups  Executors, Thread pools and Futures —Execution frameworks for asynchronous tasking  Concurrent Collections: —Queues, blocking queues, concurrent hash map, … —Data structures designed for concurrent environments  Locks and Conditions —More flexible synchronization control —Read/write locks  Synchronizers: Semaphore, Latch, Barrier —Ready made tools for thread coordination  Atomic variables —The key to writing lock-free algorithms

© Oscar Nierstrasz CP — Condition Objects CP 9.23 © 2005 Bowbeer, Goetz, Holmes, Lea and Peierls The Executor Framework  Framework for asynchronous task execution  Standardize asynchronous invocation —Framework to execute Runnable and Callable tasks – Runnable: void run() – Callable : V call() throws Exception  Separate submission from execution policy —Use anExecutor.execute(aRunnable) —Not new Thread(aRunnable).start()  Cancellation and shutdown support  Usually created via Executors factory class —Configures flexible ThreadPoolExecutor —Customize shutdown methods, before/after hooks, saturation policies, queuing

© Oscar Nierstrasz CP — Condition Objects CP 9.24 © 2005 Bowbeer, Goetz, Holmes, Lea and Peierls Executor  Decouple submission policy from task execution  Code which submits a task doesn't have to know in what thread the task will run —Could run in the calling thread, in a thread pool, in a single background thread (or even in another JVM!) —Executor implementation determines execution policy – Execution policy controls resource utilization, overload behavior, thread usage, logging, security, etc – Calling code need not know the execution policy public interface Executor { void execute(Runnable command); } public interface Executor { void execute(Runnable command); }

© Oscar Nierstrasz CP — Condition Objects CP 9.25 ExecutorService  Adds lifecycle management  ExecutorService supports both graceful and immediate shutdown public interface ExecutorService extends Executor { void shutdown(); List shutdownNow(); boolean isShutdown(); boolean isTerminated(); boolean awaitTermination(long timeout, TimeUnit unit); //... } public interface ExecutorService extends Executor { void shutdown(); List shutdownNow(); boolean isShutdown(); boolean isTerminated(); boolean awaitTermination(long timeout, TimeUnit unit); //... }  Useful utility methods too — T invokeAny(Collection > tasks) – Executes the given tasks returning the result of one that completed successfully (if any) —Others involving Future objects—covered later © 2005 Bowbeer, Goetz, Holmes, Lea and Peierls

© Oscar Nierstrasz CP — Condition Objects CP 9.26 © 2005 Bowbeer, Goetz, Holmes, Lea and Peierls Creating Executors  Sample Executor implementations from Executors  newSingleThreadExecutor —A pool of one, working from an unbounded queue  newFixedThreadPool(int N) —A fixed pool of N, working from an unbounded queue  newCachedThreadPool —A variable size pool that grows as needed and shrinks when idle  newScheduledThreadPool —Pool for executing tasks after a given delay, or periodically

© Oscar Nierstrasz CP — Condition Objects CP 9.27 Locks and Synchronizers  java.util.concurrent provides generally useful implementations —ReentrantLock, ReentrantReadWriteLock —Semaphore, CountDownLatch, Barrier, Exchanger —Should meet the needs of most users in most situations – Some customization possible in some cases by subclassing  Otherwise AbstractQueuedSynchronizer can be used to build custom locks and synchronizers —Within limitations: int state and FIFO queuing  Otherwise build from scratch —Atomics —Queues —LockSupport for thread parking/unparking © 2005 Bowbeer, Goetz, Holmes, Lea and Peierls

© Oscar Nierstrasz CP — Condition Objects CP 9.28 What you should know!  What are “condition objects”? How can they make your life easier? Harder?  What is the “nested monitor problem”?  How can you avoid nested monitor problems?  What are “permits” and “latches”? When is it natural to use them?  How does a semaphore differ from a simple condition object?  Why (when) can semaphores use notify() instead of notifyAll()?

© Oscar Nierstrasz CP — Condition Objects CP 9.29 Can you answer these questions?  Why doesn’t SimpleConditionObject need any instance variables?  What is the easiest way to avoid the nested monitor problem?  What assumptions do nested monitors violate?  How can the obvious implementation of semaphores (in Java) violate fairness?  How would you implement fair semaphores?

© Oscar Nierstrasz CP — Condition Objects CP 9.30 License > Attribution-ShareAlike 2.5 You are free: to copy, distribute, display, and perform the work to make derivative works to make commercial use of the work Under the following conditions: Attribution. You must attribute the work in the manner specified by the author or licensor. Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one. For any reuse or distribution, you must make clear to others the license terms of this work. Any of these conditions can be waived if you get permission from the copyright holder. Your fair use and other rights are in no way affected by the above. Attribution-ShareAlike 2.5 You are free: to copy, distribute, display, and perform the work to make derivative works to make commercial use of the work Under the following conditions: Attribution. You must attribute the work in the manner specified by the author or licensor. Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one. For any reuse or distribution, you must make clear to others the license terms of this work. Any of these conditions can be waived if you get permission from the copyright holder. Your fair use and other rights are in no way affected by the above.