Monthly archive for February, 2009

volatile?…

2009-02-23 13:18

Modyfikator volatile nie należy do często używanych elementów języka C(++). Jeśli więc gdzieś się go napotka, ma się sporą szansę nie odgadnąć od razu, dlaczego został użyty. Można też samemu przeoczyć sytuacje, gdy należałoby z niego korzystać.
Teoretycznie to słowo kluczowe nie powinno w ogóle istnieć; jest ono “techniczną” częścią języka, związaną ze sposobem jego kompilacji – trochę tak, jak klauzula checked z C# jest ściśle związana z metodami wykonywania obliczeń przez (ko)procesor. Wiemy jednak doskonale, że C++ wysokim poziomem abstrakcji nie grzeszy (już o C nie wspominając), więc obecność takich elementów nie powinna specjalnie dziwić.

volatile jako modyfikator zastosowany do (typu) zmiennej sprawia, że będzie ona traktowana tak, jakby jej zawartość mogła się w każdej chwili zmienić. Inaczej mówiąc, kompilator nie powinien nigdy czynić jakichkolwiek założeń co do wartości takiej zmiennej, bo jej wartość może być w dowolnym momencie przez coś zmodyfikowana.
Tak to wygląda od strony specyfikacji. W praktyce volatile stosuje się głównie w dwóch przypadkach:

  • Po pierwsze, używamy tego słowa jeśli rzeczywiście wartość naszej zmiennej może być zmodyfikowana przez jakiś ‘czynnik zewnętrzny’. Na niektórych maszynach tak na przykład działają urządzenia wejściowe: akcja w rodzaju wciśnięcia klawisza przez użytkownika powoduje zmianę zawartości jakiejś komórki pamięci. Chcąc na nią zareagować, należy więc cały czas monitorować to miejsce, bo może ono zmienić swoją zawartość zupełnie niespodziewanie. Oczywiście teraz takich rozwiązań się już nie stosuje, bo urządzenia wejściowe generują po prostu przerwania (interrupts), które są potem przerabiane przez system operacyjny na odpowiednie zdarzenia.
    Z globalnymi zmiennymi volatile można jednak często się spotkać w programach uniksowych, które funkcjonują w oparciu o sygnały. Typowym przykładem są serwery sieciowe, działające w pętli aż do momentu, gdy im się przerwie:

    1. while (!interrupted) do_work();

    Zmienna z warunku jest wtedy deklarowana jako:

    1. volatile sig_atomic_t interrupted = 0;

    zaś w procedurze obsługi sygnału – która może być wywołana w dowolnym momencie w odpowiedzi na przyjście żądanego sygnału (zwykle SIGINT) – jest ona ustawiana na 1. Gdyby nie była volatile, kompilator uznałby, że zawsze ma ona wartość zerową i “zoptymalizował” powyższą pętlę, zamieniając ją na nieskończoną.

  • Po drugie, z volatile korzysta się wtedy, chcemy w sposób zamierzony zapobiec pewnym optymalizacjom kodu. Zwykle chodzi tutaj o jakieś testowanie szybkości pewnych operacji, np. arytmetycznych. Powinno się wtedy wykonywać je na zmiennych opatrzonych modyfikatorem volatile, żeby mieć pewność, że wszystkie działania się wykonają i żadne nie zostanie wyeliminowane w procesie kompilacji. Można oczywiście wątpić w zdolności optymalizacyjne kompilatora, ale jest całkiem możliwe, że – zgodnie ze sprawdzonym po wielokroć prawem Murphy’ego – włączą się one właśnie tam, gdzie akurat byśmy ich sobie nie życzyli :)

Jeśli więc któryś z tych dwóch powyższych przypadków pasuje do naszej sytuacji, zapewne powinniśmy posłużyć się słowem kluczowym volatile.

Tags: ,
Author: Xion, posted under Programming » 7 comments

Find & Replace i wyrażenia regularne

2009-02-15 11:48

Przy wyszukiwaniu czegoś w kodzie czasami przydają się wyrażenia regularne. Pozwalają one na znajdowanie nie tyle dokładnie określonych ciągów znaków, ale ciągów pasujących do określonego wzorca. Przy odrobinie wprawy można na przykład wyszukać wszystkie deklaracje zmiennych danego typu, wszystkie wywołania funkcji przeciążonej wyłącznie w wersji z trzema parametrami, i tak dalej.

Zwykle takich rzeczy szukamy jednak nie dla samego znajdowania, lecz po to, aby je potem zmodyfikować. Czasem można to zrobić ręcznie, ale jeśli oznacza to konieczność wykonania tych samych poprawek kilkanaście czy kilkadziesiąt razy, to szybko może nam to się znudzić. Pamiętajmy zresztą, że każdy programista dysponuje tylko skończonym czasem przeznaczonym na kodowanie :)
Wtedy może przydać się zastosowanie wyrażeń regularnych nie tylko do wyszukiwania (find), ale też do zastępowania (replace). Każde porządne IDE powinno bowiem oferować możliwość dopasowywania podwyrażeń (subexpressions lub tagged expressions) w znajdowanym ciągu. Nie inaczej jest w Visual Studio.

Załóżmy przykładowo, że piszemy w C++ i mamy klasę działającą jak abstrakcyjny interfejs (wszystkie metody czysto wirtualne) i chcemy go zaimplementować. Kopiujemy więc całą definicję klasy i chcielibyśmy teraz zmienić deklaracje jej metod: ze wszystkich usunąć słówko ‘virtual‘ i frazę ‘= 0‘.
Jak to zrobić? Dość łatwo skonstruować wyrażenie regularne, które wyszuka nam wszystkie deklaracje:

  1. virtual .* = 0;

Co jednak z polem Replace with? Tam chcielibyśmy wstawić wszystkie te znaki, które dopasują się do wyrażenia .*. W tym celu powinniśmy wpierw zmienić tę frazę na tagged expression, otaczając ją nawiasami klamrowymi:

  1. virtual {.*} = 0;

Teraz stało się ono podwyrażeniem i możemy odwołać się do dopasowanych do niego znaków poprzez sekwencję \1. Zatem jako wyrażenie docelowe wstawimy po prostu:

  1. \1;

Jak nietrudno się domyślić, podwyrażeń może być więcej; możemy wtedy odwoływać się do nich za pomocą kolejnych numerków: \2, \3, itd. (są one numerowane oczywiście od lewej). Dodatkowo symbol \0 odpowiada za cały znaleziony ciąg.
Widać więc, że przy użyciu tego mechanizmu można automatycznie dokonywać zmian, które bez niego zajęłyby nam dużo czasu i były dość żmudne.

Tags: ,
Author: Xion, posted under Applications » 1 comment

Przemożna chęć regulacji

2009-02-01 17:53

Przedwczoraj na forum Warsztatu rozpoczęto dyskusję na temat gier zrobionych w tzw. klikach, które podobno coraz częściej pojawiają się wśród projektów zamieszczanych w serwisie gamedev.pl. Wątek zdążył szybko urosnąć w kilkadziesiąt postów, w których jedni postulują zwalczanie tego zjawiska, a drudzy (nieśmiało) proponują włączenie klikowców do warsztatowego mainstreamu.

Niejako automatycznie powstał więc dylemat: “Co z tym zrobić?”, na rozwiązanie którego daje się te właśnie dwa wyjścia. Którekolwiek z nich się wybierze, najważniejsze jest to, że coś ma być zrobione. Koniecznie przecież trzeba coś z tym zrobić, jakoś to ogarnąć, opanować, zorganizować, uregulować…
A ja zadaję wtedy proste pytanie: po co? Dlaczego niby należy każde zjawisko od razu łapać w regulamin, FAQ czy inny rodzaj mniej lub bardziej formalnych zasad? Od kiedy to w naszym narodzie – mającym bogatą, ponaddwustuletnią tradycję omijania wszelkich nakazów i zakazów – nagle zrodziła się taka wiara w nieuchronną konieczność odgórnej regulacji wszystkiego?…

Wydaje mi się to cokolwiek dziwaczne.

Tags:
Author: Xion, posted under Thoughts » 11 comments
 


© 2017 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.