13 Recipes and design patterns for successful concurrent programming
 
  
  
  
  - Twelve code recipes that answer common problems in parallel programming
  
 
 
  
 The 12 recipes presented in this chapter have broad applications. You can use the core ideas as a reference when you’re facing a similar problem and require a quick answer. The material demonstrates how the functional concurrent abstractions covered throughout this book make it possible to solve complex problems by developing sophisticated and rich functions with relatively few lines of code. I’ve kept the implementations of the recipes as simple as possible, so you’ll need to deal from time to time with cancellations and exception handling. 
 
  
 This chapter shows you how to put together everything you’ve learned so far to combine concurrent programming models using the functional programming abstraction as a glue to write efficient and performant programs. By the end of this chapter, you’ll have at your disposal a set of useful and reusable tools for solving common concurrent coding problems. 
 
  
 Each recipe is built in either C# or F#; for the majority of the code implementation, you can find both versions in the downloadable code online. Also, keep in mind that F# and C# are .NET programming languages with interoperability support to interact with each other. You can easily use a C# program in F# and vice versa.
 
  
 
13.1 Recycling objects to reduce memory consumption 
 
 
 
13.1.1 Solution: asynchronously recycling a pool of objects 
 
 
 
13.2 Custom parallel Fork/Join operator 
 
 
 
13.2.1 Solution: composing a pipeline of steps forming the Fork/Join pattern
 
 
 
13.3 Parallelizing tasks with dependencies: designing code to optimize performance
 
 
 
13.3.1 Solution: implementing a dependencies graph of tasks
 
 
 
13.4 Gate for coordinating concurrent I/O operations sharing resources: one write, multiple reads 
 
 
 
13.4.1 Solution: applying multiple read/write operations to shared thread-safe resources
 
 
 
13.5 Thread-safe random number generator
 
 
 
13.5.1 Solution: using the ThreadLocal object
 
 
 
13.6 Polymorphic event aggregator
 
 
 
13.6.1 Solution: implementing a polymorphic publisher-subscriber pattern
 
 
 
13.7 Custom Rx scheduler to control the degree of parallelism 
 
 
 
13.7.1 Solution: implementing a scheduler with multiple concurrent agents 
 
 
 
13.8 Concurrent reactive scalable client/server 
 
 
 
13.8.1 Solution: combining Rx and asynchronous programming 
 
 
 
13.9 Reusable custom high-performing parallel filter‑map operator 
 
 
 
13.9.1 Solution: combining filter and map parallel operations
 
 
 
13.10 Non-blocking synchronous message-passing model 
 
 
 
13.10.1 Solution: coordinating the payload between operations using the agent programming model
 
 
 
13.11 Coordinating concurrent jobs using the agent programming model 
 
 
 
13.11.1 Solution: implementing an agent that runs jobs with a configured degree of parallelism 
 
 
 
13.12 Composing monadic functions 
 
 
 
13.12.1 Solution: combining asynchronous operations using the Kleisli composition operator
 
 
 
Summary