zolern (6) [Avatar] Offline
#1
I have suggestion about more complex implementation; channels are so nice instrument in concurrent programming and deserve to be presented with a good and interesting code example.

Here it is my idea:


import threadpool

type
  MessageType = enum
    mtStart, mtIncrement, mtStopThread
  
  Message = tuple[msgType: MessageType, msgValue: int]

var actionChannel: Channel[Message]
open actionChannel


proc increment(count: int) =
  var increment = 0

  for _ in 1 .. count:
    increment.inc
    if actionChannel.ready:
      actionChannel.send((mtIncrement, increment))
      increment = 0

  actionChannel.send((mtStopThread, increment))


proc counting(): int =
  var threadsCount = 0
  
  while true:
    let (msg, value) = actionChannel.recv

    case msg:
    of mtStart:
      threadsCount = value

    of mtIncrement:
      result += value
    
    of mtStopThread:
      result += value

      doAssert threadsCount > 0

      threadsCount.dec
      if threadsCount == 0:
        return


let threadsCount = 10
actionChannel.send((mtStart, threadsCount))

for _ in 1 .. threadsCount:
  spawn increment(10_000_000)

let counter = spawn counting()

sync()

echo "Counter: ", ^counter



There are some interesting moments in this code example:

- channel content is tuple with message type and message value
- channel is used not only for counting, but also for threads management
- tricky conception how to save channel from intensive flooding (here 10 threads send messages but only one thread reads them)
dom96 (74) [Avatar] Offline
#2
Thank you, but unfortunately Chapter 6 is already rather long so I don't think I will have space to make any of the examples there more complex.