Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
AsyncStreamでマルチブロードキャストを実装する
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
1mash0
May 20, 2026
Technology
280
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
AsyncStreamでマルチブロードキャストを実装する
DMM.swift #5
1mash0
May 20, 2026
More Decks by 1mash0
See All by 1mash0
Minecraft JavaのMODをSwiftで作る
1mash0
0
110
What's new in SwiftData + SwiftData Group Lab Recap
1mash0
0
49
SwiftData: Dive into inheritance and schema migration - Swift愛好会スピンオフ WWDC25セッション要約会
1mash0
0
490
SwiftDataのカスタムデータストアを試してみた
1mash0
0
360
Other Decks in Technology
See All in Technology
クロスボーダーM&AのValue Upを支えるプロダクト開発。日米チームのハブになったプロダクトエンジニアの実践 / Product Engineering Conference 2026
genda
0
120
すぐできる衛星通信対応 あとは山奥に行くだけ
tatetate55
0
110
SQL文一行も書けない人事がCortexもろもろを使って人事業務を楽にしてみる
ponponmikankan
1
220
AI活用の現在地、 ちゃんと見えてますか?/XPfest-2026
visional_engineering_and_design
0
210
AIに丸投げしないトイル削減 / Eliminating Toil Without Leaving It All to AI
kohbis
4
1.1k
GoCon2026 - Open Source, Open World
sanposhiho
4
3.4k
薬剤師(ドメインエキスパート)と一緒に育てる薬局向けAIアシスタント
kakehashi
PRO
2
160
アリアドネの糸と、20年ごとの建て替え ── 長尾真『電子図書館』を、伊勢で読み直す / Rereading Makoto Nagao’s "Electronic Library" in Ise
ykiyota
0
160
synctest時代のhttptest Go 1.27で変わるHTTPサーバテストの裏側 / go conference2026 synctest and httptest
budougumi0617
1
2.7k
作品が生態系になった ─ Mini Tokyo 3D から世界へ
nagix
0
170
AI時代、データエンジニアが一番おもろい
genshun9
0
280
深夜のクラウド懺悔室 1:29:300 or 1:0:0
kazzpapa3
1
240
Featured
See All Featured
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
67
58k
A Soul's Torment
seathinner
7
3.6k
Claude Code のすすめ
schroneko
67
230k
How to build a perfect <img>
jonoalderson
1
6k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
1k
The Curious Case for Waylosing
cassininazir
1
500
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
300
Visualization
eitanlees
152
17k
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
280
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.4k
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2.4k
Building a Scalable Design System with Sketch
lauravandoore
464
34k
Transcript
͍·͑͢ "TZOD4USFBNͰϚϧνϒϩʔυ ΩϟετΛ࣮͢Δ %..TXJGU !NBTO@
"TZOD4USFBN w "TZOD4USFBN"TZOD4FRVFODFʹ४ڌ w ඇಉظΠςϨʔλΛखಈͰ࣮͢Δ͜ͱͳ͘ඇಉظγʔέϯεΛ࡞Ͱ͖Δ w DBMMCBDLEFMFHBUFϕʔεͷ"1*ΛBTZODBXBJUʹରԠͤ͞Δͷʹదͯ͠Δ w "TZOD4USFBN$POUJOVBUJPOΛड͚औΔΫϩʔδϟΛ༻ͯ͠ॳظԽ͢Δ w
$POUJOVBUJPOZJFME @ ϝιουΛݺͼग़ͯ͠ཁૉΛετϦʔϜʹ͢ w $POUJOVBUJPO fi OJTI Ͱऴྃ͢Δ
let stream = AsyncStream<Int> { continuation in Task { var
count = 1 while !Task.isCancelled { continuation.yield(count) count += 1 try? await Task.sleep(for: .seconds(1)) } } } let taskA = Task { for await value in stream { print("Task A:", value) } } let taskB = Task { for await value in stream { print("Task B:", value) } } try? await Task.sleep(for: .seconds(3)) taskA.cancel() try? await Task.sleep(for: .seconds(3))
"TZOD4USFBNϒϩʔυΩϟετͰͳ͍ w ྫ͑$PNCJOFͷ1BTTUISPVHI4VCKFDUʮϒϩʔυΩϟετ͢Δʯͱઆ໌ ͞Ε͍ͯΔ ʮA subject that broadcasts elements to
downstream subscribers.ʯ w Ұํ"TZOD4USFBN"TZOD4FRVFODFΛ࡞͢Δܕͱͯ͠આ໌͞Ε͍ͯΔ ʮAn asynchronous sequence generated from a closure that calls a continuation to produce new elements.ʯ
4&
"TZOD4USFBNͰϚϧνϒϩʔυΩϟετͷ࣮ํ๏ w ߪಡऀ͝ͱʹ"TZOD4USFBNΛੜ͢Δ w ߪಡऀ͝ͱͷ$POUJOVBUJPOΛ66*%Ͱཧ͢Δ w PO5FSNJOBUJPOͰऴྃͨ͠$POUJOVBUJPOΛআ͢Δ w ݩͷΠϕϯτιʔε͚ͭͩʹ͢Δ w
શ$POUJOVBUJPOZJFME @ ͢Δ
"TZOD4USFBNͰϚϧνϒϩʔυΩϟετͷ࣮ํ๏ w ߪಡऀ͝ͱʹ"TZOD4USFBNΛੜ͢Δ w ߪಡऀ͝ͱͷ$POUJOVBUJPOΛ66*%Ͱཧ͢Δ w PO5FSNJOBUJPOͰऴྃͨ͠$POUJOVBUJPOΛআ͢Δ w ݩͷΠϕϯτιʔε͚ͭͩʹ͢Δ w
શ$POUJOVBUJPOZJFME @ ͢Δ
private var continuations: [UUID: AsyncStream<Int>.Continuation] = [:] func stream() ->
AsyncStream<Int> { let id = UUID() let (stream, continuation) = AsyncStream<Int>.makeStream( of: Int.self, bufferingPolicy: self.bufferingPolicy ) continuations[id] = continuation continuation.onTermination = { [weak self] _ in Task { await self?.removeContinuation(id) } } return stream }
4&
"TZOD4USFBNͰϚϧνϒϩʔυΩϟετͷ࣮ํ๏ w ߪಡऀ͝ͱʹ"TZOD4USFBNΛੜ͢Δ w ߪಡऀ͝ͱͷ$POUJOVBUJPOΛ66*%Ͱཧ͢Δ w PO5FSNJOBUJPOͰऴྃͨ͠$POUJOVBUJPOΛআ͢Δ w ݩͷΠϕϯτιʔε͚ͭͩʹ͢Δ w
શ$POUJOVBUJPOZJFME @ ͢Δ
continuation.onTermination = { [weak self] _ in Task { await
self?.removeContinuation(id) } } private func removeContinuation(_ id: UUID) { continuations[id] = nil }
"TZOD4USFBNͰϚϧνϒϩʔυΩϟετͷ࣮ํ๏ w ߪಡऀ͝ͱʹ"TZOD4USFBNΛੜ͢Δ w ߪಡऀ͝ͱͷ$POUJOVBUJPOΛ66*%Ͱཧ͢Δ w PO5FSNJOBUJPOͰऴྃͨ͠$POUJOVBUJPOΛআ͢Δ w ݩͷΠϕϯτιʔε͚ͭͩʹ͢Δ w
શ$POUJOVBUJPOZJFME @ ͢Δ
private var task: Task<Void, Never>? func start() { task?.cancel() task
= Task { [weak self] in var count = 1 while !Task.isCancelled { await self?.yield(count) count += 1 try? await Task.sleep(for: .seconds(1)) } } }
"TZOD4USFBNͰϚϧνϒϩʔυΩϟετͷ࣮ํ๏ w ߪಡऀ͝ͱʹ"TZOD4USFBNΛੜ͢Δ w ߪಡऀ͝ͱͷ$POUJOVBUJPOΛ66*%Ͱཧ͢Δ w PO5FSNJOBUJPOͰऴྃͨ͠$POUJOVBUJPOΛআ͢Δ w ݩͷΠϕϯτιʔε͚ͭͩʹ͢Δ w
શ$POUJOVBUJPOZJFME @ ͢Δ
func yield(_ value: Int) { for continuation in continuations.values {
continuation.yield(value) } } func finish() { task?.cancel() task = nil for continuation in continuations.values { continuation.finish() } continuations.removeAll() }
actor Broadcast { typealias BufferingPolicy = AsyncStream<Int>.Continuation .BufferingPolicy private var
continuations: [UUID: AsyncStream<Int>.Continuation] = [:] private let bufferingPolicy: BufferingPolicy private var task: Task<Void, Never>? init(bufferingPolicy: BufferingPolicy) { self.bufferingPolicy = bufferingPolicy } func stream() -> AsyncStream<Int> { let id = UUID() let (stream, continuation) = AsyncStream<Int>.makeStream( of: Int.self, bufferingPolicy: self.bufferingPolicy ) continuations[id] = continuation continuation.onTermination = { [weak self] _ in Task { await self?.removeContinuation(id) } } return stream } func start() { task?.cancel() task = Task { [weak self] in var count = 1 while !Task.isCancelled { await self?.yield(count) count += 1 try? await Task.sleep(for: .seconds(1)) } } } func yield(_ value: Int) { for continuation in continuations.values { continuation.yield(value) } } func finish() { task?.cancel() task = nil for continuation in continuations.values { continuation.finish() } continuations.removeAll() } private func removeContinuation(_ id: UUID) { continuations[id] = nil } }
let broadcast = Broadcast(bufferingPolicy: .bufferingNewest(1)) let stream1 = await broadcast.stream()
let stream2 = await broadcast.stream() let taskA = Task { for await value in stream1 { print("Task A:", value) } } let taskB = Task { for await value in stream2 { print("Task B:", value) } } await broadcast.start() try? await Task.sleep(for: .seconds(3)) taskA.cancel() try? await Task.sleep(for: .seconds(3))
·ͱΊ w ߪಡऀ͝ͱʹ"TZOD4USFBNΛੜ͢Δ w ߪಡऀ͝ͱͷ"TZOD4USFBN$POUJOVBUJPOΛཧΛ͢Δ w J04ະຬͳΒ66*%Ͱཧ w J04Ҏ্ͳΒ4FUͰཧ w
ݩͷΠϕϯτιʔε͕ॏෳ͠ͳ͍Α͏ʹҙ
TXJGUBTZODBMHPSJUINT w όʔδϣϯ ͔Β4IBSFػೳ͕ಋೖ͞ΕͯϚϧνϒϩʔυΩϟ ετʹରԠͨ͠ w ߪಡͯ͠Δ5BTLΛΩϟϯηϧͯ͠ɺͷ"TZOD4USFBNʹΩϟϯηϧ͕ ͠ͳ͍ͨΊҙ w
ߪಡͯ͠Δ5BTL͕ͬͯΔͱDPOUJOVBUJPOPO5FSNJOBUJPOʹྲྀΕͯ͜ͳ͍
import AsyncAlgorithms let stream = AsyncStream<Int> { continuation in Task
{ var count = 1 while !Task.isCancelled { continuation.yield(count) count += 1 try? await Task.sleep(for: .seconds(1)) } } }.share() let taskA = Task { for await value in stream { print("Task A:", value) } } let taskB = Task { for await value in stream { print("Task B:", value) } } try? await Task.sleep(for: .seconds(3)) taskA.cancel() try? await Task.sleep(for: .seconds(3))
·ͱΊ w ߪಡऀ͝ͱʹ"TZOD4USFBNΛੜ͢Δ w ߪಡऀ͝ͱͷ"TZOD4USFBN$POUJOVBUJPOΛཧΛ͢Δ w J04ະຬͳΒ66*%Ͱཧ w J04Ҏ্ͳΒ4FUͰཧ w
ݩͷΠϕϯτιʔε͕ॏෳ͠ͳ͍Α͏ʹҙ w TXJGUBTZODBMHPSJUINTΛ͓͏