'NET Programming Language Research MSR Cambridge - PowerPoint PPT Presentation

1 / 82
About This Presentation
Title:

'NET Programming Language Research MSR Cambridge

Description:

Andrew Kennedy and Don Syme. MS.NET days March 2002. Note: This is not in V1 of the CLR ... shared-memory synchronization primitives (mutexes, monitors, r/w locks) ... – PowerPoint PPT presentation

Number of Views:48
Avg rating:3.0/5.0
Slides: 83
Provided by: nickb46
Category:

less

Transcript and Presenter's Notes

Title: 'NET Programming Language Research MSR Cambridge


1
.NET Programming Language Research _at_ MSR Cambridge
  • Nick Benton
  • Microsoft Research
  • Cambridge

2
MSR Cambridge Programming Principles and Tools
Group
  • Luca Cardelli
  • Nick Benton
  • Cedric Fournet
  • Andy Gordon
  • Tony Hoare
  • Andrew Kennedy
  • Simon Peyton Jones
  • Don Syme
  • Simon Marlow
  • Claudio Russo
  • Mark Shields
  • visitors, PhD students, interns,

3
.NET in MSR Programming Principles and Tools Group
  • Verifier spec (POPL)
  • CLR design feedback
  • Project 7 (Babel)
  • SML.NET (ICFP,ICFP,HOOTS)
  • Generics for C and .NET (PLDI)
  • Extended IL (Babel)
  • Polyphonic C (FOOL, ECOOP)
  • Stack-Walking Security analysis (POPL)
  • Assertions

4
Part 1SML.NET
  • Nick Benton, Andrew Kennedy and Claudio Russo

5
Advanced Programming Languages on the CLR
  • .NET and the CLR provide a great opportunity for
    programming language designers and implementers
  • The runtime provides services (execution engine,
    garbage collection,) which make producing a good
    implementation of your language easier
  • The frameworks libraries mean you can actually
    do useful things with your new language
    (graphics, networking, database access, web
    services,)
  • Multi-language component-based programming makes
    it much more practical for other people to use
    your language in their own projects

6
Our favourite language Standard ML
  • A safe, modular, strict, higher-order,
    functional, polymorphic programming language with
    compile-time type checking and type inference,
    garbage collection, exception handling, immutable
    data types, pattern-matching and updatable
    references, abstract data types, and parametric
    modules.
  • with several efficient implementations
  • and a formal definition with a proof of
    soundness.
  • (Schemetypesreal syntax, Haskell with call by
    value evaluation)

7
Some SML
  • datatype order LESS GREATER EQUAL
  • datatype 'a Tree Empty
  • Node of 'a ('a Tree) ('a
    Tree)
  • fun contains compare (x, Empty) false
  • contains compare (x, Node(v, left, right))
  • (case compare (x,v) of
  • LESS gt contains compare (x,left)
  • GREATER gt contains compare (x, right)
  • EQUAL gt true
  • )
  • contains ('a 'a -gt order) -gt ('a 'a Tree)
    -gt bool

8
What is SML.NET?
  • Compiler for SML that targets verifiable CIL
  • Research Issues
  • Can we compile a polymorphic functional language
    to a monomorphic, object-oriented runtime?
  • Yes
  • How can we make it produce fast, compact code?
  • Whole-program optimising compiler.
    Monomorphisation. Representation tricks. Novel
    typed intermediate language using monads to track
    side-effects.
  • How can we make cross-language working easy?
  • We extend SML to support all of the .NET CLS
    (Common Language Specification), providing smooth
    bidirectional interoperability with .NET
    framework libraries other .NET languages

9
Previous approaches to interop
  • Bilateral interface with marshalling and explicit
    calling conventions (e.g. JNI, OCaml interface
    for C).
  • Awkward, ugly, tied to one implementation, only
    for experts
  • Multilateral interface with IDL (e.g. COM, CORBA)
    together with particular language mappings (e.g.
    H/Direct, Caml COM, MCORBA).
  • Have to write IDL and use tools, tend to be
    lowest-common denominator, memory management
    often tricky

10
Interop in .NET
  • Languages share a common higher-level
    infrastructure (CLR)
  • shared heap means no tricky cross-heap pointers
    (cf reference counting in COM)
  • shared type system means no marshalling (cf
    stringlt-gtchar marshalling for Javalt-gtC)
  • shared exception model supports cross-language
    exception handling

11
SML.NET interop
  • Sounds great, but SML is not object-oriented
  • So we are going to have to do some work
  • Possible approaches to interop
  • do not extend language instead provide wrappers
    that give a functional view of a CLS library
    (Haskell, Mercury).
  • Powerful functional type systems can go a very
    long way towards modelling OO type systems
  • redesign the language (OO-SML?)
  • Our approach a middle way
  • re-use existing features where appropriate
    (non-object-oriented subset)
  • extend language for convenient interop when fit
    is bad (object-oriented features)
  • live with the CLS at boundaries dont try to
    export complex ML types to other languages (what
    would they do with them?)

12
Re-use SML features
multiple args
tuple
void
unit
null
NONE
static field
val binding
SML
static method
fun binding
CLS
namespace
structure
delegate
first-class function
mutability
ref
open
using
private fields
local decls
13
Extend language
type test
cast patterns
class definitions
classtype
instance method invocation
obj.meth
instance field access
obj.fld
custom attributes
attributes in classtype
casts
exp gt ty
CLS
SML
14
Extract from WinForms interop
open System.Windows.Forms System.Drawing
System.ComponentModelfun selectXML () let
val fileDialog OpenFileDialog() in
fileDialog.set_DefaultExt("XML")
fileDialog.set_Filter("XML files (.xml)
.xml") if fileDialog.ShowDialog()
DialogResult.OK then case
fileDialog.get_FileName() of NONE gt ()
SOME name gt replaceTree (ReadXML.make
name, "XML file '" name "'") else ()
end
no args ML unit value
CLS Namespace ML structure
static method ML function
static constant field ML value
instance method invocation
CLS string ML string
null value NONE
And note that there are no explicit types in this
code
15
Ray tracing in ML
  • ICFP programming competition build a ray tracer
    in under 3 days
  • 39 entries in all kinds of languages
  • C, C, Clean, Dylan, Eiffel, Haskell, Java,
    Mercury, ML, Perl, Python, Scheme, Smalltalk
  • ML (Caml) was in 1st and 2nd place

16
Ray tracing in SML.NET
  • Translate winning entry to SML
  • Add WinForms interop
  • Run on .NET CLR
  • Performance on this example twice as good as
    popular optimizing native compiler for SML
  • (though on others were twice as bad)

17
Visual Studio Integration
  • Bootstrap the compiler to produce a .NET
    component for parsing, typechecking, etc. of SML
  • Use interlanguage working extensions to expose
    that as a COM component which can be glued into
    Visual Studio
  • Write new ML code to handle syntax highlighting,
    tooltips, error reporting, etc.

18
Part 2Generics in the CLR and C
  • Andrew Kennedy and Don Syme

19
Note This is not in V1 of the CLR ?It will be
in V2 ? ? ?
20
Part 1 Introduction
21
What are generics?
  • Types which are parameterized by other types,
    e.g. Stackltintgt, Stackltstringgt
  • Generics, templates, parametric polymorphism
  • Ada, Eiffel, C, ML, Haskell, Mercury, Component
    Pascal,
  • Promote code reuse, increase type safety, better
    performance
  • Good for collections, higher-order programming
    and generally building higher-level, reusable
    abstractions

22
Generic code in C today (1)
  • class Stack private Object items private
    int nitems Stack() nitems 0 items
    new Object50 Object Pop() if
    (nitems 0) throw new EmptyException()
    return items--nitems
  • void Push(Object item) ... return
    itemsnitems

23
Generic code in C today (2)
  • Stack s new Stack()
  • s.Push(1)
  • s.Push(2)
  • int n (int)(s.Pop()) (int)(s.Pop())
  • Whats wrong with that?
  • Its inexpressive. Type system doesnt document
    what should be in a particular stack.
  • Its unsafe. Type errors (s.Push(2) ) lead to
    runtime exceptions instead of being caught by
    compiler
  • Its ugly. Casts everywhere.
  • Its slow. Casts are slow, and converting base
    types (e.g. ints) to Objects involves expensive
    boxing.

24
Generic code in C tomorrow (1)
  • class StackltTgt private T items private
    int nitems Stack() nitems 0 items
    new T50 T Pop() if (nitems 0)
    throw new EmptyException() return
    items--nitems
  • void Push(T item) if (items.Length
    nitems) T temp items items
    new Tnitems2 Array.CopyltTgt(temp,
    items, nitems) itemsnitems
    item

25
Generics large design space
But can type instantiations can be non-reference?
Setltintgt Listltfloatgt
  • Parameterized classes, interfaces, and methods
    e.g.

Do you erase types at runtime?
// two-parameter class class DictltK,Dgt ...
// parameterized interface interface
IComparableltTgt ... // parameterized struct
struct PairltA,Bgt ... // generic method
T SliceltTgt(T arr, int start, int count)
Do we have exact runtime type information? if (x
is Setltintgt) ....
Do you share code?
Constraints? class CltT IFoo, IBargt ...

What goes in the CLR? What goes in the
compilers?
26
Generic interfaces
  • interface IDictionaryltK,Dgt
  • D Lookup(K)
  • ...
  • class DictionaryltK,Dgt IDictionaryltK,Dgt
  • D Lookup(K)
  • ...
  • DictionaryltString,Stringgt

27
Generic methods
A generic method is just a family of methods,
indexed by type.
  • static void SortltTgt (T) ...
  • int x 5,4,3,2
  • Sort(x)

28
Explicit Constraints
interface IComparableltTgt static int
Compare(T,T) class BinaryTreeltT
IComparableltTgt gt void insert(T x)
switch (x.Compare(y)) ... T y
TreeltTgt left TreeltTgt right
Static constraints are available via interfaces.
29
Part 2 Implementing Generics for the .NET CLR
30
Generics Our design
  • Parameterized classes, interfaces, structs,
    methods, delegates Yes
  • Exact runtime types Yes
  • if (x is Setltstringgt) ...
  • Instantiations at value types Yes
  • SetltStringgt Setltintgt Listltfloatgt
  • Constraints Yes (by
    interfaces)
  • class CltT IComponentgt
  • Variance No
  • SetltStringgt is not subtype-related to SetltObjectgt

31
How does it work?
1a. Look for Stackltintgt1b. Nothing exists yet,
so create structures for Stackltintgt
Stackltintgt si new Stackltintgt()Stackltintgt si2
new Stackltintgt()Stackltstringgt ss new
Stackltstringgt()Stackltobjectgt so new
Stackltobjectgt()si.Push(5)ss.Push(Generics)
so.Push(myObj)
2a. Look for Stackltintgt2b. Type already loaded!
3a. Look for Stackltstringgt3b. ltstringgt not
compatible with ltintgt, so create structures for
Stackltstringgt
4a. Look for Stackltobjectgt4b. ltobjectgt
compatible with ltstringgt, so re-use Stackltstringgt
32
How does it work?
Stackltintgt si new Stackltintgt()Stackltintgt si2
new Stackltintgt()Stackltstringgt ss new
Stackltstringgt()Stackltobjectgt so new
Stackltobjectgt()si.Push(5)ss.Push(Generics)
so.Push(myObj)
Compile code for Stackltintgt.Push
Compile code for Stackltstringgt.Push
Re-use code from Stackltstringgt.Push
33
Implementing Generics (0)
  • Dynamic loading JIT compilation change many
    fundamental assumptions
  • Can consider code generation at runtime
  • Can use more dynamic data structures
  • The current challenge is to implement all of
  • exact runtime types code sharing dynamic
    loading non-uniform instantiations

34
Implementing Generics (1)
  • Our implementation
  • 1. Dynamic code expansion and sharing
  • Instantiating generic classes and methods is
    handled by the CLR.
  • Generate/compile code as necessary
  • Use JIT compiler
  • Share code for compatible instantiations
  • Compatibility is determined by the implementation

35
Implementing Generics (2)
  • Our implementation
  • 1. Dynamic code expansion and sharing
  • 2. Pass and store runtime type information
  • Objects carry runtime type information
  • We record this information by duplicating
    vtables.
  • Other options are possible.
  • Generic methods take an extra parameter
  • The active type context is always recoverable

36
Implementing Generics (3)
  • Our implementation
  • 1. Dynamic code expansion and sharing
  • 2. Pass and store runtime type information
  • 3. Optimized use of runtime type information

37
Generics Performance
  • 1. Instantiations at value types
  • Stack with repeated push and pops of 0...N
    elements
  • (a) List_int
  • (b) List (i.e. existing collection class)
  • (c) Listltintgt
  • 5X speedup (c) v. (b)
  • 2. No casts
  • 20 speed on similar micro-benchmarks
  • 3. Runtime type computations
  • Generic allocation 10 slower in generic code

38
Generics Design Comparison
39
Comparison with C templates
  • What C gets wrong
  • Modularity
  • need to see the template at link time
  • Efficiency
  • nearly all implementations code-expand
  • Safety
  • not checked at declaration use, but at link
    time
  • Simplicity
  • very complicated

40
Comparison with C templates
  • What we get right
  • Modularity
  • no need to see the generic IL until runtime
  • Efficiency
  • code expansion managed by the VM
  • Safety
  • check at declaration use
  • Simplicity
  • there are some corners, but the mechanism is
    simple to explain use

41
Summary
  • A world first cross-language generics.
  • A world first generics in a high-level virtual
    machine design.
  • Implementation
  • The virtual machine (runtime) level is the right
    place to implement generics for .NET
  • Potential for
  • Other implementation techniques (more aggressive
    sharing, some boxing, etc.)
  • Further extensions (type functions, variance,
    more expressive constraints)
  • Good performance

42
Part 3Polyphonic C
  • Nick Benton, Luca Cardelli and Cedric Fournet

43
Introduction
44
Programming in a networked world
  • Developers now have to work in a
  • Concurrent
  • Distributed
  • High latency
  • ( low reliability, security sensitive,
    multi-everything)
  • environment.
  • Which is hard
  • And theyre mostly not very good at it
  • Try using Outlook over dialup ?

45
Asynchronous communication
  • Distribution gt concurrency latency
    gt asynchrony gt more
    concurrency
  • Message-passing, event-based programming,
    dataflow models
  • For programming languages, coordination
    (orchestration) languages frameworks, workflow

46
Language support for concurrency
  • Make invariants and intentions more apparent
    (part of the interface)
  • Good software engineering
  • Allows the compiler much more freedom to choose
    different implementations
  • Also helps other tools

47
.NET Today
  • Multithreaded execution environment with lock per
    object
  • C has lock keyword, libraries include
    traditional shared-memory synchronization
    primitives (mutexes, monitors, r/w locks)
  • Delegate-based asynchronous calling model,
    events, messaging
  • Higher level frameworks built on that
  • Hard to understand, use and get right
  • Different models at different scales
  • Support for asynchrony all on the caller side
    little help building code to handle messages
    (must be thread-safe, reactive, and deadlock-free)

48
Polyphonic C
  • An extension of the C language with new
    concurrency constructs
  • Based on the join calculus
  • A foundational process calculus like the
    p-calculus but better suited to asynchronous,
    distributed systems
  • A single model which works both for
  • local concurrency (multiple threads on a single
    machine)
  • distributed concurrency (asynchronous messaging
    over LAN or WAN)

49
The Language
50
In one slide
  • Objects have both synchronous and asynchronous
    methods.
  • Values are passed by ordinary method calls
  • If the method is synchronous, the caller blocks
    until the method returns some result (as usual).
  • If the method is async, the call completes at
    once and returns void.
  • A class defines a collection of synchronization
    patterns (chords), which define what happens once
    a particular set of methods have been invoked on
    an object
  • When pending method calls match a pattern, its
    body runs.
  • If there is no match, the invocations are queued
    up.
  • If there are several matches, an unspecified
    pattern is selected.
  • If a pattern containing only async methods fires,
    the body runs in a new thread.

51
A Simple Buffer
  • class Buffer
  • String get() async put(String s)
  • return s

52
A Simple Buffer
  • class Buffer
  • String get() async put(String s)
  • return s
  • An ordinary (synchronous) method with no
    arguments, returning a string

53
A Simple Buffer
  • class Buffer
  • String get() async put(String s)
  • return s
  • An ordinary (synchronous) method with no
    arguments, returning a string
  • An asynchronous method (hence returning no
    result), with a string argument

54
A Simple Buffer
  • class Buffer
  • String get() async put(String s)
  • return s
  • An ordinary (synchronous) method with no
    arguments, returning a string
  • An asynchronous method (hence returning no
    result), with a string argument
  • Joined together in a chord

55
A Simple Buffer
  • class Buffer
  • String get() async put(String s)
  • return s
  • Calls to put() return immediately (but are
    internally queued if theres no waiting get()).
  • Calls to get() block until/unless theres a
    matching put()
  • When theres a match the body runs, returning the
    argument of the put() to the caller of get().
  • Exactly which pairs of calls are matched up is
    unspecified.

56
A Simple Buffer
  • class Buffer
  • String get() async put(String s)
  • return s
  • Does example this involve spawning any threads?
  • No. Though the calls will usually come from
    different pre-existing threads.
  • So is it thread-safe? You dont seem to have
    locked anything
  • Yes. The chord compiles into code which uses
    locks. (And that doesnt mean everything is
    synchronized on the object.)
  • Which method gets the returned result?
  • The synchronous one. And there can be at most one
    of those in a chord.

57
Reader/Writer
  • using threads and mutexes in Modula 3
  • An introduction to programming with threads.
    Andrew D. Birrell, January 1989.

58
Reader/Writer in five chords
  • class ReaderWriter
  • void Exclusive() private async Idle()
  • void ReleaseExclusive() Idle()
  • void Shared() private async Idle() S(1)
  • void Shared() private async S(int n)
    S(n1)
  • void ReleaseShared() private async S(int n)
  • if (n 1) Idle() else S(n-1)
  • ReaderWriter() Idle()
  • A single private message represents the state
  • none ?? Idle() ?? S(1) ?? S(2) ?? S(3)

59
Asynchronous Service Requests and Responses
  • The service might export an async method which
    takes parameters and somewhere to put the result
  • a buffer, or a channel, or
  • a delegate (O-O function pointer)

delegate async IntCB(int v) class Service
public async request(String arg, IntCB
callback) int result // do something
interesting callback(result)
60
Asynchronous Service Requests and Responses - join
  • 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(i,j)
  • // do something with i and j

61
Asynchronous Service Requests and Responses -
select
  • class Select
  • int wait()
  • async reply(int r)
  • return r
  • // client code
  • int i
  • Select x new Select()
  • service1.request(arg1, new IntCB(x.reply))
  • service2.request(arg2, new IntCB(x.reply))
  • // do something useful
  • // now wait until one result has come back
  • i x.wait()
  • // do something with i

62
Extending C with chords
  • Classes can declare methods using generalized
    chord-declarations instead of method-declarations
    .
  • chord-declaration method-header
    method-header body
  • method-header attributes modifiers
    return-type async name (parms)
  • Interesting well-formedness conditions
  • At most one header can have a return type (i.e.
    be synchronous).
  • The inheritance restriction.
  • ref and out parameters cannot appear in async
    headers.

63
Implementation
64
Example Sum of Squares
add(1)
total(0,8)
add(4)
SumOfSquares
add(9)
add(64)
65
Sum of Squares
total(1,7)
add(4)
SumOfSquares
add(9)
add(64)
66
Sum of Squares Code
  • class SumOfSquares
  • private async loop(int i)
  • if (i gt 0)
  • add(i i)
  • loop(i - 1)
  • private int total(int r, int i) private async
    add(int dr)
  • int rp r dr
  • if (i gt 1) return total(rp, i - 1)
  • return rp
  • public SumOfSquares(int x)
  • loop(x)
  • int i total(0, x)
  • System.Console.WriteLine("The result is 0.",
    i)

67
Sum of Squares Translation
  • using System
  • using System.Collections
  • using System.Threading
  • class SyncQueueEntry
  • public int pattern
  • public System.Threading.Thread mythread
  • public System.Object joinedentries
  • class SumOfSquares
  • Queue Q_totalint_int_ new Queue()
  • Queue Q_addint_ new Queue()
  • class loopint__runner
  • SumOfSquares parent
  • int field_0
  • public loopint__runner(SumOfSquares p_p,int
    p_0)
  • parent p_p
  • field_0 p_0
  • Thread t new Thread(new ThreadStart(this.do
    it))
  • t.Start()
  • try
  • Thread.Sleep(Timeout.Infinite)
  • catch (ThreadInterruptedException)
  • // wake up here
  • matchindex qe.pattern
  • joinlabel
  • switch (matchindex)
  • case 0 int r sync_p_0
  • int i sync_p_1
  • int dr (int)(qe.joinedentries)
  • int rp r dr
  • if (i gt 1) return total(rp, i - 1)
  • return rp

68
Sum of Squares Translation
  • using System
  • using System.Collections
  • using System.Threading
  • class SyncQueueEntry
  • public int pattern
  • public System.Threading.Thread mythread
  • public System.Object joinedentries
  • class SumOfSquares
  • Queue Q_totalint_int_ new Queue()
  • Queue Q_addint_ new Queue()
  • class loopint__runner
  • SumOfSquares parent
  • int field_0
  • public loopint__runner(SumOfSquares p_p,int
    p_0)
  • parent p_p
  • field_0 p_0
  • Thread t new Thread(new ThreadStart(this.do
    it))
  • t.Start()
  • try
  • Thread.Sleep(Timeout.Infinite)
  • catch (ThreadInterruptedException)
  • // wake up here
  • matchindex qe.pattern
  • joinlabel
  • switch (matchindex)
  • case 0 int r sync_p_0
  • int i sync_p_1
  • int dr (int)(qe.joinedentries)
  • int rp r dr
  • if (i gt 1) return total(rp, i - 1)
  • return rp

class SumOfSquares Queue Q_totalint_int_
new Queue() Queue Q_addint_ new Queue()

69
Sum of Squares Translation
  • using System
  • using System.Collections
  • using System.Threading
  • class SyncQueueEntry
  • public int pattern
  • public System.Threading.Thread mythread
  • public System.Object joinedentries
  • class SumOfSquares
  • Queue Q_totalint_int_ new Queue()
  • Queue Q_addint_ new Queue()
  • class loopint__runner
  • SumOfSquares parent
  • int field_0
  • public loopint__runner(SumOfSquares p_p,int
    p_0)
  • parent p_p
  • field_0 p_0
  • Thread t new Thread(new ThreadStart(this.do
    it))
  • t.Start()
  • try
  • Thread.Sleep(Timeout.Infinite)
  • catch (ThreadInterruptedException)
  • // wake up here
  • matchindex qe.pattern
  • joinlabel
  • switch (matchindex)
  • case 0 int r sync_p_0
  • int i sync_p_1
  • int dr (int)(qe.joinedentries)
  • int rp r dr
  • if (i gt 1) return total(rp, i - 1)
  • return rp

private void add(int p_0) System.Threading.Moni
tor.Enter(Q_totalint_int_) if
(!(Q_totalint_int_.Count 0))
SyncQueueEntry sqe (SyncQueueEntry)(Q_totalin
t_int_.Dequeue()) sqe.joinedentries
p_0 System.Threading.Monitor.Exit(Q_totalint
_int_) sqe.pattern 0
sqe.mythread.Interrupt() return Q_addin
t_.Enqueue(p_0) System.Threading.Monitor.Exit(Q_
totalint_int_) return
70
Current Work
  • Examples and test cases
  • Web combinators, adaptive scheduler, web services
    (Terraserver), active objects and remoting (stock
    trader)
  • Generally looking at integration with existing
    mechanisms and frameworks
  • Language design
  • Direct syntactic support for timeouts
  • Solid Implementation

71
Predictable Demo Dining Philosophers
waiting to eat
eating
waiting to eat
thinking
eating
72
Code extract
  • class Room
  • public Room (int size) hasspaces(size)
  • public void enter() private async
    hasspaces(int n)
  • if (n gt 1) hasspaces(n-1)
  • else isfull()
  • public void leave() private async
    hasspaces(int n)
  • hasspaces(n1)
  • public void leave() private async isfull()
    hasspaces(1)

73
Conclusions
  • A clean, simple, new model for asynchronous
    concurrency in C
  • Declarative, local synchronization
  • Applicable in both local and distributed settings
  • Efficiently compiled to queues and automata
  • Easier to express and enforce concurrency
    invariants
  • Compatible with existing constructs, though they
    constrain our design somewhat
  • Solid foundations
  • Works well in practice

74
Thats all
  • For more information, contact me
    nick_at_microsoft.com or see
  • http//research.microsoft.com/nick,akenn,dsyme

75
TimeoutBuffer
  • class TimeoutBuffer
  • TimeoutBuffer(int delay)
  • Timer t new Timer(new TimerCallBack(this.tick)
    , delay)
  • empty()
  • async empty() void put(Object o) has(o)
  • async empty() void tick() timeout()
  • async timeout() void put(Object o)
    timeout()
  • async timeout() Object get() timeout() throw
    new TimeOutExn()
  • async has(Object o) Object get() has(o)
    return o
  • async has(Object o) void tick() has(o)

76
Why only one synchronous method in a chord?
  • JoCaml allows multiple synchronous methods to be
    joined, as in the following rendezvous
  • But in which thread does the body run? In C,
    thread identity is very observable, since
    threads are the holders of particular re-entrant
    locks. So we rule this out in the interests of
    keeping commutative. (Of course, its still
    easy to code up an asymmetric rendezvous in
    Polyphonic C.)

int f(int x) int g(int y) return y to f
return x to y
77
The problem with inheritance
class C virtual void f() virtual async g()
virtual void f() virtual async h()
class D C override async g()
  • Weve half overridden f
  • Too easy to create deadlock or async leakage

void m(C x) x.g() x.f() m(new D())
78
The Inheritance Restriction
  • Inheritance may be used as usual, with a
    restrictionto prevent the partial overriding of
    patterns
  • For a given class, two methods f ang g are
    co-declared if there is a chord in which they are
    both declared.
  • Whenever a method is overriden,every codeclared
    method must also be overriden.
  • Hence, the compiler rejects patterns such as
  • public virtual void f() private async g()
  • In general, inheritance and concurrency do not
    mix well.Our restriction is simple it could be
    made less restrictive.

79
Types etc.
  • async is a subtype of void
  • Allow covariant return types on those two
  • An async method may override a void one
  • A void delegate may be created from an async
    method
  • An async method may implement a void method in an
    interface
  • async methods are automatically given the
    OneWay attribute, so remote calls are
    non-blocking

80
Compiling chords
  • Since synchronization is statically defined for
    every class, we can compile it efficiently (state
    automata).
  • We cache the synchronization state in a single
    word.
  • We use a bit for every (polyphonic) method.
  • We pre-compute bitmasks for every pattern.
  • Simple version just looks up queue state directly
  • For every polyphonic method, we allocate a
    queuefor storing delayed threads (or pending
    messages).
  • The compilation scheme can be optimized
  • Some states are not reachable.
  • Empty messages only need to be counted.
  • The content of (single, private) messages can be
    stored in local variables. Requires some
    analysis.

81
Implementation issues
  • When compiling a polyphonic class, we add
  • private fields for the synchronization state and
    the queues
  • private methods for the body of asynchronous
    patterns
  • some initialization code.
  • The code handling the join patterns must be
    thread-safe.
  • We use a single lock (from the first queue) to
    protect the state word and all queues.
  • This is independent from the object lock and only
    held briefly whilst queues are being manipulated.
  • For asynchronous methods, theres an auxiliary
    class for storing the pending messages.

82
Adding synchronization code
  • When an asynchronous method is called
  • add the message content to the queue
  • if the method bit is 0, set it to 1 in the
    synchronization stateand check for a completed
    pattern
  • For every pattern containing the method,compare
    the new state to the pattern mask.
  • If there is a match, then wake up a delayed
    thread(or start a new thread if the pattern is
    entirely asynchronous).
  • When a synchronous method is called
  • if the method bit is 0, set it to 1 in the
    synchronization stateand check for a completed
    pattern
  • For every pattern containing the method,compare
    the new state to the pattern mask.
  • If there is a match, dequeue the asynchronous
    arguments,adjust the mask, and run the body for
    that pattern.
  • Otherwise, enqueue the thread, go to sleep, then
    retry.
Write a Comment
User Comments (0)
About PowerShow.com