Discussion:
Embedded HTTP Server
(Wiadomość utworzona zbyt dawno temu. Odpowiedź niemożliwa.)
Maciej Sobczak
2020-06-05 20:57:50 UTC
Permalink
Z przyjemnością informuję o narodzinach wersji 1.0 nowego pakietu:

http://www.inspirel.com/httpserver/

Jest to bardzo prosta biblioteka w C++11, dla systemów Linux, Mac OS X oraz Windows, pozwalająca progamowi w C++ wyświetlić swoje GUI na przeglądarce webowej.

Idea jest również opisana tutaj:

https://en.wikipedia.org/wiki/Embedded_HTTP_server

i wbrew nazwie nie ma bezpośredniego związku z systemami wbudowanymi (chociaż na RaspberryPi i podobnych można by było z satysfakcją domknąć tą definicję).

Wszelkie komentarze mile widziane.
--
Maciej Sobczak * http://www.inspirel.com
Wojciech Muła
2020-06-06 10:44:20 UTC
Permalink
Post by Maciej Sobczak
http://www.inspirel.com/httpserver/
Jest to bardzo prosta biblioteka w C++11, dla systemów Linux, Mac OS X oraz Windows, pozwalająca progamowi w C++ wyświetlić swoje GUI na przeglądarce webowej.
https://en.wikipedia.org/wiki/Embedded_HTTP_server
i wbrew nazwie nie ma bezpośredniego związku z systemami wbudowanymi (chociaż na RaspberryPi i podobnych można by było z satysfakcją domknąć tą definicję).
Wszelkie komentarze mile widziane.
file_mime_type("html") zwróci "text/html" zamiast "text/plain"
Maciej Sobczak
2020-06-06 18:34:09 UTC
Permalink
Post by Wojciech Muła
file_mime_type("html") zwróci "text/html" zamiast "text/plain"
To dobrze? Źle? Jak powinno być i dlaczego?
--
Maciej Sobczak * http://www.inspirel.com
Wojciech Muła
2020-06-08 09:39:27 UTC
Permalink
Post by Maciej Sobczak
Post by Wojciech Muła
file_mime_type("html") zwróci "text/html" zamiast "text/plain"
To dobrze? Źle? Jak powinno być i dlaczego?
Jeśli przyjmujesz, że to rozszerzenie pliku determinuje typ MIME, to nazwa "html" nie posiada rozszerzenia.

w.
Maciej Sobczak
2020-06-08 18:33:42 UTC
Permalink
Post by Wojciech Muła
Post by Maciej Sobczak
To dobrze? Źle? Jak powinno być i dlaczego?
Jeśli przyjmujesz, że to rozszerzenie pliku determinuje typ MIME, to nazwa "html" nie posiada rozszerzenia.
Dalej nie rozumiem. Nazwa "html" nie posiada rozszerzenia, ale "index.html" jak najbardziej posiada i jest nim "html" i wtedy typ jest "text/html".

Czy chodziło o coś innego?
--
Maciej Sobczak * http://www.inspirel.com
heby
2020-06-06 12:34:45 UTC
Permalink
Post by Maciej Sobczak
Wszelkie komentarze mile widziane.
Jeśli jednak to miało by być embedded SILNIE sugeruje abyś usunął wątki.

Zamiast tego używaj coroutines.

Jeśli ktoś będzie chciał wątki to sobie dorobi albo mu dasz na bazie
tych coroutines.

W drugą stronę nie ma jak.

Wiele systemów embedded dysponuje tylko cooperative multitaskingiem.
Wątki powinny być następną, opcjonalną warstwą nad coroutines.

Tak, zdaje sobie sprawę że to absurdalna prośba, jak bibliteka jest już
gotowa. Ale pytałeś o wszelkie komentarze ...
Maciej Sobczak
2020-06-06 18:42:06 UTC
Permalink
Post by heby
Jeśli jednak to miało by być embedded SILNIE sugeruje abyś usunął wątki.
Wiele systemów embedded dysponuje tylko cooperative multitaskingiem.
Wątki powinny być następną, opcjonalną warstwą nad coroutines.
Jak do tej pory częściej widziałem sensownie działające wątki (takie prawdziwe), niż sensownie działający stos TCP. I nie chodzi o bugi, tylko o dostępne API albo metodę obsługi. Więc priorytety są inne.
Post by heby
Tak, zdaje sobie sprawę że to absurdalna prośba, jak bibliteka jest już
gotowa. Ale pytałeś o wszelkie komentarze ...
Nie jest absurdalna, bo wersja ver > 1.0 nie jest jeszcze gotowa. :-)
--
Maciej Sobczak * http://www.inspirel.com
heby
2020-06-06 20:22:58 UTC
Permalink
Post by Maciej Sobczak
Jak do tej pory częściej widziałem sensownie działające wątki (takie prawdziwe), niż sensownie działający stos TCP. I nie chodzi o bugi, tylko o dostępne API albo metodę obsługi. Więc priorytety są inne.
OK, zwróć jednak uwagę na to że taki FreeRTOS może być kompilowany jako
preemptive i cooperative.

Ogólnie abstrakcja na wątki była by też przydatna, w końcu może ktoś
będzie chciał zmienić bibliotekę wątków na inną, tak jak właśnie w
FreeRTOS gdzie to nie jest ani win ani posix.

Dodatkowo coroutines pozwalają na implementację czegoś z okolic
"stackless" albo czegoś z okolic "event driven". Oba mają pewne zalety w
embedded, ale maja też zalety w dużym programowaniu.

Nak w trybie narzekania: brakuje bibliotek w logiką na cooroutines,
nawet jesli te coroutines sa robione ręcznie, z maszyną stanów w środku
i zwykłym return. Zazwyczaj wszelakie biblioteki starają się
samodzielnie robić wątki albo wręcz robią while(foo) bar(); uważając że
jak je ktoś wbudował to są najważniejsze ;)
Maciej Sobczak
2020-06-06 22:02:47 UTC
Permalink
Post by heby
Ogólnie abstrakcja na wątki była by też przydatna, w końcu może ktoś
będzie chciał zmienić bibliotekę wątków na inną, tak jak właśnie w
FreeRTOS gdzie to nie jest ani win ani posix.
Szkoda prądu. Przecież to jest open-source. Jak ktoś bedzie chciał wymienić standardowe wątki na jakieś inne, to zmienia dosłownie w jednym miejscu to:

std::thread th(connection_thread, sock);

na co tam potrzebuje, no i może jeszcze sygnaturę wołanej funkcji. Robienie abstrakcji na coś, co jest w jednej linijce, jest po prostu niepotrzebne. Łatwiej zmienić tą jedną linijkę.

A jeszcze łatwiej zauważyć, że std::thread już jest tą abstrakcją - właśnie abstrakcją czegoś natywnego, bez narzucania konkretnego rozwiązania. I dokładnie taki jest sens istnienia tej klasy w std::. Więc jest też opcja podstawienia innej implementacji tejże standardowej klasy.

Znowu - prawdziwy cyrk to stos TCP. To tam są smoki. Przerobienie tego serwera na inne wątki to pikuś, ale przestawienie go na inny stos - i to tak, żeby zachować abstrakcję IOStreams (które są z założenia *blokujące*), to już zupełnie inna zabawa.
Post by heby
brakuje bibliotek w logiką na cooroutines,
To jest ciekawa uwaga. Pytanie, czy takie podejście ma swoją niszę rynkową, w której mieści się taki przykładowy serwer HTTP.
Bo ja nie jestem przekonany, czy zawsze cały program trzeba robić jedną metodą. Może raczej jest tak, że np. komunikację z urządzeniami fizycznymi można zrobić na coroutinach, ale interfejsu użytkownika już nie warto.
--
Maciej Sobczak * http://www.inspirel.com
heby
2020-06-06 22:36:28 UTC
Permalink
Post by Maciej Sobczak
std::thread th(connection_thread, sock);
na co tam potrzebuje, no i może jeszcze sygnaturę wołanej funkcji. Robienie abstrakcji na coś, co jest w jednej linijce, jest po prostu niepotrzebne. Łatwiej zmienić tą jedną linijkę.
Niby tak, ale już cooperative tak nie obskoczysz.

Ponadto praktyka pozkauje że zmiana "jednej linijki" w biblitece nie
jest prawidłową metodą dopasowania się do czegoś bo za chwile tej
linijki nie będzie w wersji 0.9.3.
Post by Maciej Sobczak
A jeszcze łatwiej zauważyć, że std::thread już jest tą abstrakcją - właśnie abstrakcją czegoś natywnego, bez narzucania konkretnego rozwiązania. I dokładnie taki jest sens istnienia tej klasy w std::. Więc jest też opcja podstawienia innej implementacji tejże standardowej klasy.
To tylko łatwo w teorii, w normalnych systemach "podmienianie"
std::whatever to jest *gruby* hacking...
Post by Maciej Sobczak
Znowu - prawdziwy cyrk to stos TCP. To tam są smoki. Przerobienie tego serwera na inne wątki to pikuś, ale przestawienie go na inny stos - i to tak, żeby zachować abstrakcję IOStreams (które są z założenia *blokujące*), to już zupełnie inna zabawa.
Niby tak, ale znowu: co dziwnego w tym że robisz własną abstrakcję do
"ich" abstrakcji?

Tworzysz własny ITcpStream i jakiś adapter do istniejącego/ych. Jak
IOStreams masz blokujace to masz adapter z wątkami. Jak się da robić
pooling, to masz inny adapter bez wątków albo z wątkami. Co kto potrzebuje.

Piszesz rdzeń HTTP w oderwaniu kompletnym od tego jaki stos TCP używasz.
Definiujesz jakieś ITCP, ISTream, IConnection i potem martwisz się w
napisanie kilku adapterów do tego albo do siamtego rozwiązania.

I przy okazji unit testy wychodzą za friko.
Post by Maciej Sobczak
Post by heby
brakuje bibliotek w logiką na cooroutines,
To jest ciekawa uwaga. Pytanie, czy takie podejście ma swoją niszę rynkową, w której mieści się taki przykładowy serwer HTTP.
Owszem, takie event-based są. To nie dokładnie to co coroutines, ale blisko.
Post by Maciej Sobczak
Bo ja nie jestem przekonany, czy zawsze cały program trzeba robić jedną metodą.
Dlatego sugeruje nie zmuszać ludzi do preemptive wątków. Wątki narzucają
pewne rozwiązania logiki w kodzie w sposób intruzywny, np. bez wątków w
jakiejś biblitece nie musisz synchronizować danych, ale np. ponieważ
ktoś w jakiejś biblitece użył wątków to nagle w zupełnie niewątkowym
kodzie masz race conditions bo się jakiś callback wywołał.
Post by Maciej Sobczak
Może raczej jest tak, że np. komunikację z urządzeniami fizycznymi można zrobić na coroutinach
Tam własnie nie, raczej na przerwaniach które, jak się zamknie jedno
oko, to są takie prawie wątki.
Post by Maciej Sobczak
, ale interfejsu użytkownika już nie warto.
*wszystkie* interfejsy GUI jakie istnieją w sensownym zastosowaniu są
event-based czyli takie coroutines/cooperative.

Chyba że masz na myślie coś innego niż GUI.
Maciej Sobczak
2020-06-07 19:46:34 UTC
Permalink
Post by heby
Niby tak, ale już cooperative tak nie obskoczysz.
I naiwna abstrakcja wątków też by mi tego nie dała.
Post by heby
Ponadto praktyka pozkauje że zmiana "jednej linijki" w biblitece nie
jest prawidłową metodą dopasowania się do czegoś bo za chwile tej
linijki nie będzie w wersji 0.9.3.
I tu płynnie przechodzimy do pytania o to, gdzie jest właściwy poziom abstrakcji. Bo Ty chciałbyś, żeby w bibliotece HTTP była abstrakcja wątków na wypadek portowania na inną platformę. A ja pytam, dlaczego cały serwer HTTP nie miałby być tą abstrakcją, z różnymi implementacjami na różne platformy?

Cała ta biblioteka ma dokładnie 2 pliki .cpp. Słownie: dwa. Plus 2 headery do nich. I działa na Lin/Mac/Win. Dołożenie do niej abstrakcji na okoliczność egzotycznych platform wbudowanych z pół-wątkami i dziwacznymi stosami TCP spowodowałoby, że tych plików byłoby 10. Albo 30.
I nawet nie wiem, jaka jest realna nisza rynkowa z takimi potrzebami i czy ona w ogóle jest. Bo nisza na wersję 1.0 jest na pewno, bo w szczególności ja sam tego użyję. Natomiast te abstrakcje rozwiązałyby problem ludzi o których nawet nie wiem, czy istnieją.

A nie lepiej poczekać, aż ktoś *realnie* zgłosi taką potrzebę i wtedy zrobić port tych dwóch plików z zachowaniem API całego serwera HTTP? I wtedy taki port też będzie miał 2 pliki .cpp. I ani kawałka kodu więcej.

Tak, będzie parę linijek zduplikowanych. Ale przekonaj mnie teraz, że koszt tych wszystkich abstrakcji jest mniejszy.
Post by heby
To tylko łatwo w teorii, w normalnych systemach "podmienianie"
std::whatever to jest *gruby* hacking...
Ale przecież nie pisałeś o normalnych systemach. :-)
Na normalnych to wszystko działa out-of-the-box i nie trzeba nic hacking.
Post by heby
Niby tak, ale znowu: co dziwnego w tym że robisz własną abstrakcję do
"ich" abstrakcji?
A co dziwnego w tym, że ich nie robię i zamiast tego proponuję minimalne rozwiązanie dla 99.9% potencjalnych odbiorców?
Post by heby
Piszesz rdzeń HTTP w oderwaniu kompletnym od tego jaki stos TCP używasz.
Przecież tak jest teraz. Dlatego są tam dwa pliki .cpp. Jeden to rdzeń HTTP a drugi to IOStreams na "typowym" stosie TCP.
Post by heby
*wszystkie* interfejsy GUI jakie istnieją w sensownym zastosowaniu są
event-based czyli takie coroutines/cooperative.
To ciekawa uwaga. W tej bibliotece nie ma na wierzchu niczego podobnego do kolejki, a co za tym idzie nie zmusza się użytkownika do kręcenia własną pętlą zdarzeń. Pod tym względem ta biblioteka bardziej przypomina lekki framework komunikacyjny, niż typowy framework GUI. Ale to dobry zbieg okoliczności, bo akurat HTTP jest protokołem komunikacyjnym. A kolorowe jarmarki na display'u i tak zrobisz w JS.

Czyli zamiast odpowiadać na pytanie jak zrobić GUI, odpowiadamy na pytanie, jak zrobić komunikację z tym czymś co robi GUI[*].

[*] I bez ograniczania się tylko do tego zastosowania (chociaż GUI było motywacją). HTTP może służyć również do innych rzeczy, niż GUI. I dlatego też to się nazywa "Embedded HTTP Server" a nie "GUI Framework".
--
Maciej Sobczak * http://www.inspirel.com
heby
2020-06-07 21:21:03 UTC
Permalink
Post by Maciej Sobczak
I tu płynnie przechodzimy do pytania o to, gdzie jest właściwy poziom abstrakcji. Bo Ty chciałbyś, żeby w bibliotece HTTP była abstrakcja wątków na wypadek portowania na inną platformę. A ja pytam, dlaczego cały serwer HTTP nie miałby być tą abstrakcją, z różnymi implementacjami na różne platformy?
Ależ oczywiscie, przecież normalne jest że bibliteka zaczyna się od
czegoś w rodzaju:

IHttpServer* Factory::createServer(
getTcpStreamsAbstractFactory()
, getAbstractThreadsPoolFactory()
, ConcurencyModel::Threaded
);

To ja decyduje jakie abstrakcjie to TCP i wątków dostarcze. Moge
dostarczyć Twoje np. oparte o std::, o ile je napiszesz, ale mogę
dostarczyć moje oparte o gołe FreeRTOS albo własny scheduler. Ja
decyduje czy chcę wątki a jak chce to jakie, nic o tym nie musisz wiedzieć.
Post by Maciej Sobczak
Cała ta biblioteka ma dokładnie 2 pliki .cpp. Słownie: dwa. Plus 2 headery do nich. I działa na Lin/Mac/Win. Dołożenie do niej abstrakcji na okoliczność egzotycznych platform wbudowanych z pół-wątkami i dziwacznymi stosami TCP spowodowałoby, że tych plików byłoby 10. Albo 30.
Co złego w plikach ;) Myślałem że czasy MSDOSa słusznie minęły :)
Post by Maciej Sobczak
I nawet nie wiem, jaka jest realna nisza rynkowa z takimi potrzebami i czy ona w ogóle jest.
Nie ma. Sporo piszesz jeszcze jedną biblioteczkę do http to chyba nie po
to aby zarabiać. Obecnośc niszy nie ma znaczenia.
Post by Maciej Sobczak
Bo nisza na wersję 1.0 jest na pewno, bo w szczególności ja sam tego użyję. Natomiast te abstrakcje rozwiązałyby problem ludzi o których nawet nie wiem, czy istnieją.
Jeśli nie zaimplementujesz jakiegoś ficzera to ludzie potrzebujący go,
nie wezmą tej bibliteki. Ponieważ nie napiszą Ci że coś jest potrzebne
będziesz miał fałszywe przeswiadczenie że nikomu to nie jest potrzebne.

Taki przykład: embedowanie engine tcl-a do własnego kodu powoduje ze do
dyspozycji masz *tylko* blokującą funkcję która wygląda tak:

Tcl::doEverything()
{
while( finished( ) )
Private::doSomething();
}

Najlepsze że ta funkcja pojawiła się po tym jak wypruli sobie żyły aby
zrobic stackless wersję. Efektem czego cały sens stackless (ja
kontroluje stack) został zaprzepaszczony bo jakiś miszczu założył "komu
to potrzebne, dajmy mu pętlę, będzie miał łatwiej" i nie da się z nigo
korzystać jak ze stackless. Interweniowałem na grupie, czy nie mogli by
udostepnić doSomething() ale dowiedziałem się że "na co to komu". Teraz
widzisz? Jak nie ma ficzera to do czasu aż nie pojawi się jakiś
pieniacz, jak ja, autorzy mogą żyć w błednym przekonaniu że "na co to
komu". A akurat mi to jest potrzebne (i emuluje to przez boost::context,
innymi słowy używam armaty na muchy).
Post by Maciej Sobczak
A nie lepiej poczekać, aż ktoś *realnie* zgłosi taką potrzebę i wtedy zrobić port tych dwóch plików z zachowaniem API całego serwera HTTP?
Jeśli prawidłowych abstrakcji nie zrobi się odpowiednio wcześnie to
potem ciągnięcie koncepcji "no ale przecież są wątki" staje się
nierefaktorowalne, bo tego typu koncepcje przeciekają do api usera w
postaci jakiś zdeformowanych wzorców uzycia pasujacych do wątków ale nie
pasujacych do event based. Potem tylko pozostaje powiedzieć "sorry" i tyle.
Post by Maciej Sobczak
Tak, będzie parę linijek zduplikowanych. Ale przekonaj mnie teraz, że koszt tych wszystkich abstrakcji jest mniejszy.
Koszt abstrakcji jest kosztem początkowym. Jeśli potrzeba pojawia się
później (a w zasadzie, jeśli autor po prostu nie zakładał że ona
istnieje na poczatku) to koszt jest wyższy z powodu długu
technologicznego który rośnie wraz z każda linią napisaną bez
prawidłowych abstrakcji.
Post by Maciej Sobczak
Post by heby
To tylko łatwo w teorii, w normalnych systemach "podmienianie"
std::whatever to jest *gruby* hacking...
Ale przecież nie pisałeś o normalnych systemach. :-)
Piszę o róznych rzeczach. Gdybym pisał na FreeRTOS to ogólnie nie uzyje
czegokolwiek z std::thread z racji braku implementacji std::. Jeśli
piszę jako embedded server w środku mojej aplikacji to mimo posiadania
std::threads mogę, z jakiejś przyczyny, nie chcieć ich użyć. Na przykład
z powodu tego że threads powodują spory spadek wydajności, albo np. z
powodu tego że mam system RT i nie mogę zakładać że jakieś przypadkowe
wątki uszkadzają mi cache latency albo przerwią ważny algorytm RealTime,
itd itp.
Post by Maciej Sobczak
Na normalnych to wszystko działa out-of-the-box i nie trzeba nic hacking.
Wtedy można się zastanowić dlaczego miałbym brać takie *coś* zamiast
QtHttpServer?
Post by Maciej Sobczak
Post by heby
Niby tak, ale znowu: co dziwnego w tym że robisz własną abstrakcję do
"ich" abstrakcji?
A co dziwnego w tym, że ich nie robię i zamiast tego proponuję minimalne rozwiązanie dla 99.9% potencjalnych odbiorców?
Nic. Tak wybrałeś. To nie są zarzuty i nie nakłaniam Cie do zmiany.
Prosiłeś o uwagi, nie miej pretensji że ktoś je zgłasza i argumentuje
prowadząc normalną dyskusję. Ja nic nie zarzucam, ale skoro jest
przestrzeń do dyskutowania to przecież usenet po to powstał
Post by Maciej Sobczak
Post by heby
*wszystkie* interfejsy GUI jakie istnieją w sensownym zastosowaniu są
event-based czyli takie coroutines/cooperative.
To ciekawa uwaga. W tej bibliotece nie ma na wierzchu niczego podobnego do kolejki, a co za tym idzie nie zmusza się użytkownika do kręcenia własną pętlą zdarzeń.
Ale zmusza to czekania na threads::join oraz używania w kodzie który
jest GUIoty synchroniacji między wątkami bo callbacki są threaded.
Innymi słowy Twoja bibliteka wymusiła pojawienie się w kodzie GUI
synchronizacji która tam jest zbędna.

Coroutines -> musisz kręcić jakimś server->next()
Wątki -> musisz synchronizować callbacki z i do bibloteki.

Ani jedno ani drugie nie jest lepsze. Ale mają coroutines można dodać
wątki w trywialny sposób. Mając wątki można, ale to bardzo naciągane,
próbować robić kieskie coroutines z masą hazardów i kiepskim unit
testowaniem.

Przy czym to moja opinia. Opieram ją o pewne doświadczenia które trudno
nazwać obiektywnymi.
Post by Maciej Sobczak
Pod tym względem ta biblioteka bardziej przypomina lekki framework komunikacyjny, niż typowy framework GUI.
To nie ma znaczenia co przypomina. Jeśli używa wątków i ma callbacki to
warstwa poniżej musi synchronizować dostęp do zasobów.

Innymi słowy programista GUI będzie musiał odizolować Twoją biblotekę
masa wrapperów które ukryją wątkowość Twojej bibloteki jeśli nie chce
aby mutexy rozlazły się po całym kodzie GUI.
Post by Maciej Sobczak
Czyli zamiast odpowiadać na pytanie jak zrobić GUI, odpowiadamy na pytanie, jak zrobić komunikację z tym czymś co robi GUI[*].
GUI (natywne) nie lubi jeśli ktoś komunikuje się z nim przez wątki. To
powoduje masę problemów ponieważ wszystkie najważniejsze frameworki
GUIowe na normalne maszyny zakładają model jednowątkowy na poziomi API
systemowego. Więc jeśli budujesz apliakcję na komputer w którym jest GUI
natywne, powiedzmy w Gtk i jednocześnie w tle apliakcji pracuje sobie
Twój web server to właśnie dostałeś w prezencie wątki których wcale byc
nie musi.
Post by Maciej Sobczak
[*] I bez ograniczania się tylko do tego zastosowania (chociaż GUI było motywacją).
HTTP może służyć również do innych rzeczy, niż GUI. I dlatego też to się nazywa "Embedded HTTP Server" a nie "GUI Framework".
Możliwe że się nie rozumiemy w kwestii GUI. Ja mam na myśli GUI w
programie w którym ktoś wembedował również Twój HTTP. Dzięki temu
aplikacja GUIowa, mimo że z wątkami ma 0 wspolnego, kiedy komunikuje się
z Twoim kodem, musi zarządzać hazardami. W przypadku coroutines/events
nie musi, a jesli chce mieć wątki to ich świadomie używa a jeśli nie
chce to ma ładne event based, pasujace do reszty interfejsy. I co gorsza
takich gotowców jest od cholery a dyski i pamięc tania ...
Maciej Sobczak
2020-06-08 07:49:49 UTC
Permalink
Post by heby
Ależ oczywiscie, przecież normalne jest że bibliteka zaczyna się od
IHttpServer* Factory::createServer(
getTcpStreamsAbstractFactory()
, getAbstractThreadsPoolFactory()
, ConcurencyModel::Threaded
);
Eee... Nie, to nie jest normalne. To jest overengineering.
Takich rzeczy mógłbym się być może spodziewać w kombajnach typu Boost, gdzie jednocześnie mam od razu gotowe do wyboru fafnaście implementacji tych polityk/aspektów, oraz oczywiście sensowne defaulty, żebym mógł po prostu napisać createServer(). Ale w luźnych bibliotekach to jest overengineering.
Post by heby
To ja decyduje jakie abstrakcjie to TCP i wątków dostarcze.
I nadal kogoś nie zadowolisz, bo parametryzowany mógłby być jeszcze sam protokół albo w ogóle fakt istnienia jakiegokolwiek protokołu, szyfrowanie transmisji i jaką metodą, alokator pamięci, metoda zamazywania zwolnionej już pamięci (bo jeszcze ktoś podejrzy), i w ogóle kto powiedział, że to jest komunikacja TCP a nie serial po USB albo przez Bluetooth i jeszcze pierdylion innych rzeczy, o których w poniedziałek rano nie chce mi się myśleć.
I to wszystko to jest overengineering.
Post by heby
Co złego w plikach ;) Myślałem że czasy MSDOSa słusznie minęły :)
Ale wtedy nie dałoby się napisać, że biblioteka ma 2 pliki. :-)
Post by heby
Post by Maciej Sobczak
I nawet nie wiem, jaka jest realna nisza rynkowa z takimi potrzebami i czy ona w ogóle jest.
Nie ma. Sporo piszesz jeszcze jedną biblioteczkę do http to chyba nie po
to aby zarabiać. Obecnośc niszy nie ma znaczenia.
Bingo. Ale skoro cel był inny, to ja ten cel chcę osiągnąć minimalnym kosztem.
Post by heby
Jeśli nie zaimplementujesz jakiegoś ficzera to ludzie potrzebujący go,
nie wezmą tej bibliteki.
Moje obserwacje: ludzie unikają potworów, których nie potrzebują. Zamiast tego sięgają po proste rozwiązania, które z przyzwyczajenia wloką ze sobą przez swoją karierę, zmuszając je do wzrastania razem z nimi i stawania się potworami w sposób organiczny.
Czyli nie feature-bang, tylko raczej feature-creep.
Post by heby
Taki przykład: embedowanie engine tcl-a do własnego kodu
Tak, jesteś wyjątkiem od reguły. :-)
Post by heby
Jeśli prawidłowych abstrakcji nie zrobi się odpowiednio wcześnie
Odpowiednią abstrakcją jest rozwiązanie, któro jest proste.
Post by heby
Koszt abstrakcji jest kosztem początkowym.
Ale nie wiesz jeszcze, które będą potrzebne. Więc wbrew pozorom to też jest zaciągnięciem długu. Coś jak kupowanie wszystkich możliwych gadżetów wakacyjnych gdy nie wiesz jeszcze, gdzie pojedziesz (i czy w ogóle).
Post by heby
Wtedy można się zastanowić dlaczego miałbym brać takie *coś* zamiast
QtHttpServer?
Bo skoro masz Qt, to nie będziesz robił GUI przez HTTP?
Idea jest taka, żebyś nie musiał mieć Qt.
Post by heby
Prosiłeś o uwagi, nie miej pretensji że ktoś je zgłasza
W żadnym razie nie mam. Ani jednej. W ogóle cieszę się, że ktoś jeszcze żyje na tej grupie. To dobra dyskusja, bo porusza ciekawe zagadnienia z teologii projektowania produktów. Nie tylko programistycznych. Czy lepiej jest zrobić nożyk czy scyzoryk szwajcarski? Przecież nożyk nie ma prawidłowych abstrakcji pozwalających z niego zrobić zestaw dentystyczny. A jednak nożyki idą jak woda - właśnie dlatego, że nie atakują użytkownika abstrakcjami, których nie potrzebuje.
Post by heby
Innymi słowy Twoja bibliteka wymusiła pojawienie się w kodzie GUI
synchronizacji która tam jest zbędna.
Nie wymusiła i nie jest zbędna. To użytkownik decyduje, jak tego użyje. W przykładach synchronizacja pojawiła się dopiero w ostatnim (6. SSE) i właśnie ten przykład można napisać inaczej, np. włączając wywołanie akcji HTTP we własną kolejkę zdarzeń.
Post by heby
Coroutines -> musisz kręcić jakimś server->next()
Wątki -> musisz synchronizować callbacki z i do bibloteki.
Tak. Np. w bibliotece YAMI4 są dwa poziomy API. Niższy to tzw. core, gdzie trzeba wołać funkcję agent.do_some_work(). Wyższy to tzw. high-level, gdzie "samo lata".
I zgadnij, czego ludzie używają.
Post by heby
Ani jedno ani drugie nie jest lepsze.
Zgadza się. Więc jeśli będzie potrzeba, to biblioteka HTTP w wersji eventowej też powstanie. Ale na razie nie potrzeba.
Post by heby
GUI (natywne) nie lubi jeśli ktoś komunikuje się z nim przez wątki.
Tu nie ma natywnego GUI.
Post by heby
Więc jeśli budujesz apliakcję na komputer w którym jest GUI
natywne, powiedzmy w Gtk i jednocześnie w tle apliakcji pracuje sobie
Twój web server to właśnie dostałeś w prezencie wątki których wcale byc
nie musi.
Ale których obecność nie musi być problemem.
Ciekawe - przez 30 lat wszyscy mieli pretensje do C++, że nie ma standardowych wątków. Teraz ma i jest problem, że są?
Post by heby
Możliwe że się nie rozumiemy w kwestii GUI. Ja mam na myśli GUI w
programie w którym ktoś wembedował również Twój HTTP.
A ja progam, który tego klasycznego GUI już nie ma. Ale niech będzie, że ma.
Post by heby
Dzięki temu
aplikacja GUIowa, mimo że z wątkami ma 0 wspolnego,
Ja jeszcze nie widziałem takiej aplikacji (pomijam przykłady typu kalkulator z tutoriala do tegoż GUI).
W aplikacjach, które widziałem, na potrzeby GUI był przeznaczony 1 z N wątków tejże aplikacji. I było M powodów, żeby właśnie tak zrobić.
--
Maciej Sobczak * http://www.inspirel.com
heby
2020-06-08 09:52:33 UTC
Permalink
Post by Maciej Sobczak
Post by heby
To ja decyduje jakie abstrakcjie to TCP i wątków dostarcze.
I nadal kogoś nie zadowolisz, bo parametryzowany mógłby być jeszcze sam protokół albo w ogóle fakt istnienia jakiegokolwiek protokołu, szyfrowanie transmisji i jaką metodą, alokator pamięci, metoda zamazywania zwolnionej już pamięci (bo jeszcze ktoś podejrzy), i w ogóle kto powiedział, że to jest komunikacja TCP a nie serial po USB albo przez Bluetooth i jeszcze pierdylion innych rzeczy, o których w poniedziałek rano nie chce mi się myśleć.
Nie, to wszystko jest w implementacji IStream :D A raczej może być i nie
Ty to piszesz.
Post by Maciej Sobczak
Post by heby
Jeśli nie zaimplementujesz jakiegoś ficzera to ludzie potrzebujący go,
nie wezmą tej bibliteki.
Moje obserwacje: ludzie unikają potworów, których nie potrzebują. Zamiast tego sięgają po proste rozwiązania, które z przyzwyczajenia wloką ze sobą przez swoją karierę, zmuszając je do wzrastania razem z nimi i stawania się potworami w sposób organiczny.
Czyli nie feature-bang, tylko raczej feature-creep.
Ale czyż nie myślisz o tym aby zmieniac świat czy może już przekroczyłeś
20tkę i zastanawiasz się jak dotrwać do emerytury :D ?
Post by Maciej Sobczak
Post by heby
Jeśli prawidłowych abstrakcji nie zrobi się odpowiednio wcześnie
Odpowiednią abstrakcją jest rozwiązanie, któro jest proste.
Nie, to nie abstrakcja. Powiedzmy że abstrakcja to nie dawanie w
gratisie implementacji które autorowu wydają się być prawidłowe.
Post by Maciej Sobczak
Post by heby
Koszt abstrakcji jest kosztem początkowym.
Ale nie wiesz jeszcze, które będą potrzebne. Więc wbrew pozorom to też jest zaciągnięciem długu. Coś jak kupowanie wszystkich możliwych gadżetów wakacyjnych gdy nie wiesz jeszcze, gdzie pojedziesz (i czy w ogóle).
Tu tylko chodzi o gadget IAbstractStreamFactory i IAbstractThreadFactory.

Innymi słowy wybieram się na wakacje z gotówką portfelui i kupie sobie
na miejscu co mi jest potrzebne, vs rozwiązanie kiedy wybierając sie w
góry mam bagażnik zawalony pontonami bo autor biblioteki lubi morze.
Post by Maciej Sobczak
Post by heby
Wtedy można się zastanowić dlaczego miałbym brać takie *coś* zamiast
QtHttpServer?
Bo skoro masz Qt, to nie będziesz robił GUI przez HTTP?
Może będę. W końcu to *embedded* server, więc dlaczego miałbym go nie
zaembedować robiac jakąs apliakcję z wielodostępem? Abecnie dziubdziam
hobbystycznie aplikacje z lokalnym GUI i jednoczesnym dostępem przez
www, konkretnie to kontroler falownika.
Post by Maciej Sobczak
Idea jest taka, żebyś nie musiał mieć Qt.
Jak masz gazyliony bajtów to Qt jest najmniejszym problemem. Widuje
aplikacje z kodem kilkaset kB + grube setki MB na Qt tylko po to aby
wyświetlić okienko z przyciskiem. Uchodzi, jak widać.
Post by Maciej Sobczak
Post by heby
Innymi słowy Twoja bibliteka wymusiła pojawienie się w kodzie GUI
synchronizacji która tam jest zbędna.
Nie wymusiła i nie jest zbędna. To użytkownik decyduje, jak tego użyje.
Właśnie nie. "kuźwa, znowu mutexy" i takie klimaty.
Post by Maciej Sobczak
W przykładach synchronizacja pojawiła się dopiero w ostatnim (6. SSE) i właśnie ten przykład można napisać inaczej, np. włączając wywołanie akcji HTTP we własną kolejkę zdarzeń.
Innymi słowy emulujesz coroutines/events na bazie wątków.
Post by Maciej Sobczak
Tak. Np. w bibliotece YAMI4 są dwa poziomy API. Niższy to tzw. core, gdzie trzeba wołać funkcję agent.do_some_work(). Wyższy to tzw. high-level, gdzie "samo lata".
I zgadnij, czego ludzie używają.
To nie kwestia czego używa większosc tylko czy można uzyć tego w sposób
niestandardowy. Właśnie to powodujee że nagle ten promil programistów
powie "no właśnie czegoś takiego szukam od 10 lat, genialne". A reszta
nie zauważy róznicy bo dostanie implementacje wątkową jako domyślną.
Wszyscy zadowoleni.
Post by Maciej Sobczak
Zgadza się. Więc jeśli będzie potrzeba, to biblioteka HTTP w wersji eventowej też powstanie. Ale na razie nie potrzeba.
Błedne koło, nikt takiej nie potrzebuje bo wszyscy robią to na wątkach i
nie potrzebuja już eventów mają dawno architekturę z workaroundami na
wątki żeby zachowywyały się jak eventy itd itp.
Post by Maciej Sobczak
Ale których obecność nie musi być problemem.
Ciekawe - przez 30 lat wszyscy mieli pretensje do C++, że nie ma standardowych wątków. Teraz ma i jest problem, że są?
Nie, problem że jak się pojawiły to nagle okazuje się że można je
wstawić wszędzie. Kilka lat temu widziłem gdzies biblitekę do liczenia
jakiś protych rzeczy na futures/promises. Kiedy kurz opadł okazało się
że jest dziesiątki razy mniej wydajna niż cokolwiek typu coroutine.
Wybacz, nie pamietam już co to było, coś do obliczeń tensorowych, chyba
z AI. Człowiek nie rozumiał że zrobienie future z return a+b; mija się z
celem.
Post by Maciej Sobczak
Post by heby
Dzięki temu
aplikacja GUIowa, mimo że z wątkami ma 0 wspolnego,
Ja jeszcze nie widziałem takiej aplikacji (pomijam przykłady typu kalkulator z tutoriala do tegoż GUI).
Cały Win3.11, wcześny MacOS oraz prawie każdy exampl (a one bywaj
ogromne) na Qt to takie przykłady z brzegu gdzie multitasking jest a
wątków preemptive brak i całkiem do rzeczy to działa.
Post by Maciej Sobczak
W aplikacjach, które widziałem, na potrzeby GUI był przeznaczony 1 z N wątków tejże aplikacji. I było M powodów, żeby właśnie tak zrobić.
Apliakcji bez wątków, responsywnych i wygodnych, jest też sporo. Wątki w
zasadzie są użyteczne w sytuacjach kiedy nie masz kontroli nad kodem i
musisz go puścić na żywioł. Kiedy masz kontrole zawsze można zrobić
fibers/coroutines i obejść problem drogiego synchronizowania danych i
przełączania kontekstu. Oczywiście każdy przypadek wymaga analizy, ale
nie twierdziłbym kategorycznie że apliakcja GUI musi mieć wątki. Prawa
jest taka że czasem musi bo kod jest tak kiepski że nie da się inaczej.
Jak choćby ten nieszczęsny tcl gdzie dev dodał "while() {}" bo dzięki
temu masz *uproszczone* sterowanie. Qźwa go mać.
Maciej Sobczak
2020-06-08 20:43:46 UTC
Permalink
Post by heby
Nie, to wszystko jest w implementacji IStream :D
Właśnie nie. Bo IOStream nie ma API do obsługi czegoś takiego jak gniazdo nasłuchujące, ani tym bardziej do tworzenia nowych strumieni. Więc potrzebne są osobne interfejsy do obsługi tego aspektu, który być może wygląda różnie w zależności od transportu.
Kwestie bezpieczeństwa też nie muszą być rozstrzygane tylko na poziomie transportu, więc mogą zasługiwać na osobne parametry, tak jak wspomniany alokator pamięci. Itp.
Czyli zaproponowana przez Ciebie sygnatura też dla kogoś może być niekompletna. Pytanie, gdzie jest własciwa granica pomiędzy tym, co parametryzowane a tym, co ustalone.
Post by heby
Ale czyż nie myślisz o tym aby zmieniac świat czy może już przekroczyłeś
20tkę i zastanawiasz się jak dotrwać do emerytury :D ?
Jest jeszcze etap samej emerytury, ludzie dziwne rzeczy wtedy robią.
Post by heby
Innymi słowy wybieram się na wakacje z gotówką portfelui i kupie sobie
na miejscu co mi jest potrzebne,
Nie, bo jeszcze masz w bagażniku rozkładany uniwersalny stelaż/ramę i spędzisz wakacje próbując przykręcić do niego przepłacone w kurorcie części.
Post by heby
vs rozwiązanie kiedy wybierając sie w
góry mam bagażnik zawalony pontonami bo autor biblioteki lubi morze.
I raczej zorientowałeś się pakując wcześniej bagażnik.
Post by heby
Abecnie dziubdziam
hobbystycznie aplikacje z lokalnym GUI i jednoczesnym dostępem przez
www, konkretnie to kontroler falownika.
Fajnie.
Post by heby
Post by Maciej Sobczak
Idea jest taka, żebyś nie musiał mieć Qt.
Jak masz gazyliony bajtów to Qt jest najmniejszym problemem. Widuje
aplikacje z kodem kilkaset kB + grube setki MB na Qt tylko po to aby
wyświetlić okienko z przyciskiem. Uchodzi, jak widać.
Nie takie rzeczy uchodzą. Ale są też ludzie z nieco bardziej wyrafinowanym gustem.
Post by heby
Właśnie nie. "kuźwa, znowu mutexy" i takie klimaty.
Jakie muteksy? W przykładach dopiero 6. ma mutex a i jego mogłoby nie być, gdyby połączyć get_updates() i activity().
I jaki masz problem z muteksem, skoro nie masz problemu dołączając setki MB na guzik?
Post by heby
To nie kwestia czego używa większosc tylko czy można uzyć tego w sposób
niestandardowy. Właśnie to powodujee że nagle ten promil programistów
powie "no właśnie czegoś takiego szukam od 10 lat, genialne". A reszta
nie zauważy róznicy bo dostanie implementacje wątkową jako domyślną.
Wszyscy zadowoleni.
Wszystkich można zadowolić w wersji 14.7. A w wersji 1.0 wstawiamy nogę w drzwi i liczymy zainteresowanych.
Post by heby
Oczywiście każdy przypadek wymaga analizy, ale
nie twierdziłbym kategorycznie że apliakcja GUI musi mieć wątki.
Ja się pytam, dlaczego musi nie mieć.

Ale o tym zapraszam w osobnym wątku, bo to ciekawy temat.
--
Maciej Sobczak * http://www.inspirel.com
heby
2020-06-08 21:24:20 UTC
Permalink
Post by Maciej Sobczak
Post by heby
Nie, to wszystko jest w implementacji IStream :D
Właśnie nie. Bo IOStream nie ma API do obsługi czegoś takiego jak gniazdo nasłuchujące, ani tym bardziej do tworzenia nowych strumieni.
Dlatego masz abstractFactory dla stumieni przekazane do Twojego kodu.
Post by Maciej Sobczak
Kwestie bezpieczeństwa też nie muszą być rozstrzygane tylko na poziomie transportu
Ale zazwyczaj są i to jest, powiedzmy, naturalne, że strumienie sa
szyfrowane.
Post by Maciej Sobczak
, więc mogą zasługiwać na osobne parametry, tak jak wspomniany alokator pamięci. Itp.
Owszem, ba, powinny być odporne na uderzenia meteorytów. Ale czy aby to
ja się zapędzam za daleko w wymyślaniu ficzerów ;) ?
Post by Maciej Sobczak
Czyli zaproponowana przez Ciebie sygnatura też dla kogoś może być niekompletna. Pytanie, gdzie jest własciwa granica pomiędzy tym, co parametryzowane a tym, co ustalone.
Brak odpowiedzi na to pytanie i brak abstrakcji *jakiejś* jest i tak
gorszy niż jakaś abstrakcja.
Post by Maciej Sobczak
Post by heby
Ale czyż nie myślisz o tym aby zmieniac świat czy może już przekroczyłeś
20tkę i zastanawiasz się jak dotrwać do emerytury :D ?
Jest jeszcze etap samej emerytury, ludzie dziwne rzeczy wtedy robią.
Na grupie to głównie wspominali GEORGE i jaki dobry jest Pascal z
Simulą. Czy ja wiem ... może i dziwne.
Post by Maciej Sobczak
Post by heby
Innymi słowy wybieram się na wakacje z gotówką portfelui i kupie sobie
na miejscu co mi jest potrzebne,
Nie, bo jeszcze masz w bagażniku rozkładany uniwersalny stelaż/ramę i spędzisz wakacje próbując przykręcić do niego przepłacone w kurorcie części.
Troche za dalego idzie ta analogia.
Post by Maciej Sobczak
Post by heby
vs rozwiązanie kiedy wybierając sie w
góry mam bagażnik zawalony pontonami bo autor biblioteki lubi morze.
I raczej zorientowałeś się pakując wcześniej bagażnik.
W wypożyczalni były tylko te z pontonami i te zawalone po dach nartami.
A ja latem jadę w góry. Takiego samochodu z pustym bagażnikiem nikt nie
wymyślił, wszysci wciskają mi w gratisie pełen bagażnik zbędnych dupereli.
Post by Maciej Sobczak
Post by heby
Właśnie nie. "kuźwa, znowu mutexy" i takie klimaty.
Jakie muteksy?
W kodzie klienta.
Post by Maciej Sobczak
I jaki masz problem z muteksem, skoro nie masz problemu dołączając setki MB na guzik?
No własnie chciałbym nie mieć jednago ani drugiego :D
Post by Maciej Sobczak
Post by heby
Oczywiście każdy przypadek wymaga analizy, ale
nie twierdziłbym kategorycznie że apliakcja GUI musi mieć wątki.
Ja się pytam, dlaczego musi nie mieć.
Bo znacząco podnosi to koszt jej obsługi, refaktoringu i supportu. W
dodatku kilkoma studentami jej nie opędzisz, nagle musisz mieć senior
dev którzy ogarniają głupi semafor.
Maciej Sobczak
2020-06-08 21:52:26 UTC
Permalink
Post by heby
Post by Maciej Sobczak
Kwestie bezpieczeństwa też nie muszą być rozstrzygane tylko na poziomie transportu
Ale zazwyczaj są
O, słowo kluczowe. "Zazwyczaj".
Więc zazwyczaj ludzie chcą mieć prosty interfejs, który od razu działa.
Post by heby
Brak odpowiedzi na to pytanie i brak abstrakcji *jakiejś* jest i tak
gorszy niż jakaś abstrakcja.
Ale nikt mi nie zgłaszał (realnie) zapotrzebowania na abstrakcje. Natomiast na prosty wbudowalny serwer HTTP mam zapotrzebowanie natychmiast.
Post by heby
W wypożyczalni były tylko te z pontonami i te zawalone po dach nartami.
To idź do innej wypożyczalni zamiast się awanturować, że coś jest w bagażniku.
Post by heby
Post by Maciej Sobczak
Jakie muteksy?
W kodzie klienta.
A po co?
Post by heby
Post by Maciej Sobczak
I jaki masz problem z muteksem, skoro nie masz problemu dołączając setki MB na guzik?
No własnie chciałbym nie mieć jednago ani drugiego :D
Nawet takiego małego muteksika? I jesteś gotów za to zapłacić znacznie bardziej skomplikowanym użyciem? Dziwne.
Post by heby
Post by Maciej Sobczak
Post by heby
nie twierdziłbym kategorycznie że apliakcja GUI musi mieć wątki.
Ja się pytam, dlaczego musi nie mieć.
Bo znacząco podnosi to koszt jej obsługi, refaktoringu i supportu.
A tak w dolarach? Albo w procentach?
Bo ja nie wiem, skąd to "znacząco". Z przykładów to nie wynika.
Post by heby
W
dodatku kilkoma studentami jej nie opędzisz, nagle musisz mieć senior
dev którzy ogarniają głupi semafor.
Ja myślę, że studenci są już i tak nieosiągalni w sferze C++.
Tylko seniorzy zostali.
--
Maciej Sobczak * http://www.inspirel.com
heby
2020-06-08 22:08:17 UTC
Permalink
Post by Maciej Sobczak
Post by heby
W wypożyczalni były tylko te z pontonami i te zawalone po dach nartami.
To idź do innej wypożyczalni zamiast się awanturować, że coś jest w bagażniku.
Nie ma innej. Mam do wyboru ciągnąc przyczepkę za jednym z nich albo
kupić torche rudy żelaza i zrobić własny.
Post by Maciej Sobczak
Post by heby
Post by Maciej Sobczak
Jakie muteksy?
W kodzie klienta.
A po co?
Bo są callbacki.
Post by Maciej Sobczak
Post by heby
No własnie chciałbym nie mieć jednago ani drugiego :D
Nawet takiego małego muteksika? I jesteś gotów za to zapłacić znacznie bardziej skomplikowanym użyciem? Dziwne.
Mały muteksiak to duży kłopot w kilku przypadkach.
Post by Maciej Sobczak
Post by heby
Post by Maciej Sobczak
Post by heby
nie twierdziłbym kategorycznie że apliakcja GUI musi mieć wątki.
Ja się pytam, dlaczego musi nie mieć.
Bo znacząco podnosi to koszt jej obsługi, refaktoringu i supportu.
A tak w dolarach? Albo w procentach?
Bo ja nie wiem, skąd to "znacząco". Z przykładów to nie wynika.
Z życia wynika :D Zawodowo mam jakieś doświadczenia z tym tematem.
Unikam wątków jeśli nie są niezbędne ponieważ wiem jaki koszt ponoszę
wspierając wątki w miejscach gdzie ktoś je wstawił tylko dlatego że
inaczej nie potrafił.
Post by Maciej Sobczak
Post by heby
W
dodatku kilkoma studentami jej nie opędzisz, nagle musisz mieć senior
dev którzy ogarniają głupi semafor.
Ja myślę, że studenci są już i tak nieosiągalni w sferze C++.
Tylko seniorzy zostali.
E tam :D Pojedyncze sztuki ciągle wpadają. Takich zakażonych Javą da się
nawet czasem wyleczyć. Tych od Pythona ciężko ..
Maciej Sobczak
2020-06-09 20:23:15 UTC
Permalink
Post by heby
Post by Maciej Sobczak
To idź do innej wypożyczalni zamiast się awanturować, że coś jest w bagażniku.
Nie ma innej.
To się dogadaj z właścicielem wypożyczalni. Albo załóż własną i wypożycz sam od siebie odpowiednio zapakowany bagażnik.
Post by heby
Post by Maciej Sobczak
Post by heby
Post by Maciej Sobczak
Jakie muteksy?
W kodzie klienta.
A po co?
Bo są callbacki.
No i?

Chciałeś event-based, proszę bardzo. Spróbuj sobie wyobrazić, że te callbacki to *jedyna* aktywność w programie. Tak jest w przykładach 1-5. Taki program nie różni się od programu w całości przyklejonego do tradycyjnego jednowątkowego GUI[*].

[*] OK, osobne połączenia klienckie to fizycznie różne wątki. Ale da się o tym nie myśleć, mogę specjalnie dla Ciebie dodać serializację callbacków.

Muteks jest potrzebny, jeśli masz powody, żeby robić sekcje krytyczne. Tylko od Ciebie zależy, czy będziesz miał te powody.
Post by heby
Mały muteksiak to duży kłopot w kilku przypadkach.
Ale zapomniałeś je opisać.
Post by heby
Unikam wątków jeśli nie są niezbędne ponieważ wiem jaki koszt ponoszę
wspierając wątki w miejscach gdzie ktoś je wstawił tylko dlatego że
inaczej nie potrafił.
Lubię te nasze przepychanki. Nawet pomimo tego, że są przewidywalne.
Post by heby
Post by Maciej Sobczak
Tylko seniorzy zostali.
E tam :D Pojedyncze sztuki ciągle wpadają. Takich zakażonych Javą da się
nawet czasem wyleczyć. Tych od Pythona ciężko ..
No, ale tacy przekonwertowani to przecież też nie świeżaki. Tacy od Javy to niemal na pewno widzieli jakiś wątek.
Ba - tacy od Javy to potrafią nawet kilka tysięcy wątków w jednym procesie zrobić i jeszcze się cieszyć patrząc na wykresy. Nie sądzę, żeby mieli jakiś problem etyczny związany z tą biblioteką do HTTP.
--
Maciej Sobczak * http://www.inspirel.com
heby
2020-06-09 20:47:00 UTC
Permalink
Post by Maciej Sobczak
[*] OK, osobne połączenia klienckie to fizycznie różne wątki. Ale da się o tym nie myśleć, mogę specjalnie dla Ciebie dodać serializację callbacków.
Zaczynasz emulować model event-based. Za chwile pojawi się lock-free
kolejka i już będziemy w domu.
Post by Maciej Sobczak
Muteks jest potrzebny, jeśli masz powody, żeby robić sekcje krytyczne. Tylko od Ciebie zależy, czy będziesz miał te powody.
Nie. Jeśli mam event-based to nie mam powodów aby z powodu bibloteki
robić coś ekstra.
Post by Maciej Sobczak
Post by heby
Mały muteksiak to duży kłopot w kilku przypadkach.
Ale zapomniałeś je opisać.
Na przykład tam gdzie masz do czynienia z RT.

Powiedzmy... piszesz soft do drukarki 3D sterujący wprost mechaniką.
Wystawiasz w nim serwer www do sterowania. Mutexy są mało sensowne bo
pracujesz nie dośc że w środowisku RT to jeszcze z masą przerwań o
priorytetach wyższych niż switch kontekstu.
Post by Maciej Sobczak
No, ale tacy przekonwertowani to przecież też nie świeżaki. Tacy od Javy to niemal na pewno widzieli jakiś wątek.
Prawie kazdy widział wątek. Promil wie jak działa pod maską. Do tego
tzreba pojmować dość przekrojowo od asm po wysoki poziom. Taki student
się nie trafia za często.
Post by Maciej Sobczak
Ba - tacy od Javy to potrafią nawet kilka tysięcy wątków w jednym procesie zrobić i jeszcze się cieszyć patrząc na wykresy. Nie sądzę, żeby mieli jakiś problem etyczny związany z tą biblioteką do HTTP.
Nie będą mieli ani jednego w skalowaniu hello worldów na milion watków.
Do czasu aż wpadną na problem pierwszej współdzielonej zmiennej z okolic
zagadnien memory barrier. Fakt, w http cięzko takie zagadnienia znaleźć ...
Maciej Sobczak
2020-06-09 21:14:00 UTC
Permalink
Post by heby
Zaczynasz emulować model event-based.
Nie emulować, tylko sztucznie te zagadnienia rozdzielasz.
Przecież biblioteka oparta w całości o callbacki jest eventowa niemal z założenia. To Ty usiłujesz jej przypisać jakieś inne cechy.
Post by heby
Post by Maciej Sobczak
Muteks jest potrzebny, jeśli masz powody, żeby robić sekcje krytyczne. Tylko od Ciebie zależy, czy będziesz miał te powody.
Nie. Jeśli mam event-based to nie mam powodów aby z powodu bibloteki
robić coś ekstra.
Ciągle nie pokazałeś, dlaczego miałbyś robić coś ekstra.
I dlaczego to akurat miałoby być z powodu tej biblioteki.

Powtórzę: przykłady 1-5 *nie mają* muteksów. A jakie piękne GUI mają.
Post by heby
Post by Maciej Sobczak
Post by heby
Mały muteksiak to duży kłopot w kilku przypadkach.
Ale zapomniałeś je opisać.
Na przykład tam gdzie masz do czynienia z RT.
No i? Jest cała szkoła modelowania systemów RT z obiektami chronionymi (patrz np. Ada i związane z nią papiery akademickie), gdzie muteksy w niczym nie przeszkadzają. Jaki masz problem z tymi muteksami?
Post by heby
Powiedzmy... piszesz soft do drukarki 3D sterujący wprost mechaniką.
Łał. Myślałem, że drukarki 3D to był szpan dwa lata temu. :-p
Teraz młodzież steruje dronami.
Post by heby
Wystawiasz w nim serwer www do sterowania.
Masz na myśli, że serwer www lata na RaspberryPi, który jest ukryty w obudowie drukarki (no bo jeszcze USB, ekranik, update'y z pendrive'a, i inne tego typu oczywistości, bez których nikt by tej drukarki nie dotknął) a sterowanie leci z mikrokontrolera?
Czy może masz na myśli to, że jakiś masochista uparł się, że serwer www z niesterowalnym stosem TCP musi koniecznie być na jedynym mikrokontrolerze?

No to niech będzie ta wersja od masochisty.
Post by heby
Mutexy są mało sensowne
Ale dalej nie pokazałeś, po co te muteksy. Masz jakieś fiksacje. :-)
Post by heby
Prawie kazdy widział wątek. Promil wie jak działa pod maską.
[...]
Post by heby
Fakt, w http cięzko takie zagadnienia znaleźć ...
O, to, to. Fajnie, że dostrzegasz bezcelowość swojego trollowania. :-)
--
Maciej Sobczak * http://www.inspirel.com
heby
2020-06-09 21:32:25 UTC
Permalink
Post by Maciej Sobczak
Nie emulować, tylko sztucznie te zagadnienia rozdzielasz.
Przecież biblioteka oparta w całości o callbacki jest eventowa niemal z założenia. To Ty usiłujesz jej przypisać jakieś inne cechy.
Ale "eventowa z wątkami" to nie to samo co "coroutines/cooperative".
Więc jeśli będziesz się upierał o to że callback z wątku to "event" to
mamy rózne pojęcie co to jest event-based i oba do obrony.
Post by Maciej Sobczak
Post by heby
Post by Maciej Sobczak
Muteks jest potrzebny, jeśli masz powody, żeby robić sekcje krytyczne. Tylko od Ciebie zależy, czy będziesz miał te powody.
Nie. Jeśli mam event-based to nie mam powodów aby z powodu bibloteki
robić coś ekstra.
Ciągle nie pokazałeś, dlaczego miałbyś robić coś ekstra.
I dlaczego to akurat miałoby być z powodu tej biblioteki.
Bibliteka czyta/zapisuje zmienną globalną w implementacji callbacka.

Muszę ją obarierować i używać tej bariery w kodzie który nie ma NIC
wspólnego z serwerem HTTP. W ten sposób wątki z jakiejś bibliteki
agresywnie wymuszają na mnie zmiany kodu w miejscach odległych.
Post by Maciej Sobczak
Powtórzę: przykłady 1-5 *nie mają* muteksów. A jakie piękne GUI mają.
Helloworldy zazwyczaj nie mają żadnych problemów, chyba głównie dlatego
że połowa biblitek na necie nie ma innych zastosowań niż własne helloworldy.

Innymi słowy trudno o to aby kilka przykładów było dowodem w innym
zastosowaniu.
Post by Maciej Sobczak
Post by heby
Post by Maciej Sobczak
Post by heby
Mały muteksiak to duży kłopot w kilku przypadkach.
Ale zapomniałeś je opisać.
Na przykład tam gdzie masz do czynienia z RT.
No i? Jest cała szkoła modelowania systemów RT z obiektami chronionymi (patrz np. Ada i związane z nią papiery akademickie), gdzie muteksy w niczym nie przeszkadzają. Jaki masz problem z tymi muteksami?
Zajmują czas, wymagają grubego schedulera preemptive ze skomplikowaną
logią "Wait". Co prawda taki scheduler jest w zasięgu przeciętnego
programisty, ale to już nie jest za darmo.
Post by Maciej Sobczak
Post by heby
Powiedzmy... piszesz soft do drukarki 3D sterujący wprost mechaniką.
Łał. Myślałem, że drukarki 3D to był szpan dwa lata temu. :-p
Teraz młodzież steruje dronami.
Nie, ten przykład to takie RT w domu, czyli w sam raz target Twojej
bibliteki. Hobbystyczny soft z hobbystycznymi biblitekami.
Post by Maciej Sobczak
Post by heby
Wystawiasz w nim serwer www do sterowania.
Masz na myśli, że serwer www lata na RaspberryPi
Obecnie sterowniki mają zaszyte jakeiś ARMy po 100MHz. Mimo że to RT to
w zasadzie procesor ma sporo wolnego w tzw "międzyczasie". Dlaczego nie
miałby generować jakiegoś www?
Post by Maciej Sobczak
Czy może masz na myśli to, że jakiś masochista uparł się, że serwer www z niesterowalnym stosem TCP musi koniecznie być na jedynym mikrokontrolerze?
Trudno to nazwać masochizmem że ktoś stara się wykorzystać CPU bez
dodatkowego point-of-failure jakim jest extra Pi robiące za serwer www.
Post by Maciej Sobczak
Post by heby
Mutexy są mało sensowne
Ale dalej nie pokazałeś, po co te muteksy. Masz jakieś fiksacje. :-)
Masz wątki to i masz mutexy. W zasadzie czasem tylko memory barrier z
tych mutextów, ale mimo to dalej masz *coś*. Gdyby było to tylko w
adapterze do tej bibliteki to spoko. Ale wątki złośliwie zarażają resztę
kodu pojęciem zasobu krytycznego.
Post by Maciej Sobczak
Post by heby
Prawie kazdy widział wątek. Promil wie jak działa pod maską.
[...]
Post by heby
Fakt, w http cięzko takie zagadnienia znaleźć ...
O, to, to. Fajnie, że dostrzegasz bezcelowość swojego trollowania. :-)
Trudno powiedzieć czy to trolowanie. W zasadzie nie wiem. Może to
dlatego że niedawno trafiłem na równie bezuzyteczny kawałek kodu. Niby
mógłbym użyć, ale ... detale ... jak ten while (1){} w stackless TCLu.
Prawie dobrze tylko całkiem do dupy. Taka karma :/
Maciej Sobczak
2020-06-10 18:57:54 UTC
Permalink
Post by heby
Post by Maciej Sobczak
Ciągle nie pokazałeś, dlaczego miałbyś robić coś ekstra.
I dlaczego to akurat miałoby być z powodu tej biblioteki.
Bibliteka czyta/zapisuje zmienną globalną w implementacji callbacka.
Muszę ją obarierować
Dlaczego musisz? Jeśli callbacki są szeregowane[*], to nie musisz.

[*] Ale nie są.
Post by heby
i używać tej bariery w kodzie który nie ma NIC
wspólnego z serwerem HTTP.
Eee... To po co używasz biblioteki HTTP?
Post by heby
W ten sposób wątki z jakiejś bibliteki
agresywnie wymuszają na mnie zmiany kodu w miejscach odległych.
Używasz zmiennej globalnej z odległych miejsc? Kiepsko.
Dlaczego obwiniasz jakąś bibliotekę o problemy spowodowane złą architekturą Twojego programu?
Post by heby
Post by Maciej Sobczak
Post by heby
Wystawiasz w nim serwer www do sterowania.
Masz na myśli, że serwer www lata na RaspberryPi
Obecnie sterowniki mają zaszyte jakeiś ARMy po 100MHz. Mimo że to RT to
w zasadzie procesor ma sporo wolnego w tzw "międzyczasie". Dlaczego nie
miałby generować jakiegoś www?
No więc skoro ma sporo wolnego, to jaki masz problem?
I jakie proporcje w tym problemie? Na takich sprzętach ludzie wsadzają pełny RTOS, pełny stos TCP, chcą jeszcze serwer www i w tym wszystkim jest jakiś wyimaginowany problem z muteksem? Pomyliłeś proporcje. Zwłaszcza, że w takiej składance muteksów jest już nadziabanych jakieś kilkadziesiąt.
Post by heby
Post by Maciej Sobczak
Czy może masz na myśli to, że jakiś masochista uparł się, że serwer www z niesterowalnym stosem TCP musi koniecznie być na jedynym mikrokontrolerze?
Trudno to nazwać masochizmem że ktoś stara się wykorzystać CPU bez
dodatkowego point-of-failure jakim jest extra Pi robiące za serwer www.
I dlatego wsadza serwer www do krytycznego kontrolera? Żeby nie mieć dodatkowego point-of-failure?
Ja na taką logikę nic nie poradzę i nikomu nie obiecuję swojego udziału.
Post by heby
Masz wątki to i masz mutexy.
Dalej nie pokazałeś, dlaczego.
Ani też dlaczego to miałby być problem.
Post by heby
Trudno powiedzieć czy to trolowanie. W zasadzie nie wiem. Może to
dlatego że niedawno trafiłem na równie bezuzyteczny kawałek kodu.
To straszne.
Najstraszniejsze jest jednak to, że się tak bardzo tym przejmujesz.
--
Maciej Sobczak * http://www.inspirel.com
heby
2020-06-10 20:52:21 UTC
Permalink
Post by Maciej Sobczak
Post by heby
Bibliteka czyta/zapisuje zmienną globalną w implementacji callbacka.
Muszę ją obarierować
Dlaczego musisz? Jeśli callbacki są szeregowane[*], to nie musisz.
[*] Ale nie są.
Dlatego muszę.
Post by Maciej Sobczak
Post by heby
i używać tej bariery w kodzie który nie ma NIC
wspólnego z serwerem HTTP.
Eee... To po co używasz biblioteki HTTP?
Kod od manipulowania, powiedzmy, silnikami nic o jakims http nie wie.
Ale razem pracuja na jednym cpu i moga mieć dostęp do tych samych
zasobów jak np. zmienne okreslające położenie czy stan.
Post by Maciej Sobczak
Post by heby
W ten sposób wątki z jakiejś bibliteki
agresywnie wymuszają na mnie zmiany kodu w miejscach odległych.
Używasz zmiennej globalnej z odległych miejsc? Kiepsko.
W niektórych sytuacjah, jak opisywany sterwanik druku 3D, takim stanem
jest bardzo duzo róznych małych detali. Gdzie jest glowica, jaka jest
prędkośc itd itp.
Post by Maciej Sobczak
Dlaczego obwiniasz jakąś bibliotekę o problemy spowodowane złą architekturą Twojego programu?
Ona w tym zastosowaniu NIE jest zła. Jest wręcz jedyna sensowna przy
200kB flasha.
Post by Maciej Sobczak
Post by heby
Obecnie sterowniki mają zaszyte jakeiś ARMy po 100MHz. Mimo że to RT to
w zasadzie procesor ma sporo wolnego w tzw "międzyczasie". Dlaczego nie
miałby generować jakiegoś www?
No więc skoro ma sporo wolnego, to jaki masz problem?
Poniewaz nie rozumiesz dlaczego można się wiekszośc czasu nudzić i
jednoczesnie mieć problem z wyrobieniem się w zastosowaniach RT. Otórz
twój preemptive multitasking powoduje że *akurat* w tym złosliwym
przykładzie może to powodować konkretne skutki w postacji utraty jakości
wydruku. Tylko dlatego że trzeba przełaczyc konteks kiedy glowica
właśnie wjechala w materiał.
Post by Maciej Sobczak
I jakie proporcje w tym problemie?
Jakie sobie tylko wymyslisz.
Post by Maciej Sobczak
Na takich sprzętach ludzie wsadzają pełny RTOS
Na ARM7, powiedzmy, ma to już resztkę sensu.
Post by Maciej Sobczak
, pełny stos TCP
Nie jest potrzebny. Wystarczy kawalek.
Post by Maciej Sobczak
, chcą jeszcze serwer www i w tym wszystkim jest jakiś wyimaginowany problem z muteksem? Pomyliłeś proporcje.
Raczej "mam to na codzień".
Post by Maciej Sobczak
Zwłaszcza, że w takiej składance muteksów jest już nadziabanych jakieś kilkadziesiąt.
Zero.
Post by Maciej Sobczak
Post by heby
Trudno to nazwać masochizmem że ktoś stara się wykorzystać CPU bez
dodatkowego point-of-failure jakim jest extra Pi robiące za serwer www.
I dlatego wsadza serwer www do krytycznego kontrolera? Żeby nie mieć dodatkowego point-of-failure?
Tak. Albo dla wygody. Albo bo to modne. Rózne można miec powody.
Post by Maciej Sobczak
Ja na taką logikę nic nie poradzę i nikomu nie obiecuję swojego udziału.
I nikt nie obiecuje że uzyje w tym zastosowaniu. Dzień jak co dzień w
OpenSource.
Post by Maciej Sobczak
Post by heby
Masz wątki to i masz mutexy.
Dalej nie pokazałeś, dlaczego.
Niezupełnie. Po prostu odrzucasz częśc rzewczywostości nie pasującej do
zastosowania aktualnego. Wolno Ci.
Post by Maciej Sobczak
Ani też dlaczego to miałby być problem.
To też już zostało wyjasnione.
Post by Maciej Sobczak
To straszne.
Najstraszniejsze jest jednak to, że się tak bardzo tym przejmujesz.
Czyli miałem rację. Nie chciałeś zapytać o porady co do kodu. Po prostu
musisz sobie podsykutować z rosnącym poziomem adrenaliny.

Ale nuda. EOT.
Tomasz Kaczanowski
2020-06-10 05:50:04 UTC
Permalink
Post by heby
Post by Maciej Sobczak
[*] OK, osobne połączenia klienckie to fizycznie różne wątki. Ale da
się o tym nie myśleć, mogę specjalnie dla Ciebie dodać serializację
callbacków.
Zaczynasz emulować model event-based. Za chwile pojawi się lock-free
kolejka i już będziemy w domu.
Post by Maciej Sobczak
Muteks jest potrzebny, jeśli masz powody, żeby robić sekcje krytyczne.
Tylko od Ciebie zależy, czy będziesz miał te powody.
Nie. Jeśli mam event-based to nie mam powodów aby z powodu bibloteki
robić coś ekstra.
Post by Maciej Sobczak
Post by heby
Mały muteksiak to duży kłopot w kilku przypadkach.
Ale zapomniałeś je opisać.
Na przykład tam gdzie masz do czynienia z RT.
Powiedzmy... piszesz soft do drukarki 3D sterujący wprost mechaniką.
Wystawiasz w nim serwer www do sterowania. Mutexy są mało sensowne bo
pracujesz nie dośc że w środowisku RT to jeszcze z masą przerwań o
priorytetach wyższych niż switch kontekstu.
zaraz, zaraz... chcesz napisać, że na platformach wielocorowych nie
korzystasz z wątków?

Przecież to marnowanie wydajności.
--
http://kaczus.ppa.pl
heby
2020-06-10 06:09:25 UTC
Permalink
Post by Tomasz Kaczanowski
Post by heby
Powiedzmy... piszesz soft do drukarki 3D sterujący wprost mechaniką.
Wystawiasz w nim serwer www do sterowania. Mutexy są mało sensowne bo
pracujesz nie dośc że w środowisku RT to jeszcze z masą przerwań o
priorytetach wyższych niż switch kontekstu.
zaraz, zaraz... chcesz napisać, że na platformach wielocorowych nie
korzystasz z wątków?
Dlaczego wielocorowych? Przecięny ARM sterownika drukarki 3D, w wersji
mikrokontrolerowej, ma 1 rdzeń.
Post by Tomasz Kaczanowski
Przecież to marnowanie wydajności.
Gdybym w systemie RT miał do wyboru czy drugi rdzeń poświęcę na
zagadnienia sterowania silnikami czy może na obsługę serwera www to
zgadnij co wybiorę ...
Mateusz Viste
2020-06-08 08:32:58 UTC
Permalink
Post by heby
Jeśli nie zaimplementujesz jakiegoś ficzera to ludzie potrzebujący
go, nie wezmą tej bibliteki. Ponieważ nie napiszą Ci że coś jest
potrzebne będziesz miał fałszywe przeswiadczenie że nikomu to nie
jest potrzebne.
A jednak ja co rusz dostaję jakieś prośby o dodatkowe funkcje i sugestie
dot. moich programów... Twoja teoria się nie sprawdza :)
Oczywiście może być tak jak piszesz, ale tylko w sytuacji, kiedy
istnieje szeroki wybór alternatyw i jest coś, co pasuje idealnie do
potrzeby użytkownika. Ale w takim wypadku niech faktycznie bierze to
coś innego co mu pasuje idealnie i nie zawraca dupy.

Mateusz
Wojciech Muła
2020-06-06 17:10:13 UTC
Permalink
Post by Maciej Sobczak
http://www.inspirel.com/httpserver/
Jest to bardzo prosta biblioteka w C++11, dla systemów Linux, Mac OS X oraz Windows, pozwalająca progamowi w C++ wyświetlić swoje GUI na przeglądarce webowej.
https://en.wikipedia.org/wiki/Embedded_HTTP_server
i wbrew nazwie nie ma bezpośredniego związku z systemami wbudowanymi (chociaż na RaspberryPi i podobnych można by było z satysfakcją domknąć tą definicję).
Wszelkie komentarze mile widziane.
Po pierwsze, to aż się prosi, żeby ten serwer był zwykłą klasą. Czemu ktoś nie miałby sobie stworzyć 5 serwisów WWW działających na różnych portach?

Po drugie, nie ma sposobu na zamknięcie serwera, poza zabiciem procesu. Chyba, że ja czegoś nie widzę.

Mówiąc o API: 6 wariantów register_{generic,html,text}_{post,get}_action można by sprowadzić do 2. register_action(const char* name, {post_action_type, get_action_type} callback, const char* mime_type). Zresztą, może lepiej byłoby przyjmować jako argument mapę akcji - czyli to co masz teraz w get_actions/post_actions. Niech user sobie przygotuje takie mapy w sposób, jaki mu pasuje, a ty pozbędziesz się potrzeby blokowania tych struktur.

Czasem funkcje przyjmują const char*, czase std::string& co jest niespójne.

W ogóle nie walidujesz, czy wskaźniki są niepuste. Tak samo z std::function.

Zero testów. Serio? :)

w.
Maciej Sobczak
2020-06-06 19:00:05 UTC
Permalink
Post by Wojciech Muła
Po pierwsze, to aż się prosi, żeby ten serwer był zwykłą klasą. Czemu ktoś nie miałby sobie stworzyć 5 serwisów WWW działających na różnych portach?
No właśnie. I tu poruszamy ważną kwestię. Bo piszesz, że aż się prosi, ale potem okazuje się, że nikt nie prosi, tylko czemu ktoś by miał nie prosić.

A mi chodziło o to, żeby pakiet 1.0 przekroczył próg używalności a nie o to, żeby rozwiązać problemy typu "czemy ktoś nie miałby".

Natomiast, nic nie stoi na przeszkodzie, żeby sobie zawołać funkcję server_start() 5 razy z różnymi portami, z 5 różnych wątków, bo ta funkcja i tak nie ma stanu globalnego. Nie trzeba mieć do tego klasy.
Post by Wojciech Muła
Po drugie, nie ma sposobu na zamknięcie serwera, poza zabiciem procesu. Chyba, że ja czegoś nie widzę.
Tak. Funkcja server_stop() już istniała, ale ją usunąłem. To nie jest oczywiste, jak zamknąć serwer, który ma callbacki, niektóre zapewne w trakcie pracy.
Wszystkie problemy da się rozwiązać, ale nie o to chodziło w wersji 1.0.
Post by Wojciech Muła
Mówiąc o API: 6 wariantów register_{generic,html,text}_{post,get}_action można by sprowadzić do 2. register_action(const char* name, {post_action_type, get_action_type} callback, const char* mime_type).
Nie, bo po pierwsze generic i html różnią się obsługą a po drugie nie chciałem przeciążać funkcji register, bo bardziej naturalne wydaje mi się przeciążenie funkcji akcji dla get i post:

void my_action(to-co-trzeba-dla-get) { ... }
void my_action(to-co-trzeba-dla-post) { ... }

I wtedy nie dałoby rady:

register(my_action);
Post by Wojciech Muła
Zresztą, może lepiej byłoby przyjmować jako argument mapę akcji - czyli to co masz teraz w get_actions/post_actions. Niech user sobie przygotuje takie mapy w sposób, jaki mu pasuje, a ty pozbędziesz się potrzeby blokowania tych struktur.
Ale teraz obsługa jest prostsza, właśnie dlatego, że user nie musi robić takich map.
Można by było pomyśleć o akcji catch-all. Tam user dostawałby wszystko (co nie było obsłużone) i mógłby sobie tam zrobić takie mapy, jakie zechce.
Post by Wojciech Muła
Czasem funkcje przyjmują const char*, czase std::string& co jest niespójne.
Bo chodziło o przewidywane użycie. Tam gdzie przewidywałem literał, jest const char*.
Post by Wojciech Muła
W ogóle nie walidujesz, czy wskaźniki są niepuste. Tak samo z std::function.
A po co? Bez przesady z tą walidacją. Walidować należy input z zewnątrz (i nawet opisałem to w przykładzie 3, z parametrami) a nie własne literały.
Post by Wojciech Muła
Zero testów. Serio? :)
Są testy. W katalogu, który dla zmylenia przeciwnika nazywa się examples. :-)

A jakieś inne testy byś chciał?
--
Maciej Sobczak * http://www.inspirel.com
Wojciech Muła
2020-06-08 10:25:57 UTC
Permalink
Post by Maciej Sobczak
Post by Wojciech Muła
Po pierwsze, to aż się prosi, żeby ten serwer był zwykłą klasą. Czemu ktoś nie miałby sobie stworzyć 5 serwisów WWW działających na różnych portach?
No właśnie. I tu poruszamy ważną kwestię. Bo piszesz, że aż się prosi, ale potem okazuje się, że nikt nie prosi, tylko czemu ktoś by miał nie prosić.
Czyli ograniczasz użytkowników do jednego przypadku i to w sytuacji, gdy dodanie jednego stopnia swobody nie kosztuje ani użytkownika, ani Ciebie nic.
Post by Maciej Sobczak
A mi chodziło o to, żeby pakiet 1.0 przekroczył próg używalności a nie o to, żeby rozwiązać problemy typu "czemy ktoś nie miałby".
Żeby Twojego rozwiązania użyć w jakimś normalnym programie, trzeba stworzyć wątek. Wygodne użycie, to byłoby coś takiego:

int main() {
auto server = std::make_unique<http::Server>(8008, ".");

// tu sobie programista coś inicjalizuje

server->start();

// tu się dzieje magia, która programista uprawia
// a gdy się kończy scope, to server się sam zamyka
}
Post by Maciej Sobczak
Natomiast, nic nie stoi na przeszkodzie, żeby sobie zawołać funkcję server_start() 5 razy z różnymi portami, z 5 różnych wątków, bo ta funkcja i tak nie ma stanu globalnego. Nie trzeba mieć do tego klasy.
Stoi, bo masz współdzieloną mapę routingu. A, że masz ją współdzieloną, to też masz radosnego mutexa w głównej pętli.
Post by Maciej Sobczak
Post by Wojciech Muła
Po drugie, nie ma sposobu na zamknięcie serwera, poza zabiciem procesu. Chyba, że ja czegoś nie widzę.
Tak. Funkcja server_stop() już istniała, ale ją usunąłem. To nie jest oczywiste, jak zamknąć serwer, który ma callbacki, niektóre zapewne w trakcie pracy.
Wszystkie problemy da się rozwiązać, ale nie o to chodziło w wersji 1.0.
No i to jest defekt. Ja chcę, żeby mój program się zamykał w cywilizowany sposób.
Callbacki są wołane w wątkach, robisz sobie na nie barierę (czyli np. latch) po zakończeniu głównej pętli i po kłopocie.
Post by Maciej Sobczak
Post by Wojciech Muła
Mówiąc o API: 6 wariantów register_{generic,html,text}_{post,get}_action można by sprowadzić do 2. register_action(const char* name, {post_action_type, get_action_type} callback, const char* mime_type).
void my_action(to-co-trzeba-dla-get) { ... }
void my_action(to-co-trzeba-dla-post) { ... }
register(my_action);
To jest koślawe, sorry. W HTTP masz nie tylko akcje GET i POST, ale i chyba ze 20 innych. Poza tym założenie, że ktoś będzie argumenty POST przesyłał w URL-u jest zdziebko przestarzałe, o wiele wygodniej jest słać parametry w JSONie.
Post by Maciej Sobczak
Post by Wojciech Muła
Zresztą, może lepiej byłoby przyjmować jako argument mapę akcji - czyli to co masz teraz w get_actions/post_actions. Niech user sobie przygotuje takie mapy w sposób, jaki mu pasuje, a ty pozbędziesz się potrzeby blokowania tych struktur.
Ale teraz obsługa jest prostsza, właśnie dlatego, że user nie musi robić takich map.
Pamiętanie o kilku wariantach funkcji nie jest prostsze. Już lepiej byłoby mieć jedną przeciążoną metodę register i kilka pomocniczych funkcji w stylu "make_get_action".
Post by Maciej Sobczak
Można by było pomyśleć o akcji catch-all. Tam user dostawałby wszystko (co nie było obsłużone) i mógłby sobie tam zrobić takie mapy, jakie zechce.
Post by Wojciech Muła
Czasem funkcje przyjmują const char*, czase std::string& co jest niespójne.
Bo chodziło o przewidywane użycie. Tam gdzie przewidywałem literał, jest const char*.
const char* to nie tylko literały, tego założenia nie da się odczytać z API.
Post by Maciej Sobczak
Post by Wojciech Muła
W ogóle nie walidujesz, czy wskaźniki są niepuste. Tak samo z std::function.
A po co? Bez przesady z tą walidacją. Walidować należy input z zewnątrz (i nawet opisałem to w przykładzie 3, z parametrami) a nie własne literały.
Bo programista się czasem myli, więc powinien się koncentrować na błędach w kodzie, który pisze, a nie którego używa.
Post by Maciej Sobczak
Post by Wojciech Muła
Zero testów. Serio? :)
Są testy. W katalogu, który dla zmylenia przeciwnika nazywa się examples. :-)
A jakieś inne testy byś chciał?
Np. testy jednostkowe parserów, których jest co najmniej ze 2. Jak widzę
5-krotnie zagnieżdżony kod, to nie wiem, czego się spodziewać.

w.
Maciej Sobczak
2020-06-08 19:20:38 UTC
Permalink
Post by Wojciech Muła
Żeby Twojego rozwiązania użyć w jakimś normalnym programie, trzeba stworzyć wątek.
Cała jedna linijka kodu. Której w prostych programach nawet nie trzeba (patrz przykłady).
Post by Wojciech Muła
int main() {
auto server = std::make_unique<http::Server>(8008, ".");
server->start();
Czyli też jedna dodatkowa linijka kodu, w dodatku zawsze, nawet w najprostszym programie.
Więc na czym polega postęp?
Post by Wojciech Muła
// tu się dzieje magia, która programista uprawia
// a gdy się kończy scope, to server się sam zamyka
}
Się tak łatwo nie zamyka, jeśli ma callbacki.
Post by Wojciech Muła
Post by Maciej Sobczak
Natomiast, nic nie stoi na przeszkodzie, żeby sobie zawołać funkcję server_start() 5 razy z różnymi portami, z 5 różnych wątków, bo ta funkcja i tak nie ma stanu globalnego. Nie trzeba mieć do tego klasy.
Stoi, bo masz współdzieloną mapę routingu.
Przyłapałeś mnie. Skupiłem się na portach - faktycznie mapa jest wspólna.
Czyli twierdzisz, że ktoś będzie koniecznie chciał zrobić w jednym programie 5 serwerów na różnych portach, ale tak, żeby takie same linki robiły w nich różne rzeczy?
To brzmi jak ostra perwersja. Tylko dlaczego ja mam w tym uczestniczyć?

Jeśli moja biblioteka miałaby swoją ułomnością powstrzymać kogoś przed tą perwersją, to nawet uznałbym to za moralny sukces. :-)
Post by Wojciech Muła
A, że masz ją współdzieloną, to też masz radosnego mutexa w głównej pętli.
I w czym ten mutex przeszkadza, skoro go nawet nie widać?
Post by Wojciech Muła
No i to jest defekt. Ja chcę, żeby mój program się zamykał w cywilizowany sposób.
Callbacki są wołane w wątkach, robisz sobie na nie barierę (czyli np. latch) po zakończeniu głównej pętli i po kłopocie.
O ile wszystkie wrócą. Zobacz przykład 6. Można go przepisać tak, że to funkcja get_updates() będzie robić to, co activity(). Czyli nigdy nie wróci.

Ale owszem, jest to możliwe rozwiązanie, tylko wymaga zmiany koncepcji komunikacji. Teraz, w prostej implementacji, jest to komunikacja blokująca. Wątek obsługujący połączenie nie wróci, jeśli utknął na odczycie z gniazda (a w tym stanie spędza większość czasu), dopóki *klient* tego połączenia nie zamknie. Nie wystarczy sobie ustawić flagę.
Można to rozwiązać wprowadzając dodatkowe mechanizmy typu select() albo poll(), ale zrobienie tego dobrze to złożoność porównywalna z całą resztą kodu i to są właśnie problemy, których nie chciałem rozwiązywać w wersji 1.0.

Ten problem jest rozwiązany w bibliotece YAMI4, ale to zupełnie inna liga.
Post by Wojciech Muła
To jest koślawe, sorry. W HTTP masz nie tylko akcje GET i POST, ale i chyba ze 20 innych.
Ale ja nie obiecuję obsługi tych 20 innych.
Post by Wojciech Muła
Poza tym założenie, że ktoś będzie argumenty POST przesyłał w URL-u jest zdziebko przestarzałe, o wiele wygodniej jest słać parametry w JSONie.
Przecież właśnie tak jest. Dlatego funkcje dla POST mają dodatkowy argument istream - tam są te dane, które normalni ludzie przekazują.

I właśnie dlatego funkcje dla GET i POST *różnią się* sygnaturami.
Post by Wojciech Muła
Pamiętanie o kilku wariantach funkcji nie jest prostsze. Już lepiej byłoby mieć jedną przeciążoną metodę register i kilka pomocniczych funkcji w stylu "make_get_action".
Czyli że:

register(make_get_action(my_action));

jest lepsze od:

register_get_action(my_action);

Sorry - ani trochę.
Post by Wojciech Muła
Post by Maciej Sobczak
A po co? Bez przesady z tą walidacją. Walidować należy input z zewnątrz (i nawet opisałem to w przykładzie 3, z parametrami) a nie własne literały.
Bo programista się czasem myli, więc powinien się koncentrować na błędach w kodzie, który pisze, a nie którego używa.
Ale dlaczego ma się koncentrować na błędach w kodzie, którego używa, skoro takich nie znalazł a za to ma błędy w swoim? :-)

I czym się różni pomyłka polegająca na użyciu pustego wskaźnika od pomyłki polegającej na użyciu wskaźnika do niewłaściwej funkcji?
Otóż niczym się nie różni - a kompleksowe rozwiązanie tego zagadnienia (czyli zapewnienie, że programista sięgnął po właściwą funkcję) nie leży po stronie użytej biblioteki. To jest jedno z częstych nieporozumień w temacie weryfikacji albo defensywnego kodowania.

Na tej podstawie zakładam, że programista poda wskaźnik do właściwej funkcji. To założenie jest częścią kontraktu tej biblioteki.
Post by Wojciech Muła
Post by Maciej Sobczak
A jakieś inne testy byś chciał?
Np. testy jednostkowe parserów, których jest co najmniej ze 2. Jak widzę
5-krotnie zagnieżdżony kod, to nie wiem, czego się spodziewać.
Uwaga, szpan: pokrycie strukturalne zapewniłem testami systemowymi.

Bez przesady z tymi testami.
--
Maciej Sobczak * http://www.inspirel.com
heby
2020-06-08 19:32:08 UTC
Permalink
Post by Maciej Sobczak
I czym się różni pomyłka polegająca na użyciu pustego wskaźnika od pomyłki polegającej na użyciu wskaźnika do niewłaściwej funkcji?
Na tym że pierwsa jest wykrywana przez trywialny assert. Nie użycie go
świadczy o bardzo kiepskiej jakości kodzie ponieważ bibiloteka nawet
*takiej* oczywistości nie weryfikuje, a powinna weryfikować jak nawięcej
(w debugu).
Post by Maciej Sobczak
Otóż niczym się nie różni
Z praktyki wynika że nullowe pointery są znacznie wiekszym problemem niż
niewłaściwe pointery, bo te drugie często załatwia się kontrolą typów.
Szczególnie kiedy biblitekę używasz po raz pierwszy i spodziewasz się
choć odrobiny wsparcia po jej stronie.
Post by Maciej Sobczak
Bez przesady z tymi testami.
Nie wykluczam że w projaktach hobbystycznych jest jakiś margines
projektów gdzie faktycznie psu na budę te testy. Skoro taki masz target...
Maciej Sobczak
2020-06-08 21:44:16 UTC
Permalink
Post by heby
Post by Maciej Sobczak
I czym się różni pomyłka polegająca na użyciu pustego wskaźnika od pomyłki polegającej na użyciu wskaźnika do niewłaściwej funkcji?
Na tym że pierwsa jest wykrywana przez trywialny assert.
Który nie wykrywa niczego innego. To, że jesteś na lądzie, nie znaczy, że pod właściwym adresem (pun intended).
Post by heby
Nie użycie go
świadczy o bardzo kiepskiej jakości kodzie
Według jakich kryteriów?
Post by heby
ponieważ bibiloteka nawet
*takiej* oczywistości nie weryfikuje
Od kiedy to biblioteki HTTP służą do weryfikacji programów?
Post by heby
a powinna weryfikować jak nawięcej
Według jakiego procesu produkcji oprogramowania?
Post by heby
Z praktyki wynika że nullowe pointery są znacznie wiekszym problemem niż
niewłaściwe pointery, bo te drugie często załatwia się kontrolą typów.
Nie, bo wszystkie akcje GET mają ten sam typ.

register_get_html("action1", action1);
register_get_html("action2", action2);
register_get_html("action3", action2);

Jest bug. Co więcej, zdecydowanie łatwiej jest go zrobić, niż napisać NULL.
Post by heby
Szczególnie kiedy biblitekę używasz po raz pierwszy i spodziewasz się
choć odrobiny wsparcia po jej stronie.
Wsparcie jest w tym, że API jest minimalne i nie narzuca się z niepotrzebnymi abstrakcjami.
Post by heby
Nie wykluczam że w projaktach hobbystycznych jest jakiś margines
projektów gdzie faktycznie psu na budę te testy. Skoro taki masz target...
Targetem są świadomi inżynierowie, którzy nie oczekują od biblioteki HTTP, że im zrobi weryfikację poprawności programu...
--
Maciej Sobczak * http://www.inspirel.com
heby
2020-06-08 22:22:19 UTC
Permalink
Post by Maciej Sobczak
Post by heby
Na tym że pierwsa jest wykrywana przez trywialny assert.
Który nie wykrywa niczego innego.
Ale to co wykrywa jest przydatne.
Post by Maciej Sobczak
Post by heby
Nie użycie go
świadczy o bardzo kiepskiej jakości kodzie
Według jakich kryteriów?
Programowania defensywnego na inpucie.
Post by Maciej Sobczak
Post by heby
ponieważ bibiloteka nawet
*takiej* oczywistości nie weryfikuje
Od kiedy to biblioteki HTTP służą do weryfikacji programów?
W każdym inpucie powinna być weryfikacja, ponieważ *ułatwia* to
debugowanie klientowi.

W każdym innym miejscu powinna być weryfikacja, bo ułatwia to
refaktoring *autorowi*.
Post by Maciej Sobczak
Post by heby
a powinna weryfikować jak nawięcej
Według jakiego procesu produkcji oprogramowania?
Dojrzałego.
Post by Maciej Sobczak
Post by heby
Z praktyki wynika że nullowe pointery są znacznie wiekszym problemem niż
niewłaściwe pointery, bo te drugie często załatwia się kontrolą typów.
Nie, bo wszystkie akcje GET mają ten sam typ.
No w tym wypadku nie. W sytuacji ogólnej tak.
Post by Maciej Sobczak
register_get_html("action1", action1);
register_get_html("action2", action2);
register_get_html("action3", action2);
Jest bug. Co więcej, zdecydowanie łatwiej jest go zrobić, niż napisać NULL.
To dlatego że masz ascii-art programming. I rozumiem że nie da się tego
zrobić łatwo i bezpiecznie. Dość specyficzny przypadek gdzie kontrola
typów nie zadziała. Nie da się mieć wszystkiego, ale to nie znaczy że
nie można mieć choć troche.
Post by Maciej Sobczak
Post by heby
Szczególnie kiedy biblitekę używasz po raz pierwszy i spodziewasz się
choć odrobiny wsparcia po jej stronie.
Wsparcie jest w tym, że API jest minimalne i nie narzuca się z niepotrzebnymi abstrakcjami.
Assert to nie abstrakcja. To ... nic.
Post by Maciej Sobczak
Post by heby
Nie wykluczam że w projaktach hobbystycznych jest jakiś margines
projektów gdzie faktycznie psu na budę te testy. Skoro taki masz target...
Targetem są świadomi inżynierowie, którzy nie oczekują od biblioteki HTTP, że im zrobi weryfikację poprawności programu...
Chyba takich jest relatywnie mało. Sądzepo ilości assertów w poważnych
biblitekach.
Maciej Sobczak
2020-06-09 20:43:13 UTC
Permalink
Post by heby
Post by Maciej Sobczak
Post by heby
Nie użycie go
świadczy o bardzo kiepskiej jakości kodzie
Według jakich kryteriów?
Programowania defensywnego na inpucie.
Rzucam tezą, że ktoś z dobrą intencją ulepił koncept a cała masa ludzi ten koncept powiela, już bez zastanowienia o co autorowi chodziło.

Weź sobie funkcję std::sort. Ma trzy argumenty, trzeci to właśnie callback komparatora (zwany w kręgach zbliżonych do akademickich "predykatem"). Otwórz sobie header "algorithm" ze swojego kompilatora i poszukaj tam co robi funkcja std::sort ze swoim trzecim argumentem (czyli "inputem", jak to nazywasz).

Sprawdza, czy programista nie podał pustego wskaźnika/funktora/itp.?

Tak więc biblioteka HTTP jest właśnie w takim towarzystwie (przynajmniej w tej konkretnej kwestii...).
Post by heby
Post by Maciej Sobczak
Od kiedy to biblioteki HTTP służą do weryfikacji programów?
W każdym inpucie powinna być weryfikacja,
To nie jest input, tylko część programu. Inputem jest URL z przeglądarki albo dane z formatki w POST. I *to* należy walidować.
Post by heby
ponieważ *ułatwia* to
debugowanie klientowi.
Debugowanie ułatwia fakt, że gdybyś faktycznie spróbował zrobić taki błąd w tej bibliotece, zamiast trollować na rympał, to byś zobaczył, że std::function rzuca wtedy wyjątek, który biblioteka uczciwie wypisuje na podanym strumieniu do logowania błędów.
Spróbuj.

To programowanie defensywne, podobnie jak paranoja wokół unit testów, to niestety efekt braku refleksji nad własnym warsztatem.
Post by heby
Post by Maciej Sobczak
Targetem są świadomi inżynierowie, którzy nie oczekują od biblioteki HTTP, że im zrobi weryfikację poprawności programu...
Chyba takich jest relatywnie mało. Sądzepo ilości assertów w poważnych
biblitekach.
No to ile assertów znalazłeś w std::sort na trzecim argumencie?
Ja sprawdziłem w bibliotekach standardowych z trzech różnych kompilatorów.
--
Maciej Sobczak * http://www.inspirel.com
heby
2020-06-09 21:15:48 UTC
Permalink
Post by Maciej Sobczak
Post by heby
Programowania defensywnego na inpucie.
Rzucam tezą, że ktoś z dobrą intencją ulepił koncept a cała masa ludzi ten koncept powiela, już bez zastanowienia o co autorowi chodziło.
Weź sobie funkcję std::sort. Ma trzy argumenty, trzeci to właśnie callback komparatora (zwany w kręgach zbliżonych do akademickich "predykatem"). Otwórz sobie header "algorithm" ze swojego kompilatora i poszukaj tam co robi funkcja std::sort ze swoim trzecim argumentem (czyli "inputem", jak to nazywasz).
Sprawdza, czy programista nie podał pustego wskaźnika/funktora/itp.?
Teraz weź dowolny nagłówek z Qt i poszukaj sobie Q_ASSERT. Niezłe
głupki, nie? Kto by traciła na to czas, Paaaanie...
Post by Maciej Sobczak
Tak więc biblioteka HTTP jest właśnie w takim towarzystwie (przynajmniej w tej konkretnej kwestii...).
No ale to kiepskie towarzystwo. Co by o std:: nie mówić, jakościowo to
jest takie sobie, że nie wspomnę już że ma co najmniej kilka implementacji.
Post by Maciej Sobczak
Post by heby
Post by Maciej Sobczak
Od kiedy to biblioteki HTTP służą do weryfikacji programów?
W każdym inpucie powinna być weryfikacja,
To nie jest input, tylko część programu. Inputem jest URL z przeglądarki albo dane z formatki w POST. I *to* należy walidować.
Więc mamy różne pojęcie o inpucie. Jako klient bibliteki widzę to
inaczej, nic nie poradzę.
Post by Maciej Sobczak
Post by heby
ponieważ *ułatwia* to
debugowanie klientowi.
Debugowanie ułatwia fakt, że gdybyś faktycznie spróbował zrobić taki błąd w tej bibliotece, zamiast trollować na rympał, to byś zobaczył, że std::function rzuca wtedy wyjątek, który biblioteka uczciwie wypisuje na podanym strumieniu do logowania błędów.
Exceptions to nie asercje. Nie służa do tego samego. Narzekanie jest na
asercje a raczej ich brak. Asercje to rodzaj dokumentacji dla klienta.
Przydają się w debugu. Nic nie kosztują w runtime. Gdzie są wady które
powodują że nie warto?
Post by Maciej Sobczak
To programowanie defensywne, podobnie jak paranoja wokół unit testów, to niestety efekt braku refleksji nad własnym warsztatem.
Paranoja wokół unit testów oznacza po drugiej stronie luzacki kod bez
śladu testowania. Rozsądek nakazuje być gdzieś w środku, specyfikacja
nakazuje czasem mieć prawie 100% pokrycia. Trudno tu doszukiwac się
refleksji, choć często muszę stopować młodych gniewnych którym wszystko
zawsze wychodzi dobrze od razu, tylko troche nie działa. Jednak pisanie
unit testów czasem się przydaje. Jak coś zapraszam do mnie, sam zobaczysz.
Post by Maciej Sobczak
Post by heby
Post by Maciej Sobczak
Targetem są świadomi inżynierowie, którzy nie oczekują od biblioteki HTTP, że im zrobi weryfikację poprawności programu...
Chyba takich jest relatywnie mało. Sądzepo ilości assertów w poważnych
biblitekach.
No to ile assertów znalazłeś w std::sort na trzecim argumencie?
Trudno nazwać std:: poważną bibliteką pod kątem jakości. Obserwowałem
kiedyś rozwój stlport i muszę przyznać że podejście z gatunku "chyba
dobrze, komituj na produkcję" dało mi dużo do myślenia i zmianę własnego
warsztatu ze zwrotem przeciwnym.
Post by Maciej Sobczak
Ja sprawdziłem w bibliotekach standardowych z trzech różnych kompilatorów.
To sprawdź jeszcze resztę świata. Zacznij od Qt. Spodoba Ci się, tam
pracują sami nadprzyrodzeni hackerzy którzy mają reglamentowane asserty.
Ale i tak można ich tam troszkę znaleźć. Widocznie ktoś stwierdził że
czasem warto pilnować czy coś nie jest nullem, nawet jeśli klient tej
biblioteki jest nadprzyrodzonym superkoderem z kontraktem i +10 do
szczęścia.
Maciej Sobczak
2020-06-10 19:13:55 UTC
Permalink
Post by heby
Post by Maciej Sobczak
Weź sobie funkcję std::sort.
Teraz weź dowolny nagłówek z Qt
Nie używam.
Post by heby
Niezłe
głupki, nie?
Nie. To ich wybór. Ja wybrałem tak jak autorzy std::sort.
Post by heby
No ale to kiepskie towarzystwo. Co by o std:: nie mówić, jakościowo to
jest takie sobie,
Tak, teraz musisz się koniecznie wytrollować z tej retorycznej dziury, do której się sam wtrollowałeś.
Post by heby
że nie wspomnę już że ma co najmniej kilka implementacji.
Podobnie jak standard POSIX. Też ma kilka implementacji.

Skoro jest wiele implementacji biblioteki standardowej i wszystkie mają podobne zdanie na ten sam temat (pomimo naturalnej konkurencji pomiędzy nimi), to można to zdanie nazwać jakimś konsensusem w danym temacie.
W przypadku jednej biblioteki (np. Qt) można to nazwać opinią.
Post by heby
Asercje to rodzaj dokumentacji dla klienta.
Nie. Dla klienta jest header. Jak się autor postara, to dokumentacja też tam jest. Ale przede wszystkim dla klienta jest header.

Asercje jako kontrakt są do bani właśnie przez to, że nie ma ich w headerze.
Post by heby
Przydają się w debugu. Nic nie kosztują w runtime. Gdzie są wady które
powodują że nie warto?
Nie rozwiązują problemu, jakim jest niewłaściwa użyta funkcja i dają fałszywe poczucie bezpieczeństwa. O, fajnie, asserty przeszły, jest OK. A tu klops.

Uwaga: asserty są fajne *na końcu* funkcji - jako sanity-check, czy funkcja zrobiła to co miała zrobić.
Własnie dlatego, że są w implementacji, a nie w headerze.
Post by heby
Trudno nazwać std:: poważną bibliteką pod kątem jakości.
Rozumiem.
Post by heby
Post by Maciej Sobczak
Ja sprawdziłem w bibliotekach standardowych z trzech różnych kompilatorów.
To sprawdź jeszcze resztę świata.
A co będzie, jak znowu trafię na bibliotekę, która nie sprawdza?
Post by heby
Zacznij od Qt.
Zacząłem od trzech różnych implementacji std.
--
Maciej Sobczak * http://www.inspirel.com
heby
2020-06-10 20:54:22 UTC
Permalink
Post by Maciej Sobczak
Post by heby
To sprawdź jeszcze resztę świata.
A co będzie, jak znowu trafię na bibliotekę, która nie sprawdza?
To będziesz miał powód watpić czy Twoje rozwiązanie, i kolegow z std::,
jest prawidłowe. Skoro reszta świata w jakimś procencie uzywa.
Oczywiście to wszystko moga byc idioci, wiadomo.
Maciej Sobczak
2020-06-10 20:35:55 UTC
Permalink
Post by heby
Post by Maciej Sobczak
Ja sprawdziłem w bibliotekach standardowych z trzech różnych kompilatorów.
To sprawdź jeszcze resztę świata. Zacznij od Qt.
A co mi tam. Sprawdziłem. Zacząłem od Qt.

https://github.com/qt/qtbase/blob/dev/src/corelib/tools/qalgorithms.h

Konkretnie, funkcja qSort z callbackiem komparatora jest tutaj:

https://github.com/qt/qtbase/blob/dev/src/corelib/tools/qalgorithms.h#L181

i bez walidowania swoich argumentów woła qSortHelper, który jest tutaj:

https://github.com/qt/qtbase/blob/dev/src/corelib/tools/qalgorithms.h#L340

i który bez walidowania swoich argumentów wywołuje callback tutaj:

https://github.com/qt/qtbase/blob/dev/src/corelib/tools/qalgorithms.h#L351
Post by heby
Spodoba Ci się
Bez szału. Tzn. walidację callbacków robią poprawnie - w sensie że nie robią. O, to w sumie podobnie jak w bibliotece standardowej. Konsensus w tej sprawie się przez to poszerzył o kolejną zgodną opinię.

Natomiast ogólne wrażenie - jak na bibliotekę, która miała rzekomo inspirować jakością, nie urywa.
Przykładowo, w jednym miejscu (w qSortHelper, 343) jest tak:

int span = int(end - start);

a w innym (w qStableSortHelper, 452) tak:

const int span = end - begin;

Dziwne, nie? I niekonsekwencja w nazwach iteratorów albo w użyciu const w dokładnie takim samym idiomie, to akurat najmniejszy pikuś.
Ćwiczenie: czy wartość (end - start) zawsze mieści się w int?

Co się stanie, jeśli się nie zmieści? Jak to wpłynie na następne dwie linijki:

if (span < 2)
return;

?

Dalej: oszczędzanie na nawiasach klamrowych, niekonsekwentne ich stosowanie, albo raz się namespace kończy komentarzem, innym razem bez komentarza. To tak na szybko.

Nie twierdze, że bardzo źle. W kategorii open-source na pewno powyżej średniej.

Ale nie o to chodzi. Chodzi o to, że strasznie jestem ciekaw, jaki argument teraz wymyślisz.
--
Maciej Sobczak * http://www.inspirel.com
heby
2020-06-10 20:55:47 UTC
Permalink
Post by Maciej Sobczak
Ale nie o to chodzi. Chodzi o to, że strasznie jestem ciekaw, jaki argument teraz wymyślisz.
Żaden. Z płaskoziemcami tez mi się cieżko rozmawia i w sumie to mało
konstruktywne. Ponadto EOT to EOT. Ziew.
Wojciech Muła
2020-06-23 07:33:05 UTC
Permalink
Post by Maciej Sobczak
Post by Wojciech Muła
int main() {
auto server = std::make_unique<http::Server>(8008, ".");
server->start();
Czyli też jedna dodatkowa linijka kodu, w dodatku zawsze, nawet w najprostszym programie.
Więc na czym polega postęp?
Na braku konieczności ręcznego tworzenia i zarządzania wątkiem.
Post by Maciej Sobczak
Się tak łatwo nie zamyka, jeśli ma callbacki.
Co mnie jako twórcę biblioteki obchodzi, że ktoś ma burdel w callbackach. Ja gwarantuję, że moje wątki się skończą jeśli skończą się callbacki.
Post by Maciej Sobczak
Post by Wojciech Muła
Stoi, bo masz współdzieloną mapę routingu.
Przyłapałeś mnie. Skupiłem się na portach - faktycznie mapa jest wspólna.
Czyli twierdzisz, że ktoś będzie koniecznie chciał zrobić w jednym programie 5 serwerów na różnych portach, ale tak, żeby takie same linki robiły w nich różne rzeczy?
To brzmi jak ostra perwersja. Tylko dlaczego ja mam w tym uczestniczyć?
Bo np. na jednym porcie masz dane dla userów, na drugim możesz dawać output z debuggera, profilera, co tam sobie robisz. Wiesz, to że Twój serwer jest prosty, nie znaczy, że aplikacja która go użyje też jest prosta. Gdyby była prosta, pewnie nikt by jej nie pisał w C++.
Post by Maciej Sobczak
Post by Wojciech Muła
A, że masz ją współdzieloną, to też masz radosnego mutexa w głównej pętli.
I w czym ten mutex przeszkadza, skoro go nawet nie widać?
Bo mutexy są kosztowne czasowo. I akurat tego jednego mogłoby nie być.
Post by Maciej Sobczak
Post by Wojciech Muła
No i to jest defekt. Ja chcę, żeby mój program się zamykał w cywilizowany sposób.
Callbacki są wołane w wątkach, robisz sobie na nie barierę (czyli np. latch) po zakończeniu głównej pętli i po kłopocie.
O ile wszystkie wrócą. Zobacz przykład 6. Można go przepisać tak, że to funkcja get_updates() będzie robić to, co activity(). Czyli nigdy nie wróci.
Ale owszem, jest to możliwe rozwiązanie, tylko wymaga zmiany koncepcji komunikacji. Teraz, w prostej implementacji, jest to komunikacja blokująca. Wątek obsługujący połączenie nie wróci, jeśli utknął na odczycie z gniazda (a w tym stanie spędza większość czasu), dopóki *klient* tego połączenia nie zamknie. Nie wystarczy sobie ustawić flagę.
Ale w końcu wróci, choćby przez timeout. I o to chodzi.
Post by Maciej Sobczak
Post by Wojciech Muła
To jest koślawe, sorry. W HTTP masz nie tylko akcje GET i POST, ale i chyba ze 20 innych.
Ale ja nie obiecuję obsługi tych 20 innych.
Super, więc jak będę chciał mieć operację DELETE albo PUT, to muszę sobie szukać innego rozwiązania.
Post by Maciej Sobczak
Post by Wojciech Muła
Poza tym założenie, że ktoś będzie argumenty POST przesyłał w URL-u jest zdziebko przestarzałe, o wiele wygodniej jest słać parametry w JSONie.
Przecież właśnie tak jest. Dlatego funkcje dla POST mają dodatkowy argument istream - tam są te dane, które normalni ludzie przekazują.
I właśnie dlatego funkcje dla GET i POST *różnią się* sygnaturami.
No fajnie, tylko to sztuczne rozróżnienie. W protokole HTTP nie ma znaczenia typ akcji, zawsze masz ten same input, w akcji GET też możesz wysłać dane, np. JSONa.
Post by Maciej Sobczak
Post by Wojciech Muła
Pamiętanie o kilku wariantach funkcji nie jest prostsze. Już lepiej byłoby mieć jedną przeciążoną metodę register i kilka pomocniczych funkcji w stylu "make_get_action".
register(make_get_action(my_action));
register_get_action(my_action);
Sorry - ani trochę.
Jest bardziej elastyczne i tyle. Ja wolę mieć jedną metodę i zrobić sobie odpowiednie konstruktory.
Zresztą, najlepiej byłby mieć register(my_action) i wybierać wariant za pomocą typetraits.
Post by Maciej Sobczak
Post by Wojciech Muła
Np. testy jednostkowe parserów, których jest co najmniej ze 2. Jak widzę
5-krotnie zagnieżdżony kod, to nie wiem, czego się spodziewać.
Uwaga, szpan: pokrycie strukturalne zapewniłem testami systemowymi.
Bez przesady z tymi testami.
Chciałeś review, to masz. Ja wiem, że parsery klepane ręcznie nie mające testów to proszenie się o kłopoty, będą wcześniej, czy później.

w.
Maciej Sobczak
2020-06-23 21:13:07 UTC
Permalink
Post by Wojciech Muła
Post by Maciej Sobczak
Więc na czym polega postęp?
Na braku konieczności ręcznego tworzenia i zarządzania wątkiem.
Ale przecież nie ma takiej konieczności w żadnym z przykładów.
Natomiast w Twojej propozycji nie tyle nie ma takiej konieczności, co raczej nie ma takiej możliwości, bo schowałeś to "zarządzanie" w jakimś obiekcie, którego API nie podałeś.
Post by Wojciech Muła
Co mnie jako twórcę biblioteki obchodzi, że ktoś ma burdel w callbackach. Ja gwarantuję, że moje wątki się skończą jeśli skończą się callbacki.
To jest ciekawa propozycja na kolejną wersję biblioteki.
Post by Wojciech Muła
Bo np. na jednym porcie masz dane dla userów, na drugim możesz dawać output z debuggera, profilera, co tam sobie robisz.
I to trzeba mieć osobne porty do tego?
Ja na przykład w tej konkretnej chwili podłączam się przeglądarką do jednego portu pod adresem groups.google.com a tam zdumiewające rzeczy, jedna grupa dla tych co lubią C++, inna dla tych, co nie lubią, itd. Masa różnych rzeczy, dla różnych odbiorców. Wyobrażasz sobie, różne rzeczy na jednym porcie mieć?
Post by Wojciech Muła
Bo mutexy są kosztowne czasowo.
A tak w liczbach, mógłbyś?
W sensie - w porównaniu do całkowitego czasu, który przeglądarce zejdzie na pełnej obsłudze, od konstrukcji zapytania GET do zakończenia wyświetlenia obrazu na ekranie?
Post by Wojciech Muła
Post by Maciej Sobczak
Post by Wojciech Muła
To jest koślawe, sorry. W HTTP masz nie tylko akcje GET i POST, ale i chyba ze 20 innych.
Ale ja nie obiecuję obsługi tych 20 innych.
Super, więc jak będę chciał mieć operację DELETE albo PUT, to muszę sobie szukać innego rozwiązania.
Tak. Ewentualnie możesz zwrócić się do autora z uprzejmą prośbą, żeby to dorobił. Czy ten schemat pracy to jest dla Ciebie jakieś nowe zjawisko?
Post by Wojciech Muła
Post by Maciej Sobczak
I właśnie dlatego funkcje dla GET i POST *różnią się* sygnaturami.
No fajnie, tylko to sztuczne rozróżnienie.
Ale użyteczne w kontekście docelowego użycia.
Post by Wojciech Muła
Post by Maciej Sobczak
register(make_get_action(my_action));
register_get_action(my_action);
Sorry - ani trochę.
Jest bardziej elastyczne i tyle. Ja wolę mieć jedną metodę i zrobić sobie odpowiednie konstruktory.
Zresztą, najlepiej byłby mieć register(my_action) i wybierać wariant za pomocą typetraits.
Łomatko.
Więc najwyraźniej potrzebujesz innej biblioteki. Normalna sprawa.
Post by Wojciech Muła
Chciałeś review, to masz. Ja wiem, że parsery klepane ręcznie nie mające testów to proszenie się o kłopoty, będą wcześniej, czy później.
Nie zrozumiałeś. To, że testów nie ma w pakiecie razem z biblioteką, nie znaczy wcale, że parser nie był przetestowany - ani tym bardziej, że w ogóle nie było żadnych testów.

W ogóle pomysł, że razem z produktem dostaje się w tym samym pudełku jego stanowisko testowe, to jakiś wymysł nie mający analogii w żadnej innej branży, nawet w tych inżynierskich.
--
Maciej Sobczak * http://www.inspirel.com
Loading...