🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: pl.comp.lang.c
Article #267788

Re: Ciemna strona C++

#267788
From: Sektor van Skijlen
Date: Fri, 23 Nov 2007 14:13
185 lines
10915 bytes
Dnia Thu, 22 Nov 2007 13:21:31 +0100, Marcin ?Qrczak? Kowalczyk skrobie:
> Dnia 22-11-2007, Cz o godzinie 08:30 +0000, Sektor van Skijlen pisze:

> > W praktyce to oznacza, że w którymś momencie MUSISZ po prostu
> > najzwyczajniej w świecie obsłużyć ten wyjątek i nie ma od tego
> > ucieczki.

> W którymś momencie tak, ale lepiej nie przy każdym sleepie osobno,
> tylko zbiorczo w głównej funkcji wątku.

Momencik.

Na pewno masz rację. I bardzo chętnie bym to zrobił, tylko nie w sytuacji, gdy
InterruptedException nie jest pochodną RuntimeException, więc z jednego
głupiego sleep() muszę go przepropagować przez całą ścieżkę.

Ciekaw jestem swoją drogą, czy nie kończy się to czasem tym, że programiści
wkurzeni koniecznością definiowania propagacji po prostu każą się wątkowi
ukryć "pod osią ciężarówki RuntimeException".

> > > Mam rozumieć, że lepiej, kiedy sprzątanie przez wątek po jego przerwaniu
> > 
> > Stop! Nie mówimy tutaj o przerwaniu wyjątku. Mówiłem o zrobieniu sleep.

> O przerwaniu wątku, a nie wyjątku.

Taaa... już mi się wszystko plącze :)

> Sleep jest jedną z funkcji,
> która reaguje na przerwanie wątku z zewnątrz (Thread.interrupt).
> Stąd możliwość InterruptedException.

Super! Tylko po jasną cholerę mam w związku z tym deklarować propagację przez
wszystkie możliwe funkcje?

> Nie należy pisać tak jak napisałeś (połykać InterruptedException).
> http://www-128.ibm.com/developerworks/java/library/j-jtp05236.html

Dla mnie ideałem byłoby, gdyby w funkcji głównej wątku, lub w funkcji
startującej aplikację (bo wątek przerywalny to również wątek główny,
startujący aplikację) można było objąć cały kod trajem, jeśli trzeba jakoś
specjalnie zareagować na nakaz zakończenia.

Oczywiście prawda jest też taka, że gdybym miał C++ z biblioteką wątków i taki
wątek byłby kończony za pomocą rzucenia wyjątku, to nie musiałbym właściwie
(teoretycznie) robić niczego, nic się nawet nie stanie jak nie przechwycę
wątku w ogóle. Wszystko mi zrobią destruktory.

Natomiast w takiej np. Javie być może istnieje potrzeba przechwycenia tego
wyjątku gdzieś w środku, żeby po prostu wykonało się odpowiednie finally. Co
jest właściwie tożsame z wywołaniem destruktora w C++, tyle że w Javie trzeba
to zrobić ręcznie.

Oddzielną sprawą jest jednak sensowność kończenia wątku wyjątkiem. Ja sobie
ten wyjątek mogę gdzieś w środku przechwycić. Jak nie przemierzając w podanym
przykładzie. Wypadałoby ten wyjątek spropagować, ewentualnie na odpowiednim
poziomie zakończyć wątek. Jak biblioteka wątków chciałaby mnie zmusić do tego,
żeby nie "przechwytywać wyjątku na daremno"?

> Pewnym odpowiednikiem tego w SUS są funkcje, które są przerywane przez
> pthread_cancel w stanie PTHREAD_CANCEL_DEFERRED + PTHREAD_CANCEL_ENABLE
> (domyślnym zresztą):
> http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_09.html#tag_02_09_05_02

> Jedno i drugie jest raczej sztuczką niż porządnym projektem językowym.

Nie do końca.

> Ponieważ te języki nie dostarczają mechanizmów pozwalających
> programiście informować, w których momentach można przerwać wątek,
> domyślnie zakłada się, że można to zrobić wtedy, kiedy wątek na coś
> czeka (ale nie na mutex). Bo po pierwsze jest szansa, że takie momenty
> będą zdarzały się wystarczająco często, a po drugie jest szansa, że
> wszelkie niezmienniki globalnych struktur danych będą wtedy zachowane.

Zgadza się, ale w stan sleep można wprowadzić wątek nie tylko wywołując sleep
(mówię w sensie systemowo-ogólnym), ale również w stanie oczekiwania na I/O.
Tymczasem w Javie InterruptedException jest rzucane tylko przez Thread.sleep i
Object.wait. InputStream.read przykładowo rzuca tylko IOException!

> Różnica między Javą a Uniksem polega w tym miejscu na tym, że Java
> zmusza programistów do zauważenia, że dana funkcja jest przerywalna,
> a Unix nie.

Super - tylko skoro wątek może być przerwany tylko przez InterruptedException,
to w jaki sposób następuje "killowanie" wątku javowego? Jeśli nikt nie używa
żadnego sleep() w środku, to wątku nie można przerwać w ogóle? A jeśli można,
to jak się to odbywa?

> W połączeniu ze sprawą odśmiecania powoduje to, że
> w Uniksowym C/C++ pthread_cancel ma małe szanse poprawnego działania.
> Większość programistów nawet nie wie, że taka funkcja istnieje, i nie
> pisze kodu tak żeby działał poprawnie w obliczu asynchronicznych
> przerwań.

Jeśli mówimy o GNU pthreads i GCC/C++ to podobno działają poprawnie, bo
używany jest w pthread_cancel ten sam mechanizm, co w wyjątkach w C++.

> Zgadzam się, że checked exceptions powodują z reguły więcej kłopotu niż
> pożytku, ale z tego nie wynika, że jest w nic samo zło.

Jest wystarczająco dużo tego zła, żeby stwierdzić, że ten ficzer jest porażką.

> > Bo jeśli mówimy o normalnym przerwaniu wykonywania się wątku, to
> > w takim razie powinien on teoretycznie wystąpić w dowolnym momencie.
> > Nie tylko jak się wykonuje sleep().

> Gdyby mógł wystąpić w zupełnie dowolnym momencie, to nie dałoby się
> pisać poprawnego kodu, bo np. nie da się zagwarantować, że z pewnych
> dwóch instrukcji wykonają się obie albo żadna.

Oj, nie rozumiem, niby dlaczego. Jeśli wykonuję a + b + c, a drugi plus rzuci
wyjątkiem (bo akurat ktoś stwierdził, że sprzeda procesowi killa), to jaki
problem tu może wystąpić?

W C++ mógłby ci tutaj wystąpić problem ze wskaźnikami i nowo utworzonymi
obiektami. No, jeśli chciałbyś mieć 100% exception-safe kod, to należałoby
używać wyłącznie auto_ptr do przechowywania tymczasowej wartości wskaźnika na
obiekt. Chyba że w danej funkcji panuje taka zasada, że w razie wyjątku i tak
kończymy aplikację (i masz pewność, że system zwolni wszystkie zasoby
przydzielone przez proces).

Trochę inna sprawa występuje w przypadku, gdyby chcieć wspierać semantykę
wznowienia - ale właśnie wspomniałem o tym, że semantyka wznowienia powinna
być maksymalnie utrudniona. Na przykład tak, że każda funkcja systemowa
(jakimś sposobem) rzuca wyjątkiem za każdym wywołaniem, jeśli proces już raz
dostał killa.

> Należy umożliwić wątkowi blokowanie przerywania

Nie. Należy umożliwić wątkowi sprzątanie istniejących zasobów w razie
przerwania, natomiast na pewno nie odkładanie reakcji na przerwanie ad
calendas graecas.

> oraz zintegrować
> automatyczne blokowanie z innymi konstrukcjami języka (większość
> programistów nie myśli o możliwości przerwania wątku i tego nie
> zmienimy). Jeśli się postarać, jeśli język ma szansę rozpoznać
> regiony, które muszą się wykonać w całości, w sposób niewymagający
> od programisty dużego zachodu, to można domyślnie dopuścić przerywanie
> w dowolnym momencie.

Tak - a to z kolei wymaga oznaczenia obszarów, na terenie których następuje
niestabilność stanu aplikacji.

Ale wtedy można bez problemu przerwać to wyjątkiem.

> Przy czym w C++ nie ma na to szans, bo jest zdecydowanie zbyt wiele
> miejsc, których nie można przerwać, ale nie ma jak ich automatycznie
> rozpoznać. Na przykład region między new a przypisaniem gołego wskaźnika
> do sprytnego wskaźnika nie może być przerywalny (przynajmniej przy
> standardowym alokatorze).

Moment - o ile ja znam C++, to przerwanie przez wyjątek może nastąpić tylko w
dwóch miejscach: w operatorze new (wtedy pamięć jest automatycznie usuwana)
lub po przypisaniu (zakładamy, że w trakcie przypisywania nie wystąpi).

Jeśli przerywamy wątek wyjątkiem, to tak powinno to działać. Ale nie mam
pomysłu, jak to zorganizować.

> > > > Natomiast "łatwe języki" zwykle dają złudzenie łatwości tematu w przypadku
> > > > trudnych zagadnień. Jednym z takich trudnych zagadnień jest wielowątkowość.
> > 
> > > Dawałyby takie złudzenie gdyby ułatwiały projekt, który z pewnych
> > > subtelnych powodów jest niepoprawny, w porównaniu do poprawnego
> > > projektu, który miałby trudniej z winy języka. Ale nie przypominam
> > > sobie takich cech różnych języków, więc nie wiem, co masz na myśli.
> > 
> > Same wątki w Javie już wystarczą. Nadużywa się ich, zamiast zrobić to samo na
> > włóknach.

> Uważasz, że lepiej wprowadzać sztuczne utrudnienia w używaniu wątków,
> żeby zniechęcać do nich programistę?

Uważam, że należy wspierać alternatywne rozwiązania i wskazywać ich zalety.

I nie doradzać wątków do wszelkiej równoległej pracy, lecz właśnie wskazywać,
dlaczego one się do równoległej pracy na jednym obiekcie nie nadają.


-- 
//  _    ___         Michal "Sektor" Malecki <sektor(whirl)kis.p.lodz.pl>
\\ L_ |/ `|  /^\ ,()                         <ethouris(O)gmail.com>
// \_ |\  \/ \_/ /\ C++ bez cholesterolu: http://www.intercon.pl/~sektor/cbx
"Java is answer for a question that has never been stated"
Technical Details
Message-ID: <fi6n5f$fpr$1@kujawiak.man.lodz.pl>
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.rmf.pl!agh.edu.pl!news.agh.edu.pl!newsfeed.silweb.pl!news.man.lodz.pl!not-for-mail
References: <fghgeo$spf$1@nemesis.news.tpi.pl> <fghsb4$kpq$1@news.dialog.net.pl> <fgo4c7$mtu$1@news.vectranet.pl> <20071106073039.433f4934@Vorago> <fgqn9m$74j$2@news.vectranet.pl> <618565031.20071107113041@pkierski.net> <fgt6sh$jov$1@news.vectranet.pl> <fgtb6j$nur$1@news.vectranet.pl> <fgv6ba$k14$1@bozon2.softax.pl> <fgvkne$u3b$1@news.vectranet.pl> <fh1tjd$dtt$1@bozon2.softax.pl> <fh2lj6$qkh$1@news.vectranet.pl> <fha3as$pap$1@bozon2.softax.pl> <fhaj8u$e02$1@news.vectranet.pl> <fhf09d$ohq$1@bozon2.softax.pl> <fhfi9l$640$1@news.vectranet.pl> <fhurmu$5d9$1@bozon2.softax.pl> <fhv020$8k1$1@news.vectranet.pl> <fi1bs4$nn3$1@bozon2.softax.pl> <fi27ds$gt1$1@kujawiak.man.lodz.pl> <1195688300.8426.30.camel@qrnik> <fi3ems$7ig$1@kujawiak.man.lodz.pl> <1195734091.8426.77.camel@qrnik>

Show Full Headers
Complete Article Headers
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.rmf.pl!agh.edu.pl!news.agh.edu.pl!newsfeed.silweb.pl!news.man.lodz.pl!not-for-mail
From: Sektor van Skijlen <ethouris@guess.if.gmail.com.is.valid.or.invalid>
Newsgroups: pl.comp.lang.c
Subject: Re: Ciemna strona C++
Date: Fri, 23 Nov 2007 14:13:03 +0000 (UTC)
Organization: LODMAN - Metropolitan Area Network in LODZ, Poland
Lines: 185
Sender: Michal Malecki <sektor@student.kis.p.lodz.pl>
Message-ID: <fi6n5f$fpr$1@kujawiak.man.lodz.pl>
References: <fghgeo$spf$1@nemesis.news.tpi.pl> <fghsb4$kpq$1@news.dialog.net.pl> <fgo4c7$mtu$1@news.vectranet.pl> <20071106073039.433f4934@Vorago> <fgqn9m$74j$2@news.vectranet.pl> <618565031.20071107113041@pkierski.net> <fgt6sh$jov$1@news.vectranet.pl> <fgtb6j$nur$1@news.vectranet.pl> <fgv6ba$k14$1@bozon2.softax.pl> <fgvkne$u3b$1@news.vectranet.pl> <fh1tjd$dtt$1@bozon2.softax.pl> <fh2lj6$qkh$1@news.vectranet.pl> <fha3as$pap$1@bozon2.softax.pl> <fhaj8u$e02$1@news.vectranet.pl> <fhf09d$ohq$1@bozon2.softax.pl> <fhfi9l$640$1@news.vectranet.pl> <fhurmu$5d9$1@bozon2.softax.pl> <fhv020$8k1$1@news.vectranet.pl> <fi1bs4$nn3$1@bozon2.softax.pl> <fi27ds$gt1$1@kujawiak.man.lodz.pl> <1195688300.8426.30.camel@qrnik> <fi3ems$7ig$1@kujawiak.man.lodz.pl> <1195734091.8426.77.camel@qrnik>
NNTP-Posting-Host: student.kis.p.lodz.pl
Mime-Version: 1.0
X-Trace: kujawiak.man.lodz.pl 1195827183 16187 212.191.89.21 (23 Nov 2007 14:13:03 GMT)
X-Complaints-To: abuse@man.lodz.pl
NNTP-Posting-Date: Fri, 23 Nov 2007 14:13:03 +0000 (UTC)
User-Agent: tin/1.8.3-20070201 ("Scotasay") (UNIX) (FreeBSD/6.2-RELEASE-p3 (sparc64))
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit