Seminar Ojektorientierte Programmiersprachen WS 2003/04 FU-Berlin Dozent: Prof.Dr.-Ing.Peter Löhr Vortrag C# und Nichtsequentialität ( Polyphonic C# ) 2 Polyphonic C# C# vs Java Definition Beispiele Spezifikation Restriktion Programming in Polyphonic C# Implementation and Translation Schlussfolgerung Quelle 3 Blocksynchronization (C# vs Java) C# Code public void WithdrawAmount(int num){ lock(this){ if(num < this.amount) this.amount -= num; }} Java Code public void withdrawAmount(int num){ synchronized(this){ if(num < this.amount) this.amount -= num; }} 4 MethodSynchronization (C# vs Java) C# Code [MethodImpl(MethodImplOptions.Synchronized)] public void WithdrawAmount(int n){ if(n < this.amount) this.amount - n; } Java Code public synchronized void withdrawAmount(int n){ if(n < this.amount) this.amount - n; } 5 Threads (C# vs Java ) Java Extending Java.lang.Thread Overriding run method Or implementing java.lang.Runnable interface and its run method every class inherits the wait(), notify() and notifyAll() from java.lang.Object Multithreaded „run methods“ designed up front for multithreaded scenarios 6 Threads (C# vs Java ) C# creating a new System.Threading.Thread object passing it a System.Threading.ThreadStart delegate Delegate initialized with the method that is to be run as a thread any method can be passed to a ThreadStart object and run in a multithreaded scenario Every class inherits Wait(), Pulse() and PulseAll() methods in the System.Threading.Monitor 7 Einleitung Asynchrone Nachrichten und Erreignisse Benutzerschnittstellen- Treibererreignisse , verteilte Systeme , Web Services etc Alle diese asynchrone Nachrichten werden von Threads behandlet Threads sind immernoch kostbare Resourcen an vielen Systemen Verstecken von Threads hinter Sprachmechanismus 8 Einleitung Nick Benton, Luca Cardelli und Cedric Fournet bei Microsoft Research Concurrency should be a language feature High-level abstraction for asynchronous programming Hence better optimization possibilities for the compiler (queues, lightweight threads, thread pools) 9 Was ist nun Polyphnic C# ? eine Erweiterung von C# mit neuen asynchronen nichtsequentiallen Konstrukten Basierend auf dem Join Calculus Eine geignete Sprache für asynchron verteilten Systemen 10 Was ist nun Polyphnic C# ? Alle features von C# bleiben erhalten Hinzufügen von zwei neuen SprachKonstrukten Asynchronous methods und Chords 11 Was ist nun Polyphnic C# ? Standard Methoden sind alle synchron Der Aufruf kehrt nach der Ausführung des Rumpfs zurück Asynchrone Methode haben async vor Methodennamen Kehren sofort ohne Rückgabewert zurück 12 Was ist nun Polyphnic C# ? Chords Auch synchronization pattern oder join pattern genannt Besteht aus Methodenkopf und Methodenrumpf Der Kopf kann aus mehreren Methoden bestehen Sie werden durch einen & getrennt 13 Was ist nun Polyphnic C# ? In einem Chord kann es nur eine synchrone Methode geben aber viele async Ausführung des Rumpfs nur wenn alle Methoden aufgerufen sind Sonst wird der Thread in einer Schlange gestellt Steht eine async Methode alleine, wird sie in einem neuen Thread sofort ausgeführt Eine Methode kann in vielen Chords(synchronization patterns) auftauchen 14 Ein einfaches Beispiel class Buffer { String get() & async put(String s) { return s; } } 15 Ein einfaches Beispiel class Buffer { String get() & async put(String s) { return s; } } Eine einfache paramterlose synchrone Methode mit String Rückgabewert 16 Ein einfaches Beispiel class Buffer { String get() & async put(String s) { return s; } } Eine einfache paramterlose synchrone Methode mit String Rückgabewert Eine asynchrone Methode mit String-Parameter (liefert keinen Wert Zurück) 17 Ein einfaches Beispiel class Buffer { String get() & async put(String s) { return s; } } Eine einfache paramterlose synchrone Methode mit String Rückgabewert Eine asynchrone Methode mit String-Parameter (liefert keinen Wert Zurück) Beide in einem Chord (synchronization pattern) 18 Chords Ein Object kann mehrere Chords enthalten Welche Methode der passende Partner einer anderen wird, ist unbestimmt 19 Beispiel mit zwei Chords class Buffer { int get() & async put(int n) { return n; } string get() & async put(int n){ return n.ToString(); } } Welches put mit welchem get synchronisiert wird, ist unbestimmt 20 Buffer buff = new Buffer(); buff.put(‘‘blue“); buff.put(‘‘sky“); Console.Write(buff.get()+“ ‘‘+buff.get()); Ausgabe unbestimmt ‘‘blue sky“ oder auch ‘‘sky blue“ 21 Informelle Spezifikation Return-type = type | void | async chord-declaration ::= method-header | [& method-header]* body method-header ::= attributes modifiers return-type member-name(formals) 22 Restriktion für Vererbung Bei Überschreibung einer Methode eines Chords einer Superklasse müssen alle Methoden dieses Chords überschrieben werden impliziert Transivität 23 Restriktion für Vererbung class C { virtual void f() & virtual async g(){ /* body1 */ } virtual void f() & virtual async h(){ /* body2 */ } class D:C { override async g(){ /* body3 */ } Gefahr eines Deadlocks 24 Programming in Polyphonic C# Reader-Writer Locks Asynchrone Nachrichten Active Objects 25 Reader-Writer Locks public class ReaderWriter { public ReaderWriter() { Idle(); } public void Shared() & async Idle() { S(1); } public void Shared() & async S(int n) { S(n+1); } public void ReleaseShared() & async S(int n) { if (n == 1) Idle(); else S(n-1); } public void Exclusive() & async Idle() {} public void ReleaseExclusive() { Idle(); } } 26 Asynchrone Nachricht public delegate async IntCB(int v); public class Service { public async request(String arg, IntCB callback) { int result; // do something interesting… callback(result); } } 27 Asynchrone Nachricht class Join2 { void wait(out int i, out int j) & async first(int r1) & async second(int r2) { i = r1; j = r2; return; } } // client code: int i,j; Join2 x = new Join2(); service1.request(arg1, new IntCB(x.first)); service2.request(arg2, new IntCB(x.second)); // do something useful // now wait until both results have come back x.wait(out i,out j); // do something with i and j 28 Active objects(1/2) public abstract class ActiveObject { protected bool done; abstract protected void ProcessMessage(); public ActiveObject () { done = false; mainLoop(); } async mainLoop() { while (!done) { ProcessMessage(); } } } 29 Active objects(2/2) class StockServer : ActiveObject { private ArrayList clients; public async AddClient(Client c) & void ProcessMessage(){ clients.Add(c); } public async WireQuote(Quote q) & void ProcessMessage(){ foreach(Client c in clients) c.UpdateQuote(q); } public async CloseDown() & void ProcessMessage(){ done = true; } } 30 Implementation and Translation struct BitMask{ private int v; // = 0; public void set(int m) {v |= m; } public void clear(int m) { v &= ~m; } public bool match(int m ) { return ( ~v & m)==0; } } class intQ { private Queue q; public intQ() {q = new Queue(); } public void add(int i) { q.Enqueue(i); } public int get() {return (int) q.Daqueue(); } public bool empty {get{return q.Count == 0;}} } 31 Implementation and Translation class voidQ{ private int n; public voidQ() { n = 0; } public void add() { n++; } public void get() { n--; } public bool empty {get{ return n==0; }} } 32 Implementation and Translation class threadQ { private Queue q; public threadQ() { q = new Queue(); } public bool empty {get{ return (q.Count == 0); }} public void yield(object myCurrentLok){ q.Enqueue(Thread.CurrentThread); Monitor.Exit(myCurrentLock); try { Thread.Sleep(Temeout.Infinite); } catch (ThreadInterruptedException) {} Monitor.Enter(myCurrentLock; q.Dequeue(); } public void wakeup() {((Thread) q.Peek()).Interrupt();} } 33 Eine Polyphonic-klasse Class Token{ public Token(int initialToken){ for(int i=0;i<initialTokens;i++)Release(); } public int Grab(int id) & public async Release(){ return id; } } 34 Die kompilierte Klasse(1/3) class Token{ private const int mGrab = 1 << 0; private const int mRelease = 1 << 1; private threadQ GrabQ = new threadQ(); private voidQ ReleaseQ = new voidQ(); private const int mGrabRelease = mGrab | mRelease; private BitMask s = new BitMask(); private object mlock = GrabQ(); 35 Die kompilierte Klasse(2/3) .................. private void scan(){ if(s.match(mGrabRelease)) GrabQ.wakeup(); } public Token(int initialTokens){ for(int i=0;i< initialTokens;i++)Release(); } [OneWay] public void Release(){ lock(mlock){ ReleaseQ.add(), if(!s.match(mRelease)){ s.set(mRelease); scan(); } } } 36 Die kompilierte Klasse(3/3) ........................... public int Grab(int id){ Monitor.Enter(mlock); if( !s.match(mGrab) )goto now; later: GrabQ.yield(mlock);if(GrabQ.empty) s.clear(mGrab); now: if(s.match(mRelease)){ ReleaseQ.get(); if(ReleaseQ.empty)s.clear(mRelease); scan(); Monitor.Exit(mlock); { return id; //source code for the chord } }else{s.set(mGrab);goto later;} } } 37 Fully Asynchronous Chords .............. public async live(string s,int id){ Grab(id); Release(); Console.WriteLine(s); } 38 Translated Fully Asynchronous Chord private class liveArgs{ public string s;public int id; public liveArgs(string s,int id){ this.s= s;this.id=id; } } private void liveBody(object o){ liveArgs a = (liveArgs)o; string s = a.s;int id= a.id; Grab(id);Release(); Console.WriteLine(s); } 39 Translated Fully Asynchronous Chord ........... [OneWay] Public void live(string s,int id){ liveArgs a = new lineArgs(s,id); WaitCallback c = new WaitCallback(liveBody); ThreadPool.QueueUserWorkItem(c,a); } } 40 Future Work Concurrency Types Timeouts and Priorities Optimizations Declarative support for timeouts or priorities Finer control over dynamic scheduling Lock optimization Queue optimization Thread optimization Pattern-Matching Additional constraints in arguments 41 Schlussfolgerung Ein sauber und einfaches Modell für asynchrone Nichtsequentiallität in C# Modell geignet für Lokale Nichtsequentiallität (viele Threads auf einer Maschine ) Verteilte Nichtsequentiallität ( asynchrone Erreignisse über LAN oder WAN ) Kompatible mit existierenden Konstrukten 42 Polyphonic C# Dining Philosophers Demo Copyright (C) 2001 Microsoft Corporation 43 Quellen: Introduction to Polyphonic C# http://research.microsoft.com/~nick/polyphony/intro.htm Modern Concurrency Abstractions for C# (Nick Benton, Luca Cardelli, and C´edric Fournet) http://research.microsoft.com/~nick/polyphony/PolyphonyECOOP.A4.pdf 44