Register for your free account! | Forgot your password?

Go Back   elitepvpers > Coders Den > C/C++
You last visited: Today at 04:17

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



SimpleSig - minimalistic signal/slots lib for C++

Discussion on SimpleSig - minimalistic signal/slots lib for C++ within the C/C++ forum part of the Coders Den category.

Reply
 
Old 10/20/2013, 18:36   #16
 
Master674b's Avatar
 
elite*gold: 0
Join Date: Dec 2012
Posts: 255
Received Thanks: 110
Quote:
Originally Posted by Tasiro View Post
Warum so kompliziert void etc. ausschalten? Es reicht, ProxyRet<void> zu spezialisieren und ProxyRet<const void> etc. davon ableiten zu lassen.


std::move ist in utility definiert. std::enable_if in type_traits.


Compare (InputIterator first, InputIterator last): Die Benennung last ist irreführend. last wird niemals dereferenziert.


Minimum und Maximum sind einfacher mit std::min_element und std::max_element zu implementieren, Signal::size mit std::count_if.


ProxyRet <R> operator () (const Args &... args) const: Was ist mit "perfect forwarding"?


Warum muss ich die "custom-compare Funktionen" in eine Klasse packen, Compare nennen und zu Templatefunktionen machen? Warum nicht das Konzept der Funktionsobjekte wie in der Standardbibliothek unterstützen?


_generic_invoke(const FuncT& function): Wie wäre es mit remove_if?
Es müsste so gehen, ich habe es nicht getestet:
Code:
template <typename FuncT>
void _generic_invoke (const FuncT & function) const {
	Detail::CallLock g (m_callLock);
	m_connections.remove_if ([& function] (const std::shared_ptr <Detail::ConnectionBase <signature_t>> & connection) {
		if (! connection->connected ())
			return true;
		function (connection->connectedSlot);
		return false;
	});
}
mutable und const heißen beide "ist thread-sicher", oder sollten es. Auch ein konstantes Objekt (oder const T&) braucht ein veränderliches Objekt der Klasse std::mutex.
1. Jo, wäre auch eine Möglichkeit, wohl grade einfach nicht daran gedacht.
2. Ups, type_traits vergessen.
3. Vielleicht, nennt boost und stl aber genauso.
4. Stimmt, die fordern nur noch nen algorithm include auf den ich so auch verzichten kann.
5. Perfect forwarding geht hier nicht. Es sind ja mehrere Funktionen, die die Argumente brauchen. Würde es bei der 1. Funktion in einem move resultieren, hätten die restlichen ein leeres Ergebnis, da das Argument gemoved wurde.
6. kA wie meinst du denn? mit ner Predicate Funktion als invoke Argument?
7. Nicht gesehen, dass std::forward_list eine remove_if Funktion anbietet.
Master674b is offline  
Old 10/20/2013, 19:36   #17


 
MrSm!th's Avatar
 
elite*gold: 7110
Join Date: Jun 2009
Posts: 28,904
Received Thanks: 25,394
Quote:
mutable und const heißen beide "ist thread-sicher", oder sollten es. Auch ein konstantes Objekt (oder const T&) braucht ein veränderliches Objekt der Klasse std::mutex.
Achso, mir ist entgangen, dass es sich nur um einzelne Member und nicht das ganze Objekt dreht.

Nochmal zu std::function, weil ich mir eigentlich sicher war, dass std::function zu dem Zweck existiert, der Arbeit mit Lambdas, Functors und normalen Funktionspointern eine gemeinsame Schnittstelle anzubieten. Also müsste doch ein Parameter vom Typ std::function auch alle 3 fassen können, oder habe ich da etwas falsch verstanden?
MrSm!th is offline  
Old 10/20/2013, 21:27   #18
 
elite*gold: 0
Join Date: Aug 2012
Posts: 236
Received Thanks: 94
Quote:
Originally Posted by Master674b View Post
6. kA wie meinst du denn? mit ner Predicate Funktion als invoke Argument?
Es wäre schön, wenn ich ein Lambda nutzen könnte.
static Compare ist nicht so schön wie operator () (iter begin, iter end) const.

Quote:
Originally Posted by MrSm!th View Post
Nochmal zu std::function, weil ich mir eigentlich sicher war, dass std::function zu dem Zweck existiert, der Arbeit mit Lambdas, Functors und normalen Funktionspointern eine gemeinsame Schnittstelle anzubieten. Also müsste doch ein Parameter vom Typ std::function auch alle 3 fassen können, oder habe ich da etwas falsch verstanden?
std::function akzeptiert so ziemlich alles als Argument, nur ist es i. Allg. langsamer. Hier nicht, da der Typ der Slots nicht bekannt ist.
Tasiro is offline  
Old 10/20/2013, 21:58   #19
 
Master674b's Avatar
 
elite*gold: 0
Join Date: Dec 2012
Posts: 255
Received Thanks: 110
Quote:
Originally Posted by Tasiro View Post
Es wäre schön, wenn ich ein Lambda nutzen könnte.
static Compare ist nicht so schön wie operator () (iter begin, iter end) const.

std::function akzeptiert so ziemlich alles als Argument, nur ist es i. Allg. langsamer. Hier nicht, da der Typ der Slots nicht bekannt ist.
Ist aber ein Problem, wenn es ein Template ist, dann müsstest du den so aufrufen:

Code:
CompareF::operator()<T>(...);
das ist dann nicht mehr so schön. Da müsste dann der Funktor als template definiert werden.
Master674b is offline  
Old 10/20/2013, 22:21   #20
 
elite*gold: 0
Join Date: Aug 2012
Posts: 236
Received Thanks: 94
Quote:
Originally Posted by Master674b View Post
Ist aber ein Problem, wenn es ein Template ist, dann müsstest du den so aufrufen:

Code:
CompareF::operator()<T>(...);
das ist dann nicht mehr so schön. Da müsste dann der Funktor als template definiert werden.
Ja, wie std::less. Als Operation übergebe ich etwa std::less <int> ().
Auf deine Signale bezogen, wäre das dann z. B.:
Code:
std::cout << Signal <int (int, int, int)> ({slot1, slot2}).invoke ({1, 2, 3}, [] (std::initializer_list <int> results) {
    return std::max_element (results.begin (), results.end ());
}):
Tasiro is offline  
Old 10/21/2013, 13:35   #21
 
Master674b's Avatar
 
elite*gold: 0
Join Date: Dec 2012
Posts: 255
Received Thanks: 110
Ok, überleg ich mir.
Master674b is offline  
Old 10/21/2013, 23:21   #22
 
elite*gold: 0
Join Date: Aug 2012
Posts: 236
Received Thanks: 94
Ich sehe gerade - es sind std::unique_ptr, std::shared_ptr und std::weak_ptr dabei, fehlt nur noch std::auto_ptr.
Könntest du mir bitte erklären, wozu du std::shared_ptr brauchst (und nicht std::unique_ptr und T*, oder std::shared_ptr<const T>)? Es wäre schön, ein Beispiel dafür zu haben.

Es fehlt vielleicht noch der ein oder andere Kommentar hier und da, etwa bei ProxyRet<const void>.
Tasiro is offline  
Old 10/21/2013, 23:50   #23
 
Master674b's Avatar
 
elite*gold: 0
Join Date: Dec 2012
Posts: 255
Received Thanks: 110
Quote:
Originally Posted by Tasiro View Post
Ich sehe gerade - es sind std::unique_ptr, std::shared_ptr und std::weak_ptr dabei, fehlt nur noch std::auto_ptr.
Könntest du mir bitte erklären, wozu du std::shared_ptr brauchst (und nicht std::unique_ptr und T*, oder std::shared_ptr<const T>)? Es wäre schön, ein Beispiel dafür zu haben.

Es fehlt vielleicht noch der ein oder andere Kommentar hier und da, etwa bei ProxyRet<const void>.
Connection Objekte können geshared werden. Deswegen, geht gar nicht mit nem unique_ptr.
Master674b is offline  
Old 10/22/2013, 00:56   #24
 
elite*gold: 0
Join Date: Aug 2012
Posts: 236
Received Thanks: 94
Quote:
Originally Posted by Master674b View Post
Connection Objekte können geshared werden.
Wie? Durch Kopieren des Signals? Wenn ich dann eine Kopie erstelle und danach die vorher dem Orginal hinzugefügte Verbindung trenne, wird doch aber auch in der (vielleicht genau deswegen erstellten) Kopie das Signal getrennt... Soll das so?

Beispiel:
Code:
int f () { return 1; }
int g () { return 2; }

int main () {
	SimpleSig::Signal <int ()> signal1;
	auto connection1 (signal1.connect (f));
	auto connection2 (signal1.connect (g));
	std::cout << * signal1.invoke <SimpleSig::Maximum> () << '\n';
	auto signal2 (signal1);
	std::cout << * signal1.invoke <SimpleSig::Maximum> () << " - " << * signal2.invoke <SimpleSig::Maximum> () << '\n';
	connection2.disconnect ();
	std::cout << * signal1.invoke <SimpleSig::Maximum> () << " - " << * signal2.invoke <SimpleSig::Maximum> () << '\n';
	std::cin.get ();
}

//Ausgabe:
// 2
// 2 - 2
// 1 - 1
Tasiro is offline  
Old 10/22/2013, 14:39   #25
 
Master674b's Avatar
 
elite*gold: 0
Join Date: Dec 2012
Posts: 255
Received Thanks: 110
Quote:
Originally Posted by Tasiro View Post
Wie? Durch Kopieren des Signals? Wenn ich dann eine Kopie erstelle und danach die vorher dem Orginal hinzugefügte Verbindung trenne, wird doch aber auch in der (vielleicht genau deswegen erstellten) Kopie das Signal getrennt... Soll das so?

Beispiel:
Code:
int f () { return 1; }
int g () { return 2; }

int main () {
	SimpleSig::Signal <int ()> signal1;
	auto connection1 (signal1.connect (f));
	auto connection2 (signal1.connect (g));
	std::cout << * signal1.invoke <SimpleSig::Maximum> () << '\n';
	auto signal2 (signal1);
	std::cout << * signal1.invoke <SimpleSig::Maximum> () << " - " << * signal2.invoke <SimpleSig::Maximum> () << '\n';
	connection2.disconnect ();
	std::cout << * signal1.invoke <SimpleSig::Maximum> () << " - " << * signal2.invoke <SimpleSig::Maximum> () << '\n';
	std::cin.get ();
}

//Ausgabe:
// 2
// 2 - 2
// 1 - 1
Jo das soll so sein. Findest du das negativ? Du kannst die Connection-Objekte selbst ja auch kopieren bzw. davon ne ScopedConnection erstellen, die muss dann ja zwangsweise auch auf das selbe ConnectionBase Objekt zeigen.

Das mit dem Kopieren des Signals könnte man auch ändern, wenn gewünscht. Dazu müsste man einfach im Kopierkonstruktor ne neue Kopie der ConnectionBase machen, statt den shared_ptr zu kopieren. Dann kannst du die bereits verbundenen Signale aus dem kopierten Signal nur noch über clear disconnecten. Bin mir grad nicht sicher, ob ich das positiv oder negativ finde.
Master674b is offline  
Old 10/22/2013, 15:52   #26
 
elite*gold: 0
Join Date: Aug 2012
Posts: 236
Received Thanks: 94
Quote:
Originally Posted by Master674b View Post
Jo das soll so sein. Findest du das negativ? Du kannst die Connection-Objekte selbst ja auch kopieren bzw. davon ne ScopedConnection erstellen, die muss dann ja zwangsweise auch auf das selbe ConnectionBase Objekt zeigen.
Das ist kontraintuitiv. Wenn ich etwas kopiere, dann nehme ich an, dass die Kopie prinzipiell unabhängig ist und eine nachfolgende Änderung an Elementen des Orginals die Kopie nicht beeinflusst. Du kannst zwar intern intelligente Zeiger nutzen, soviel du willst, das sollte sich aber nicht auf das erwartete Verhalten auswirken.
Eine Verbindung hat für mich nur ein Signal, nicht unbegrenzt viele. Wenn ich also eine Verbindung trenne, wirkt sich das nicht auf alle möglichen Kopien aus. Dann könnte aber die Verbindung eine Referenz auf das besitzende Signal haben und sich selbst aus dem Signal austragen, intelligente Zeiger wären dann dafür auch nicht mehr notwendig. Wenn du dann bei einer verketteten Liste bleibst, sollten die Verbindungen vielleicht noch einen Iterator besitzen, der auf sie selbst (bzw. direkt davor) in der Liste zeigt. Wenn es eine einfach verkettete Liste ist, muss eine sich trennende/schließende Verbindung außerdem den Iterator der nächsten Verbindung aktualisieren. Wenn du keine Reihenfolge für die Aufrufe garantierst, könntest du auch std::vector nutzen und bei einer in der Mitte getrennten/geschlossenen Verbindung diese durch das letzte Element der Liste ersetzen.
Tasiro is offline  
Old 10/22/2013, 16:54   #27
 
Master674b's Avatar
 
elite*gold: 0
Join Date: Dec 2012
Posts: 255
Received Thanks: 110
Quote:
Originally Posted by Tasiro View Post
Das ist kontraintuitiv. Wenn ich etwas kopiere, dann nehme ich an, dass die Kopie prinzipiell unabhängig ist und eine nachfolgende Änderung an Elementen des Orginals die Kopie nicht beeinflusst. Du kannst zwar intern intelligente Zeiger nutzen, soviel du willst, das sollte sich aber nicht auf das erwartete Verhalten auswirken.
Eine Verbindung hat für mich nur ein Signal, nicht unbegrenzt viele. Wenn ich also eine Verbindung trenne, wirkt sich das nicht auf alle möglichen Kopien aus. Dann könnte aber die Verbindung eine Referenz auf das besitzende Signal haben und sich selbst aus dem Signal austragen, intelligente Zeiger wären dann dafür auch nicht mehr notwendig. Wenn du dann bei einer verketteten Liste bleibst, sollten die Verbindungen vielleicht noch einen Iterator besitzen, der auf sie selbst (bzw. direkt davor) in der Liste zeigt. Wenn es eine einfach verkettete Liste ist, muss eine sich trennende/schließende Verbindung außerdem den Iterator der nächsten Verbindung aktualisieren. Wenn du keine Reihenfolge für die Aufrufe garantierst, könntest du auch std::vector nutzen und bei einer in der Mitte getrennten/geschlossenen Verbindung diese durch das letzte Element der Liste ersetzen.
Eigentlich wäre der smart pointer dann immer noch notwendig. Ein Signal könnte ja schon zerstört sein.
Um das zu beheben bräuchten die beiden gegenseitig Referenzen aufeinander, das klingt nach nem Designfehler für mich.
Master674b is offline  
Old 10/22/2013, 20:45   #28
 
elite*gold: 0
Join Date: Aug 2012
Posts: 236
Received Thanks: 94
Quote:
Originally Posted by Master674b View Post
Eigentlich wäre der smart pointer dann immer noch notwendig. Ein Signal könnte ja schon zerstört sein.
Den Gültigkeitsbereich nicht beachten kann ich auch so. Davon abgesehen sollten Verbindungen nicht kopierbar sein und nur als Referenzen, Zeiger oder in Wrapper-Objekten verfügbar sein; was passierte denn, wenn ich eine bestehende Verbindung kopierte?

Quote:
Originally Posted by Master674b View Post
Um das zu beheben bräuchten die beiden gegenseitig Referenzen aufeinander, das klingt nach nem Designfehler für mich.
Dann solltest du nicht anbieten, dass Verbindungen sich selbstständig trennen können. Wenn es effizient sein soll, wird das vom Nutzer verwendete Objekt so oder so einen Zeiger auf oder in das Signal haben, auch wenn das dann nicht das vom Signal verwaltete Objekt sein muss. Du könntest etwa (nur ein Beispiel) in dem Signal eine Liste von std::function<T> haben und bei Bedarf ein Verbindungsobjekt erstellen (connection_ref<T>), welches zum einen auf das std::function<T>-Objekt und zum anderen auf das Signal zeigt. Damit hast zu zyklische Zeiger erfolgreich vermieden, kannst aber dafür keine Referenz mehr zurückgeben und musst das Objekt jedes Mal neu erstellen. Außerdem können dann Verbindungen ohne besitzendes Signal nicht existieren. (Wer will der Erste sein, der darlegt, unter welchen Umständen das vielleicht doch möglich wäre?)
Tasiro is offline  
Old 10/22/2013, 21:21   #29
 
Master674b's Avatar
 
elite*gold: 0
Join Date: Dec 2012
Posts: 255
Received Thanks: 110
Quote:
Originally Posted by Tasiro View Post
Den Gültigkeitsbereich nicht beachten kann ich auch so. Davon abgesehen sollten Verbindungen nicht kopierbar sein und nur als Referenzen, Zeiger oder in Wrapper-Objekten verfügbar sein; was passierte denn, wenn ich eine bestehende Verbindung kopierte?

Dann solltest du nicht anbieten, dass Verbindungen sich selbstständig trennen können. Wenn es effizient sein soll, wird das vom Nutzer verwendete Objekt so oder so einen Zeiger auf oder in das Signal haben, auch wenn das dann nicht das vom Signal verwaltete Objekt sein muss. Du könntest etwa (nur ein Beispiel) in dem Signal eine Liste von std::function<T> haben und bei Bedarf ein Verbindungsobjekt erstellen (connection_ref<T>), welches zum einen auf das std::function<T>-Objekt und zum anderen auf das Signal zeigt. Damit hast zu zyklische Zeiger erfolgreich vermieden, kannst aber dafür keine Referenz mehr zurückgeben und musst das Objekt jedes Mal neu erstellen. Außerdem können dann Verbindungen ohne besitzendes Signal nicht existieren. (Wer will der Erste sein, der darlegt, unter welchen Umständen das vielleicht doch möglich wäre?)
Ich guck mir nachher mal an wie andere Signal libs das regeln. Jedenfalls brauch ich diese Sicherheit hier. Bei mir im Projekt ist das ein LuaSignal, d.h. die Klasse brauche ich, um Lua-Callbacks zu realisieren, und die sollen natürlich so sicher wie nur irgend wie möglich sein. Auch wenn im Script der Gültigkeitsbereich der Verbindungen missachtet wird, darf nichts schief gehen.

Danke dir übrigens für die Mühen und Vorschläge =) Sobald ich meine VS 2013 Lizenz hab guck ich mal ob ich das ganze eventuell noch etwas anpasse oder mehr Optionen bereitstelle.
Master674b is offline  
Old 10/23/2013, 00:34   #30
 
elite*gold: 0
Join Date: Aug 2012
Posts: 236
Received Thanks: 94
Quote:
Originally Posted by Master674b View Post
Ich guck mir nachher mal an wie andere Signal libs das regeln. Jedenfalls brauch ich diese Sicherheit hier. Bei mir im Projekt ist das ein LuaSignal, d.h. die Klasse brauche ich, um Lua-Callbacks zu realisieren, und die sollen natürlich so sicher wie nur irgend wie möglich sein. Auch wenn im Script der Gültigkeitsbereich der Verbindungen missachtet wird, darf nichts schief gehen.
Es ist also für eine Programmiersprache? Das ist dann ein anderes Thema. Ich kenne Lua nicht, wenn es aber schwach typisiert ist und eine automatische Speicherverwaltung sein Eigen nennt, müsste doch eigentlich irgendwo eine Referenz "hängen bleiben" und somit verhindern, dass deine Rückruf-Funktionen verworfen wird. Du müsstest dann doch nur noch testen, ob es wirklich Funktionen ist. Damit ist Rückrufen Genüge getan. Zumindest, wenn Lua die Verbindungen nicht selbst verwalten darf... Aber auch dann unterstützt deine Signal-Bibliothek das momentan nicht hinreichend, dass etwas kaputtgehen könnte - weder durch Lua, noch durch irgendjemanden sonst.
Angenommen, deine Verbindungen haben keinen intelligenten Zeiger oder eine sonstige Sicherungsmethode. Solange du mit deinen Signalen umgehst, wird das aber auch nur dann gefährlich, wenn du Lua die Kontrolle über Verbindungsobjekte übergibst. Diese sollten schließlich nur in dem Kontext eines Signals vorkommen und nicht darüber hinaus am Leben gelassen werden.

Quote:
Originally Posted by Master674b View Post
Danke dir übrigens für die Mühen und Vorschläge =)
Das mache ich gerne, es würde mich freuen, geholfen zu haben.

Quote:
Originally Posted by Master674b View Post
Sobald ich meine VS 2013 Lizenz hab guck ich mal ob ich das ganze eventuell noch etwas anpasse oder mehr Optionen bereitstelle.
Das war der 31.10., oder?
Tasiro is offline  
Thanks
1 User
Reply


Similar Threads Similar Threads
[Selling] Minimalistic Design - GFX-Shop by Carfunkel
04/09/2013 - elite*gold Trading - 1 Replies
https://dl.dropbox.com/u/64993027/selling/1epvp%20 gfx%20store.pnghttps://dl.dropbox.com/u/64993027/s elling/2referenzen.pnghttps://dl.dropbox.com/u/649 93027/selling/3was%20noch%20kommt.pnghttps://dl.dr opbox.com/u/64993027/selling/4im%20einsatz.pnghttp s://dl.dropbox.com/u/64993027/selling/5im%20einsat z.png
Ton-Signal bei PN.
01/26/2013 - Metin2 - 9 Replies
Servus, gibt es einen Hack, Bot der, wenn man eine PN bekommt, ein Signalton abgibt? Weil ich oft nen Laden auf habe und was anderes vorhabe als alle 5 Minuten zu gucken ob ich PN't wurde..
Minimalistic UI
06/25/2011 - World of Warcraft - 2 Replies
Please close thread posted in invalid forum section. Edit - You can find the post at http://www.elitepvpers.com/forum/wow-addons/126331 6-minamalistic-ui.html
Signal bei PN?
07/30/2010 - Metin2 - 22 Replies
Hayhou :D Meine Frage ist ganz einfach, wie kann man es so einstellen, das man bei einer PN ein TonSignal bekommt?? Also mit Clientmodding.... Was bringts?? Ganz einfach, ich mekre wnen ich auf meinen Bot chars ne PN bekomme und die Bots fallen nicht auf MFG Bauch
Kein Signal am Monitor / No signal on screen
09/23/2009 - Technical Support - 2 Replies
Also mein Problem ist das wenn ich den Pc hochfahre keinen Signal an meinem TFT Monitor bekomme. Ich habe erst ein DVI Kabel verwendet, und dachte es würde vl. daran liegen und daher meinen alten Monitor per VGA angeschlossen mit dem gleichen Ergebnis. Mein PC ist einige Monate gestanden, davor hat es eigentlich funktioniert. Was ich schon probiert habe: -1 Ram Riegel in anderen Slot gesteckt und hochgefahren -On Board Graka versucht zu verwenden -Die eingebaute Graka versucht zu...



All times are GMT +2. The time now is 04:17.


Powered by vBulletin®
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2024 elitepvpers All Rights Reserved.