mirror of
https://github.com/LiteyukiStudio/magicoca.git
synced 2024-11-15 13:24:25 +08:00
✨ 添加通道连接特性,可用+连接两个通道,连接后将交换双方的接收端
This commit is contained in:
parent
873123a99d
commit
ffd7847fb1
@ -1 +1,5 @@
|
|||||||
|
from multiprocessing import set_start_method
|
||||||
|
|
||||||
from magicoca.chan import Chan, T
|
from magicoca.chan import Chan, T
|
||||||
|
|
||||||
|
set_start_method("spawn", force=True)
|
@ -12,8 +12,8 @@ class Chan(Generic[T]):
|
|||||||
Chan is a simple channel implementation using multiprocessing.Pipe.
|
Chan is a simple channel implementation using multiprocessing.Pipe.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
_send_conn: The sending end of the pipe.
|
send_conn: The sending end of the pipe.
|
||||||
_recv_conn: The receiving end of the pipe.
|
recv_conn: The receiving end of the pipe.
|
||||||
|
|
||||||
Methods:
|
Methods:
|
||||||
send: Send a value to the channel.
|
send: Send a value to the channel.
|
||||||
@ -29,7 +29,7 @@ class Chan(Generic[T]):
|
|||||||
"""
|
"""
|
||||||
Initialize the channel.
|
Initialize the channel.
|
||||||
"""
|
"""
|
||||||
self._send_conn, self._recv_conn = Pipe()
|
self.send_conn, self.recv_conn = Pipe()
|
||||||
|
|
||||||
def send(self, value: T):
|
def send(self, value: T):
|
||||||
"""
|
"""
|
||||||
@ -37,9 +37,9 @@ class Chan(Generic[T]):
|
|||||||
Args:
|
Args:
|
||||||
value: The value to send.
|
value: The value to send.
|
||||||
"""
|
"""
|
||||||
self._send_conn.send(value)
|
self.send_conn.send(value)
|
||||||
|
|
||||||
def recv(self, timeout: float | None) -> T | None:
|
def recv(self, timeout: float | None = None) -> T | None:
|
||||||
"""Receive a value from the channel.
|
"""Receive a value from the channel.
|
||||||
If the timeout is None, it will block until a value is received.
|
If the timeout is None, it will block until a value is received.
|
||||||
If the timeout is a positive number, it will wait for the specified time, and if no value is received, it will return None.
|
If the timeout is a positive number, it will wait for the specified time, and if no value is received, it will return None.
|
||||||
@ -55,16 +55,16 @@ class Chan(Generic[T]):
|
|||||||
从通道接收的值。
|
从通道接收的值。
|
||||||
"""
|
"""
|
||||||
if timeout is not None:
|
if timeout is not None:
|
||||||
if not self._recv_conn.poll(timeout):
|
if not self.recv_conn.poll(timeout):
|
||||||
return None
|
return None
|
||||||
return self._recv_conn.recv()
|
return self.recv_conn.recv()
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
"""
|
"""
|
||||||
Close the channel. destructor
|
Close the channel. destructor
|
||||||
"""
|
"""
|
||||||
self._send_conn.close()
|
self.send_conn.close()
|
||||||
self._recv_conn.close()
|
self.recv_conn.close()
|
||||||
|
|
||||||
def __iter__(self) -> "Chan[T]":
|
def __iter__(self) -> "Chan[T]":
|
||||||
"""
|
"""
|
||||||
@ -91,3 +91,12 @@ class Chan(Generic[T]):
|
|||||||
Returns: The value received from the channel.
|
Returns: The value received from the channel.
|
||||||
"""
|
"""
|
||||||
return self.recv(None)
|
return self.recv(None)
|
||||||
|
|
||||||
|
def __add__(self, other: "Chan[T]") -> "Chan[T]":
|
||||||
|
"""
|
||||||
|
Connect 1 channel.send to another channel.recv.
|
||||||
|
Args:
|
||||||
|
other:
|
||||||
|
Returns:
|
||||||
|
"""
|
||||||
|
self.recv_conn, other.recv_conn = other.recv_conn, self.recv_conn
|
||||||
|
55
pdm.lock
55
pdm.lock
@ -5,7 +5,7 @@
|
|||||||
groups = ["default", "dev"]
|
groups = ["default", "dev"]
|
||||||
strategy = ["inherit_metadata"]
|
strategy = ["inherit_metadata"]
|
||||||
lock_version = "4.5.0"
|
lock_version = "4.5.0"
|
||||||
content_hash = "sha256:7448dc54658d779bbdd51b39ae72faf632280702d8719337a0fff377415332ba"
|
content_hash = "sha256:0036f04f76c33e040729d2763c99d933269bae8a2417a2f5846a78887dd196c9"
|
||||||
|
|
||||||
[[metadata.targets]]
|
[[metadata.targets]]
|
||||||
requires_python = ">=3.10"
|
requires_python = ">=3.10"
|
||||||
@ -45,6 +45,48 @@ files = [
|
|||||||
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
|
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mypy"
|
||||||
|
version = "1.11.2"
|
||||||
|
requires_python = ">=3.8"
|
||||||
|
summary = "Optional static typing for Python"
|
||||||
|
groups = ["dev"]
|
||||||
|
dependencies = [
|
||||||
|
"mypy-extensions>=1.0.0",
|
||||||
|
"tomli>=1.1.0; python_version < \"3.11\"",
|
||||||
|
"typing-extensions>=4.6.0",
|
||||||
|
]
|
||||||
|
files = [
|
||||||
|
{file = "mypy-1.11.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d42a6dd818ffce7be66cce644f1dff482f1d97c53ca70908dff0b9ddc120b77a"},
|
||||||
|
{file = "mypy-1.11.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:801780c56d1cdb896eacd5619a83e427ce436d86a3bdf9112527f24a66618fef"},
|
||||||
|
{file = "mypy-1.11.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41ea707d036a5307ac674ea172875f40c9d55c5394f888b168033177fce47383"},
|
||||||
|
{file = "mypy-1.11.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6e658bd2d20565ea86da7d91331b0eed6d2eee22dc031579e6297f3e12c758c8"},
|
||||||
|
{file = "mypy-1.11.2-cp310-cp310-win_amd64.whl", hash = "sha256:478db5f5036817fe45adb7332d927daa62417159d49783041338921dcf646fc7"},
|
||||||
|
{file = "mypy-1.11.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:75746e06d5fa1e91bfd5432448d00d34593b52e7e91a187d981d08d1f33d4385"},
|
||||||
|
{file = "mypy-1.11.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a976775ab2256aadc6add633d44f100a2517d2388906ec4f13231fafbb0eccca"},
|
||||||
|
{file = "mypy-1.11.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cd953f221ac1379050a8a646585a29574488974f79d8082cedef62744f0a0104"},
|
||||||
|
{file = "mypy-1.11.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:57555a7715c0a34421013144a33d280e73c08df70f3a18a552938587ce9274f4"},
|
||||||
|
{file = "mypy-1.11.2-cp311-cp311-win_amd64.whl", hash = "sha256:36383a4fcbad95f2657642a07ba22ff797de26277158f1cc7bd234821468b1b6"},
|
||||||
|
{file = "mypy-1.11.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e8960dbbbf36906c5c0b7f4fbf2f0c7ffb20f4898e6a879fcf56a41a08b0d318"},
|
||||||
|
{file = "mypy-1.11.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:06d26c277962f3fb50e13044674aa10553981ae514288cb7d0a738f495550b36"},
|
||||||
|
{file = "mypy-1.11.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6e7184632d89d677973a14d00ae4d03214c8bc301ceefcdaf5c474866814c987"},
|
||||||
|
{file = "mypy-1.11.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3a66169b92452f72117e2da3a576087025449018afc2d8e9bfe5ffab865709ca"},
|
||||||
|
{file = "mypy-1.11.2-cp312-cp312-win_amd64.whl", hash = "sha256:969ea3ef09617aff826885a22ece0ddef69d95852cdad2f60c8bb06bf1f71f70"},
|
||||||
|
{file = "mypy-1.11.2-py3-none-any.whl", hash = "sha256:b499bc07dbdcd3de92b0a8b29fdf592c111276f6a12fe29c30f6c417dd546d12"},
|
||||||
|
{file = "mypy-1.11.2.tar.gz", hash = "sha256:7f9993ad3e0ffdc95c2a14b66dee63729f021968bff8ad911867579c65d13a79"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mypy-extensions"
|
||||||
|
version = "1.0.0"
|
||||||
|
requires_python = ">=3.5"
|
||||||
|
summary = "Type system extensions for programs checked with the mypy type checker."
|
||||||
|
groups = ["dev"]
|
||||||
|
files = [
|
||||||
|
{file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
|
||||||
|
{file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "packaging"
|
name = "packaging"
|
||||||
version = "24.1"
|
version = "24.1"
|
||||||
@ -97,3 +139,14 @@ files = [
|
|||||||
{file = "tomli-2.0.2-py3-none-any.whl", hash = "sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38"},
|
{file = "tomli-2.0.2-py3-none-any.whl", hash = "sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38"},
|
||||||
{file = "tomli-2.0.2.tar.gz", hash = "sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed"},
|
{file = "tomli-2.0.2.tar.gz", hash = "sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typing-extensions"
|
||||||
|
version = "4.12.2"
|
||||||
|
requires_python = ">=3.8"
|
||||||
|
summary = "Backported and Experimental Type Hints for Python 3.8+"
|
||||||
|
groups = ["dev"]
|
||||||
|
files = [
|
||||||
|
{file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
|
||||||
|
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
|
||||||
|
]
|
||||||
|
@ -23,6 +23,7 @@ tag_regex = '^v(?:\D*)?(?P<version>([1-9][0-9]*!)?(0|[1-9][0-9]*)(\.(0|[1-9][0-9
|
|||||||
[tool.pdm.dev-dependencies]
|
[tool.pdm.dev-dependencies]
|
||||||
dev = [
|
dev = [
|
||||||
"pytest>=8.3.3",
|
"pytest>=8.3.3",
|
||||||
|
"mypy>=1.11.2",
|
||||||
]
|
]
|
||||||
[tool.pdm]
|
[tool.pdm]
|
||||||
distribution = true
|
distribution = true
|
||||||
|
@ -1,20 +1,16 @@
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
from magicoca.chan import Chan
|
from magicoca.chan import Chan
|
||||||
from multiprocessing import Process
|
from multiprocessing import Process, set_start_method
|
||||||
|
|
||||||
|
|
||||||
class TestChan:
|
|
||||||
def test_chan_shift(self):
|
|
||||||
ch = Chan[int]()
|
|
||||||
|
|
||||||
def p1f(chan: Chan[int]):
|
def p1f(chan: Chan[int]):
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
time.sleep(1)
|
|
||||||
chan << i
|
chan << i
|
||||||
chan << -1
|
chan << -1
|
||||||
|
|
||||||
def p2f(chan: Chan[int]):
|
def p2f(chan: Chan[int]):
|
||||||
recv_ans = []
|
recv_ans = []
|
||||||
while True:
|
while True:
|
||||||
a = int << chan
|
a = int << chan
|
||||||
@ -25,6 +21,14 @@ class TestChan:
|
|||||||
if recv_ans != list(range(10)) + [-1]:
|
if recv_ans != list(range(10)) + [-1]:
|
||||||
raise ValueError("Chan Shift Test Failed")
|
raise ValueError("Chan Shift Test Failed")
|
||||||
|
|
||||||
|
class TestChan:
|
||||||
|
|
||||||
|
def test_test(self):
|
||||||
|
print("Test is running")
|
||||||
|
|
||||||
|
def test_chan_shift(self):
|
||||||
|
"""测试运算符"""
|
||||||
|
ch = Chan[int]()
|
||||||
print("Test Chan Shift")
|
print("Test Chan Shift")
|
||||||
p1 = Process(target=p1f, args=(ch,))
|
p1 = Process(target=p1f, args=(ch,))
|
||||||
p2 = Process(target=p2f, args=(ch,))
|
p2 = Process(target=p2f, args=(ch,))
|
||||||
@ -34,25 +38,9 @@ class TestChan:
|
|||||||
p2.join()
|
p2.join()
|
||||||
|
|
||||||
def test_chan_sr(self):
|
def test_chan_sr(self):
|
||||||
|
"""测试收发"""
|
||||||
ch = Chan[int]()
|
ch = Chan[int]()
|
||||||
|
|
||||||
def p1f(chan: Chan[int]):
|
|
||||||
for i in range(10):
|
|
||||||
time.sleep(1)
|
|
||||||
chan.send(i)
|
|
||||||
chan.send(-1)
|
|
||||||
|
|
||||||
def p2f(chan: Chan[int]):
|
|
||||||
recv_ans = []
|
|
||||||
while True:
|
|
||||||
a = chan.recv()
|
|
||||||
recv_ans.append(a)
|
|
||||||
print("Recv2", a)
|
|
||||||
if a == -1:
|
|
||||||
break
|
|
||||||
if recv_ans != list(range(10)) + [-1]:
|
|
||||||
raise ValueError("Chan SR Test Failed")
|
|
||||||
|
|
||||||
print("Test Chan SR")
|
print("Test Chan SR")
|
||||||
p1 = Process(target=p1f, args=(ch,))
|
p1 = Process(target=p1f, args=(ch,))
|
||||||
p2 = Process(target=p2f, args=(ch,))
|
p2 = Process(target=p2f, args=(ch,))
|
||||||
@ -60,3 +48,18 @@ class TestChan:
|
|||||||
p2.start()
|
p2.start()
|
||||||
p1.join()
|
p1.join()
|
||||||
p2.join()
|
p2.join()
|
||||||
|
|
||||||
|
def test_connect(self):
|
||||||
|
"""测试双通道连接"""
|
||||||
|
chan1 = Chan[int]()
|
||||||
|
chan2 = Chan[int]()
|
||||||
|
|
||||||
|
chan1 + chan2
|
||||||
|
|
||||||
|
print("Test Chan Connect")
|
||||||
|
p1 = Process(target=p1f, args=(chan1,))
|
||||||
|
p2 = Process(target=p2f, args=(chan2,))
|
||||||
|
p1.start()
|
||||||
|
p2.start()
|
||||||
|
p1.join()
|
||||||
|
p2.join()
|
||||||
|
Loading…
Reference in New Issue
Block a user