Skip to content

Instantly share code, notes, and snippets.

@decentral1se
Created May 18, 2020 14:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save decentral1se/39d5bcc3aa83c07760a8cf7786b89bf8 to your computer and use it in GitHub Desktop.
Save decentral1se/39d5bcc3aa83c07760a8cf7786b89bf8 to your computer and use it in GitHub Desktop.
chmxdx_letters.py
from contextlib import asynccontextmanager
from string import ascii_letters
from typing import Dict
import attr
from trio import (
BrokenResourceError,
ClosedResourceError,
Lock,
MemoryReceiveChannel,
MemorySendChannel,
open_memory_channel,
open_nursery,
run,
)
from trio.abc import Stream
from trio.testing import memory_stream_pair
@attr.s(auto_attribs=True)
class Channel:
id: int
protocol: "Protocol"
stream: Stream
sendq: MemorySendChannel
recvq: MemoryReceiveChannel
async def handler(self, msg: bytes):
print(f"P{self.protocol.id}::C{self.id} got {msg.decode()}")
async def asend(self, msg: bytes):
await self.protocol.asend(msg)
async def recv_task(self):
while True:
try:
msg = await self.recvq.receive()
await self.handler(msg)
if msg == b"Z":
return
except (ClosedResourceError, BrokenResourceError):
print("P{self.protocol.id} memory channel down, exiting")
return
@attr.s(auto_attribs=True)
class Message:
id: int
val: bytes
@attr.s(auto_attribs=True)
class Protocol:
id: int
lock: Lock
stream: Stream
channels: Dict[int, Channel] = attr.Factory(dict)
BUFFER: int = 15
MESSAGE_LENGTH: int = 2
TIMEOUT: int = 10
def parse(self, msg: bytes):
id, val = bytes(msg[0:1]), bytes(msg[1:2])
return Message(id=int(id), val=val)
async def asend(self, msg: bytes):
async with self.lock:
await self.stream.send_all(msg)
async def recv_task(self):
while True:
try:
resp = await self.stream.receive_some(self.MESSAGE_LENGTH)
msg = self.parse(resp)
if msg.id not in self.channels:
continue
channel = self.channels[msg.id]
await channel.sendq.send(msg.val)
except (ClosedResourceError, BrokenResourceError):
print("P{self.id} stream down, exiting")
return
@asynccontextmanager
async def channel(self, id: int):
sendq, recvq = open_memory_channel(self.BUFFER)
async with open_nursery() as nursery:
channel = Channel(
id=id,
stream=self.stream,
protocol=self,
sendq=sendq,
recvq=recvq,
)
nursery.start_soon(channel.recv_task)
self.channels[id] = channel
yield channel
async def channel(id, protocol):
async with protocol.channel(id=id) as channel:
for letter in ascii_letters:
message = (b"%d" % id) + letter.encode()
await channel.asend(message)
async def left_side_protocol(stream):
async with open_nursery() as nursery:
protocol = Protocol(id=1, stream=stream, lock=Lock())
nursery.start_soon(protocol.recv_task)
async with open_nursery() as n:
for i in range(0, 5):
n.start_soon(lambda: channel(id=i, protocol=protocol))
nursery.cancel_scope.cancel()
async def right_side_protocol(stream):
async with open_nursery() as nursery:
protocol = Protocol(id=2, stream=stream, lock=Lock())
nursery.start_soon(protocol.recv_task)
async with open_nursery() as n:
for i in range(0, 5):
n.start_soon(lambda: channel(id=i, protocol=protocol))
nursery.cancel_scope.cancel()
async def main():
left_side_stream, right_side_stream = memory_stream_pair()
async with open_nursery() as nursery:
nursery.start_soon(left_side_protocol, left_side_stream)
nursery.start_soon(right_side_protocol, right_side_stream)
run(main)
@decentral1se
Copy link
Author

Output:

P1::C4 got a
P2::C1 got a
P1::C1 got a
P2::C3 got a
P1::C0 got a
P2::C4 got a
P1::C3 got a
P2::C2 got a
P1::C2 got a
P2::C0 got a
P2::C1 got b
P1::C4 got b
P1::C1 got b
P2::C3 got b
P2::C4 got b
P1::C0 got b
P2::C2 got b
P1::C3 got b
P1::C2 got b
P2::C0 got b
P1::C4 got c
P2::C1 got c
P1::C1 got c
P2::C3 got c
P2::C4 got c
P1::C0 got c
P2::C2 got c
P1::C3 got c
P1::C2 got c
P2::C0 got c
P2::C1 got d
P1::C4 got d
P1::C1 got d
P2::C3 got d
P1::C0 got d
P2::C4 got d
P2::C2 got d
P1::C3 got d
P1::C2 got d
P2::C0 got d
P1::C4 got e
P2::C1 got e
P2::C3 got e
P1::C1 got e
P2::C4 got e
P1::C0 got e
P1::C3 got e
P2::C2 got e
P1::C2 got e
P2::C0 got e
P1::C4 got f
P2::C1 got f
P2::C3 got f
P1::C1 got f
P1::C0 got f
P2::C4 got f
P2::C2 got f
P1::C3 got f
P1::C2 got f
P2::C0 got f
P2::C1 got g
P1::C4 got g
P2::C3 got g
P1::C1 got g
P1::C0 got g
P2::C4 got g
P2::C2 got g
P1::C3 got g
P1::C2 got g
P2::C0 got g
P2::C1 got h
P1::C4 got h
P2::C3 got h
P1::C1 got h
P1::C0 got h
P2::C4 got h
P2::C2 got h
P1::C3 got h
P1::C2 got h
P2::C0 got h
P2::C1 got i
P1::C4 got i
P2::C3 got i
P1::C1 got i
P2::C4 got i
P1::C0 got i
P1::C3 got i
P2::C2 got i
P1::C2 got i
P2::C0 got i
P2::C1 got j
P1::C4 got j
P1::C1 got j
P2::C3 got j
P2::C4 got j
P1::C0 got j
P1::C3 got j
P2::C2 got j
P1::C2 got j
P2::C0 got j
P1::C4 got k
P2::C1 got k
P2::C3 got k
P1::C1 got k
P2::C4 got k
P1::C0 got k
P1::C3 got k
P2::C2 got k
P1::C2 got k
P2::C0 got k
P2::C1 got l
P1::C4 got l
P1::C1 got l
P2::C3 got l
P1::C0 got l
P2::C4 got l
P2::C2 got l
P1::C3 got l
P1::C2 got l
P2::C0 got l
P2::C1 got m
P1::C4 got m
P2::C3 got m
P1::C1 got m
P2::C4 got m
P1::C0 got m
P1::C3 got m
P2::C2 got m
P2::C0 got m
P1::C2 got m
P1::C4 got n
P2::C1 got n
P1::C1 got n
P2::C3 got n
P2::C4 got n
P1::C0 got n
P2::C2 got n
P1::C3 got n
P2::C0 got n
P1::C2 got n
P1::C4 got o
P2::C1 got o
P2::C3 got o
P1::C1 got o
P2::C4 got o
P1::C0 got o
P2::C2 got o
P1::C3 got o
P2::C0 got o
P1::C2 got o
P1::C4 got p
P2::C1 got p
P2::C3 got p
P1::C1 got p
P1::C0 got p
P2::C4 got p
P2::C2 got p
P1::C3 got p
P2::C0 got p
P1::C2 got p
P2::C1 got q
P1::C4 got q
P1::C1 got q
P2::C3 got q
P1::C0 got q
P2::C4 got q
P1::C3 got q
P2::C2 got q
P2::C0 got q
P1::C2 got q
P1::C4 got r
P2::C1 got r
P1::C1 got r
P2::C3 got r
P2::C4 got r
P1::C0 got r
P2::C2 got r
P1::C3 got r
P1::C2 got r
P2::C0 got r
P1::C4 got s
P2::C1 got s
P1::C1 got s
P2::C3 got s
P1::C0 got s
P2::C4 got s
P2::C2 got s
P1::C3 got s
P1::C2 got s
P2::C0 got s
P2::C1 got t
P1::C4 got t
P2::C3 got t
P1::C1 got t
P1::C0 got t
P2::C4 got t
P2::C2 got t
P1::C3 got t
P1::C2 got t
P2::C0 got t
P2::C1 got u
P1::C4 got u
P2::C3 got u
P1::C1 got u
P1::C0 got u
P2::C4 got u
P2::C2 got u
P1::C3 got u
P2::C0 got u
P1::C2 got u
P2::C1 got v
P1::C4 got v
P1::C1 got v
P2::C3 got v
P1::C0 got v
P2::C4 got v
P1::C3 got v
P2::C2 got v
P2::C0 got v
P1::C2 got v
P2::C1 got w
P1::C4 got w
P2::C3 got w
P1::C1 got w
P2::C4 got w
P1::C0 got w
P1::C3 got w
P2::C2 got w
P2::C0 got w
P1::C2 got w
P1::C4 got x
P2::C1 got x
P1::C1 got x
P2::C3 got x
P2::C4 got x
P1::C0 got x
P1::C3 got x
P2::C2 got x
P1::C2 got x
P2::C0 got x
P1::C4 got y
P2::C1 got y
P2::C3 got y
P1::C1 got y
P1::C0 got y
P2::C4 got y
P2::C2 got y
P1::C3 got y
P2::C0 got y
P1::C2 got y
P1::C4 got z
P2::C1 got z
P2::C3 got z
P1::C1 got z
P1::C0 got z
P2::C4 got z
P1::C3 got z
P2::C2 got z
P1::C2 got z
P2::C0 got z
P1::C4 got A
P2::C1 got A
P1::C1 got A
P2::C3 got A
P2::C4 got A
P1::C0 got A
P2::C2 got A
P1::C3 got A
P2::C0 got A
P1::C2 got A
P1::C4 got B
P2::C1 got B
P1::C1 got B
P2::C3 got B
P2::C4 got B
P1::C0 got B
P2::C2 got B
P1::C3 got B
P1::C2 got B
P2::C0 got B
P1::C4 got C
P2::C1 got C
P1::C1 got C
P2::C3 got C
P1::C0 got C
P2::C4 got C
P2::C2 got C
P1::C3 got C
P1::C2 got C
P2::C0 got C
P1::C4 got D
P2::C1 got D
P1::C1 got D
P2::C3 got D
P2::C4 got D
P1::C0 got D
P1::C3 got D
P2::C2 got D
P2::C0 got D
P1::C2 got D
P2::C1 got E
P1::C4 got E
P2::C3 got E
P1::C1 got E
P2::C4 got E
P1::C0 got E
P1::C3 got E
P2::C2 got E
P2::C0 got E
P1::C2 got E
P1::C4 got F
P2::C1 got F
P1::C1 got F
P2::C3 got F
P2::C4 got F
P1::C0 got F
P2::C2 got F
P1::C3 got F
P2::C0 got F
P1::C2 got F
P2::C1 got G
P1::C4 got G
P2::C3 got G
P1::C1 got G
P1::C0 got G
P2::C4 got G
P2::C2 got G
P1::C3 got G
P2::C0 got G
P1::C2 got G
P1::C4 got H
P2::C1 got H
P2::C3 got H
P1::C1 got H
P2::C4 got H
P1::C0 got H
P2::C2 got H
P1::C3 got H
P1::C2 got H
P2::C0 got H
P1::C4 got I
P2::C1 got I
P1::C1 got I
P2::C3 got I
P2::C4 got I
P1::C0 got I
P1::C3 got I
P2::C2 got I
P1::C2 got I
P2::C0 got I
P1::C4 got J
P2::C1 got J
P2::C3 got J
P1::C1 got J
P2::C4 got J
P1::C0 got J
P1::C3 got J
P2::C2 got J
P1::C2 got J
P2::C0 got J
P2::C1 got K
P1::C4 got K
P2::C3 got K
P1::C1 got K
P2::C4 got K
P1::C0 got K
P1::C3 got K
P2::C2 got K
P2::C0 got K
P1::C2 got K
P2::C1 got L
P1::C4 got L
P2::C3 got L
P1::C1 got L
P1::C0 got L
P2::C4 got L
P1::C3 got L
P2::C2 got L
P1::C2 got L
P2::C0 got L
P1::C4 got M
P2::C1 got M
P2::C3 got M
P1::C1 got M
P2::C4 got M
P1::C0 got M
P1::C3 got M
P2::C2 got M
P1::C2 got M
P2::C0 got M
P2::C1 got N
P1::C4 got N
P2::C3 got N
P1::C1 got N
P1::C0 got N
P2::C4 got N
P1::C3 got N
P2::C2 got N
P1::C2 got N
P2::C0 got N
P2::C1 got O
P1::C4 got O
P1::C1 got O
P2::C3 got O
P1::C0 got O
P2::C4 got O
P2::C2 got O
P1::C3 got O
P2::C0 got O
P1::C2 got O
P2::C1 got P
P1::C4 got P
P2::C3 got P
P1::C1 got P
P2::C4 got P
P1::C0 got P
P1::C3 got P
P2::C2 got P
P2::C0 got P
P1::C2 got P
P1::C4 got Q
P2::C1 got Q
P2::C3 got Q
P1::C1 got Q
P1::C0 got Q
P2::C4 got Q
P1::C3 got Q
P2::C2 got Q
P1::C2 got Q
P2::C0 got Q
P2::C1 got R
P1::C4 got R
P1::C1 got R
P2::C3 got R
P1::C0 got R
P2::C4 got R
P1::C3 got R
P2::C2 got R
P2::C0 got R
P1::C2 got R
P2::C1 got S
P1::C4 got S
P1::C1 got S
P2::C3 got S
P2::C4 got S
P1::C0 got S
P1::C3 got S
P2::C2 got S
P2::C0 got S
P1::C2 got S
P1::C4 got T
P2::C1 got T
P1::C1 got T
P2::C3 got T
P1::C0 got T
P2::C4 got T
P1::C3 got T
P2::C2 got T
P1::C2 got T
P2::C0 got T
P1::C4 got U
P2::C1 got U
P2::C3 got U
P1::C1 got U
P1::C0 got U
P2::C4 got U
P2::C2 got U
P1::C3 got U
P1::C2 got U
P2::C0 got U
P1::C4 got V
P2::C1 got V
P1::C1 got V
P2::C3 got V
P1::C0 got V
P2::C4 got V
P1::C3 got V
P2::C2 got V
P1::C2 got V
P2::C0 got V
P1::C4 got W
P2::C1 got W
P1::C1 got W
P2::C3 got W
P1::C0 got W
P2::C4 got W
P1::C3 got W
P2::C2 got W
P2::C0 got W
P1::C2 got W
P2::C1 got X
P1::C4 got X
P1::C1 got X
P2::C3 got X
P2::C4 got X
P1::C0 got X
P2::C2 got X
P1::C3 got X
P1::C2 got X
P2::C0 got X
P1::C4 got Y
P2::C1 got Y
P1::C1 got Y
P2::C3 got Y
P2::C4 got Y
P1::C0 got Y
P1::C3 got Y
P2::C2 got Y
P2::C0 got Y
P1::C2 got Y
P2::C1 got Z
P1::C4 got Z
P2::C3 got Z
P1::C1 got Z
P1::C0 got Z
P2::C4 got Z
P1::C3 got Z
P2::C2 got Z
P1::C2 got Z
P2::C0 got Z

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment