PubSub

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Avatar de l’utilisateur
❤x1
Messages : 16
Inscription : jeu. 10/janv./2019 17:26
Contact :

PubSub

Message par ❤x1 »

Salut les gens!

Vous connaissez le concept du Pub/Sub? C'est trop bien le Pub/Sub! C'est super pratique pour les projets amateurs parce que ça aide à garder le code propre au fur et à mesure qu'il grandit!

Vous savez quel langage n'avait pas de Pub/Sub jusqu'ici ? Purebasic! Mais ça, c'était avant.

Code : Tout sélectionner

;============================================================
;  PubSub.pbi
;
;  Lightweight pub-sub for PureBasic apps. Independent of PureBasic's built-in event loop: use any integer as an event ID and route it through Subscribe / Emit.
;
;  Features:
;    - Subscribe / Unsubscribe / Emit
;    - Clear / ClearAll
;    - Optional payload pointer carried to every listener
;    - Listener priorities (higher fires first)
;    - One-shot listeners (auto-removed after their first call)
;    - Safe under re-entrant emits from inside a callback
;
;  Usage:
;    Procedure OnSomething(EventID, *Payload)
;       Debug "fired: " + EventID
;    EndProcedure
;
;    PubSub::Subscribe(#MyEvent, @OnSomething(), PubSub::#Priority_High)
;    PubSub::Emit(#MyEvent)
;

DeclareModule PubSub
	; Callback signature. Every listener gets the event ID it was fired for and the *Payload pointer that the emitter passed (which may be #Null).
	Prototype Listener(EventID, *Payload)
	
	Enumeration ; Priority shortcuts. Any integer works; these are just helpers.
		#Priority_Lowest  = -1000
		#Priority_Low     = -100
		#Priority_Normal  = 0
		#Priority_High    = 100
		#Priority_Highest = 1000
	EndEnumeration
	
	; Public procedures declaration
	Declare   Subscribe(EventID.i, *Callback.Listener, Priority.l = #Priority_Normal, OneShot.a = #False)
	Declare   Unsubscribe(EventID.i, *Callback.Listener)
	Declare   Emit(EventID.i, *Payload = #Null)
	Declare   Clear(EventID.i)
	Declare   ClearAll()
	Declare.i ListenerCount(EventID.i)
EndDeclareModule

Module PubSub
	EnableExplicit
	; Private variables, structures and constants
	Structure ListenerEntry
		Callback.i
		Priority.l
		OneShot.a
	EndStructure
	
	Structure EventBucket
		EventID.i
		List Listeners.ListenerEntry()
	EndStructure
	
	Global NewMap Events.EventBucket()
	
	; Public procedures
	Procedure Subscribe(EventID.i, *Callback.Listener, Priority.l = #Priority_Normal, OneShot.a = #False)
		Protected Key.s = Str(EventID)
		Protected Inserted = #False
		
		If Not FindMapElement(Events(), Key)
			AddMapElement(Events(), Key)
			Events()\EventID = EventID
		EndIf
		
		; Insert before the first existing listener with strictly lower priority, so equal-priority listeners preserve subscription order (FIFO).
		ForEach Events()\Listeners()
			If Events()\Listeners()\Priority < Priority
				InsertElement(Events()\Listeners())
				Inserted = #True
				Break
			EndIf
		Next
		
		If Not Inserted
			LastElement(Events()\Listeners())
			AddElement(Events()\Listeners())
		EndIf
		
		Events()\Listeners()\Callback = *Callback
		Events()\Listeners()\Priority = Priority
		Events()\Listeners()\OneShot  = OneShot
	EndProcedure
	
	Procedure Unsubscribe(EventID.i, *Callback.Listener)
		Protected Key.s = Str(EventID)
		
		If Not FindMapElement(Events(), Key)
			ProcedureReturn
		EndIf
		
		ForEach Events()\Listeners()
			If Events()\Listeners()\Callback = *Callback
				DeleteElement(Events()\Listeners())
				Break
			EndIf
		Next
		
		If ListSize(Events()\Listeners()) = 0
			DeleteMapElement(Events())
		EndIf
	EndProcedure
	
	Procedure Emit(EventID.i, *Payload = #Null)
		Protected Key.s = Str(EventID)
		Protected i, Count
		Protected Cb.Listener
		
		If Not FindMapElement(Events(), Key)
			ProcedureReturn
		EndIf
		
		Count = ListSize(Events()\Listeners())
		If Count = 0
			ProcedureReturn
		EndIf
		
		; Snapshot listeners before firing; a callback may Subscribe, Unsubscribe, Clear, or Emit recursively, and we must not let that corrupt iteration of the live list.
		Protected Dim Snapshot.ListenerEntry(Count - 1)
		i = 0
		ForEach Events()\Listeners()
			Snapshot(i)\Callback = Events()\Listeners()\Callback
			Snapshot(i)\Priority = Events()\Listeners()\Priority
			Snapshot(i)\OneShot  = Events()\Listeners()\OneShot
			i + 1
		Next
		
		; Fire snapshot in stored order (already priority-sorted).
		For i = 0 To Count - 1
			Cb = Snapshot(i)\Callback
			Cb(EventID, *Payload)
		Next
		
		; Sweep one-shots that fired. The bucket may have been mutated
		; or removed by a recursive call, so re-find before touching.
		If FindMapElement(Events(), Key)
			For i = 0 To Count - 1
				If Snapshot(i)\OneShot
					ForEach Events()\Listeners()
						If Events()\Listeners()\Callback = Snapshot(i)\Callback And Events()\Listeners()\OneShot
							DeleteElement(Events()\Listeners())
							Break
						EndIf
					Next
				EndIf
			Next
			
			If ListSize(Events()\Listeners()) = 0
				DeleteMapElement(Events())
			EndIf
		EndIf
	EndProcedure
	
	Procedure Clear(EventID.i)
		Protected Key.s = Str(EventID)
		If FindMapElement(Events(), Key)
			DeleteMapElement(Events())
		EndIf
	EndProcedure
	
	Procedure ClearAll()
		ClearMap(Events())
	EndProcedure
	
	Procedure.i ListenerCount(EventID.i)
		Protected Key.s = Str(EventID)
		If FindMapElement(Events(), Key)
			ProcedureReturn ListSize(Events()\Listeners())
		EndIf
		ProcedureReturn 0
	EndProcedure
EndModule

CompilerIf #PB_Compiler_IsMainFile
	XIncludeFile "PubSub.pbi"
	
	#Event_Hello = 1
	#Event_Bye   = 2
	
	Procedure A(EventID, *Payload)
		Debug "A fired on " + EventID
	EndProcedure
	
	Procedure B(EventID, *Payload)
		Debug "B fired on " + EventID + "  payload=" + PeekS(*Payload)
	EndProcedure
	
	Procedure Once(EventID, *Payload)
		Debug "one-shot fired on " + EventID
	EndProcedure
	
	PubSub::Subscribe(#Event_Hello, @A(), PubSub::#Priority_Low)
	PubSub::Subscribe(#Event_Hello, @B(), PubSub::#Priority_High)   ; fires before A
	PubSub::Subscribe(#Event_Hello, @Once(), PubSub::#Priority_Normal, #True)
	
	Define msg.s = "world"
	PubSub::Emit(#Event_Hello, @msg)   ; B, Once, A
	PubSub::Emit(#Event_Hello, @msg)   ; B, A   (Once is gone)
	
	Debug "listeners on #Event_Hello: " + PubSub::ListenerCount(#Event_Hello)
	PubSub::ClearAll()
	Debug "after ClearAll: " + PubSub::ListenerCount(#Event_Hello)
CompilerEndIf
Mon blog : https://lastlife.net/
Mes trucs PB en open source : Inputify, UITK, SelfHost.
Mes trucs SB en open source : MaterialSB
Avatar de l’utilisateur
case
Messages : 1566
Inscription : lun. 10/sept./2007 11:13

Re: PubSub

Message par case »

non j'ai pas trop compris le pub/sub
j'ai pas le temps de tester le code ce soir mais je regarderai si je peux comprendre ^^
merci du partage
ImageImage
Avatar de l’utilisateur
Kwai chang caine
Messages : 7086
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: PubSub

Message par Kwai chang caine »

Vous connaissez le concept du Pub/Sub?
Évidemment que non :oops:

Et alors cette fois... Je sens que je suis pas prêt de le connaître :|
Et si en plus CASE a pas compris immédiatement autant dire que c'est même pas la peine que j'essaie :wink:

j'ai lu au moins 10 descriptions de ce phénomène... Et chaque explication était encore plus compliqué à comprendre que la précédente 8O
Noirs de mots venant d'une autre planète se sont bousculés dans le bidet qui me sert de tête...

Service globalisé de messagerie asynchrone
Middleware de messagerie
Publish-subscribe
Rubriques
Abonnés
Apache Kafla
Kinesis
Rabbitmq
Firebase

Ce qui est bien avec toi, c'est qu'à chacune ou presque de tes combines j'ai l'impression d'avoir 3 ans et jamais avoir touché un clavier de ma vie :mrgreen:

En tout cas merci de m'avoir complexé encore un peu plus :lol: 8)
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel
Avatar de l’utilisateur
TazNormand
Messages : 1300
Inscription : ven. 27/oct./2006 12:19
Localisation : Calvados (14)

Re: PubSub

Message par TazNormand »

Salut @tou(te)s

@KCC: regarde la page Wikipedia : https://fr.wikipedia.org/wiki/Publish-subscribe

En gros, tu as des "éditeurs" qui publie du contenu catégorisé sans se soucier si derrière il y a des "abonnés" à ces catégories", et tu as les "lecteurs" qui sont abonnés à des catégories sans pour autant que tu contenu soit publié régulièrement

Pour faire simple :
KCC aime et publie dans les catégories :
  • cuisiner
    programmer en PB
    La formule 1
    Regarder toktik
Sam (moi) aime lire :
  • programmer en PB
    cuisiner
Case aime lire :
  • Programmer en PB
    La formule 1
Donc toi KCC tu publies dans les 4 catégories, moi je ne suis abonné à 2, Case à 2 autres dont une commune, et personne ne lit toktik

mais toi, tu t'en moques, tu publies partout de toute façon, et si un jour Shadow passe par là et se dit tient je vais m'abonner à toktik, il aura accès au contenu.

Enfin si j'ai bien compris le principe

@+
Image
Image
Avatar de l’utilisateur
Kwai chang caine
Messages : 7086
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: PubSub

Message par Kwai chang caine »

Merci beaucoup TAZ de ta longue explication 8)

Et ben ....c'est pas des choses pour les vieux ça :oops:
C'est impressionnant tous ces trucs qui sortent presque quotidiennement pour faire papa maman et qui compliquent encore plus l'utilisation des versions de base, comme si elles en avait déjà besoin :?
Avant...il se créait quelque chose, c'était un réel besoin, on comprenait tous parce que chacun avait eu le problème un jour ou l'autre 8)
Maintenant, y'a une tronche qui pond un œuf sur quelque chose qui rajoute une couche ou modifie quelque chose que parfois on ne connait déjà pas :lol:

La seule chose que j'avoue avoir résisté au maximum en trouvant ça ridicule quand j'en en entendait parler de partout, car j'y croyait pas, c'est l'IA :oops: "Mi a coule pas" :mrgreen: Après...c'est des révolutions qui font parfois pschiiit !!! comme aurait dit jacko :mrgreen:
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel
Avatar de l’utilisateur
TazNormand
Messages : 1300
Inscription : ven. 27/oct./2006 12:19
Localisation : Calvados (14)

Re: PubSub

Message par TazNormand »

Salut

On est depuis plusieurs années dans une société de consommateurs passifs, avec de la consommation à outrance, je parle de conso de médias (toktik, instadram, ...)

Perso je "consomme" un peu sur insta (impression 3d, pâtisserie, électronique FLTM (DIY en anglais), humoristes...) et sur FlipBoard, l'avantage donc de s'abonner à des thématiques choisies (pub/sub donc) mais c'est vite chronophage sans que tu t'en aperçoives, tu as bouffé 1h à regarder des tutos courts sur l’impression 3d ou sur l'électronique.

Concernant l'IA, c'est un incontournable qui ne fera pas "pschitt", perso je m'en sers pour lui faire générer des scripts PowerShell pour mon taf sur de petites tâches, mais j'ai vu sur une appli un peu plus "lourde" avec même une GUI, et c'est bluffant, mais j'ai un avantage sur les + jeunes : je peux regarder ce que fais le code et le corriger ou l'adapter à mes besoins/spécificités.

Le souci est que les jeunes n'ont pas vraiment l'esprit critique, ni la connaissance approfondie pour juger et font une confiance aveugle au code généré sans le contrôler voir même le comprendre pour certains (je généralise, mais je pense que c'est quand même la tendance majoritaire)

L'IA s'introduit partout, ma femme demande des conseils à Gemini pour organiser des week-ends, et franchement en 5 minutes, tu as la même chose que ce que tu peux rechercher toi-même pendant 3h. Et je ne parle pas des questions sur le jardin, les questions "médicales"...

Ce qui m'inquiète pour l'avenir de mes enfants et de ceux de leur générations (18-25 ans) c'est que certains métiers vont disparaître avant même qu'ils aient eu le temps de commencer une carrière.

Bon, je suis hors-sujet pour le coup, désolé ❤x1 pour la pollution de ton topic

Bonne journée à tou(te)s

Aussi, quid des gens dont le niveau intellectuel (sans dénigrement) ou de formation ne leur permet pas de prétendre à certains métiers. C'est comme les caisses automatiques des supermarchés : le job de caissière n'est surement pas un job épanouissant, mais il a le mérite de permettre à certaines personnes de pouvoir travailler et gagner de l'argent.

Je vous conseille le film "Idiocracy", qui prend un aspect effrayant de nos jours
Image
Image
Répondre