Save 37% off PRO during our Black Friday Sale! »

Introduction to Concurrency in Haskell

Introduction to Concurrency in Haskell

Introduction to Concurrency in Haskell

4d29918c109bc75d2a1fd8420660d72b?s=128

Abhinav Sarkar

September 12, 2015
Tweet

Transcript

  1. Introduction to Concurrency in Haskell Abhinav Sarkar Functional Conf /

    Sep 12, 2015
  2. I Am Abhinav Sarkar @abhin4v @nilenso

  3. Haskell Pure functional programming Strict type system Immutable data structures

    Good for concurrent programs
  4. Real World Scenarios Threads Locks/Synchronization Inter thread communication Asynchronous exceptions

    Transactions
  5. Multiuser Chat

  6. Features Users Channels Message and Tell

  7. Feature Plan Accept user connections User to user chat User

    quitting and timeouts (maybe) Channels: joining, leaving and chatting
  8. Start!

  9. m o d u l e L i n k

    . T y p e s w h e r e d a t a U s e r = U s e r { u s e r N a m e : : S t r i n g } d e r i v i n g ( S h o w , E q , O r d ) d a t a C l i e n t = C l i e n t { c l i e n t U s e r : : U s e r , c l i e n t H a n d l e : : H a n d l e } d e r i v i n g ( S h o w , E q ) d a t a S e r v e r = S e r v e r { s e r v e r U s e r s : : M V a r ( M a p . M a p U s e r C l i e n t ) }
  10. Accept User Connections

  11. m o d u l e L i n k

    . S e r v e r w h e r e i m p o r t L i n k . T y p e s r u n S e r v e r : : I n t - > I O ( ) r u n S e r v e r p o r t = w i t h S o c k e t s D o $ d o h S e t B u f f e r i n g s t d o u t L i n e B u f f e r i n g s e r v e r < - n e w S e r v e r s o c k < - l i s t e n O n . P o r t N u m b e r . f r o m I n t e g r a l $ p o r t p r i n t f " L i s t e n i n g o n p o r t % d \ n " p o r t f o r e v e r $ d o ( h a n d l e , h o s t , p o r t ' ) < - a c c e p t s o c k p r i n t f " A c c e p t e d c o n n e c t i o n f r o m % s : % s \ n " h o s t ( s h o w p o r t ' ) f o r k I O $ c o n n e c t C l i e n t s e r v e r h a n d l e ` f i n a l l y ` h C l o s e h a n d l e
  12. Threads Green threads Non blocking IO Memory efficient -threaded ghc

    option
  13. MVar Mutable variable As a container for shared state As

    a blocking primitive For locks/synchronization
  14. c o n n e c t C l i

    e n t : : S e r v e r - > H a n d l e - > I O ( ) c o n n e c t C l i e n t s e r v e r h a n d l e = d o h S e t N e w l i n e M o d e h a n d l e u n i v e r s a l N e w l i n e M o d e h S e t B u f f e r i n g h a n d l e L i n e B u f f e r i n g r e a d N a m e w h e r e
  15. r e a d N a m e : :

    I O ( ) r e a d N a m e = d o n a m e < - h G e t L i n e h a n d l e i f n u l l n a m e t h e n r e a d N a m e e l s e d o l e t u s e r = U s e r n a m e o k < - c h e c k A d d C l i e n t s e r v e r u s e r h a n d l e c a s e o k o f N o t h i n g - > d o h P r i n t f h a n d l e " T h e n a m e % s i s i n u s e , p l e a s e c h o o s e a n o t h e r \ n " n a m e r e a d N a m e J u s t c l i e n t - > r u n C l i e n t s e r v e r c l i e n t ` f i n a l l y ` r e m o v e C l i e n t s e r v e r u s e r
  16. c h e c k A d d C l

    i e n t : : S e r v e r - > U s e r - > H a n d l e - > I O ( M a y b e C l i e n t ) c h e c k A d d C l i e n t S e r v e r { . . } u s e r @ U s e r { . . } h a n d l e = m o d i f y M V a r s e r v e r U s e r s $ \ c l i e n t M a p - > i f M a p . m e m b e r u s e r c l i e n t M a p t h e n r e t u r n ( c l i e n t M a p , N o t h i n g ) e l s e d o c l i e n t < - C l i e n t u s e r h a n d l e p r i n t f " N e w u s e r c o n n e c t e d : % s \ n " u s e r N a m e r e t u r n ( M a p . i n s e r t u s e r c l i e n t c l i e n t M a p , J u s t c l i e n t ) r e m o v e C l i e n t : : S e r v e r - > U s e r - > I O ( ) r e m o v e C l i e n t S e r v e r { . . } u s e r = m o d i f y M V a r _ s e r v e r U s e r s $ r e t u r n . M a p . d e l e t e u s e r
  17. User to User Chat

  18. m o d u l e L i n k

    . T y p e s w h e r e d a t a C l i e n t = C l i e n t { c l i e n t U s e r : : U s e r , c l i e n t H a n d l e : : H a n d l e , c l i e n t C h a n : : C h a n M e s s a g e } d a t a M e s s a g e = M s g U s e r S t r i n g d e r i v i n g ( S h o w , E q )
  19. m o d u l e L i n k

    . P r o t o c o l w h e r e i m p o r t L i n k . T y p e s p a r s e C o m m a n d : : S t r i n g - > M a y b e M e s s a g e p a r s e C o m m a n d c o m m a n d = c a s e w o r d s c o m m a n d o f " M S G " : u s e r N a m e : m s g - > J u s t $ M s g ( U s e r u s e r N a m e ) ( u n w o r d s m s g ) _ - > N o t h i n g f o r m a t M e s s a g e : : M e s s a g e - > S t r i n g f o r m a t M e s s a g e ( M s g u s e r m s g ) = p r i n t f " M S G % s % s " ( u s e r N a m e u s e r ) m s g
  20. Chans Unbounded blocking queues

  21. r u n C l i e n t :

    : S e r v e r - > C l i e n t - > I O ( ) r u n C l i e n t S e r v e r { . . } C l i e n t { . . } = f o r e v e r $ d o r < - t r y $ r a c e r e a d C o m m a n d r e a d M e s s a g e c a s e r o f L e f t ( e : : S o m e E x c e p t i o n ) - > p r i n t f " E x c e p t i o n : % s \ n " ( s h o w e ) R i g h t c m - > c a s e c m o f L e f t m c o m m a n d - > c a s e m c o m m a n d o f N o t h i n g - > p r i n t f " C o u l d n o t p a r s e c o m m a n d \ n " J u s t c o m m a n d - > h a n d l e C o m m a n d c o m m a n d R i g h t m e s s a g e - > h a n d l e M e s s a g e m e s s a g e w h e r e
  22. r e a d C o m m a n

    d : : I O ( M a y b e M e s s a g e ) r e a d C o m m a n d = d o c o m m a n d < - h G e t L i n e c l i e n t H a n d l e p r i n t f " < % s > : % s \ n " ( u s e r N a m e c l i e n t U s e r ) c o m m a n d r e t u r n $ p a r s e C o m m a n d c o m m a n d r e a d M e s s a g e : : I O M e s s a g e r e a d M e s s a g e = r e a d C h a n c l i e n t C h a n s e n d M e s s a g e : : M e s s a g e - > I O ( ) s e n d M e s s a g e m e s s a g e = w r i t e C h a n c l i e n t C h a n
  23. h a n d l e C o m m

    a n d : : M e s s a g e - > I O ( ) h a n d l e C o m m a n d ( M s g u s e r m s g ) = c l i e n M a p < - r e a d M V a r s e r v e r U s e r s c a s e M a p . l o o k u p u s e r c l i e n t M a p o f N o t h i n g - > p r i n t f " N o s u c h u s e r : % s \ n " ( u s e r N a m e u s e r ) J u s t c l i e n t - > s e n d M e s s a g e ( M s g c l i e n t U s e r m s g ) c l i e n t h a n d l e M e s s a g e : : M e s s a g e - > I O ( ) h a n d l e M e s s a g e = p r i n t T o H a n d l e c l i e n t H a n d l e . f o r m a t M e s s a g e
  24. r a c e : : I O a -

    > I O b - > I O ( E i t h e r a b ) r a c e i o a i o b = d o m < - n e w E m p t y M V a r b r a c k e t ( f o r k I O ( f m a p L e f t i o a ) ( p u t M V a r m ) ) k i l l T h r e a d $ \ _ - > b r a c k e t ( f o r k I O ( f m a p R i g h t i o b ) ( p u t M V a r m ) ) k i l l T h r e a d $ \ _ - > r e a d M V a r m
  25. MVar For inter thread communication

  26. Chatting in Channels

  27. None
  28. None
  29. Software Transactional Memory

  30. Why Transactions? Atomic changes to multiple variables Read from multiple

    channels efficiently Robustness in the presence of failure
  31. m o d u l e L i n k

    . T y p e s w h e r e t y p e U s e r N a m e = S t r i n g t y p e C h a n n e l N a m e = S t r i n g d a t a U s e r = U s e r { u s e r N a m e : : ! U s e r N a m e } d e r i v i n g ( S h o w , E q , O r d ) d a t a C h a n n e l = C h a n n e l { c h a n n e l N a m e : : C h a n n e l N a m e , c h a n n e l U s e r s : : T V a r ( S e t . S e t U s e r ) , c h a n n e l C h a n : : T C h a n M e s s a g e }
  32. d a t a S e r v e r

    = S e r v e r { s e r v e r U s e r s : : M V a r ( M a p . M a p U s e r C l i e n t ) , s e r v e r C h a n n e l s : : T V a r ( M a p . M a p C h a n n e l N a m e C h a n n e l ) } d a t a C l i e n t = C l i e n t { c l i e n t U s e r : : ! U s e r , c l i e n t H a n d l e : : ! H a n d l e , c l i e n t C h a n : : T C h a n M e s s a g e , c l i e n t C h a n n e l C h a n s : : T V a r ( M a p . M a p C h a n n e l N a m e ( T C h a n M e s s a g e ) ) }
  33. d a t a M e s s a g

    e = M s g U s e r S t r i n g | T e l l C h a n n e l N a m e S t r i n g | J o i n C h a n n e l N a m e | L e a v e C h a n n e l N a m e | M s g R e p l y U s e r S t r i n g | T e l l R e p l y C h a n n e l N a m e U s e r S t r i n g | J o i n e d C h a n n e l N a m e U s e r | L e a v e d C h a n n e l N a m e U s e r d e r i v i n g ( S h o w , E q )
  34. STM Monad A monad of its own Type system prevents

    doing IO
  35. TVar TVar: Transactional variable n e w T V a

    r : : a - > S T M ( T V a r a ) r e a d T V a r : : T V a r a - > S T M a w r i t e T V a r : : T V a r a - > a - > S T M ( ) a t o m i c a l l y : : S T M a - > I O a r e t r y : : S T M a
  36. TChan Transactional channels Efficient merging n e w T C

    h a n : : S T M ( T C h a n a ) w r i t e T C h a n : : T C h a n a - > a - > S T M ( ) r e a d T C h a n : : T C h a n a - > S T M a o r E l s e : : S T M a - > S T M a - > S T M a
  37. r u n C l i e n t :

    : S e r v e r - > C l i e n t - > I O ( ) r u n C l i e n t S e r v e r { . . } c l i e n t @ C l i e n t { . . } = d o c o m m a n d T h r e a d < - f o r k I O $ r e a d C o m m a n d s r u n ` f i n a l l y ` d o k i l l T h r e a d c o m m a n d T h r e a d c l i e n t C h a n n e l M a p < - r e a d T V a r I O c l i e n t C h a n n e l C h a n s f o r M _ ( M a p . k e y s c l i e n t C h a n n e l M a p ) $ \ c h a n n e l N a m e - > h a n d l e M e s s a g e ( L e a v e c h a n n e l N a m e ) w h e r e
  38. r u n : : I O ( ) r

    u n = f o r e v e r $ d o r < - t r y . a t o m i c a l l y $ d o c l i e n t C h a n n e l M a p < - r e a d T V a r c l i e n t C h a n n e l C h a n s f o l d r ( o r E l s e . r e a d T C h a n ) r e t r y $ c l i e n t C h a n : M a p . e l e m s c l i e n t C h a n n e l M a p c a s e r o f L e f t ( e : : S o m e E x c e p t i o n ) - > p r i n t f " E x c e p t i o n : % s \ n " ( s h o w e ) R i g h t m e s s a g e - > h a n d l e M e s s a g e m e s s a g e r e a d C o m m a n d s : : I O ( ) r e a d C o m m a n d s = f o r e v e r $ d o c o m m a n d < - h G e t L i n e c l i e n t H a n d l e p r i n t f " < % s > : % s \ n " ( u s e r N a m e c l i e n t U s e r ) c o m m a n d c a s e p a r s e C o m m a n d c o m m a n d o f N o t h i n g - > p r i n t f " C o u l d n o t p a r s e c o m m a n d : % s \ n " c o m m a n d J u s t c - > s e n d M e s s a g e I O c l i e n t c
  39. h a n d l e M e s s

    a g e : : M e s s a g e - > I O ( ) h a n d l e M e s s a g e ( J o i n c h a n n e l N a m e ) = a t o m i c a l l y $ d o c l i e n t C h a n n e l M a p < - r e a d T V a r c l i e n t C h a n n e l C h a n s - - g e t u s e r ' s c h a n n e l s - - i f u s e r h a s n o t a l r e a d y j o i n e d t h e c h a n n e l u n l e s s ( M a p . m e m b e r c h a n n e l N a m e c l i e n t C h a n n e l M a p ) $ d o c h a n n e l M a p < - r e a d T V a r s e r v e r C h a n n e l s - - g e t s e r v e r c h a n n e l s c h a n n e l @ C h a n n e l { c h a n n e l C h a n } < - c a s e M a p . l o o k u p c h a n n e l N a m e c h a n n e l M a p o f J u s t ( c h a n n e l @ C h a n n e l { c h a n n e l U s e r s } ) - > d o - - i f t h e c h a n n e l a l r e a d y e x i s t s o n t h e s e r v e r , a d d u s e r t o i t m o d i f y T V a r ' c h a n n e l U s e r s $ S e t . i n s e r t c l i e n t U s e r r e t u r n c h a n n e l N o t h i n g - > d o - - e l s e c r e a t e a n e w c h a n n e l w i t h t h i s u s e r i n i t a n d a d d i t t o t h e s e r v e r c h a n n e l < - n e w C h a n n e l c h a n n e l N a m e $ S e t . s i n g l e t o n c l i e n t U s e r m o d i f y T V a r ' s e r v e r C h a n n e l s $ M a p . i n s e r t c h a n n e l N a m e c h a n n e l r e t u r n c h a n n e l - - d u p l i c a t e c h a n n e l T C h a n f o r t h i s u s e r a n d a d d i t t o t h e u s e r s ' s c h a n n e l s c l i e n t C h a n n e l C h a n < - d u p T C h a n c h a n n e l C h a n m o d i f y T V a r ' c l i e n t C h a n n e l C h a n s $ M a p . i n s e r t c h a n n e l N a m e c l i e n t C h a n n e l C h a n - - s e n d a J O I N E D m e s s a g e t o t h e c h a n n e l f o r t h i s u s e r t e l l M e s s a g e c h a n n e l $ J o i n e d c h a n n e l N a m e c l i e n t U s e r
  40. High Level Design

  41. High Level Design Threads are cheap. Don't be afraid to

    launch new threads. Non blocking IO. No need of event loops. Small components connected through channels Write small functions in STM and compose them
  42. High Level Design Structure programs like assembly lines Processing functions

    read from and write to channels Channels connect processing functions like conveyor belts Channels can be duplicated and merged
  43. That's All Folks

  44. References Parallel and Concurrent Programming in Haskell - Simon Marlow

    Real World Haskell - O'Sullivan, Stewart, Goerzen
  45. https://github.com/abhin4v/link https://tinyurl.com/introconchs @abhin4v abhinav@nilenso.com

  46. Questions?