wiele entry pointow to funkcji

0

potrzebuje zrobic z pozoru prosta rzecz, funkcje ktora moge zaczac w wielu miejscach.

int funkcja(int context){

...

tu_1:

...

tu_2:


...

tu_3:

...

}

pisze program ktory bedzie przetwarzal dane w sposob rozproszony, i potrzebuje wskoczyc w odpowiednim momencie w przerwana funkcje i ja kontynuowac.

funkcji raczej nie moge rozbic na wiele innych gdyz w srodku sa zagniezdzone ify/switche i inne funkcje.

0

na chama:

int funkcja(int context, int jumptarget)
{
    switch(jumptarget)
    {
        case 0: break;
        case 1: goto tu_1;
        case 2: goto tu_2;
        case 3: goto tu_3;
         ...
    }

       ...
tu_1:
       ...
tu_2:
       ...
tu_3:
       ...
}

Akurat uzyles poprawnego zapisu label'owego, wiec sadze ze juz miales/probowales wykorzystac goto, tylko sie nie pochwaliles.

jesli widzac to, przyjdzie Ci do glowy ze goto jest złe i ze go nie nalezy uzywac bo-cos-tam, i nie chcesz z tego powodu z niego korzystac, to wpierw zauwaz, ze jezeli w ogole wychodzisz z pytaniem i takimi ograniczeniami jak przedstawiles, to kod juz masz bardzo ciezko skitrany i dodanie dwoch, trzech, dziewieciu "forward only goto" nie za wiele w nim juz bardziej ubrudzi.

powinienes ulozyc program tak, aby poszczegolne kroki obliczen/przetwarzania byly przynajmniej osobnymi funkcjami, lub przynajmniej zeby byly rozdzielone tak, abys mogl je latwo odseparowac if/switchami i wybierac pomiedzy nimi. Jezeli zadnej z tych rzeczy zrobic nie mozesz, pozostaje Ci przepisanie kodu i uporzadkowanie go, albo uzycie goto. Z tym, ze jesli nie chcesz sie podjac jego porzadkowania bo za trudne albo za wiele pracy, to i goto moze Ci nie pomoc, gdyz aby wlasciwie i bezpiecznie je zastosowac, i tak musisz wszystko gruntownie przeanalizowac

@rozproszony/kontynuowac/zagniezdzone if/switch - mam nadzieje ze bardzo dobrze wiesz co robisz i bedziesz potrafil zapewnic spojnosc wszystkich owych zagniezdzonych warunkow

Jesli zas dostales jakas gigant-funkcje z poleceniem od kolegi/przelozonego/wykladowcy: "wez to zrownolegl na 4 procki" to zapomnij co w/w napisalem -- nie tedy droga, poza 0,1% specjalnie po to zbudowanych przypadkow, nie da sie ot tak pociac funkcji/kodu na cztery bloczki i kazdy z nich odpalic na procku obok

0

Takie coś, jak przerwanie funkcji w połowie, wyskoczenie i wskoczenie później z powrotem, to generalnie nie jest zła rzecz, tylko że nie za pomocą goto a za pomocą kontynuacji (w języku, który posiada kontynuacje). Uzasadnione to jest np. przy zamianie kodu rekurencyjnego na iteracyjny (dzięki temu nie trzeba używać jawnego stosu, a kod jest nadal krótki i "sekwencyjny"), albo w momencie, gdy nie mamy kontroli nad kodem klienckim, a nie może on kontynuować dopóki nie zostanie spełniony jakiś warunek i nie chcemy "trzymać wątku". I działa to nawet w przypadku zagnieżdżonych pętli / warunków. Niemniej to jest raczej wyższa szkoła jazdy i nie należy używać, jeśli naprawdę nie ma powodu.

0

Zgadzam sie, z tym, ze kontynuacja to zaleznie od implementacji, albo zwykly call tylko bez gwarantowanego powrotu, albo inne wcielenie delegate/closure, ktora przebudowujego kod na obiekt ze stanem plus dzieli metode na pol w punkcie kontynuacji.. Pierwsze nie pomoze autorowi w niczym, zas drugie -- to jest to co powinno (przynajmniej) byc tutaj zrobione recznie.. "niestety" t oc++:)

obawiam sie natomaist, ze tutaj wlasnie nijak nie bedzie tego zachowanego stanu! Autor mowi o "entry point", sadze wiec ze jest to jakas dll/exe do zaladowania np. pod menedzerem MPI'a i ow 'trick' ma byc wykonany w zaleznosci od numeru procesu natychmiast po jego starcie.. mi to wyglada na czyste lenistwo i "nie chce mi sie wylaczyc tego kodu odpalanego na zakonczenie fazy poza te dziwne warunki"

0

A nie lepiej użyć długich skoków z nagłówka setjmp.h, zamiast pisać jakieś dispatchery ? Autorowi chyba chodziło o wznowienie przerwanej funkcji a nie wywoływanie jej na nowo.

A jeżeli chodzi o zastosowanie przerywania funkcji w połowie to raz mi się to zdarzyło wykorzystać: przy wykrywaniu gdzie zaczyna się początek stosu głównego wątku w programie. W Linuksie oczywiście nie da się tego stwierdzić bez haków (na Windowsie jest ładna funkcja WinApi). Mechanizm wyglądał tak, że po kolei odwoływałem się do adresów aż nie trafiłem na guard page'a. Wtedy był zgłaszany SIGSEGV, i z signal handlera wyskakiwałem longjmp z powrotem do funkcji mając już w pamięci ostatni ważny adres.
Ciekawe czy dało się to jakoś prościej rozwiązać ;D (adres z /proc/stat jest niepoprawny ;P)

0

królik: Wiesz, twoja przednia wypowiedź w zasadzie sprowadzała się do rady typu: "zmień język programowania", co trudno nazwać rozwiązaniem.
Użycie static jest konieczne by pomiędzy kolejnymi wywołaniami nie stracić stanu w jakim znajduje się funkcja, zwykłe zmienne swoją zawartość.

Jak dla mnie to teraz odgrywasz fun-boy'a C#.

0

Ee tam. Bo to tylko C# ma yield return czy co?

Static jest do bani, bo zapamiętuje stan w sposób globalny. A stan powinien być zapamiętany przez tego, kto wywołuje tę funckję. W przypadku wołania takiej funkcji z dwóch wątków zachowanie będzie nieprzewidywalne.

Ale istnieje sposób na to w C/C++: setjmp i longjmp:
http://homepage.mac.com/sigfpe/Computing/continuations.html

Niemniej i tak mam wrażenie, że gdybyśmy poznali dokładnie powód stosowania tej konstrukcji, to by się okazało, że można to zrobić lepiej / prościej inaczej.

0

Trzeba było od razy dać tego linka, bo raczej na pewno o coś takiego chodziło.
W każdym razie ja sobie zabookmarkowałem tę stronę dzięki :).

0

o kontynuacjach/longjump krolik juz pisal, a i rnd odrzucil naglowek.. sam nie podawalem wczeniej nic, gdyz IMHO to jest jeszcze 'gorsze' niz lokalne goto, w sensie, ze trzeba sie z tym o wiele ostrozniej sie obchodzic. szczerze mowiac, liczylem ze autor watku raczy sie pojawic i dopowiedziec co chce faktycznie zrobic zanim ktos wykopie rzeczy o ktore on faktycznie pyta..

1 użytkowników online, w tym zalogowanych: 0, gości: 1