Design Patterns in Operating Systems
A Word on Patterns These routinely appear as solutions to common classes of problems They can help in numerous ways Well known resuable solution with documentation Pitfalls known in advance Performance and testing known & done in advance Generally offer levels of abstraction to cope with complexity by decoupling events and actions
Patterns in Operating Systems There are many, and we’ll examine a few closely The Observer, The Decorator, The Active Object, The Façade, The Singleton, The Visitor, The Factory
Singletons Used to share access to a singular object Usually, it’s an error to create this object twice Examples: A teller’s transaction log, a kernel’s memory manager thread, rollbacks Can be used (somewhat sloppily) to provide global access to a shared resource What kinds of issues arise in a SMP environment? For more information, see problem 6.21 in the text
UML Singleton ------------------------------------------ Data: (1) private object instance Methods: private Singleton() public getInstance()
The Action in a Singleton public Object getInstance() { if(myInstance == null) { //lazy instantiation myInstance = new Object(); } return myInstance;
Singletons and SMP Architectures Race Condition public Object getInstance() { if(myInstance == null) { myInstance = new Object(); } return myInstance;
Double-Checked Lock Somewhat similar in spirit to Petersons, but more general Check for null Acquire my lock Check again for null, and if null instantiate
DC Action in Java public Object getInstance() { if(myInstance == null) { mutex.acquire(); If(myInstance == null) { myInstance = new Object(); } mutex.release(); return myInstance;
DC Action in Java public Object getInstance() { if(myInstance == null) { mutex.acquire(); If(myInstance == null) { myInstance = new Object(); } mutex.release(); return myInstance; Two parallel threads may both discover myInstance to be null But only one will acquire the lock So the thread in first will build the (1) object The second thread blocks here and when released, notices myInstance is no longer null
Rewrite using synchronized blocks public Object getInstance() { if(myInstance == null) { mutex.acquire(); If(myInstance == null) { myInstance = new Object(); } mutex.release(); return myInstance;
Rewrite using synchronized blocks public synchronized Object getInstance() { //if(myInstance == null) { //no need now for this //mutex.acquire(); If(myInstance == null) { myInstance = new Object(); } //mutex.release(); return myInstance;
Double-Checked Locking More information on our message board and at: http://www.cs.wustl.edu/~schmidt/PDF/DC-Locking.pdf
Spinlocks Versus Blocking TestAndSet usually is a spinlock Semaphores frequently are implemented as blocking When is one more appropriate? Which is heavyweight? Would we ever not want to spin?
Socket Programming -> Too Low Level? What’s the solution? Make a class that wraps the low level details and provides a clean-and-simple interface You’ve just made a Façade or Wrapper Class
Façade or Wrapper Pattern Wrap an OO interface around existing code Or cross-platform library code Goals: Ease of use, simplicity, known pitfalls Example: rendering in Vista is done using DirectX, but those wanting to create windows & GUIs can still use createWindowEx()
GUI’s Further: The Decorator Defn: Allows users to wrap objects in containers that provide additional functionality. Example: new JScrollPane( new JTextArea()) new JBorder( new JTextArea())
The Decorator Pattern Observed
The Observer (from Wiki) “The observer pattern (a subset of the asynchronous publish/subscribe pattern) is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods. It is mainly used to implement distributed event handling systems.”
More on Observer See java.util.Observer //listeners And java.util.Observable //the trigger Lets see some code… http://en.wikipedia.org/wiki/Observer_pattern
The Infamous Factory Defers Object instantiation to concrete subclasses Usually defined as an interface Lets make one for Windows
The Factory Pattern Observed public interface Factory { public Object create(); }