رویدادها events
انتشاردهنده رویداد درون برنامه: موضوعهای نقطهدار با علامت جایگزین، کنشگر یکبار مصرف و نخ کارگر اختیاری.
واردسازی رویدادها
رویدادها یک مرکز ساده انتشار و اشتراک درون یک برنامه است. روی یک موضوع کنشگر ثبت میکنید و انتشار همه کنشگرهایی را که موضوعشان میخواند صدا میزند. نوع داده یک پارامتر است، پس هر انتشاردهنده یک نوع داده میبرد: انتشاردهنده<صحیح>، انتشاردهنده<رشته> یا انتشاردهندهای از ساختار خودتان.
موضوعها واژههایی هستند که با نقطه جدا شدهاند، مثل user.login. در موضوع کنشگر، * دقیقاً یک واژه و # باقی موضوع را، حتی اگر چیزی نمانده باشد، میپذیرد. پس user.* با user.login میخواند ولی با user.a.b نه، و order.# با order و order.new و order.new.eu میخواند.
چند نکته:
- کنشگر یک لامبدا است و لامبدا متغیرهای اطرافش را با مقدار میگیرد. وضعیت مشترک را با اشارهگر، مجموعه روی پشته یا متغیر سراسری
ناپایانگه دارید، مثل مثالها. - کنشگرها بیرون از قفل اجرا میشوند، پس یک کنشگر میتواند روی همان انتشاردهنده
روی،خاموشیاانتشاررا صدا بزند. کنشگری که در میان انتشار اضافه شود از رویداد بعدی به بعد را میبیند. روییک شناسه برمیگرداند وخاموشهمان شناسه را میگیرد. تابعها با هم مقایسه نمیشوند.- انتشاردهنده ناهمگام رویدادها را روی نخی که خودتان میدهید انجام میدهد.
جدید ناهمگامفقط صف را میسازد و نخی شروع نمیکند؛پردازش صفرا روی یک نخ خودتان اجرا کنید تا کنشگرها یکییکی و به ترتیب ورود به صف اجرا شوند.تخلیهصبر میکند تا صف خالی شود و آخرین کنشگر برگردد؛ هرگز آن را از درون کنشگر صدا نزنید. - انتشاردهنده را با
آزادکنآزاد کنید. برای ناهمگام، اولبستنرا صدا بزنید و به نخی کهپردازش صفرا اجرا میکند بپیوندید، چونآزادکنمنتظر آن نمیماند.
ثبت، انتشار، برداشتن
روی و یکبار یک موضوع و یک کنشگر میگیرند. روی همه همه رویدادها را میگیرد. انتشار میگوید چند کنشگر صدا زده شد.
واردسازی رویدادها
ناپایا e := رویدادها.جدید() برگردان رویدادها.انتشاردهنده<صحیح>
ناپایا log := وکتور {} برگردان وکتور<رشته>
تابع note(s: رشته):
log.بیفزا(s)
پایان
تابع ریشه:
e = رویدادها.جدید() برگردان رویدادها.انتشاردهنده<صحیح>
a := رویدادها.روی(e، "user.login"، (ev: رویدادها.رویداد<صحیح>): note("a " + ev.موضوع + " " + ev.داده) پایان)
b := رویدادها.روی(e، "user.*"، (ev: رویدادها.رویداد<صحیح>): note("b " + ev.موضوع + " " + ev.داده) پایان)
_c := رویدادها.یکبار(e، "user.login"، (ev: رویدادها.رویداد<صحیح>): note("once " + ev.داده) پایان)
_d := رویدادها.روی همه(e، (ev: رویدادها.رویداد<صحیح>): note("any " + ev.موضوع) پایان)
_f := رویدادها.روی(e، "order.#"، (ev: رویدادها.رویداد<صحیح>): note("order " + ev.موضوع) پایان)
سرچاپ "count login"، رویدادها.شمار(e، "user.login")
سرچاپ "count user.a.b"، رویدادها.شمار(e، "user.a.b")
سرچاپ "count order"، رویدادها.شمار(e، "order")
سرچاپ "count order.x.y"، رویدادها.شمار(e، "order.x.y")
سرچاپ "calls"، رویدادها.انتشار(e، "user.login"، 1)
سرچاپ "calls"، رویدادها.انتشار(e، "user.login"، 2)
سرچاپ "calls"، رویدادها.انتشار(e، "user.logout"، 3)
سرچاپ "calls"، رویدادها.انتشار(e، "order.new.eu"، 4)
سرچاپ "calls"، رویدادها.انتشار(e، "other"، 5)
سرچاپ "off a"، رویدادها.خاموش(e، a)
سرچاپ "off a again"، رویدادها.خاموش(e، a)
سرچاپ "off topic"، رویدادها.خاموش موضوع(e، "user.*")
سرچاپ "off b"، رویدادها.خاموش(e، b)
سرچاپ "len"، رویدادها.تعداد(e)
سرچاپ "calls"، رویدادها.انتشار(e، "user.login"، 6)
selfoff := رویدادها.روی(e، "x"، (ev: رویدادها.رویداد<صحیح>): note("x " + ev.داده) پایان)
_adder := رویدادها.روی(e، "x"، (_ev: رویدادها.رویداد<صحیح>):
_id := رویدادها.روی(e، "y"، (_v: رویدادها.رویداد<صحیح>): note("y") پایان)
_ok := رویدادها.خاموش(e، selfoff)
پایان)
سرچاپ "len before"، رویدادها.تعداد(e)
رویدادها.انتشار(e، "x"، 7)
سرچاپ "len after"، رویدادها.تعداد(e)
رویدادها.انتشار(e، "x"، 8)
تکرار log.طول() در i:
سرچاپ log.بگیر(i)
پایان
log.آزادکن()
رویدادها.آزادکن(e)
برگشت 0
پایانرویدادها روی نخ کارگر
جدید ناهمگام صفی با اندازه دادهشده میسازد و پردازش صف که روی نخ خودتان اجرا میشود کارگر آن است. انتشار ناهمگام رویداد را در صف میگذارد و فوراً برمیگردد و فقط وقتی صف پر باشد صبر میکند. بستن پذیرش را قطع میکند؛ پردازش صف آنچه را در صف است تمام میکند و برمیگردد، پس بعد از آن به نخ بپیوندید.
واردسازی رویدادها
واردسازی حافظه
ناپایا total := 0
ناپایا last := 0
ناپایا ordered := درست
ناپایا seen := 0
تابع add(ev: رویدادها.رویداد<صحیح>):
total = total + ev.داده
اگر ev.داده نابرابر last + 1:
ordered = نادرست
پایان
last = ev.داده
seen = seen + 1
پایان
تابع worker(p: رویدادها.انتشاردهنده<صحیح>*):
رویدادها.پردازش صف(p[0])
پایان
تابع ریشه:
e := رویدادها.جدید ناهمگام(4) برگردان رویدادها.انتشاردهنده<صحیح>
box := حافظه.تخصیص صفرشده(اندازهگونه(رویدادها.انتشاردهنده<صحیح>) برگردان طبیعی۶۴) برگردان رویدادها.انتشاردهنده<صحیح>*
box[0] = e
th := نخساز(worker، box)
_id := رویدادها.روی(e، "tick"، (ev: رویدادها.رویداد<صحیح>): add(ev) پایان)
سرچاپ "first queued"، رویدادها.انتشار ناهمگام(e، "tick"، 1)
تکرار 2 تا 200 در i:
_ok := رویدادها.انتشار ناهمگام(e، "tick"، i)
پایان
رویدادها.تخلیه(e)
سرچاپ "seen"، seen
سرچاپ "total"، total
سرچاپ "ordered"، ordered
سرچاپ "pending"، رویدادها.در انتظار(e)
_ok := رویدادها.انتشار ناهمگام(e، "tick"، 201)
_ok2 := رویدادها.انتشار ناهمگام(e، "other"، 999)
رویدادها.بستن(e)
نخپیوند(th)
سرچاپ "after close seen"، seen
سرچاپ "total"، total
سرچاپ "emit after close"، رویدادها.انتشار ناهمگام(e، "tick"، 5)
رویدادها.بستن(e)
plain := رویدادها.جدید() برگردان رویدادها.انتشاردهنده<صحیح>
سرچاپ "async on sync emitter"، رویدادها.انتشار ناهمگام(plain، "x"، 1)
رویدادها.آزادکن(plain)
رویدادها.آزادکن(e)
حافظه.آزادسازی(box برگردان تهی*)
برگشت 0
پایانساختار بهعنوان داده
نوع داده پارامتر است، پس یک ساختار مثل یک عدد جابهجا میشود: Emitter<Order> یک Order کامل را در ev.داده به هر دستگیره میدهد. روی همه همه موضوعها را میبیند، حتی آنهایی که کس دیگری به آنها گوش نمیدهد، و جای خوبی برای شمارنده ممیزی یا یک خط گزارش است. انتشار تعداد دستگیرههای اجراشده را برمیگرداند، پس order.shipped در مثال زیر ۱ میدهد (فقط دستگیره ممیزی).
واردسازی رویدادها
ناپایا revenue := 0
ناپایا audited := 0
ساختار Order:
همگانی id: صحیح = 0
همگانی item: رشته = ""
همگانی qty: صحیح = 0
پایان
تابع ریشه:
bus := رویدادها.جدید() برگردان رویدادها.انتشاردهنده<Order>
_a := رویدادها.روی(bus، "order.paid"، (ev: رویدادها.رویداد<Order>):
revenue += ev.داده.qty * 10
سرچاپ "paid"، ev.داده.id، ev.داده.item
پایان)
_b := رویدادها.روی(bus، "order.cancelled"، (ev: رویدادها.رویداد<Order>):
سرچاپ "cancelled"، ev.داده.id
پایان)
_c := رویدادها.روی همه(bus، (_ev: رویدادها.رویداد<Order>): audited += 1 پایان)
سرچاپ رویدادها.انتشار(bus، "order.paid"، Order { id = 1، item = "tea"، qty = 3 })
سرچاپ رویدادها.انتشار(bus، "order.cancelled"، Order { id = 2 })
سرچاپ رویدادها.انتشار(bus، "order.shipped"، Order { id = 1 })
سرچاپ "revenue"، revenue، "audited"، audited
رویدادها.آزادکن(bus)
پایانانتشار از داخل دستگیره
دستگیرهها بیرون از قفل انتشاردهنده اجرا میشوند، پس دستگیره میتواند دوباره روی همان انتشاردهنده منتشر کند. انتشار تودرتو دستگیرههایش را همان لحظه و پیش از بازگشت دستگیره بیرونی اجرا میکند و انتشار بیرونی همچنان فقط دستگیرههای خودش را میشمارد. این زنجیرهها را کوتاه نگه دارید و مطمئن شوید تمام میشوند، چون چیزی جلوی دستگیرهای را که بیقیدوشرط موضوع خودش را منتشر میکند نمیگیرد.
واردسازی رویدادها
ناپایا bus := رویدادها.جدید() برگردان رویدادها.انتشاردهنده<صحیح>
ناپایا depth := 0
تابع ریشه:
bus = رویدادها.جدید() برگردان رویدادها.انتشاردهنده<صحیح>
_a := رویدادها.روی(bus، "count"، (ev: رویدادها.رویداد<صحیح>):
سرچاپ "count"، ev.داده
اگر ev.داده < 3:
depth += 1
_n := رویدادها.انتشار(bus، "count"، ev.داده + 1)
پایان
پایان)
_b := رویدادها.روی(bus، "count"، (ev: رویدادها.رویداد<صحیح>):
اگر ev.داده == 3:
_n := رویدادها.انتشار(bus، "done"، ev.داده)
پایان
پایان)
_c := رویدادها.روی(bus، "done"، (ev: رویدادها.رویداد<صحیح>): سرچاپ "done at"، ev.داده پایان)
سرچاپ "handlers called"، رویدادها.انتشار(bus، "count"، 1)
سرچاپ "nested emits"، depth
رویدادها.آزادکن(bus)
پایانبرداشتن دستگیرههای یک بخش
بخشی که دستگیره ثبت میکند باید شناسهها را نگه دارد و هنگام رفتن پس بدهد، وگرنه انتشاردهنده کدی را صدا میزند که دیگر قرار نیست اجرا شود. خاموش یک شناسه میگیرد و تعداد پس از پاکسازی راه سادهای برای اطمینان از این است که چیزی جا نمانده. انتشار موضوعی که دستگیره ندارد خطا نیست و فقط ۰ برمیگرداند.
واردسازی رویدادها
ناپایا clicks := 0
ساختار Panel:
همگانی ids: وکتور<صحیح> = وکتور {}
پایان
تابع openPanel(bus: رویدادها.انتشاردهنده<رشته>): Panel:
ناپایا p := Panel {}
p.ids.بیفزا(رویدادها.روی(bus، "ui.click"، (_ev: رویدادها.رویداد<رشته>): clicks += 1 پایان))
p.ids.بیفزا(رویدادها.روی(bus، "ui.key.*"، (_ev: رویدادها.رویداد<رشته>): clicks += 10 پایان))
برگشت p
پایان
تابع closePanel(bus: رویدادها.انتشاردهنده<رشته>، p: Panel):
هر id در p.ids:
_ok := رویدادها.خاموش(bus، id)
پایان
p.ids.آزادکن()
پایان
تابع ریشه:
bus := رویدادها.جدید() برگردان رویدادها.انتشاردهنده<رشته>
p := openPanel(bus)
سرچاپ "open"، رویدادها.تعداد(bus)، رویدادها.انتشار(bus، "ui.click"، "a")، رویدادها.انتشار(bus، "ui.key.enter"، "b")
closePanel(bus، p)
سرچاپ "closed"، رویدادها.تعداد(bus)، رویدادها.انتشار(bus، "ui.click"، "c")
سرچاپ "clicks"، clicks
رویدادها.آزادکن(bus)
پایانگونهها
رویداد Event
ساختار رویداد<T>| نام | انگلیسی | گونه | توضیح |
|---|---|---|---|
| موضوع | topic | رشته = "" | موضوع کامل، مثل user.login. |
| داده | data | T | دادهای که به Emit داده شد. |
کنشگر Handler
ساختار کنشگر<T>| نام | انگلیسی | گونه | توضیح |
|---|---|---|---|
| شناسه | id | صحیح = 0 | شناسهای که On برگرداند. |
| الگو | pattern | رشته = "" | الگوی موضوعی که کنشگر با آن ثبت شد. |
| یک بار | once | منطقی = نادرست | کنشگر بعد از نخستین فراخوانی برداشته میشود. |
| تابع | cb | تابع(رویداد | تابعی که با رویداد صدا زده میشود. |
انتشاردهنده Emitter
ساختار انتشاردهنده<T>| نام | انگلیسی | گونه | توضیح |
|---|---|---|---|
| کنشگرها | hs | کنشگر | جدول کنشگرها. |
| قفل | mu | sync.Mutex | قفل جدول و صف. |
| وضعیت درونی | ctl | صحیح۶۴* | شمارندهها و پرچمهای صف. |
| ناهمگام | async | منطقی = نادرست | انتشاردهنده صف دارد، پس به نخی نیاز دارد که پردازش صف را اجرا کند. |
| صف | qbuf | رویداد | صف رویدادهایی که منتظر کارگرند. |
| شرط | cv | sync.CondVar | شرطی که کارگر و منتظرها را بیدار میکند. |
تابعها
جدید New
تابع جدید<T>(): انتشاردهنده<T>Emit کنشگرها را روی نخ فراخواننده صدا میزند.واردسازی رویدادها
ناپایا e := رویدادها.جدید() برگردان رویدادها.انتشاردهنده<صحیح>
ناپایا log := وکتور {} برگردان وکتور<رشته>
تابع note(s: رشته):
log.بیفزا(s)
پایان
تابع ریشه:
e = رویدادها.جدید() برگردان رویدادها.انتشاردهنده<صحیح>
a := رویدادها.روی(e، "user.login"، (ev: رویدادها.رویداد<صحیح>): note("a " + ev.موضوع + " " + ev.داده) پایان)
b := رویدادها.روی(e، "user.*"، (ev: رویدادها.رویداد<صحیح>): note("b " + ev.موضوع + " " + ev.داده) پایان)
_c := رویدادها.یکبار(e، "user.login"، (ev: رویدادها.رویداد<صحیح>): note("once " + ev.داده) پایان)
_d := رویدادها.روی همه(e، (ev: رویدادها.رویداد<صحیح>): note("any " + ev.موضوع) پایان)
_f := رویدادها.روی(e، "order.#"، (ev: رویدادها.رویداد<صحیح>): note("order " + ev.موضوع) پایان)
سرچاپ "count login"، رویدادها.شمار(e، "user.login")
سرچاپ "count user.a.b"، رویدادها.شمار(e، "user.a.b")
سرچاپ "count order"، رویدادها.شمار(e، "order")
سرچاپ "count order.x.y"، رویدادها.شمار(e، "order.x.y")
سرچاپ "calls"، رویدادها.انتشار(e، "user.login"، 1)
سرچاپ "calls"، رویدادها.انتشار(e، "user.login"، 2)
سرچاپ "calls"، رویدادها.انتشار(e، "user.logout"، 3)
سرچاپ "calls"، رویدادها.انتشار(e، "order.new.eu"، 4)
سرچاپ "calls"، رویدادها.انتشار(e، "other"، 5)
سرچاپ "off a"، رویدادها.خاموش(e، a)
سرچاپ "off a again"، رویدادها.خاموش(e، a)
سرچاپ "off topic"، رویدادها.خاموش موضوع(e، "user.*")
سرچاپ "off b"، رویدادها.خاموش(e، b)
سرچاپ "len"، رویدادها.تعداد(e)
سرچاپ "calls"، رویدادها.انتشار(e، "user.login"، 6)
selfoff := رویدادها.روی(e، "x"، (ev: رویدادها.رویداد<صحیح>): note("x " + ev.داده) پایان)
_adder := رویدادها.روی(e، "x"، (_ev: رویدادها.رویداد<صحیح>):
_id := رویدادها.روی(e، "y"، (_v: رویدادها.رویداد<صحیح>): note("y") پایان)
_ok := رویدادها.خاموش(e، selfoff)
پایان)
سرچاپ "len before"، رویدادها.تعداد(e)
رویدادها.انتشار(e، "x"، 7)
سرچاپ "len after"، رویدادها.تعداد(e)
رویدادها.انتشار(e، "x"، 8)
تکرار log.طول() در i:
سرچاپ log.بگیر(i)
پایان
log.آزادکن()
رویدادها.آزادکن(e)
برگشت 0
پایانروی On
تابع روی<T>(e: انتشاردهنده<T>، pattern: رشته، cb: تابع(رویداد<T>)): صحیحنمونهی این مورد همراه با موارد بالاتر آمده است: events-Basic.salam
یکبار Once
تابع یکبار<T>(e: انتشاردهنده<T>، pattern: رشته، cb: تابع(رویداد<T>)): صحیحنمونهی این مورد همراه با موارد بالاتر آمده است: events-Basic.salam
روی همه OnAny
تابع روی همه<T>(e: انتشاردهنده<T>، cb: تابع(رویداد<T>)): صحیحنمونهی این مورد همراه با موارد بالاتر آمده است: events-Basic.salam
خاموش Off
تابع خاموش<T>(e: انتشاردهنده<T>، id: صحیح): منطقینمونهی این مورد همراه با موارد بالاتر آمده است: events-Basic.salam
خاموش موضوع OffTopic
تابع خاموش موضوع<T>(e: انتشاردهنده<T>، pattern: رشته): صحیحنمونهی این مورد همراه با موارد بالاتر آمده است: events-Basic.salam
شمار Count
تابع شمار<T>(e: انتشاردهنده<T>، topic: رشته): صحیحنمونهی این مورد همراه با موارد بالاتر آمده است: events-Basic.salam
تعداد Len
تابع تعداد<T>(e: انتشاردهنده<T>): صحیحنمونهی این مورد همراه با موارد بالاتر آمده است: events-Basic.salam
انتشار Emit
تابع انتشار<T>(e: انتشاردهنده<T>، topic: رشته، data: T): صحیحنمونهی این مورد همراه با موارد بالاتر آمده است: events-Basic.salam
جدید ناهمگام NewAsync
تابع جدید ناهمگام<T>(capacity: صحیح): انتشاردهنده<T>پردازش صف را روی نخ خودتان اجرا کنید.واردسازی رویدادها
واردسازی حافظه
ناپایا total := 0
ناپایا last := 0
ناپایا ordered := درست
ناپایا seen := 0
تابع add(ev: رویدادها.رویداد<صحیح>):
total = total + ev.داده
اگر ev.داده نابرابر last + 1:
ordered = نادرست
پایان
last = ev.داده
seen = seen + 1
پایان
تابع worker(p: رویدادها.انتشاردهنده<صحیح>*):
رویدادها.پردازش صف(p[0])
پایان
تابع ریشه:
e := رویدادها.جدید ناهمگام(4) برگردان رویدادها.انتشاردهنده<صحیح>
box := حافظه.تخصیص صفرشده(اندازهگونه(رویدادها.انتشاردهنده<صحیح>) برگردان طبیعی۶۴) برگردان رویدادها.انتشاردهنده<صحیح>*
box[0] = e
th := نخساز(worker، box)
_id := رویدادها.روی(e، "tick"، (ev: رویدادها.رویداد<صحیح>): add(ev) پایان)
سرچاپ "first queued"، رویدادها.انتشار ناهمگام(e، "tick"، 1)
تکرار 2 تا 200 در i:
_ok := رویدادها.انتشار ناهمگام(e، "tick"، i)
پایان
رویدادها.تخلیه(e)
سرچاپ "seen"، seen
سرچاپ "total"، total
سرچاپ "ordered"، ordered
سرچاپ "pending"، رویدادها.در انتظار(e)
_ok := رویدادها.انتشار ناهمگام(e، "tick"، 201)
_ok2 := رویدادها.انتشار ناهمگام(e، "other"، 999)
رویدادها.بستن(e)
نخپیوند(th)
سرچاپ "after close seen"، seen
سرچاپ "total"، total
سرچاپ "emit after close"، رویدادها.انتشار ناهمگام(e، "tick"، 5)
رویدادها.بستن(e)
plain := رویدادها.جدید() برگردان رویدادها.انتشاردهنده<صحیح>
سرچاپ "async on sync emitter"، رویدادها.انتشار ناهمگام(plain، "x"، 1)
رویدادها.آزادکن(plain)
رویدادها.آزادکن(e)
حافظه.آزادسازی(box برگردان تهی*)
برگشت 0
پایانانتشار ناهمگام EmitAsync
تابع انتشار ناهمگام<T>(e: انتشاردهنده<T>، topic: رشته، data: T): منطقینمونهی این مورد همراه با موارد بالاتر آمده است: events-Async.salam
در انتظار Pending
تابع در انتظار<T>(e: انتشاردهنده<T>): صحیحنمونهی این مورد همراه با موارد بالاتر آمده است: events-Async.salam
تخلیه Flush
تابع تخلیه<T>(e: انتشاردهنده<T>)نمونهی این مورد همراه با موارد بالاتر آمده است: events-Async.salam
پردازش صف Drain
تابع پردازش صف<T>(e: انتشاردهنده<T>)نمونهی این مورد همراه با موارد بالاتر آمده است: events-Async.salam
بستن Close
تابع بستن<T>(e: انتشاردهنده<T>)پردازش صف صف را تمام میکند و برمیگردد. دوبار صدا زدنش بیخطر است.نمونهی این مورد همراه با موارد بالاتر آمده است: events-Async.salam
آزادکن Free
تابع آزادکن<T>(e: انتشاردهنده<T>)پردازش صف را اجرا میکند بپیوندید.نمونهی این مورد همراه با موارد بالاتر آمده است: events-Async.salam