<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-8323132172904612534</atom:id><lastBuildDate>Sat, 13 Feb 2010 21:21:43 +0000</lastBuildDate><title>bs.mechanik::devBlog</title><description>"chciałbym poczytać o tym jak, pierwszy raz uciekłeś z domu"</description><link>http://www.bsmechanik.pl/</link><managingEditor>bs.mechanik@gmail.com (bs.mechanik)</managingEditor><generator>Blogger</generator><openSearch:totalResults>37</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/Bsmechanikdevblog" /><feedburner:info uri="bsmechanikdevblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-3650362302040859888</guid><pubDate>Fri, 16 Oct 2009 23:12:00 +0000</pubDate><atom:updated>2009-10-17T10:41:07.609+02:00</atom:updated><title>Krótka przerwa</title><description>Chciałbym z przykrością poinformować, że na okres kilku najbliższych miesięcy będę musiał wstrzymać to niezwykłe i interesujące zajęcie jakim jest blogowanie (sam proces nic nierobienia w tym względzie, praktykuję już od jakiegoś czasu). Powody jako takie są. Studia (ok, tu żartuję) a także kilka innych pomniejszych / powiększych spraw, które mimo wszystko są ważniejsze i bardziej czasochłonne. Myślę, że nikt się wiec nie obrazi. Obiecuję, że za jakiś czas pojawi się coś ciekawego, tak w ramach rekompensaty. 
Nie będę bawił się w ceregiele związane z usuwaniem bloga - niech sobie wisi w czeluściach internetu. A nuż/widelec coś/komuś się przyda - no w końcu kilka notek napisałem na trzeźwo. Na serio, to szkoda mi tych 1,22 z VAT, które wydałem na domenę. 

No koniec tego bezwładnego sypania literkami po ekranie. 

Do zobaczenia :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8323132172904612534-3650362302040859888?l=www.bsmechanik.pl' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Bsmechanikdevblog/~4/oJHiTffyC6E" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Bsmechanikdevblog/~3/oJHiTffyC6E/krotka-przerwa.html</link><author>bs.mechanik@gmail.com (bs.mechanik)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.bsmechanik.pl/2009/10/krotka-przerwa.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-7549928736445007472</guid><pubDate>Tue, 01 Sep 2009 06:56:00 +0000</pubDate><atom:updated>2009-09-01T16:19:47.153+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Ogólne</category><title>Opera 10 oficjalnie wydana</title><description>Opera Software zaprezentowała finalną wersję, dziesiątej odsłony swojej przeglądarki. Jak już widać było w wersjach beta i RC, zmianom uległ interfejs użytkownika - jest znacznie bardziej elastyczny i wygodniejszy w użyciu. 
Okienko "Speed dial" jest bardziej konfigurowalne (możliwość wyboru tła, określenie liczby wyświetlanych okienek). Możemy także schować główne menu, co daje nam jeszcze większą przestrzeń na wyświetlanie stron. Interesująca jest także możliwość zmiany położenia paska kart - można go umieścić choćby po lewej stronie, gdzie domyślnie wyświetlane są miniaturki stron. &lt;br&gt;
Ciekawą funkcjonalnością jest także Opera Turbo. Pozwala ona na znacznie przyspieszenie ładowania stron (ale tylko w przypadku wolnych łączy), poprzez kompresję jej zawartości. Faktycznie, tracimy na jakości grafik, jednak nie zawsze jest to szczególnie istotna rzecz.
Podobnie jak poprzednie beta wersje, przechodzi ona w 100% ostatni test ACID. 
Najważniejsze jednak, w porównaniu do poprzednich wersji (9.6x), znacznie poprawiono szybkość renderowania stron.&lt;br&gt;
&lt;a href="http://www.opera.com/download/get.pl?id=32264&amp;thanks=true&amp;sub=true"&gt;Download&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8323132172904612534-7549928736445007472?l=www.bsmechanik.pl' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Bsmechanikdevblog/~4/4GlF1P7m8uM" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Bsmechanikdevblog/~3/4GlF1P7m8uM/opera-10-oficjalnie-wydana.html</link><author>bs.mechanik@gmail.com (bs.mechanik)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.bsmechanik.pl/2009/09/opera-10-oficjalnie-wydana.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-7370822158091946321</guid><pubDate>Tue, 11 Aug 2009 10:08:00 +0000</pubDate><atom:updated>2009-08-12T11:15:35.219+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">c++</category><category domain="http://www.blogger.com/atom/ns#">assembler</category><title>SSE w klasie - #2</title><description>&lt;p&gt;Po omówieniu podstaw związanych z programowaniem przy użyciu instrukcji SIMD, czas przedstawić nieco bardziej użyteczne informacje. Dzisiejszym daniem głównym więc, będzie niewielka (rozwijana w kolejnych częściach mini kursu) klasa czterowymiarowego wektora. Życzę smacznego i zapraszam do lektury :). &lt;/p&gt;

&lt;p&gt;Na początku zaczniemy od przygotowania składników. Dziś zamiast wyrównanej do szesnastu bajtów tablicy typu &lt;span style="color: maroon"&gt;&lt;font face="Courier New"&gt;float&lt;/font&gt;&lt;font face="Verdana" color="#000000"&gt;, skorzystamy ze struktury:&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: maroon"&gt;__declspec&lt;/span&gt;(&lt;span style="color: maroon"&gt;align&lt;/span&gt;(&lt;span style="color: blue"&gt;16&lt;/span&gt;))
&lt;span style="color: maroon"&gt;struct &lt;/span&gt;VectorData{
    &lt;span style="color: maroon"&gt;float &lt;/span&gt;x,y,z,w;
};&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&lt;font face="Verdana"&gt;Dla instrukcji SSE liczy się tak naprawdę odpowiednio przygotowany skrawek pamięci – w jaki sposób zostanie on zaalokowany (czy to będzie tablica czy struktura) zależy tylko od preferencji programisty. &lt;/font&gt;&lt;/p&gt;

&lt;font face="Verdana"&gt;Mając wszystko przygotowane, możemy przejść do przyrządzania dania głównego. Na pierwszy ogień pójdzie więc konstruktor domyślny, w którym to będziemy zerować współrzędne wektora. &lt;br /&gt;Samo zerowanie jest oczywiście sprawą trywialną, choć początkowo może przysporzyć nieco problemów. &lt;/font&gt;

&lt;font face="Verdana"&gt;Tradycyjnie, można to zrobić na dwa sposoby:&lt;/font&gt;
&lt;font face="Verdana"&gt;
  &lt;ul&gt;
    &lt;li&gt;
      &lt;pre class="code"&gt;&lt;font face="Verdana"&gt;“manualne” przypisanie zer&lt;/font&gt;&lt;/pre&gt;
    &lt;/li&gt;

    &lt;li&gt;
      &lt;font face="Verdana"&gt;skorzystanie z instrukcji&lt;/font&gt;&lt;font face="Courier New"&gt; memset&lt;/font&gt; &lt;font face="Verdana"&gt;(nagłówek&lt;/font&gt; &lt;font face="Courier New"&gt;cstring&lt;/font&gt; &lt;font face="Verdana"&gt;lub&lt;/font&gt; &lt;font face="Courier New"&gt;string.h&lt;/font&gt;&lt;font face="Verdana"&gt;)&lt;/font&gt;
    &lt;/li&gt;
  &lt;/ul&gt;

&lt;font face="Verdana"&gt;Skorzystanie z &lt;font face="Courier"&gt;memset&lt;/font&gt; powinno nieco przyśpieszyć tą prostą operację, ponieważ nie odwołujemy się do koprocesora, tylko operujemy danymi bezpośrednio w pamięci. Mimo iż w konstruktorze nie potrzebujemy wyjątkowej wydajności (jest on wykonywany zazwyczaj tylko raz), to jednak wykorzystamy trochę mocy :). &lt;/font&gt;

  &lt;pre class="code"&gt;&lt;font face="Verdana"&gt;Otóż i niezwykle wyrafinowana treść naszej funkcji: &lt;/font&gt;&lt;/pre&gt;

  &lt;pre class="code"&gt;&lt;span style="color: maroon"&gt;_asm&lt;/span&gt;{
    mov esi,&lt;span style="color: maroon"&gt;this
    &lt;/span&gt;movaps xmm0,[esi]
    xorps xmm0,xmm0
    movaps [esi],xmm0
}&lt;/pre&gt;

  &lt;font face="Verdana"&gt;Jak widzimy, są tu dwie nowe rzeczy. Pojawił się wskaźnik&lt;/font&gt; &lt;font face="Courier New" color="#800000"&gt;this&lt;/font&gt; &lt;font face="Verdana"&gt;oraz instrukcja&lt;/font&gt; &lt;font face="Courier New"&gt;xorps&lt;/font&gt;.&lt;br /&gt;&lt;font face="Verdana"&gt;Wskaźnik&lt;/font&gt; &lt;font face="Courier New" color="#800000"&gt;this&lt;/font&gt; &lt;font face="Verdana"&gt;używany jest by dostać się to struktury przechowującej wektor. Zadziała to jednak tylko wtedy gdy zmienna ta będzie pierwszym polem klasy. Wówczas adres na który wskazuje &lt;font face="Courier" color="#800000"&gt;this&lt;/font&gt; jest równoznaczny z adresem owego pola. &lt;br /&gt;W przeciwnym wypadku, pobranie adresu trzeba będzie wykonać “ręcznie”:&lt;/font&gt;
  &lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/font&gt;

&lt;pre class="code"&gt;&lt;span style="color: maroon"&gt;void &lt;/span&gt;*p = &amp;amp;m_vecData

&lt;span style="color: maroon"&gt;_asm&lt;/span&gt;{
    mov esi,p
    &lt;span style="color: gray"&gt;//...
&lt;/span&gt;}&lt;/pre&gt;

&lt;font face="Verdana"&gt;Cóż takiego robi instrukcja &lt;/font&gt;&lt;font face="Courier New"&gt;xorps&lt;/font&gt;&lt;font face="Verdana"&gt;? Jest to nic innego jak zwykły &lt;a href="http://pl.wikipedia.org/wiki/Alternatywa_wykluczająca"&gt;xor&lt;/a&gt;, w wersji dla SSE, działający na poszczególnych elementach naszego wektora. Wykonując tą operację na dwóch takich samych wektorach, zerujemy je. Jest to znacznie szybsze, niż “statyczne” przypisanie wartości zero do każdej ze współrzędnych. &lt;/font&gt;

&lt;font face="Verdana"&gt;Mając konstruktor domyślny, możemy stworzyć konstruktor kopiujący oraz operator przypisania. Praktycznie rzecz ujmując będą to dwie identyczne funkcje. Ich działanie będzie się tylko ograniczać do kopiowania wartości pomiędzy rejestrami xmm. Spójrzmy więc jak to wygląda:&lt;/font&gt;

&lt;pre class="code"&gt;&lt;span style="color: maroon"&gt;_asm&lt;/span&gt;{
    mov edi,vec
    mov esi,&lt;span style="color: maroon"&gt;this

    &lt;/span&gt;movaps xmm0,[esi]
    movaps xmm1,[edi]

    movaps xmm0,xmm1

    movaps [esi],xmm0
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;font face="Verdana"&gt;Zakładam, że &lt;/font&gt;&lt;font face="Courier New" color="#800000"&gt;&lt;font color="#000000"&gt;vec,&lt;/font&gt; &lt;font face="Verdana" color="#000000"&gt;to stała referencja na obiekt naszej klasy, przekazana do konstruktora kopiującego bądź operatora przypisania. &lt;br /&gt;Działanie, jak już wspominałem, jest bardzo proste. Rejestry &lt;font face="Courier New"&gt;edi&lt;/font&gt; i &lt;font face="Courier New"&gt;esi&lt;/font&gt; przechowują wskaźniki na nasze obiekty, które następnie (za pomocą &lt;font face="Courier New"&gt;movaps&lt;/font&gt;) kopiowane są do odpowiednich rejestrów SSE – &lt;font face="Courier New"&gt;xmm0&lt;/font&gt; dla naszego wektora oraz &lt;font face="Courier New"&gt;xmm1&lt;/font&gt; dla wektora przekazanego w parametrze. Przypisanie wektorów to po prostu skopiowanie zawartości &lt;font face="Courier New"&gt;xmm1&lt;/font&gt; do &lt;font face="Courier New"&gt;xmm0&lt;/font&gt;. Ostatnia instrukcja zapisuje wynik w &lt;font face="Courier New" color="#800000"&gt;this&lt;/font&gt;. &lt;/font&gt;&lt;/font&gt;

&lt;p&gt;&lt;font face="Verdana" color="#000000"&gt;Na koniec omówimy sobie operator&lt;/font&gt; &lt;font face="Courier New" color="#800000"&gt;new&lt;/font&gt; i &lt;font face="Courier New" color="#800000"&gt;delete&lt;font face="Verdana" color="#000000"&gt;, ponieważ jak się okazuje, domyślne operatory nie będą kompatybilne z naszą klasą wektora. 
      &lt;br /&gt;W podstawowym ujęciu, instrukcje SSE dzielimy na dwie kategorie: operujące na wyrównanych i niewyrównanych danych. Gdy operujemy na danych niewyrównanych, działanie SSE jest nieco wolniejsze, ponieważ potrzeba więcej cykli by dostać się do odpowiedniej komórki pamięci. Przykładem tego typu instrukcji może być &lt;font face="Courier New"&gt;mov&lt;strong&gt;u&lt;/strong&gt;ps&lt;/font&gt; – jest to odpowiednik &lt;font face="Courier New"&gt;mov&lt;strong&gt;a&lt;/strong&gt;ps&lt;/font&gt; (&lt;strong&gt;u&lt;/strong&gt; – unaligned, &lt;strong&gt;a&lt;/strong&gt; - aligned), tylko, że tablica lub struktura, do której chcemy uzyskać dostęp, nie musi być wyrównana do granicy szesnastu bajtów. &lt;/font&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font color="#000000"&gt;Cóż więc wspólnego mają z tym operatory &lt;font face="Courier New" color="#800000"&gt;new&lt;/font&gt; i &lt;font face="Courier New" color="#800000"&gt;delete&lt;/font&gt;? To, że przydzielają one niewyrównane do odpowiadającej nam wartości, kawałki pamięci. Należy zatem operatory te przeciążyć. Na szczęście jest to operacja równie trywialna, jak te, które zaprezentowałem powyżej. Jeden ze sposobów zrobienia tego, &lt;a href="http://netrix.gamedev.pl/index.php/2008/12/08/wyrownanie-pamieci-dla-operatorow-new-i-new/"&gt;opisał Netrix&lt;/a&gt;, mi jednak udało się, znaleźć znacznie prostsze rozwiązanie. Okazuje się bowiem, że istnieją funkcje które robią to za nas: &lt;font face="Courier New"&gt;_aligned_malloc&lt;/font&gt; i &lt;font face="Courier New"&gt;_aligned_free&lt;/font&gt;. Zewnętrznie działają tak samo jak standardowe wersje &lt;font face="Courier New"&gt;malloc&lt;/font&gt; i &lt;font face="Courier New"&gt;free&lt;/font&gt;, więc ich użytkowanie nie powinno sprawiać większego problemu. &lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font color="#000000"&gt;Implementację dodawania i odejmowania zostawiam jako zadanie domowe :). Instrukcje, które je wykonują omówiłem w poprzedniej części kursiku więc nie powinno to stanowić większego problemu. &lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font color="#000000"&gt;W &lt;a href="http://odsiebie.com/pokaz/4735214---b340.html"&gt;załączniku&lt;/a&gt; znajduje się kod do dzisiejszego kursiku. Dodałem także metodę zerującą wektor. &lt;/font&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8323132172904612534-7370822158091946321?l=www.bsmechanik.pl' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Bsmechanikdevblog/~4/pAnTwU6IsZ4" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Bsmechanikdevblog/~3/pAnTwU6IsZ4/sse-w-klasie-2_11.html</link><author>bs.mechanik@gmail.com (bs.mechanik)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">6</thr:total><feedburner:origLink>http://www.bsmechanik.pl/2009/08/sse-w-klasie-2_11.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-4649117720615418612</guid><pubDate>Wed, 05 Aug 2009 10:49:00 +0000</pubDate><atom:updated>2009-08-05T13:12:27.566+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Ogólne</category><title>Najsławniejsi po polsku</title><description>Przeglądając ostatnio serwisy z newsami dotyczącymi tematyki IT oraz ogólnie pojętego programowania, natrafiłem na dość interesującą informację. Powstał bowiem blog, którego autor postawił sobie za cel, tłumaczenie notek ze stron domowych takich sław jak &lt;a href="http://www.joelonsoftware.com/"&gt;Joel Spolsky&lt;/a&gt; lub &lt;a href="http://www.codinghorror.com/blog/"&gt;Jeff Atwood&lt;/a&gt;. Jest to z pewnością bardzo ciekawa inicjatywa, szczególnie dla osób, które jeszcze z angielskim mają lekkie problemy :)&lt;p&gt;
Adres strony: &lt;a href="http://www.devblogi.pl/"&gt;http://www.devblogi.pl&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8323132172904612534-4649117720615418612?l=www.bsmechanik.pl' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Bsmechanikdevblog/~4/gSVYjx94yYM" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Bsmechanikdevblog/~3/gSVYjx94yYM/najsawniejsi-po-polsku.html</link><author>bs.mechanik@gmail.com (bs.mechanik)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://www.bsmechanik.pl/2009/08/najsawniejsi-po-polsku.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-28637309827870099</guid><pubDate>Sat, 23 May 2009 14:55:00 +0000</pubDate><atom:updated>2009-05-23T16:55:46.059+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">krótka recenzja</category><title>Samsung yp-u1</title><description>&lt;p&gt;Dziś będzie trochę inna notka, nie nawiązująca zbyt wiele do programowania. Jak widać, znajduje się w kategorii krótka recenzja, lecz nie będę tu opisywał kolejnej, niezwykle fascynującej książki, z wciągającą fabułą i akcją. Chciałbym opisać niewielkie urządzenie, z którym miałem przyjemność spędzić ostatnie 3 lata. Nie jest to już więc sprzęt najnowszy, raczej ciężko go dziś kupić, jednak po tylu latach użytkowania chciałbym napisać kilka spostrzeżeń na temat tego niewielkiego odtwarzacza mp3.&lt;/p&gt;  &lt;p&gt;Na początek kilka podstawowych danych technicznych:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;wymiary&lt;/strong&gt;: 25.6 x 87.4 x 13.6 mm &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;waga&lt;/strong&gt;: 33g &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;zakres częstotliwości&lt;/strong&gt;: 20Hz~20KHz &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;czas odtwarzania&lt;/strong&gt;: 13h (wbudowany akumulator litowo-polimerowy) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Jak więc widać, jest to dość zgrabne i lekkie urządzenie. Dodatkowo bez problemów radzi sobie z formatami mp3 (także ze zmiennym bitrate) ogg, wma czy wav. Raz tylko zdarzył mi się plik, który podczas odtwarzania zawiesił odtwarzacz. Komunikacja z komputerem została rozwiązana standardowo: port USB 2.0, choć sposób chowania konektora jest nieco oryginalny (o tym później). Wyświetlacz jest cztero linijkowy, podświetlany w razie potrzeby na biało. Prezentowany tekst jest wyraźny i ostry. Nawet podczas przesuwania nie miga ani nie smuży, co często się zdarza w odtwarzaczach tego typu. Podświetlenie także nie pozostawia nic do życzenia – równomiernie rozłożone na całość ekranu. &lt;/p&gt;  &lt;p&gt;Posiadana przeze mnie wersja miała 512MB (YP-U1X), lecz dostępna ilość miejsca do za&lt;a href="http://lh5.ggpht.com/_YlcK27LLDCs/ShgObjGW7rI/AAAAAAAAAQw/zFioAiA4g2Q/s1600-h/yp-u1_blg%5B21%5D.jpg"&gt;&lt;img title="yp-u1_blg" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; margin-left: 0px; margin-right: 0px; border-right-width: 0px" height="418" alt="yp-u1_blg" src="http://lh3.ggpht.com/_YlcK27LLDCs/ShgOcbGFGJI/AAAAAAAAAQ0/HdY_rfQDM6c/yp-u1_blg_thumb%5B19%5D.jpg?imgmax=800" width="328" align="right" border="0" /&gt;&lt;/a&gt;pisu to 496MB.     &lt;br /&gt;Nawigacja po menu zostało zrobiona w sposób bardzo intuicyjny, szczególnie, że całość została przetłumaczona na język polski. Co ciekawe, “nieprzetłumaczalne” jest tylko “Settings” i “Language”, by po zmianie języka na koreański, bez problemów można było przywrócić stare ustawienia.     &lt;br /&gt;Główny ekran odtwarzania jest mocno konfigurowalny. Bez problemów można wyświetlić informacje na temat trybu odtwarzania, włączonego efektu dźwiękowego, bitrate (pliki ze zmiennym są oznaczane jako VBR), numeru pliku i poziomu baterii. Ciekawą opcją są dwa sposoby przewijania nazw utworów: poziomy i pionowy. Ten ostatni jest szczególnie przydatny, gdy nazwa piosenki jest dość długa by w krótkim czasie mogła zostać zaprezentowana w całości.     &lt;br /&gt;Nawigacja po drzewie plików też nie przysporzyła mi nigdy problemów – całość rozwiązana standardowo i intuicyjnie. Niektórym osobom nie podobał się sposób włączania&amp;#160; i wyłączania odtwarzacza: kilku sekundowe przytrzymanie przycisku Play. Przyznam, że nigdy nie miałem problemów z przypadkowym wyłączeniem playera, tym bardziej, że czas reakcji jest dość szybki, a dodatkowo jest możliwość włączenia “brzęczyka” – dźwiękowe informowanie o wciśniętych przyciskach. Odtwarzacz obsługuje także własny typ playlist. Nie korzystałem z nich jednak nigdy; wolałem standardową, “folderową” kolejność utworów.     &lt;br /&gt;Dodatkową opcją jest nagrywanie dźwięku, lecz należy traktować to jako dodatek. Jakość nagrań jest&amp;#160; bardzo zła, poza tym, zapisywane sa tylko w formacie wav.&lt;/p&gt;  &lt;p&gt;Zewnętrznie urządzenie zostało wykonane dość estetycznie. Warto zauważyć, że, wbrew pozorom, jest to bardzo mocna konstrukcja. Nie raz zdarzyło mi się, że podczas wyciągania telefonu z kieszeni, wypadł mi także player – działa do dziś.&lt;/p&gt;  &lt;p&gt;Wyżej wspominałem o ciekawym rozwiązaniu dotyczącym chowania wtyczki USB. Pierwszy raz spotkałem się z takim podejściem do problemu, by zamiast wysuwania, zastosować składanie – jest to ostatni (jeśli nie jedyny) model odtwarzacza mp3 Samsunga, który stosuje taki sposób. Niestety, po 3 latach intensywnego użytkowania (także często jako przenośna pamięć) rozwiązanie takie nie sprawdziło się. Jeśli przez pierwszy okres używania Yeepa nie było żadnych problemów, to teraz (zauważyłem to kilka miesięcy temu) urządzenie nie łączy się z komputerem w kilku warunkach. Przede wszystkim wejście USB nie może być zamontowane poziomo. Wówczas odtwarzacz opada (konektor się składa) i traci kontakt z komputerem – widać jakieś ruchome części odpowiedzialne za łączenie zostały uszkodzone.&amp;#160; &lt;br /&gt;Warto także zaznaczyć, że nie należy doprowadzać do zerowego stanu baterii. Często jest tak, że mimo informacji o niskim stanie akumulatora, po kilku chwilach odtwarzacz może zagrać jeszcze jeden, czy dwa utwory. Jest to jednak nie zalecane postępowanie. Ogólnie bateria sprawuje się dość dobrze – aktualnie trzyma od 6 do 8 godzin ciągłego odtwarzania muzyki. Warto zaznaczyć, że podświetlanie jest dość mocno “proądożerne” :)&lt;/p&gt;  &lt;p&gt;Dołączone w zestawie słuchawki są wykonane solidnie i charakteryzują się dobrą jakością dźwięku podobnie jak sam odtwarzacz – nie jestem jednak znawcą i audiofilem, więc opinie będą na ten temat różne.&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;Podsumowując: YP-U1 to solidnie, proste w obsłudze, dobrze wykonane urządzenie nie pozbawione jednak kilku wad. Bez problemu zmieści sie w kieszeni i pozwoli posłuchać ulubionej muzyki w prawie każdych warunkach. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8323132172904612534-28637309827870099?l=www.bsmechanik.pl' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Bsmechanikdevblog/~4/tIeWxBU2x_E" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Bsmechanikdevblog/~3/tIeWxBU2x_E/samsung-yp-u1.html</link><author>bs.mechanik@gmail.com (bs.mechanik)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">11</thr:total><feedburner:origLink>http://www.bsmechanik.pl/2009/05/samsung-yp-u1.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-8771671177130340940</guid><pubDate>Wed, 20 May 2009 07:57:00 +0000</pubDate><atom:updated>2009-08-06T09:18:19.160+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">c++</category><category domain="http://www.blogger.com/atom/ns#">assembler</category><title>SSE w praktyce - #1</title><description>&lt;p&gt;Dziś postaram się przedstawić podstawowe operacje jakie możemy wykonać przy użyciu multimedialnych rozszerzeń procesora. Pokażę możliwość bezpośredniego wykorzystania assemblera, zaś w następnych notkach skupię się na wewnętrznych poleceniach kompilatora, specjalnie przygotowanych do obsługi SSE. Aby prezentowany kod mógł zostać uruchomiony potrzebny jest procesor klasy Intel Pentium III lub lepszy.    &lt;br /&gt;Więc do dzieła ;)&lt;/p&gt;  &lt;p&gt;Jednak, jak to zwykle bywa, na początek jeszcze trochę teorii.    &lt;br /&gt;Programując przy użyciu SSE mamy do dyspozycji 8 dodatkowych, 128 bitowych rejestrów (w przypadku kodu dla procesorów 64 bitowych, liczba ta zwiększa sie do 16) - od xmm0 do xmm7. Wszystkie operacje, jakie będziemy chcieli wykonać przy użyciu omawianych tu instrukcji multimedialnych, będą operować właśnie na tych rejestrach. Jak już wiadomo, każdy z nich może przechować 4 wartości zmiennoprzecinkowe pojedynczej precyzji (&lt;span style="color: maroon"&gt;&lt;font face="Courier New"&gt;float&lt;/font&gt;&lt;/span&gt;). &lt;/p&gt;  &lt;p&gt;Na początek przygotujmy dane na których będziemy pracować: czteroelementowa, jednowymiarowa, wyrównana do 128 bitów tablica typu &lt;span style="color: maroon"&gt;&lt;font face="Courier New"&gt;float &lt;/font&gt;&lt;/span&gt;– czyli nasz wektor. &lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: maroon"&gt;__declspec&lt;/span&gt;(&lt;span style="color: maroon"&gt;align&lt;/span&gt;(&lt;span style="color: blue"&gt;16&lt;/span&gt;)) &lt;span style="color: maroon"&gt;float &lt;/span&gt;&lt;span style="color: #010001"&gt;gVector4&lt;/span&gt;[&lt;span style="color: blue"&gt;4&lt;/span&gt;];&lt;/pre&gt;

&lt;font face="Verdana"&gt;Zobaczmy na początek, w jaki sposób możemy dostać się do danych naszego wektora. Nie będziemy tego robić standardowo,&lt;br /&gt;za pomocą operatora [ ] – posłużymy się do tego odpowiednimi instrukcjami SSE.&lt;br /&gt;Pierwszą podstawową rzeczą, będzie skopiowanie zawartości komórki pamięci, gdzie znajduje się nasz wektor, do rejestru xmm.&lt;/font&gt;

&lt;pre class="code"&gt;&lt;span style="color: maroon"&gt;_asm&lt;/span&gt;{
    &lt;span style="color: #010001"&gt;lea esi&lt;/span&gt;,&lt;span style="color: #010001"&gt;gVector4
    movaps xmm0&lt;/span&gt;,[&lt;span style="color: #010001"&gt;esi&lt;/span&gt;]
    &lt;span style="color: gray"&gt;//wykonaj operacje...
    &lt;/span&gt;&lt;span style="color: #010001"&gt;movaps &lt;/span&gt;[&lt;span style="color: #010001"&gt;esi&lt;/span&gt;],&lt;span style="color: #010001"&gt;xmm0
&lt;/span&gt;}&lt;/pre&gt;

&lt;font face="Verdana"&gt;Pierwsza linijka odpowiada za pobranie adresu zmiennej gVector4 (dokładny opis działania instrukcji &lt;font face="Courier New"&gt;lea &lt;/font&gt;&lt;/font&gt;&lt;font face="Verdana"&gt;można znaleźć &lt;a href="http://rudy.mif.pg.gda.pl/~bogdro/dos/a_kurs03.htm"&gt;tu&lt;/a&gt;)&lt;br /&gt;i skopiowanie go do rejestru &lt;font face="Courier New"&gt;esi&lt;/font&gt; (wskaźnik danych). &lt;br /&gt;Następnie możemy zobaczyć już instrukcję z rodziny SSE – &lt;/font&gt;&lt;font face="Courier New"&gt;movaps&lt;/font&gt;&lt;font face="Verdana"&gt;. Odpowiada ona za kopiowanie zawartości rejestrów xmm&lt;br /&gt;między sobą, a także pamięcią. W tym przypadku, zawartość komórki pamięci na który wskazuje rejestr &lt;font face="Courier New"&gt;esi&lt;/font&gt;, zostanie przesłana do rejestru &lt;font face="Courier New"&gt;xmm0&lt;/font&gt;. &lt;br /&gt;Ostatnia instrukcja kopiuje zawartość rejestru &lt;font face="Courier New"&gt;xmm0&lt;/font&gt; pod adres wskazywany przez &lt;font face="Courier New"&gt;esi&lt;/font&gt; – czyli do naszej zmiennej.&lt;/font&gt;

&lt;font face="Verdana"&gt;Jak widać, mimo że jest to assembler, nie jest to takie trudne. &lt;/font&gt;

&lt;font face="Verdana"&gt;Wygenerujmy więc nieco więcej bardziej praktycznego kodu. &lt;br /&gt;Jak pewnie zważyliście, deklarowanie za każdym razem owej specyficznej tablicy z pewnością nie należy do specjalnie wygodnych.&lt;br /&gt;Uprośćmy więc nieco ten proces:&lt;/font&gt;

&lt;pre class="code"&gt;&lt;span style="color: maroon"&gt;typedef __declspec&lt;/span&gt;(&lt;span style="color: maroon"&gt;align&lt;/span&gt;(&lt;span style="color: blue"&gt;16&lt;/span&gt;)) &lt;span style="color: maroon"&gt;float &lt;/span&gt;&lt;span style="color: #010001"&gt;AlignedVector4D&lt;/span&gt;[&lt;span style="color: blue"&gt;4&lt;/span&gt;];&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;font face="Verdana"&gt;Ten niewielki kawałek kodu, z pewnością pozytywnie wpłynie na czytelność kodu.&lt;br /&gt;Poznajmy więc kilka podstawowych operacji: dodawanie, odejmowanie, mnożenie i dzielenie.&lt;br /&gt;Na początek zdefiniujmy dwa wektory, na których będziemy wykonywać nasze operacje:&lt;/font&gt;

&lt;pre class="code"&gt;&lt;span style="color: #010001"&gt;AlignedVector4D vec1 &lt;/span&gt;= {&lt;span style="color: blue"&gt;5.0&lt;/span&gt;,&lt;span style="color: blue"&gt;6.0&lt;/span&gt;,&lt;span style="color: blue"&gt;3.0&lt;/span&gt;,&lt;span style="color: blue"&gt;1.0&lt;/span&gt;};
&lt;span style="color: #010001"&gt;AlignedVector4D vec2 &lt;/span&gt;= {&lt;span style="color: blue"&gt;2.5&lt;/span&gt;,&lt;span style="color: blue"&gt;3.0&lt;/span&gt;,&lt;span style="color: blue"&gt;1.5&lt;/span&gt;,&lt;span style="color: blue"&gt;0.5&lt;/span&gt;};&lt;/pre&gt;

&lt;font face="Verdana"&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;Za dodawanie odpowiada instrukcja &lt;font face="Courier New"&gt;addps&lt;/font&gt;. Przykład użycia:&lt;/font&gt;

&lt;pre class="code"&gt;&lt;span style="color: maroon"&gt;_asm&lt;/span&gt;{
    &lt;span style="color: #010001"&gt;lea esi&lt;/span&gt;,[&lt;span style="color: #010001"&gt;vec1&lt;/span&gt;];
    &lt;span style="color: #010001"&gt;lea edi&lt;/span&gt;,[&lt;span style="color: #010001"&gt;vec2&lt;/span&gt;];

    &lt;span style="color: #010001"&gt;movaps xmm0&lt;/span&gt;,[&lt;span style="color: #010001"&gt;esi&lt;/span&gt;];
    &lt;span style="color: #010001"&gt;movaps xmm1&lt;/span&gt;,[&lt;span style="color: #010001"&gt;edi&lt;/span&gt;];

    &lt;span style="color: #010001"&gt;addps xmm0&lt;/span&gt;,&lt;span style="color: #010001"&gt;xmm1&lt;/span&gt;;

    &lt;span style="color: #010001"&gt;movaps &lt;/span&gt;[&lt;span style="color: #010001"&gt;esi&lt;/span&gt;],&lt;span style="color: #010001"&gt;xmm0
&lt;/span&gt;}&lt;/pre&gt;

&lt;font face="Verdana"&gt;Jak widać kod jest bardzo prosty. Dwie początkowe instrukcje odpowiadają za pobranie adresu zmiennych, następnie kopiujemy je&lt;br /&gt;do rejestrów xmm0 oraz xmm1 by dodać je do siebie w następnej instrukcji. Wynik zapisywany jest do xmm0 które jest kopiowane&lt;br /&gt;pod adres jaki wskazuje esi, czyli do zmiennej vec1. &lt;br /&gt;Zauważmy, że obecność kopiowania do rejestru xmm1 nie jest konieczna – addps, podobnie jak movaps może pracować na jednym&lt;br /&gt;operandzie znajdującym sie w pamięci operacyjnej:&lt;/font&gt;

&lt;pre class="code"&gt;&lt;span style="color: maroon"&gt;_asm&lt;/span&gt;{
    &lt;span style="color: #010001"&gt;lea esi&lt;/span&gt;,[&lt;span style="color: #010001"&gt;vec1&lt;/span&gt;];
    &lt;span style="color: #010001"&gt;lea edi&lt;/span&gt;,[&lt;span style="color: #010001"&gt;vec2&lt;/span&gt;];

    &lt;span style="color: #010001"&gt;movaps xmm0&lt;/span&gt;,[&lt;span style="color: #010001"&gt;esi&lt;/span&gt;];
    &lt;span style="color: #010001"&gt;addps xmm0&lt;/span&gt;,[&lt;span style="color: #010001"&gt;edi&lt;/span&gt;];
    &lt;span style="color: #010001"&gt;movaps &lt;/span&gt;[&lt;span style="color: #010001"&gt;esi&lt;/span&gt;],&lt;span style="color: #010001"&gt;xmm0
&lt;/span&gt;}&lt;/pre&gt;

&lt;font face="Verdana"&gt;Pozostałe operacje wykonuje się analogicznie:&lt;br /&gt;&lt;font face="Courier New"&gt;subps&lt;/font&gt; – odejmowanie&lt;br /&gt;&lt;font face="Courier New"&gt;mulps&lt;/font&gt; – mnożenie&lt;br /&gt;&lt;font face="Courier New"&gt;divps&lt;/font&gt; – dzielenie&lt;/font&gt;

&lt;font face="Verdana"&gt;To byłoby na tyle. W kolejnych częściach poznamy trochę więcej interesujących rzeczy ;)&lt;/font&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8323132172904612534-8771671177130340940?l=www.bsmechanik.pl' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Bsmechanikdevblog/~4/olr-2_ABEAI" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Bsmechanikdevblog/~3/olr-2_ABEAI/sse-w-praktyce-1.html</link><author>bs.mechanik@gmail.com (bs.mechanik)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://www.bsmechanik.pl/2009/05/sse-w-praktyce-1.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-4772651333750185834</guid><pubDate>Tue, 28 Apr 2009 23:03:00 +0000</pubDate><atom:updated>2009-04-29T01:03:02.637+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">produkcje</category><title>isabellFrame update</title><description>&lt;p&gt;Podczas prac nad silnikiem, zmieniłem kilka elementów Frameworka. Poprawiłem przede wszystkim dostęp do urządzeń wejścia (klawiatura i mysz). Dotychczas jedynym sposobem było podpięcie się pod rendering (metoda &lt;font face="Courier New"&gt;render&lt;/font&gt; klasy &lt;font face="Courier New"&gt;CBaseRenderer&lt;/font&gt;) i z tego miejsca pobieranie stosownych informacji. Teraz należy skorzystać z listenera (&lt;span style="color: #010001"&gt;&lt;font face="Courier New"&gt;IInputListener&lt;/font&gt;&lt;/span&gt;).     &lt;br /&gt;Zmiany pojawiły się także w metodach pobierających informacje o systemie – są one wykonywane w bardziej stabilny sposób oraz mogą pobrać więcej danych.     &lt;br /&gt;Do działania aplikacji nie jest już konieczna klasa renderująca. Główną pętlę przeniosłem do &lt;font face="Courier New"&gt;CIsabellFramework&lt;/font&gt;. Także informacje o błędach są teraz bardziej kompletne: dodany został opis błędu oraz nazwa metody która go spowodowała.     &lt;br /&gt;Poprawiłem także kilka mniej znaczących uchybień.     &lt;br /&gt;W katalogu samples znajduje się sześć przykładowych aplikacji wykorzystujących określone funkcjonalności Frameworka.     &lt;br /&gt;&lt;a href="http://odsiebie.com/pokaz/2502257---c33e.html" target="_blank"&gt;Download&lt;/a&gt;.&amp;#160; &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8323132172904612534-4772651333750185834?l=www.bsmechanik.pl' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Bsmechanikdevblog/~4/Asha5Gr_oJ8" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Bsmechanikdevblog/~3/Asha5Gr_oJ8/isabellframe-update.html</link><author>bs.mechanik@gmail.com (bs.mechanik)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://www.bsmechanik.pl/2009/04/isabellframe-update.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-6186324813234903496</guid><pubDate>Thu, 23 Apr 2009 00:52:00 +0000</pubDate><atom:updated>2009-04-23T02:52:45.602+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">c++</category><title>Polimorfizm statyczny</title><description>&lt;p&gt;Główna metodą, dzięki której możemy zastosować polimorfizm to dziedziczenie, wraz z funkcjami (czysto) wirtualnymi. Jest to najbardziej intuicyjny sposób znany większości programistów. O tym, jak wygląda to od strony kompilatora, napisał swego czasu &lt;a href="http://xion.org.pl/" target="_blank"&gt;Xion&lt;/a&gt; w jednej ze swoich &lt;a href="http://xion.org.pl/2008/07/24/jak-dzialaja-metody-wirtualne/#comments" target="_blank"&gt;notek&lt;/a&gt;. Dziś jednak chciałbym się skupić na innej, rzadziej stosowanej, implementacji owej techniki.&lt;/p&gt;  &lt;p&gt;Główną wadą polimorfizmu jest jego wydajność. Dziś, w czasach rozkwitu języków zarządzanych, nie jest to problem wyjątkowo dotkliwy, jednak w pewnych zastosowaniach, nawet tak niewielkie narzuty muszą być brane pod uwagę. Mowa tu oczywiście o dynamicznym wiązaniu metod, których klasa zostaje ustalona dopiero podczas wykonywania programu. Jak można obejść ten problem? Stosując szablony. &lt;/p&gt;  &lt;p&gt;Przeanalizujmy prosty przykład: rysowanie i zarządzanie obiektami geometrycznymi.    &lt;br /&gt;Załóżmy, że chcemy przygotować klasę, która rysowałaby różnego rodzaju obiekty geometryczne: od punktów po wielokąty zdefiniowane przez użytkownika. Logicznym rozwiązaniem problemu, jest zastosowanie polimorfizmu. &lt;/p&gt;  &lt;p&gt;Na początek, stwórzmy więc interfejs definiujący operacje jakie ma wykonywać owy obiekt:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: maroon"&gt;class &lt;/span&gt;&lt;span style="color: #010001"&gt;IGeometryObject&lt;/span&gt;{

    &lt;span style="color: maroon"&gt;public&lt;/span&gt;:
        &lt;span style="color: maroon"&gt;virtual void &lt;/span&gt;&lt;span style="color: #010001"&gt;draw&lt;/span&gt;(&lt;span style="color: maroon"&gt;void&lt;/span&gt;) = &lt;span style="color: blue"&gt;0&lt;/span&gt;; &lt;span style="color: gray"&gt;//rysowanie obiektu na plotnie
        &lt;/span&gt;&lt;span style="color: maroon"&gt;virtual void &lt;/span&gt;&lt;span style="color: #010001"&gt;setColor&lt;/span&gt;(&lt;span style="color: maroon"&gt;unsigned &lt;/span&gt;&lt;span style="color: #010001"&gt;uColorType&lt;/span&gt;); &lt;span style="color: gray"&gt;//ustawia kolor obiektu

        &lt;/span&gt;&lt;span style="color: maroon"&gt;virtual void &lt;/span&gt;&lt;span style="color: #010001"&gt;create&lt;/span&gt;(&lt;span style="color: maroon"&gt;void&lt;/span&gt;) = &lt;span style="color: blue"&gt;0&lt;/span&gt;; &lt;span style="color: gray"&gt;//przydzielenie pamieci dla obiektu
        &lt;/span&gt;&lt;span style="color: maroon"&gt;virtual void &lt;/span&gt;&lt;span style="color: #010001"&gt;release&lt;/span&gt;(&lt;span style="color: maroon"&gt;void&lt;/span&gt;) = &lt;span style="color: blue"&gt;0&lt;/span&gt;; &lt;span style="color: gray"&gt;//zwolnienie zasobow obiektu
&lt;/span&gt;};&lt;/pre&gt;

&lt;p&gt;Jak widać, nie ma tu nic szczególnego – klika metod czysto wirtualnych. Stwórzmy teraz metody innej klasy, których zadaniem jest rysowanie takich obiektów:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: maroon"&gt;class &lt;/span&gt;&lt;span style="color: #010001"&gt;CGeometryDrawer&lt;/span&gt;{

    &lt;span style="color: maroon"&gt;public&lt;/span&gt;:

        &lt;span style="color: maroon"&gt;void &lt;/span&gt;&lt;span style="color: #010001"&gt;drawObjectsList&lt;/span&gt;(&lt;span style="color: maroon"&gt;const &lt;/span&gt;&lt;span style="color: #010001"&gt;std&lt;/span&gt;::&lt;span style="color: #010001"&gt;vector&lt;/span&gt;&amp;lt;&lt;span style="color: #010001"&gt;IGeometryObject&lt;/span&gt;*&amp;gt; &amp;amp;&lt;span style="color: #010001"&gt;vElems&lt;/span&gt;){
            &lt;span style="color: maroon"&gt;for&lt;/span&gt;(&lt;span style="color: maroon"&gt;unsigned &lt;/span&gt;&lt;span style="color: #010001"&gt;i&lt;/span&gt;=&lt;span style="color: blue"&gt;0&lt;/span&gt;;&lt;span style="color: #010001"&gt;i&lt;/span&gt;&amp;lt;&lt;span style="color: #010001"&gt;vElems&lt;/span&gt;.&lt;span style="color: #010001"&gt;size&lt;/span&gt;();&lt;span style="color: #010001"&gt;i&lt;/span&gt;++)&lt;span style="color: #010001"&gt;vElems&lt;/span&gt;[&lt;span style="color: #010001"&gt;i&lt;/span&gt;]-&amp;gt;&lt;span style="color: #010001"&gt;draw&lt;/span&gt;();
        }

        &lt;span style="color: maroon"&gt;void &lt;/span&gt;&lt;span style="color: #010001"&gt;drawObject&lt;/span&gt;(&lt;span style="color: #010001"&gt;IGeometryObject &lt;/span&gt;*&lt;span style="color: #010001"&gt;pObject&lt;/span&gt;){&lt;span style="color: #010001"&gt;pObject&lt;/span&gt;-&amp;gt;&lt;span style="color: #010001"&gt;draw&lt;/span&gt;();}
};&lt;/pre&gt;

&lt;p&gt;Główną zaletą takiego podejścia jest to, że kolekcja &lt;font face="Courier"&gt;vElems &lt;/font&gt;&lt;font face="Verdana"&gt;może być heterogeniczna, czyli zawierać elementy różnych klas. Wystarczy tylko, że każda z nich będzie implementować interfejs &lt;/font&gt;&lt;font face="Courier"&gt;&lt;span style="color: #010001"&gt;IGeometryObject&lt;font face="Verdana"&gt;. &lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color: #010001"&gt;Był to więc przykład standardowego podejścia do problemu. Jak już wcześniej wspominałem, dla każdego wywołania jednej z wirtualnych metod interfejsu &lt;span style="color: #010001"&gt;IGeometryObject&lt;/span&gt; musimy się liczyć z niewielkim narzutem, związanym z dynamicznym powiązaniem metody.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Czas na prezentację tytułowego sposobu. Podstawową różnicą będzie tu brak klasy, po której będzie obowiązek dziedziczenia – dzięki szablonom narzucimy odpowiedni interfejs wewnątrz metod:&lt;/span&gt;&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: maroon"&gt;class &lt;/span&gt;&lt;span style="color: #010001"&gt;CGeometryDrawer&lt;/span&gt;{

    &lt;span style="color: maroon"&gt;public&lt;/span&gt;:

        &lt;span style="color: maroon"&gt;template &lt;/span&gt;&amp;lt;&lt;span style="color: maroon"&gt;typename &lt;/span&gt;&lt;span style="color: #010001"&gt;GeometryObject&lt;/span&gt;&amp;gt;
        &lt;span style="color: maroon"&gt;void &lt;/span&gt;&lt;span style="color: #010001"&gt;drawObjectsList&lt;/span&gt;(&lt;span style="color: maroon"&gt;const &lt;/span&gt;&lt;span style="color: #010001"&gt;std&lt;/span&gt;::&lt;span style="color: #010001"&gt;vector&lt;/span&gt;&amp;lt;&lt;span style="color: #010001"&gt;GeometryObject&lt;/span&gt;&amp;gt; &amp;amp;&lt;span style="color: #010001"&gt;vElems&lt;/span&gt;){
            &lt;span style="color: maroon"&gt;for&lt;/span&gt;(&lt;span style="color: maroon"&gt;unsigned &lt;/span&gt;&lt;span style="color: #010001"&gt;i&lt;/span&gt;=&lt;span style="color: blue"&gt;0&lt;/span&gt;;&lt;span style="color: #010001"&gt;i&lt;/span&gt;&amp;lt;&lt;span style="color: #010001"&gt;vElems&lt;/span&gt;.&lt;span style="color: #010001"&gt;size&lt;/span&gt;();&lt;span style="color: #010001"&gt;i&lt;/span&gt;++)&lt;span style="color: #010001"&gt;vElems&lt;/span&gt;[&lt;span style="color: #010001"&gt;i&lt;/span&gt;].&lt;span style="color: #010001"&gt;draw&lt;/span&gt;();
        }

        &lt;span style="color: maroon"&gt;template &lt;/span&gt;&amp;lt;&lt;span style="color: maroon"&gt;typename &lt;/span&gt;&lt;span style="color: #010001"&gt;GeometryObject&lt;/span&gt;&amp;gt;
        &lt;span style="color: maroon"&gt;void &lt;/span&gt;&lt;span style="color: #010001"&gt;drawObject&lt;/span&gt;(&lt;span style="color: #010001"&gt;GeometryObject &lt;/span&gt;&amp;amp;&lt;span style="color: #010001"&gt;object&lt;/span&gt;){&lt;span style="color: #010001"&gt;object&lt;/span&gt;.&lt;span style="color: #010001"&gt;draw&lt;/span&gt;();}
};&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Jak widać, nowa wersja klasy rysującej korzysta z metod szablonowych. Metody te, definiując typ &lt;span style="color: #010001"&gt;&lt;font face="Courier"&gt;GeometryObject&lt;/font&gt;&lt;/span&gt;, narzucają dla niego obecność funkcji składowej &lt;font face="Courier"&gt;draw&lt;/font&gt;. Dzięki temu, możemy przekazać obiekty dowolnych klas – istotne jest tylko to, by miały definicje &lt;font face="Courier"&gt;draw&lt;/font&gt;. Ważne, by to metody były szablonowe, nie zaś cała klasa. W przeciwnym wypadku bylibyśmy ograniczeni tylko do obsługi typu przekazanego podczas definiowania obiektu klasy &lt;span style="color: #010001"&gt;&lt;font face="Courier"&gt;CGeometryDrawer&lt;/font&gt;&lt;/span&gt;. 

  &lt;br /&gt;Warto także zaznaczyć, że kolekcja &lt;font face="Courier"&gt;vElems&lt;/font&gt; musi zawierać obiekty tego samego typu (homogeniczne). W przypadku polimorfizmu dynamicznego, dzięki zastosowaniu dziedziczenia, mogliśmy dodać do kolekcji, klasy różnych typów, w tym przypadku nie jest to jednak możliwe. Można co prawda, przekazać do metody &lt;span style="color: #010001"&gt;&lt;font face="Courier"&gt;drawObjectsList&lt;/font&gt;&lt;/span&gt; wektor wskaźników, ale wtedy funkcje składowe byłby wiązane dynamicznie, więc tracimy zyski związane ze statycznym wiązaniem. &lt;/p&gt;

&lt;p&gt;Ogólnie rzecz ujmując&lt;strong&gt; polimorfizm dynamiczny&lt;/strong&gt; można określić jako: &lt;em&gt;powiązany&lt;/em&gt; i &lt;em&gt;dynamiczny&lt;/em&gt;. &lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;powiązany&lt;/em&gt;, ponieważ typy obiektów są zależne od innego typu (dziedziczenie po klasie bazowej, w tym przypadku interfejsie) &lt;/li&gt;

  &lt;li&gt;&lt;em&gt;dynamiczny&lt;/em&gt;, bo klasa wywoływanej metody jest ustalana podczas działania programu. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do jego podstawowych zalet można zaliczyć:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;możliwość działania na kolekcjach heterogenicznych obiektów&lt;/li&gt;

  &lt;li&gt;metody korzystające z polimorfizmu mogą być dostarczane w postaci skompilowanej (lib lub dll)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Polimorfizm statyczny&lt;/strong&gt; jest zaś &lt;em&gt;niepowiązany&lt;/em&gt; i &lt;em&gt;statyczny&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;niepowiązany&lt;/em&gt;, bo klasy konkretne (niewirtualne) nie muszą być dziedziczone po określonym interfejsie lub innej klasie&lt;/li&gt;

  &lt;li&gt;&lt;em&gt;statyczny&lt;/em&gt; – klasy metod są ustalane już na etapie kompilacji&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Zalety:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;większa wydajność&lt;/li&gt;

  &lt;li&gt;klasy konkretne nie muszą implementować całości określonego interfejsu, ponieważ wymagana jest znajomość tylko tych operacji które są rzeczywiście wywoływane w programie&lt;/li&gt;

  &lt;li&gt;istnieje możliwość stosowania typów podstawowych&lt;/li&gt;
&lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8323132172904612534-6186324813234903496?l=www.bsmechanik.pl' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Bsmechanikdevblog/~4/z86MtFxg9q0" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Bsmechanikdevblog/~3/z86MtFxg9q0/polimorfizm-statyczny.html</link><author>bs.mechanik@gmail.com (bs.mechanik)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://www.bsmechanik.pl/2009/04/polimorfizm-statyczny.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-1046536077084719549</guid><pubDate>Wed, 25 Mar 2009 10:57:00 +0000</pubDate><atom:updated>2009-03-25T11:58:04.335+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Ogólne</category><category domain="http://www.blogger.com/atom/ns#">warsztat</category><title>afterparty…</title><description>&lt;p&gt;Zakończyła się juz coroczna Konferencja Inżynierii Gier Komputerowych. Był to mój pierwszy raz na tego typu spotkaniu i muszę przyznać, że pewnie nie ostatni. Niesamowita atmosfera i nowe znajomości to z pewnością podstawowe powody dla których warto tam się pojawić. Prezentacje, mimo, że nie wszystkie, były na wysokim poziomie, zaś smaczkiem był pokaz ewolucji renderera w grze NecroVision. Do najbardziej emocjonujących chwil, można z pewnością zaliczyć compo, w którym to nasza drużyna (Gwardia Grembosza), zajęła czwarte miejsce. Praca z pewnością nie była tak doskonała technicznie jak PsychoL, Rzeźników, jednak jej tworzenie przyniosło wiele radości. Brałem też udział w Konkursie IT, organizowanym przez Rega, choć tam juz było trochę trudniej, ze względu na dość szeroki wachlarz pytań i silną konkurencję.&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;Nie będę pisał szczegółowej relacji z przebiegu spotkania, bo uczynili to juz inni (patrz – linki blogów).     &lt;br /&gt;Pozdrowienia dla wszystkich uczestników i do zobaczenia za rok! :)     &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8323132172904612534-1046536077084719549?l=www.bsmechanik.pl' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Bsmechanikdevblog/~4/eF6gYhdJJcY" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Bsmechanikdevblog/~3/eF6gYhdJJcY/afterparty.html</link><author>bs.mechanik@gmail.com (bs.mechanik)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.bsmechanik.pl/2009/03/afterparty.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-2117488252319635723</guid><pubDate>Fri, 13 Mar 2009 01:42:00 +0000</pubDate><atom:updated>2009-03-13T03:05:30.810+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">c++</category><category domain="http://www.blogger.com/atom/ns#">assembler</category><title>CPUID, czyli procesorze przedstaw się</title><description>&lt;p&gt;We wcześniejszych notkach pisałem o technologii SSE. &lt;a href="http://bsmechanik.blogspot.com/2008/12/wicej-mocy.html"&gt;Krótki opis&lt;/a&gt;, &lt;a href="http://bsmechanik.blogspot.com/2009/01/kompilator-vs-inline-asembler_06.html"&gt;wsparcie ze strony kompilatora&lt;/a&gt; – czas więc na bardziej praktyczne podejście do tematu. W artykule tym skupię się jednak na działaniu instrukcji, która nie jest związana bezpośrednio z technologią SSE, a mianowicie na CPUID - proste, bezargumentowe polecenie, pozwalające uzyskać wiele przydatnych informacji na temat procesora. &lt;/p&gt;  &lt;p&gt;Pisząc program korzystający z zestawu instrukcji SIMD, chcemy czasem zachować zgodność ze starszymi modelami procesorów, które nie wspomagają konkretnej wersji SSE lub 3DNow!. Wykorzystując także najnowsze wersje rozszerzeń multimedialnych (aktualnie jest to 4.1), musimy mieć na uwadze to, że wielu użytkowników nie posiada jeszcze procesorów, które je potrafią obsłużyć. Aby nie ograniczać liczby potencjalnych odbiorców, musimy więc zaopatrzyć się w metody, które wykonają stosowne obliczenia w sposób tradycyjny, lub za pomocą niższych wersji SSE. Problemem pozostaje oczywiście pobranie informacji o tym, jaki typ funkcji możemy wykonać na procesorze użytkownika. Rozwiązanie jest wbrew pozorom dość proste. Przyjrzyjmy się kilku z nich. &lt;/p&gt;  &lt;p&gt;Jeśli interesuje nas lista podstawowych możliwości, możemy skorzystać z funkcji udostępnianych przez Windows Api: &lt;a href="http://msdn.microsoft.com/en-us/library/ms724482(VS.85).aspx" target="_blank"&gt;IsProcessorFeaturePresent&lt;/a&gt; i &lt;a href="http://msdn.microsoft.com/en-us/library/ms724381(VS.85).aspx" target="_blank"&gt;GetSystemInfo&lt;/a&gt;. Pierwsza z nich zwraca informacje o wersji obsługiwanych SSE (niestety, tylko do wersji trzeciej), MMX, 3DNow! a także garść innych danych (choćby dostępność &lt;a href="http://msdn.microsoft.com/en-us/library/aa366796(VS.85).aspx" target="_blank"&gt;Physical Address Extension&lt;/a&gt;). Kolejna z wymienionych funkcji, może być szczególnie przydatna, bo za jej pomocą można dowiedzieć się, ile fizycznych procesorów jest aktualnie zainstalowanych w systemie. Pobiera także dane dotyczące m.in. rozmiaru strony w pamięci operacyjnej.     &lt;br /&gt;Skorzystanie z powyższej funkcjonalności jest bardzo proste, zaś przykłady są na stronach ich dokumentacji, więc nie będę prezentował ich użycia.&lt;/p&gt;  &lt;p&gt;Sprawdzanie jednak, czy procesor posiada obsługę MMX, w dzisiejszych czasach, nie jest już koniecznie wymagane – od ładnych kilku lat, należy to do standardowej funkcjonalności procesorów rodziny x86. Co jednak, gdy chcemy skorzystać z udogodnień SSE 4.1? Jego obsługa dziś nie jest jeszcze tak oczywista, podobnie jak SSSE 3. Tu z pomocą przychodzi nam assembler.    &lt;br /&gt;Instrukcja &lt;font face="Courier New"&gt;CPUID&lt;/font&gt; dostępna jest od rodziny procesorów Pentium i późniejszych Intel486. Nie wszystkie funkcje były wspomagane od razu, jednak od czasów Pentium 4, sytuacja nie zmieniła się zbyt mocno.     &lt;br /&gt;Ogólna idea działania jest bardzo prosta: do rejestru &lt;font face="Courier New"&gt;EAX &lt;/font&gt;&lt;font face="Verdana"&gt;przekazujemy numer funkcji (operacje jaką chcemy wykonać), wywołujemy instrukcję &lt;font face="Courier New"&gt;CPUID&lt;/font&gt; i dostajemy interesujące nas informacje w odpowiednich rejestrach. Na początek pobierzmy nazwę producenta – jest to 12 znakowy łańcuch, zapisany w 3 rejestrach:&lt;/font&gt;&lt;/p&gt;  &lt;pre class="code"&gt; &lt;span style="color: maroon"&gt;char &lt;/span&gt;&lt;span style="color: #020002"&gt;szName&lt;/span&gt;[&lt;span style="color: blue"&gt;13&lt;/span&gt;];

&lt;span style="color: maroon"&gt;_asm&lt;/span&gt;{
    &lt;span style="color: #020002"&gt;mov eax&lt;/span&gt;,&lt;span style="color: blue"&gt;0x00000000&lt;/span&gt;;
    &lt;span style="color: #020002"&gt;cpuid&lt;/span&gt;;
 
    &lt;span style="color: #020002"&gt;mov DWORD PTR szName&lt;/span&gt;,&lt;span style="color: #020002"&gt;ebx 
    mov DWORD PTR szName&lt;/span&gt;+&lt;span style="color: blue"&gt;4&lt;/span&gt;,&lt;span style="color: #020002"&gt;edx 
    mov DWORD PTR szName&lt;/span&gt;+&lt;span style="color: blue"&gt;8&lt;/span&gt;,&lt;span style="color: #020002"&gt;ecx
&lt;/span&gt;}

&lt;span style="color: #020002"&gt;szName&lt;/span&gt;[&lt;span style="color: blue"&gt;12&lt;/span&gt;] = &lt;span style="color: blue"&gt;0&lt;/span&gt;;
&lt;span style="color: #020002"&gt;printf&lt;/span&gt;(&lt;span style="color: red"&gt;&amp;quot;%s\n&amp;quot;&lt;/span&gt;,&lt;span style="color: #020002"&gt;szName&lt;/span&gt;);&lt;/pre&gt;

&lt;font face="Verdana"&gt;Na procesorach Intela zostanie wyświetlone: &lt;font face="Courier New"&gt;GenuineIntel&lt;font face="Verdana"&gt;, zaś AMD:&lt;/font&gt; &lt;/font&gt;&lt;/font&gt;AuthenticAMD.&lt;font face="Verdana"&gt; &lt;br /&gt;Jak to działa? Bardzo prosto. &lt;br /&gt;Pierwsza instrukcja &lt;font face="Courier New"&gt;mov&lt;/font&gt; zapisuje do rejestru &lt;font face="Courier New"&gt;EAX&lt;/font&gt; numer funkcji (w tym przypadku jest to funkcja o numerze 0). Następnie wywołujemy &lt;font face="Courier New"&gt;CPUID&lt;/font&gt;, które pobiera numer funkcji z rejestru &lt;font face="Courier New"&gt;EAX&lt;/font&gt; i wykonuje odpowiednią operacje. Funkcja, którą przekazaliśmy, zwraca wspomniany już identyfikator producenta procesora, w porcjach czterobajtowych, w rejestrach &lt;font face="Courier New"&gt;EBX&lt;/font&gt;, &lt;font face="Courier New"&gt;EDX&lt;/font&gt;, &lt;font face="Courier New"&gt;ECX&lt;/font&gt;. Aby dostać się do niego, przekazujemy do instrukcji &lt;font face="Courier New"&gt;mov&lt;/font&gt; wskaźnik na tablicę &lt;font face="Courier New"&gt;szName&lt;/font&gt; (warto przypomnieć, że nazwa tablicy jest jednocześnie wskaźnikiem jej początku) i nazwę konkretnego rejestru – ważne aby zastosować zaprezentowaną kolejność by dostać prawidłowo “poskładany” łańcuch. Pod przekazany adres tablicy kopiowana jest zawartość czterobajtowych rejestrów, więc, żeby uzupełnić tablicę, zwiększamy wskaźnik o ilość skopiowanych dotychczas danych (czyli właśnie 4 bajty) dla rejestrów &lt;font face="Courier New"&gt;EDX&lt;/font&gt; i &lt;font face="Courier New"&gt;ECX&lt;/font&gt;.&lt;/font&gt;

&lt;font face="Verdana"&gt;Nie było to więc zbyt trudne zadanie. Dowiedzmy się więc, coś na temat SSE. Numer funkcji, za pomocą której dowiemy się o wspieranych przez procesor wersjach SSE, to &lt;font face="Courier New"&gt;0x0000001&lt;/font&gt;, zaś interesujące nas informacje (czyli Standard Feature Flags) będą się znajdować w rejestrach &lt;font face="Courier New"&gt;EDX&lt;/font&gt; i &lt;font face="Courier New"&gt;ECX&lt;/font&gt;. &lt;/font&gt;

&lt;pre class="code"&gt; &lt;span style="color: maroon"&gt;unsigned &lt;/span&gt;&lt;span style="color: #020002"&gt;s1&lt;/span&gt;, &lt;span style="color: #020002"&gt;s2&lt;/span&gt;;

&lt;span style="color: maroon"&gt;_asm&lt;/span&gt;{
    &lt;span style="color: #020002"&gt;mov eax&lt;/span&gt;,&lt;span style="color: blue"&gt;0x00000001&lt;/span&gt;;
    &lt;span style="color: #020002"&gt;cpuid&lt;/span&gt;;

    &lt;span style="color: #020002"&gt;mov s1&lt;/span&gt;,&lt;span style="color: #020002"&gt;edx&lt;/span&gt;;
    &lt;span style="color: #020002"&gt;mov s2&lt;/span&gt;,&lt;span style="color: #020002"&gt;ecx&lt;/span&gt;;
}&lt;/pre&gt;

&lt;p&gt;Zmienne &lt;font face="Courier New"&gt;s1&lt;/font&gt; i &lt;font face="Courier New"&gt;s2&lt;/font&gt; zostały wykorzystane tu jako wektory bitowe – każdy z 32 bitów przechowuje wartość 0 lub 1 (właściwość jest lub nie jest dostępna). W rejestrze &lt;font face="Courier New"&gt;EDX&lt;/font&gt; (więc u nas w zmiennej &lt;font face="Courier New"&gt;s1&lt;/font&gt;) przechowywane są informacje na temat dostępności MMX (bit 23), SSE (bit 25), SSE2 (bit 26). Czy jest obsługiwane SSE w wersji trzeciej dowiemy się sprawdzając bit zerowy zmiennej &lt;font face="Courier New"&gt;s2&lt;/font&gt;, SSSE3 bit 9 a SSE4.1 bit 19. Jak to zrobimy? Oczywiście posługując się operatorem &lt;font face="Courier New"&gt;&amp;gt;&amp;gt;&lt;/font&gt; (jego działanie i typowe zastosowanie opisał &lt;a href="http://xion.org.pl/" target="_blank"&gt;Xion&lt;/a&gt;, w swoim &lt;a href="http://www.gamedev.pl/tutorials.php?x=view&amp;amp;id=217" target="_blank"&gt;megatutorialu&lt;/a&gt;). 

  &lt;br /&gt;Ogólny schemat wygląda następująco:&lt;/p&gt;

&lt;pre class="code"&gt;((&lt;span style="color: #020002"&gt;zmienna &lt;/span&gt;&amp;gt;&amp;gt; &lt;span style="color: #020002"&gt;numer_bitu&lt;/span&gt;) &amp;amp; &lt;span style="color: blue"&gt;1&lt;/span&gt;) ? &lt;span style="color: #020002"&gt;printf&lt;/span&gt;(&lt;span style="color: red"&gt;&amp;quot;jest&amp;quot;&lt;/span&gt;) : &lt;span style="color: #020002"&gt;printf&lt;/span&gt;(&lt;span style="color: red"&gt;&amp;quot;nie ma&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;Czyli, jeśli chcemy sprawdzić dostępność SSE2, piszemy:&lt;/p&gt;

&lt;pre class="code"&gt;((&lt;span style="color: #020002"&gt;s1 &lt;/span&gt;&amp;gt;&amp;gt; &lt;span style="color: blue"&gt;26&lt;/span&gt;) &amp;amp; &lt;span style="color: blue"&gt;1 &lt;/span&gt;)? &lt;span style="color: #020002"&gt;printf&lt;/span&gt;(&lt;span style="color: red"&gt;&amp;quot;jest\n&amp;quot;&lt;/span&gt;) : &lt;span style="color: #020002"&gt;printf&lt;/span&gt;(&lt;span style="color: red"&gt;&amp;quot;nie ma\n&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;Dla bitu zerowego (SSE3), nie musimy wywoływać operatora &lt;font face="Courier New"&gt;&amp;gt;&amp;gt;&lt;/font&gt;. &lt;/p&gt;

&lt;p&gt;Możemy także ubezpieczyć się, przed (czysto teoretyczną) sytuacją braku wsparcia dla CPUID. W takim przypadku, gdy spróbujemy wykonać tą instrukcję, wyrzucany jest wyjątek, zaś naszym zadaniem jest przechwycenie go. &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: maroon"&gt;__try&lt;/span&gt;{

    &lt;span style="color: maroon"&gt;_asm&lt;/span&gt;{
        &lt;span style="color: gray"&gt;//...
        &lt;/span&gt;&lt;span style="color: #020002"&gt;cpuid
        &lt;/span&gt;&lt;span style="color: gray"&gt;//...
    &lt;/span&gt;}

}
&lt;span style="color: maroon"&gt;__except&lt;/span&gt;(&lt;span style="color: #020002"&gt;EXCEPTION_EXECUTE_HANDLER&lt;/span&gt;) { 
    &lt;span style="color: maroon"&gt;if &lt;/span&gt;(&lt;span style="color: #020002"&gt;_exception_code&lt;/span&gt;() == &lt;span style="color: #020002"&gt;STATUS_ILLEGAL_INSTRUCTION&lt;/span&gt;){
        &lt;span style="color: #020002"&gt;printf&lt;/span&gt;(&lt;span style="color: red"&gt;&amp;quot;Instrukcja nie jest wspierana przez procesor. &amp;quot;&lt;/span&gt;);
    }
}&lt;/pre&gt;

&lt;font face="Verdana"&gt;W tym przypadku mamy możliwość złapania wyjątku systemowego, a taki zostanie wyrzucony, jeśli spróbujemy użyć instrukcji nie wspieranej przez nasz procesor. Tak samo można zrobić dla instrukcji SIMD, jednak moim zdaniem nie jest to eleganckie. W przypadku CPUID, taki kod “opakowujący” jest użyty na wszelki wypadek i jego wykonanie jest praktycznie znikome, zaś dla SSE szanse te znacznie rosną i powinniśmy wykryć odpowiednie właściwości znacznie wcześniej.  &lt;/font&gt;


&lt;p&gt;Dokładny opis CPUID znajdziemy oczywiście w podręcznikach Intela, szczególnie w &lt;em&gt;IA-32 Intel Architecture Software Developer’s Manual VOLUME 2A: Instruction Set Reference, A-M, &lt;/em&gt;stronach 3-179 do 3-208. Warto wspomnieć, że za pomocą tej instrukcji, możemy dowiedzieć się bardzo wielu niskopoziomowych szczegółów na temat procesora. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8323132172904612534-2117488252319635723?l=www.bsmechanik.pl' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Bsmechanikdevblog/~4/HBPXwBApWYY" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Bsmechanikdevblog/~3/HBPXwBApWYY/cpuid-czyli-procesorze-przedstaw-sie.html</link><author>bs.mechanik@gmail.com (bs.mechanik)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.bsmechanik.pl/2009/03/cpuid-czyli-procesorze-przedstaw-sie.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-7189747207983898422</guid><pubDate>Wed, 25 Feb 2009 22:22:00 +0000</pubDate><atom:updated>2009-02-25T23:25:39.607+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">c++</category><category domain="http://www.blogger.com/atom/ns#">Visual Studio</category><title>Istotna kolejność</title><description>&lt;p&gt;Dzięki operatorowi &lt;font color="#333333"&gt;&lt;font face="Courier New"&gt;&lt;span style="color: maroon"&gt;sizeof&lt;/span&gt;() &lt;/font&gt;&lt;font face="Verdana"&gt;możemy dowiedzieć się jaki jest rozmiar danego typu w bajtach. Standard świadomie nie określa odgórnych rozmiarów typów podstawowych, zostawiając to zależnym od platformy sprzętowej (opisane są tylko relacje wielkości pomiędzy typami). Mimo, że wszystkie produkowane dziś procesory operują na słowach 64 bitowych, to jednak znaczna większość użytkowników posiada 32 bitowe systemy operacyjne, dla których tworzony jest kod aplikacji. &lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#333333"&gt;&lt;font face="Verdana"&gt;Przypatrzmy się więc dwóm z pozoru identycznym strukturom:&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: maroon"&gt;struct &lt;/span&gt;&lt;span style="color: #010001"&gt;A&lt;/span&gt;{
    &lt;span style="color: maroon"&gt;short &lt;/span&gt;&lt;span style="color: #010001"&gt;a1&lt;/span&gt;;
    &lt;span style="color: maroon"&gt;int &lt;/span&gt;&lt;span style="color: #010001"&gt;b1&lt;/span&gt;;
    &lt;span style="color: maroon"&gt;short &lt;/span&gt;&lt;span style="color: #010001"&gt;a2&lt;/span&gt;;
};
&lt;span style="color: maroon"&gt;struct &lt;/span&gt;&lt;span style="color: #010001"&gt;B&lt;/span&gt;{
    &lt;span style="color: maroon"&gt;short &lt;/span&gt;&lt;span style="color: #010001"&gt;a1
    &lt;/span&gt;&lt;span style="color: maroon"&gt;short &lt;/span&gt;&lt;span style="color: #010001"&gt;a2&lt;/span&gt;;
    &lt;span style="color: maroon"&gt;int &lt;/span&gt;&lt;span style="color: #010001"&gt;b1&lt;/span&gt;;
};&lt;/pre&gt;&lt;p&gt;&lt;font color="#333333"&gt;&lt;font face="Verdana"&gt;Mają służyć tylko jako przykład, więc nie są to wyjątkowo praktyczne typy. Jak widzimy obydwie struktury mają po dwa pola typu &lt;span style="color: maroon"&gt;&lt;font face="Courier New"&gt;short&lt;/font&gt;&amp;#160;&lt;font color="#000000"&gt;i jedno typu &lt;span style="color: maroon"&gt;&lt;font face="Courier New"&gt;int&lt;/font&gt;&lt;font color="#000000"&gt;.&lt;/font&gt;&lt;/span&gt; Zróbmy teraz mały eksperyment i wyświetlmy rozmiary obu tych typów:&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: #010001"&gt;printf&lt;/span&gt;(&lt;span style="color: red"&gt;&amp;quot;%d %d\n&amp;quot;&lt;/span&gt;,&lt;span style="color: maroon"&gt;sizeof&lt;/span&gt;(&lt;span style="color: #010001"&gt;A&lt;/span&gt;), &lt;span style="color: maroon"&gt;sizeof&lt;/span&gt;(&lt;span style="color: #010001"&gt;B&lt;/span&gt;));&lt;/pre&gt;&lt;p&gt;Naszym oczom ukaże się dość zadziwiający widok, bo rozmiary typów &lt;font face="Courier New"&gt;A&lt;/font&gt; i &lt;font face="Courier New"&gt;B&lt;/font&gt; są różne, i wynoszą odpowiednio 12 i 8 bajtów (na procesorze z rodziny IA-32). Dość zaskakujące, nieprawdaż? Tylko z pozoru. 
  &lt;br /&gt;Zacznijmy więc od początku. Z prostego dodawania wynika, że obie te struktury powinny zajmować 8 bajtów (2+2+4). Pierwsza z nich jednak, zajmuje o 4 bajty więcej. W tym momencie przyda się podstawowa wiedza na temat działania procesora. Danymi, na których procesory 32 bitowe, pracują z największą wydajnością to właśnie 32 bity. Tyle wynosi rozmiar słowa i rejestrów ogólnego przeznaczenia. Wysłanie większej, lub mniejszej, ilości danych, jest realizowane wolniej, dlatego nie zawsze zaleca się ich używanie. Spójrzmy teraz na strukturę &lt;font face="Courier New"&gt;A&lt;/font&gt;. Aby efektywnie móc przesłać wartość jej pól do rejestrów, najlepiej zrobić to 32 bitowymi paczkami. Napotykamy jednak na problem. Wedle tej idei, zmienną &lt;font face="Courier New"&gt;b1&lt;/font&gt; trzeba wysyłać 2 razy (po 16 bitów wraz z &lt;font face="Courier New"&gt;a1&lt;/font&gt; i &lt;font face="Courier New"&gt;a2&lt;/font&gt;). Nie jest bezpieczne i poprawne rozwiązanie. W takim przypadku kompilatory stosują bardzo prostą sztuczkę: wyrównują zmienne do 32 bitów, co w tym przypadku oznacza, że &lt;font face="Courier New"&gt;a1&lt;/font&gt; oraz &lt;font face="Courier New"&gt;a2&lt;/font&gt; będą zajmować po 4 bajty. Na każdej z tych zmiennych zyskujemy dodatkowo po 2 bajty, więc zagadka została wyjaśniona. Dlaczego więc struktura &lt;font face="Courier New"&gt;B&lt;/font&gt;, zajmuje 8 bajtów? Decyduje o tym właśnie ułożenie zmiennych. W tym przypadku zmienne &lt;font face="Courier New"&gt;a1&lt;/font&gt; i &lt;font face="Courier New"&gt;a2&lt;/font&gt; można wysłać za pomocą jednego wywołania instrukcji &lt;font face="Courier New"&gt;mov&lt;/font&gt;, więc wyrównanie ich nie jest potrzebne. 
  &lt;br /&gt;Obrazowo można przedstawić to tak, że struktura (a zarazem i klasa) to pojemnik z 32 bitowymi (lub 64, w przypadku procesorów i systemów operacyjnych 64 bitowych) pudełkami, do których są kolejno dodawane zmienne. Jeśli dana zmienna nie zajmuje całego pudełka, a kolejna zmienna już nie mieści się do niego, wolne miejsce zostaje zapełnione – natura nie lubi próżni. :)&amp;#160; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8323132172904612534-7189747207983898422?l=www.bsmechanik.pl' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Bsmechanikdevblog/~4/6XqEkUVHzHI" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Bsmechanikdevblog/~3/6XqEkUVHzHI/istotna-kolejnosc.html</link><author>bs.mechanik@gmail.com (bs.mechanik)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://www.bsmechanik.pl/2009/02/istotna-kolejnosc.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-1613551492527374240</guid><pubDate>Sun, 01 Feb 2009 23:14:00 +0000</pubDate><atom:updated>2009-02-02T00:31:57.232+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">c++</category><category domain="http://www.blogger.com/atom/ns#">Visual Studio</category><title>Kodowanie znaków, WinApi i Visual Studio</title><description>&lt;p&gt;Wielu początkujących programistów, po używaniu środowisk typu Dev-C++, przesiada się na Visual Studio. Mimo, że na początku może lekko przytłaczać, pakiet Microsoftu jest dość intuicyjnym narzędziem. Stworzenie aplikacji okienkowej w WinApi jest pewnie naszym pierwszym celem. Rozpoczynamy więc lekturę odpowiednich kursów, kopiujemy przykładowy kod i… Jak to zwykle bywa natrafiamy na problem. Okazuje się, że jego przyczyną jest błąd podobny do tego:&lt;/p&gt;&lt;pre class="code"&gt;error C2664: 'CreateWindowExW' : cannot convert parameter 2 from 'char [12]' to 'LPCWSTR'&lt;/pre&gt;&lt;p&gt;Błąd informuje nas o tym, że kompilator nie może zrzutować drugiego parametru funkcji &lt;font face="Courier New"&gt;CreateWindowEx&lt;/font&gt; z typu &lt;font face="Courier New" color="#800000"&gt;char&lt;/font&gt; na typ &lt;font face="Courier New"&gt;LPCWSTR&lt;/font&gt;. Przyjrzyjmy sie może czym jest &lt;font face="Courier New"&gt;LPCWSTR&lt;/font&gt;. Zaglądając do pliku WinNT.h (skąd wiem, że akurat tam? Wystarczy kliknąć prawym przyciskiem myszy na typ i wybrać: “Go to definition”) możemy odczytać:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: maroon"&gt;typedef &lt;/span&gt;__nullterminated CONST WCHAR *LPCWSTR, *PCWSTR;&lt;/pre&gt;&lt;p&gt;Jest to więc stała &lt;font face="Courier New" color="#000000"&gt;(&lt;font color="#800000"&gt;#define&lt;/font&gt; CONST &lt;font color="#800000"&gt;const&lt;/font&gt;) &lt;font face="Verdana"&gt;typu &lt;/font&gt;&lt;font face="Courier" color="#800000"&gt;wchar_t &lt;font color="#000000"&gt;(&lt;/font&gt;typedef wchar_t &lt;font color="#000000"&gt;WCHAR) &lt;font face="Verdana"&gt;zakończona zerem (Microsoft wprowadził adnotacje do C++, jedną z nich jest właśnie &lt;font face="Courier New"&gt;__nullterminated – &lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Verdana"&gt;&lt;font color="#000000"&gt;więcej informacji pod &lt;/font&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms235402(VS.80).aspx"&gt;&lt;font color="#000000"&gt;tym&lt;/font&gt;&lt;/a&gt;&lt;font color="#000000"&gt; adresem). &lt;br /&gt;Teraz przyjrzyjmy się bliżej naszej funkcji. Analiza błędu, przedstawionego nam przez IDE odkryje przed nami pewną ciekawostkę. Okazuje się bowiem, że nie wywoływaliśmy funkcji &lt;font face="Courier New"&gt;CreateWindowExW&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Verdana" color="#000000"&gt;, zaprezentowanej w błędzie, tylko &lt;font face="Courier New"&gt;CreateWindowEx&lt;/font&gt;. W czym tkwi haczyk? Zobaczmy jak zadeklarowana jest owa funkcja:&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: maroon"&gt;#ifdef &lt;/span&gt;UNICODE&lt;br&gt;&lt;span style="color: maroon"&gt;#define &lt;/span&gt;CreateWindowEx  CreateWindowExW&lt;br&gt;&lt;span style="color: maroon"&gt;#else&lt;br&gt;&lt;/span&gt;&lt;span style="color: gray"&gt;#define CreateWindowEx  CreateWindowExA&lt;br&gt;&lt;/span&gt;&lt;span style="color: maroon"&gt;#endif &lt;/span&gt;&lt;span style="color: gray"&gt;// !UNICODE&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;Tak. Oto całość. Jak na zwykłą deklaracje, kod wydaje się dość dziwny, jednak jego znaczenie jest dość proste. Na początku sprawdzane jest, czy została zdefiniowana stała preprocesora o nazwie &lt;font face="Courier New"&gt;UNICODE. &lt;font face="Verdana"&gt;Jeśli tak, każde wywołanie funkcji &lt;font face="Courier New"&gt;CreateWindowEx&lt;/font&gt; będzie zastępowane przez &lt;font face="Courier New"&gt;CreateWindowExW&lt;/font&gt;. W wypadku gdy stała nie jest zdefiniowana wywoływana będzie &lt;font face="Courier New"&gt;CreateWindowExA&lt;/font&gt;&lt;font face="ver"&gt;*&lt;/font&gt;.&amp;#160; Tylko czym różnią się te funkcje z przyrostkami “A” i “W” ? Otóż jeśli funkcja ma postfix “W” oznacza to, że operuje na znakach Unicode, czyli &lt;font face="Courier New" color="#800000"&gt;wchar_t&lt;/font&gt; (&lt;font face="Courier New"&gt;LPCWSTR&lt;/font&gt;), zaś “A” oznacza zwykłe kodowanie ASCII (&lt;font face="Courier New" color="#800000"&gt;char&lt;/font&gt;). &lt;br /&gt;Pozostaje jeszcze jedno pytanie. Skąd wiadomo, że stała &lt;font face="Courier New"&gt;UNICODE&lt;/font&gt; jest zdefiniowana i jak, w razie potrzeby, ją zdefiniować? Aby zapoznać się z pełną listą stałych wystarczy wejść we właściwości projektu, tam w element &lt;strong&gt;C++&lt;/strong&gt; (znajdujący się w &lt;strong&gt;Configuration Properties&lt;/strong&gt;) a następnie w &lt;strong&gt;Command Line&lt;/strong&gt;. Dla standardowego projektu Win32 możemy przeczytać następujące stałe: WIN32, DEBUG lub NDEBUG dla projektu Release, UNICODE oraz WINDOWS. Zmianę lub dodanie własnej stałej, wykonujemy poprzez &lt;strong&gt;Preprocesor Definitions&lt;/strong&gt; elementu &lt;strong&gt;Preprocesor&lt;/strong&gt; (dalej jesteśmy w &lt;strong&gt;C++&lt;/strong&gt;). Tylko, że nie ma tam UNICODE, nawet jeśli stała ta jest zdefiniowana. Co należy zrobić by korzystać ze standardowego kodowania? Cóż, znów przyjdzie nam z pomocą okienko z właściwościami projektu. Klikamy na zakładkę &lt;strong&gt;General&lt;/strong&gt; w &lt;strong&gt;Configuration Properties&lt;/strong&gt; i tam &lt;strong&gt;Character Set&lt;/strong&gt; ustawiamy na &lt;strong&gt;Not Set&lt;/strong&gt;.&amp;#160; &lt;br /&gt;Klikamy na OK, rekompilujemy nasz projekt i możemy korzystać ze starego dobrego typu &lt;font face="Courier New" color="#800000"&gt;char&lt;/font&gt;. &lt;/font&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;*&lt;font size="1"&gt;Warto wspomnieć o tym, że tak naprawdę kompilator nie wie, czym jest funkcja &lt;font face="Courier New"&gt;CreateWindowEx&lt;/font&gt;. Każde jej wywołanie, zostanie mechanicznie zastąpione jedną z dwóch wyżej wymienionych funkcji, jeszcze przed kompilacją – na tym ogólnie polega idea preprocesora tekstu w C++.&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8323132172904612534-1613551492527374240?l=www.bsmechanik.pl' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Bsmechanikdevblog/~4/DEnPRM40mv4" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Bsmechanikdevblog/~3/DEnPRM40mv4/kodowanie-znakow-winapi-i-visual-studio.html</link><author>bs.mechanik@gmail.com (bs.mechanik)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://www.bsmechanik.pl/2009/02/kodowanie-znakow-winapi-i-visual-studio.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-9139514996627321648</guid><pubDate>Fri, 09 Jan 2009 21:27:00 +0000</pubDate><atom:updated>2009-01-09T22:48:06.184+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">produkcje</category><title>isabellFrame</title><description>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_YlcK27LLDCs/SWfGDfqe3yI/AAAAAAAAAPM/t3ZGlgPu7eE/s1600-h/isabellLogo2.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 80px; height: 103px;" src="http://1.bp.blogspot.com/_YlcK27LLDCs/SWfGDfqe3yI/AAAAAAAAAPM/t3ZGlgPu7eE/s320/isabellLogo2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5289414050711527202" /&gt;&lt;/a&gt;

&lt;p&gt;Jest to niewielki framework, ułatwiający tworzenie gier oraz aplikacji multimedialnych. Wykorzystuje Direct3D 9.0c    &lt;br /&gt;(wersja August 2008) oraz Direct Input 8.0. Napisany przy użyciu Microsoft Visual C++ 2008.&lt;/p&gt;  &lt;p&gt;Zawiera:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;podstawową obsługę zarządzania uprzędzeniem renderującym. &lt;/li&gt;    &lt;li&gt;obsługę okna głównego aplikacji &lt;/li&gt;    &lt;li&gt;pobieranie informacji o komputerze i systemie operacyjnym &lt;/li&gt;    &lt;li&gt;sprawdzanie możliwości karty graficznej &lt;/li&gt;    &lt;li&gt;obsługę wejścia (standardowe komunikaty Windows, Direct Input buforowany oraz niebuforowany) &lt;/li&gt;    &lt;li&gt;obsługa błędów za pomocą stosu wyjątków &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;   &lt;br /&gt;Jest to wersja 1.0 więc jest już stabilna, będę wdzięczny jednak za wszystkie informacje o błędach i nieprawidłowych zachowaniach. Dokumentacja zostanie opublikowana za jakiś czas.     &lt;br /&gt;Biblioteka jest darmowa do wszelakich zastosowań.     &lt;br /&gt;    &lt;br /&gt;Download po &lt;a href="http://odsiebie.com/pokaz/1295686---e726.html"&gt;tym&lt;/a&gt; adresem.     &lt;br /&gt;W paczce znajdują się nagłówki (katalog include), dwie wersje biblioteki (postfix “d” oznacza wersję debug, zaś “r” release ) oraz dwa przykłady wykorzystania frameworka (katalog tut).&amp;#160; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8323132172904612534-9139514996627321648?l=www.bsmechanik.pl' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Bsmechanikdevblog/~4/4SRC4aN-ttc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Bsmechanikdevblog/~3/4SRC4aN-ttc/isabellframe.html</link><author>bs.mechanik@gmail.com (bs.mechanik)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_YlcK27LLDCs/SWfGDfqe3yI/AAAAAAAAAPM/t3ZGlgPu7eE/s72-c/isabellLogo2.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.bsmechanik.pl/2009/01/isabellframe.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-3061308374971830938</guid><pubDate>Mon, 05 Jan 2009 23:05:00 +0000</pubDate><atom:updated>2009-02-26T19:28:39.539+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">c++</category><category domain="http://www.blogger.com/atom/ns#">assembler</category><category domain="http://www.blogger.com/atom/ns#">Visual Studio</category><title>Kompilator vs. inline assembler</title><description>&lt;p&gt;
Optymalizacje niskopoziomowe, mimo że stosowane coraz rzadziej, nadal w wielu przypadkach, są jedynym wyjściem by przyśpieszyć działanie aplikacji. Z roku na rok jednak, kompilatory czynią dość znaczące postępy w automatycznym optymalizowaniu kodu i nie zawsze musimy uciekać się do drastycznych metod wstawek asemblerowych, które wbrew powszechnej opinii, nie są już zalecane. Przyjrzyjmy się jednak jednemu, specyficznemu przypadkowi: użycie SSE.&lt;br&gt;Mamy trzy możliwości do wyboru:
&lt;ol&gt;&lt;li&gt;Optymalizacje stosowane przez kompilator (w opisywanym przypadku Visual Studio 2008).&lt;/li&gt;&lt;li&gt;Użycie wewnętrznych poleceń, tzw. intrinsic. &lt;/li&gt;&lt;li&gt;Bezpośrednie zastosowanie instrukcji SSE procesora.&lt;/li&gt;&lt;/ol&gt;Będziemy wykonywać operacje na wektorach, które będą reprezentowane przez zwykłą, wyrównaną do 16 bajtów (128 bitów) tablicą 4 wartości float:&lt;p&gt;&lt;span style="color: maroon"&gt;__declspec&lt;/span&gt;(&lt;span style="color: maroon"&gt;align&lt;/span&gt;(&lt;span style="color: blue"&gt;16&lt;/span&gt;)) &lt;span style="color: maroon"&gt;float &lt;/span&gt;vector[&lt;span style="color: blue"&gt;4&lt;/span&gt;];&lt;/p&gt;Pewnie wiele osób zastanawia się, skąd ta dziwna składnia tworzenia tablicy. Wyrównanie danych narzuca restrykcje dotyczące rozmiaru. Wyrównanie do 16 bajtów (czyli polecenie &lt;span style="color: maroon"&gt;__declspec&lt;/span&gt;(&lt;span style="color: maroon"&gt;align&lt;/span&gt;(&lt;span style="color: blue"&gt;16&lt;/span&gt;) ) informuje nas, że określona zmienna będzie zajmować dokładnie tyle. Przypomnijmy, że rejestry SSE są 128 bitowe i aby optymalnie wykonywać operacje musimy wysyłać dane do nich właśnie takimi, 128 bitowymi, paczkami. 
Aby porównać ze sobą wymienione wyżej trzy sposoby optymalizacji, zajrzymy do kodu wynikowego generowanego przez kompilator. Można to zrobić wchodząc we właściwości projektu (Project-&gt;Properties), następnie w zakładkę C++, Output Files i tam ustawić Aseembler Output na Assembly With Source Code. Będziemy porównywać podstawowe operacje typu przy zastosowaniu pierwszej wersji SSE, wektorem zaś będzie struktura:&lt;p&gt;&lt;span style="color: maroon"&gt;struct &lt;/span&gt;Vector{&lt;br/&gt;&lt;span style="color: maroon"&gt;__declspec&lt;/span&gt;(&lt;span style="color: maroon"&gt;align&lt;/span&gt;(&lt;span style="color: blue"&gt;16&lt;/span&gt;)) &lt;span style="color: maroon"&gt;float &lt;/span&gt;data[&lt;span style="color: blue"&gt;4&lt;/span&gt;];&lt;br /&gt;};&lt;/p&gt;&lt;p&gt;&lt;strong&gt;1. Optymalizacje kompilatora.&lt;/strong&gt;&lt;/p&gt;Jest to najprostszy sposób by użyć dodatkowej mocy procesora. Zaznaczamy kilka checkbox’ów, rekompilujemy projekt i dostajemy szybszy (przynajmniej w teorii) program. Zobaczmy jak sytuacja przedstawia się, gdy chcemy użyć SSE. 
Na początek przejdźmy do opcji projektu i tam C++ -&gt; Code Generation -&gt; Enable Enhanced Instruction Set ustawiamy na Streaming SIMD Extensions. Mając wszystko przygotowane, możemy przystąpić do pracy.&lt;p&gt;Posłużmy się prostą funkcją dodającą wektory:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: maroon"&gt;void &lt;/span&gt;addVectors(Vector &amp;amp;v1,Vector &amp;amp;v2, Vector *pOut){&lt;br&gt;&amp;#9;pOut-&amp;gt;data[&lt;span style="color: blue"&gt;0&lt;/span&gt;] = v1.data[&lt;span style="color: blue"&gt;0&lt;/span&gt;] + v2.data[&lt;span style="color: blue"&gt;0&lt;/span&gt;];&lt;br&gt;&amp;#9;pOut-&amp;gt;data[&lt;span style="color: blue"&gt;1&lt;/span&gt;] = v1.data[&lt;span style="color: blue"&gt;1&lt;/span&gt;] + v2.data[&lt;span style="color: blue"&gt;1&lt;/span&gt;];&lt;br&gt;&amp;#9;pOut-&amp;gt;data[&lt;span style="color: blue"&gt;2&lt;/span&gt;] = v1.data[&lt;span style="color: blue"&gt;2&lt;/span&gt;] + v2.data[&lt;span style="color: blue"&gt;2&lt;/span&gt;];&lt;br&gt;&amp;#9;pOut-&amp;gt;data[&lt;span style="color: blue"&gt;3&lt;/span&gt;] = &lt;span style="color: blue"&gt;1.0f&lt;/span&gt;;&lt;br&gt;}&lt;/pre&gt;&lt;p&gt;Warto zauważyć, że element w, czyli ostatni, powinien być ustawiany na wartość 1.0f. Nie zastosowałem tutaj pętli, choć kompilator przy tak niewielkiej ilości iteracji i tak zastosowałby rozwinięcie.&lt;/p&gt;&lt;p&gt;Spójrzmy teraz na kod, który został wyprodukowany:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: gray"&gt;//; 8    :     pOut-&amp;gt;data[0] = v1.data[0] + v2.data[0];&lt;/span&gt;&lt;br&gt;    mov    eax, DWORD PTR _v1$[ebp]&lt;br&gt;    fld    DWORD PTR [eax]&lt;br&gt;    mov    ecx, DWORD PTR _v2$[ebp]&lt;br&gt;    fadd    DWORD PTR [ecx]&lt;br&gt;    mov    edx, DWORD PTR _pOut$[ebp]&lt;br&gt;    fstp    DWORD PTR [edx]&lt;br&gt;&lt;span style="color: gray"&gt;//; 9    :     pOut-&amp;gt;data[1] = v1.data[1] + v2.data[1];&lt;br&gt;    //dodawanie wartosci y
//; 10   :     pOut-&amp;gt;data[2] = v1.data[2] + v2.data[2];&lt;br&gt;    //dodawanie wartosci z
//; 12   :     pOut-&amp;gt;data[3] = 1.0f;&lt;br&gt;&lt;/span&gt;    mov    eax, DWORD PTR _pOut$[ebp]&lt;br&gt;    movss    xmm0, DWORD PTR __real@&lt;span style="color: blue"&gt;3f800000&lt;br&gt;&lt;/span&gt;    movss    DWORD PTR [eax+&lt;span style="color: blue"&gt;12&lt;/span&gt;], xmm0&lt;/pre&gt;&lt;p&gt;Pominąłem tu prolog i epilog funkcji, bo nie są w tym momencie istotne. Nie ma także dodawania elementów y i z, ponieważ jest to realizowane w taki sam sposób jak dla elementu x. Zmieniane są tylko wartości rejestrów ecx dla instrukcji fadd (która odpowiada za dodawanie przez koprocesor FPU), oraz rejestru edx dla funkcji fstp odpowiednio o 4 (współrzędna x) i 8 (współrzędna y). Jak widać, samo dodawanie jest realizowane standardowo. Pierwszy raz instrukcja SSE jest użyta podczas przypisania elementu w (data[3]) – movss odpowiedzialna za ustawienie najniższej wartości rejestru na odpowiednią wartość.&lt;/p&gt;&lt;p&gt;Wnioski są bardzo proste: korzystanie z optymalizacji dostarczanych przez kompilator (w kontekście korzystania z SSE) nie dają zbyt wiele korzyści, a czasem nawet mogą zaszkodzić – powyższy kod nie uruchomi się na procesorach niższej klasy niż pentuim III – wszystko przez jedną instrukcję movss, która de facto, nie przyśpieszyła zauważalnie naszego kodu.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;2. Wewnętrzne polecenia kompilatora.&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Są to instrukcje, dzięki którym kompilator wie jak poprawnie użyć poleceń asemblera. By móc z nich skorzystać musimy dołączyć do projektu nagłówek xmmintrin.h, gdzie znajdują się wszystkie deklaracje funkcji i typów. Także i w tym przypadku wykorzystamy prostą funkcję dodającą dwa wektory:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: maroon"&gt;void &lt;/span&gt;addVectors(Vector &amp;amp;v1,Vector &amp;amp;v2, Vector *pOut){&lt;br&gt;     _mm_store_ps(pOut-&amp;gt;data,_mm_add_ps(*(&lt;span style="color: maroon"&gt;__m128&lt;/span&gt;*)&amp;amp;v1.data,*(&lt;span style="color: maroon"&gt;__m128&lt;/span&gt;*)&amp;amp;v2.data));&lt;br&gt;     pOut-&amp;gt;data[&lt;span style="color: blue"&gt;3&lt;/span&gt;] = &lt;span style="color: blue"&gt;1.0f&lt;/span&gt;;&lt;br&gt;}&lt;/pre&gt;&lt;p&gt;Tak. Oto cała funkcja. Dodaje ona dwa wektory, więc funkcjonalnością jest ona identyczna z tą zaprezentowaną wcześniej. Na tym jednak kończą się podobieństwa. Jak widać sposób dodawania jest tutaj inny. Jest on wykonywany za pomocą funkcji _mm_add_ps, przyjmującej zmienne typu __m128 – by przekazać wyrównaną tablicę trzeba użyć rzutowania. Za pomocą _mm_store_ps zapisujemy wartość typu __m128, zwracaną przez _mm_add_ps, do tablicy. Zostaje jeszcze przypisanie wartości dla w. Tworząc własną klasę do zarządzania wektorami, można pominąć tę operację, dodając metodę dostępową zwracającą dla w zawsze 1.0f – wartość zapisana w ostatniej komórce będzie więc bez znaczenia.&lt;/p&gt;&lt;p&gt;Zobaczmy więc, co zostało ostatecznie wygenerowane:&lt;/p&gt;&lt;pre class="code"&gt;    mov    eax, DWORD PTR _v2$[ebx]&lt;br&gt;    movaps    xmm0, XMMWORD PTR [eax]&lt;br&gt;    mov    ecx, DWORD PTR _v1$[ebx]&lt;br&gt;    movaps    xmm1, XMMWORD PTR [ecx]&lt;br&gt;    addps    xmm1, xmm0&lt;br&gt;    movaps    XMMWORD PTR $T20497[ebp], xmm1&lt;br&gt;    movaps    xmm0, XMMWORD PTR $T20497[ebp]&lt;br&gt;    mov    edx, DWORD PTR _pOut$[ebx]&lt;br&gt;    movaps    XMMWORD PTR [edx], xmm0
    mov    eax, DWORD PTR _pOut$[ebx]&lt;br&gt;    fld1&lt;br&gt;    fstp    DWORD PTR [eax+12]&lt;/pre&gt;&lt;p&gt;Jak widać, kompilator utworzył znacznie mniej kodu. Pierwsze cztery linijki zapisują przekazane wektory do odpowiednich rejestrów SSE (xmm0, xmm1). Następnie addps dodaje te wektory (zwróćmy uwagę – jedno polecenie dodaje po cztery wartości dla każdego rejestru). Kolejne operacje dotyczą zapisania wyniku w przekazanej zmiennej, zaś trzy ostatnie przypisania wartości 1.0 dla ostatniej komórki tablicy. Tak utworzony kod jest zdecydowanie bardziej wydajny od poprzedniego. Widzimy tu zgodne z oczekiwaniami wykorzystanie instrukcji SSE (movaps, addps). Można zapisać to jeszcze lepiej?&lt;/p&gt;&lt;p&gt;&lt;strong&gt;3. Inline asembler  &lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Została nam ostatnia opcja: bezpośrednia wstawka asemblerowa. Wbrew pozorom nie będzie to trudne zadanie – jak już wyżej było pokazane, dodawanie to zaledwie jedna instrukcja.&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: maroon"&gt;void &lt;/span&gt;addVectors(Vector &amp;amp;v1,Vector &amp;amp;v2, Vector *pOut){&lt;br&gt;&lt;span style="color: maroon"&gt;    _asm&lt;/span&gt;{&lt;br&gt;        mov eax,v1;&lt;br&gt;        mov ecx,v2;&lt;br&gt;        movaps xmm0, [eax];&lt;br&gt;        addps xmm0,[ecx];&lt;br&gt;
        mov eax, pOut;&lt;br&gt;        movaps [eax],xmm0;&lt;br&gt;    }&lt;br&gt;     pOut-&amp;gt;data[&lt;span style="color: blue"&gt;3&lt;/span&gt;] = &lt;span style="color: blue"&gt;1.0f&lt;/span&gt;;&lt;br&gt;}&lt;/pre&gt;&lt;p&gt;Pierwsze dwie instrukcje przenoszą adresy (warto zauważyć, że wejściowe wektory przekazywane są przez referencje) danych na do odpowiednich rejestrów. Następnie movaps przenosi do rejestru xmm0, to co znajduje się pod adresem wskazywanym przez rejestr eax. Instrukcja addps dodaje zawartość rejestru xmm0 oraz miejsca w pamięci wskazywanego przez ecx. Ostatnie instrukcje zapisują wynik w wyjściowej zmiennej pOut.&lt;/p&gt;&lt;p&gt;Kod, który da nam kompilator, będzie praktycznie identyczny z tym znajdującym się&amp;#160; wewnątrz bloku _asm{}. Dodatkowo dojdzie jeszcze ostatnie przypisanie dla data[3].&lt;/p&gt;&lt;p&gt;Jak widać okazaliśmy się lepsi od kompilatora. ;)&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Co więc wybrać?&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Pytanie nie jest taki proste. Nie zawsze bowiem, mamy chęć i czas by pisać kod w asemblerze – funkcje operujące na macierzach są zdecydowanie bardziej skomplikowane. Wyniki jakie dają metody z rodziny _mm* są wystarczająco zadawalające, jednak czasem można zaoszczędzić kilka instrukcji, pisząc niskopoziomowo. Dodatkowo funkcję lub metodę można oznaczyć jako inline lub __forceinline, dzięki temu ciało funkcji będzie wstawiane bezpośrednio w miejsce wywołania. Dzięki temu można uniknąć dodatkowego narzutu. Korzystanie z asemblera ma jednak jedną zasadniczą wadę. Funkcje napisane w taki sposób nie są w żadne sposób optymalizowane. Kompilator grzecznie wklei kod, który wcale nie będzie musiał być wykonywany. W takich przypadkach zdecydowanie bezpieczniej jest użyć intrinsic.&lt;/p&gt;&lt;p&gt;Ostatnim dylematem, może okazać sie potrzeba pisania własnych metod obsługi wektorów i macierzy. Jeśli korzystamy z DirectX, mamy tam do dyspozycji funkcje z rodziny D3DX, które (choć nie wszystkie) zostały odpowiednio już przygotowane – optymalizacja normalizacji wektorów lub mnożenia macierzy jest na prawdę dobrze wykonana.&lt;/p&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8323132172904612534-3061308374971830938?l=www.bsmechanik.pl' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Bsmechanikdevblog/~4/4ndIdq85SwI" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Bsmechanikdevblog/~3/4ndIdq85SwI/kompilator-vs-inline-asembler_06.html</link><author>bs.mechanik@gmail.com (bs.mechanik)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.bsmechanik.pl/2009/01/kompilator-vs-inline-asembler_06.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-9152943948258393647</guid><pubDate>Fri, 05 Dec 2008 16:13:00 +0000</pubDate><atom:updated>2009-03-13T02:49:03.791+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">assembler</category><title>Więcej mocy</title><description>Współczesne gry są bardzo wymagającymi aplikacjami. Renderowanie dynamicznego, pełnego efektów, obrazu ze stałą prędkością co najmniej 30 &lt;a href="http://pl.wikipedia.org/wiki/FPS"&gt;FPS&lt;/a&gt; staje się coraz trudniejszym zadaniem, nawet dla obiektywnie mocnych komputerów. Dobra optymalizacja kodu jest podstawą do sprawnego i szybkiego działania programu. Mówiąc "optymalizacja" mamy zazwyczaj na myśli lepsze konstruowanie algorytmów lub wykorzystanie innych technik dążących do rozwiązania problemu. Czasem jednak, trzeba przejść "o jeden poziom niżej" - stworzyć kod, który jest bliżej określonego sprzętu. Najprościej sytuacja wygląda na konsolach. Tam developer ma z góry ustalona platformę na którą zostanie stworzona gra. Jest więc w stanie stworzyć takie funkcje, które będą działać maksymalnie szybko. Gorzej jest w przypadku PC. Jak powszechnie wiadomo: ilu graczy, tyle różnych konfiguracji. Istnieją jednak pewne ustalone standardy. W przypadku kart graficznych definiowane są one poprzez obsługę odpowiednich wersji DirectX lub OpenGL. Co prawda, różne rozwiązania sprzętowe sprawiają, że wydajność renderowania może być różna, jednak minimalne wymagania zostają ustalone. W kwestii programisty, zostaje odpowiednio wydajne wykorzystanie powyższych API. 

Wbrew pozorom, procesory także posiadają możliwości, które jesteśmy w stanie bezpośrednio wykorzystać. Mowa tutaj o dodatkowych rozszerzeniach multimedialnych.
Są to specjalne instrukcje, dzięki którym możemy znacznie przyśpieszyć działanie naszej aplikacji:
&lt;ul&gt;&lt;li&gt;MMX (Początkowo Intel, teraz także AMD)&lt;/li&gt;&lt;li&gt;3DNow! (AMD)&lt;/li&gt;&lt;li&gt;SSE(Początkowo tylko Intel, teraz także AAMD)&lt;/li&gt;&lt;/ul&gt;
&lt;span style="font-weight:bold;"&gt;MMX.&lt;/span&gt; Jest to zestaw dodatkowych 57 instrukcji wykonujących operacje arytmetyczne i logiczne w technologii SIMD. SIMD (Single Instruction, Multiple Data) umożliwia nam dokonanie obliczeń za pomocą jednej instrukcji na grupie danych, spakowanych do jednego rejestru. Dzięki MMX programista mógł wykonywać równoległe obliczenia na maksymalnie dwóch, 32 bitowych zmiennych. Całość posiadała jednak, z dłuższej perspektywy, dość istotną wadę: Intel nie przeznaczył żadnych dodatkowych rejestrów dla MMX. Wszystkie operacje odbywały się na ośmiu 64 bitowych aliasach rejestrów &lt;a href="http://pl.wikipedia.org/wiki/Koprocesor"&gt;FPU&lt;/a&gt;, co zmuszało koprocesor do przełączania kontekstów działania - w niektórych przypadkach kod MMX był wolniejszy od tego tradycyjnego.
&lt;p&gt;
&lt;span style="font-weight:bold;"&gt;3DNow!&lt;/span&gt; Była to odpowiedź AMD na MMX. Założenia są bardzo podobne to tych zastosowanych u konkurencji, aczkolwiek nie obeszło się bez pewnych różnic. Podstawową był typ danych na których mogły być wykonywane operacje: u AMD były to liczby zmiennoprzecinkowe pojedynczej precyzji. Poza tym, dla 3DNow! przygotowano tylko 21 instrukcji, jednak w kolejnych generacjach procesorów zestaw ten powiększał się.
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-weight:bold;"&gt;SSE.&lt;/span&gt; Technologia z pozoru wydaje sie być podobna do wyżej zaprezentowanych, jednak wprowadzenie jej wraz z procesorami Pentium III było dość istoną ewolucją. Do dyspozycji programisty oddano osiem oddzielnych, 128 bitowych rejestrów, mogących przechować do czterych wartości zmiennoprzecinkowych pojedynczej precyzji. Dzięki temu wzorst wydajności jest zuważalny, szczególnie podczas wykonywania operacji wektorowych i macierzowych. Kolejne genereacje SSE dodają nowe instrukcje, dzięki czemu czesc operacji matematycznych (np. dot product), można wykonać za pomocą jednego wywołania instrukcji w assemblerze.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8323132172904612534-9152943948258393647?l=www.bsmechanik.pl' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Bsmechanikdevblog/~4/VZJVp1KilrE" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Bsmechanikdevblog/~3/VZJVp1KilrE/wicej-mocy.html</link><author>bs.mechanik@gmail.com (bs.mechanik)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.bsmechanik.pl/2008/12/wicej-mocy.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-3273486823725758950</guid><pubDate>Thu, 04 Dec 2008 23:10:00 +0000</pubDate><atom:updated>2009-03-17T00:21:11.642+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">krótka recenzja</category><title>C++ 50 efektywnych sposobów na udoskonalenie Twoich programów</title><description>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.ii.uj.edu.pl/library/cp50sp.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 181px; height: 236px;" src="http://www.ii.uj.edu.pl/library/cp50sp.jpg" border="0" alt="" /&gt;&lt;/a&gt;
Autor: Scott Meyers&lt;br&gt;
Wydawnictwo: &lt;a href="http://helion.pl/ksiazki/cp50sp.htm"&gt;Helion&lt;/a&gt;
&lt;p&gt;
Jest to jedna z bardziej oryginalnych książek na temat programowania w C++, jaką miałem przyjemność czytać.
Autor w sposób lekki i przystępny, tłumaczy dość zawiłe dla początkującego programisty, elementy języka. Tytułowymi "sposobami", są poszczególne rozdziały książki - dodatkowo pogrupowane w tematyczne bloki. Dowiemy się więc jak zarządzać pamięcią, poprawnie implementować konstruktory i destruktory, zapoznamy się z projektem i implementacją funkcji i klas, oraz poznamy kilka reguł projektowania obiektowego. Praktycznie rzecz biorąc, cała merytoryczna zawartość jest już przedstawiona w spisie treści - każdy rozdział to osobny "sposób". Książki nie należy traktować jako całości. Nie jest to kurs C++, który powoli wprowadza w tajniki języka. Każdy rozdział traktuje o osobnym zagadnieniu, choć w większości autor zaznacza, w którym miejscu książki poruszony został podobny temat. Poczucie humoru, oraz lekkość z jaką Scott Meyers tłumaczy kolejne zagadnienia, sprawia, że tą dość krótką książkę (244 strony) możemy przeczytać w jeden dzień. Wiedza jednak, warta będzie wydanych pieniędzy.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8323132172904612534-3273486823725758950?l=www.bsmechanik.pl' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Bsmechanikdevblog/~4/vK2aIlksFNg" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Bsmechanikdevblog/~3/vK2aIlksFNg/c-50-efektywnych-sposobw-na.html</link><author>bs.mechanik@gmail.com (bs.mechanik)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.bsmechanik.pl/2008/12/c-50-efektywnych-sposobw-na.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-7788862984248359486</guid><pubDate>Thu, 04 Dec 2008 00:15:00 +0000</pubDate><atom:updated>2009-03-17T00:23:28.552+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">c++</category><title>Zarządzanie pamięcią</title><description>Szybkość przydziału pamięci na ładowane zasoby jest, wbrew pozorom, dość istotną kwestią działania niektórych aplikacji. Co prawda w grach, użytkownik zazwyczaj cierpliwie czeka, aż całość zostanie załadowana, jednak wydłużanie tego czasu może być mało pożądanym efektem. Warto zaznaczyć, że posiadacze konsol mogą być w nieco lepszej sytuacji. W przypadku tych urządzeń, jeśli średni czas ładowania określonej lokacji lub etapu, jest dłuższy, gra musi czymś zabawić czekającego gracza :). 
Aplikacjami codziennego użytku, w których wydajne zarządzanie i alokowanie pamięci jest ważne, są przeglądarki internetowe. Szybkość renderowania stron, przechodzenia pomiędzy zakładkami oraz zamykania programu, jest dość mocno uzależniona od kodu zarządzającego pamięcią. 
&lt;p&gt;
Jest wiele sposobów dzięki którym możemy skrócić czas wyświetlania się komunikatu "Loading..." ;). 
Podstawową sprawą jest sposób zapisu danych na dysku. Powszechnie wiadomo, operacje na wielu małych plikach wykonują się dłużej, niż na jednym, im równoznacznym. Możemy więc stworzyć własny wirtualny system plików (VFS). Na czym on polega? Najczęściej spotykana implementacja takiego rozwiązania, to spakowane archiwa (rar, zip, 7z...). Jeden plik przechowuje w sobie dane wielu plików, które dodatkowo są spakowane. Najbardziej klasycznym przykładem, gry która korzysta z tego rozwiązania jest Quake 3. Zasoby gry były spakowane w oddzielne pliki *.pk, w których to dodatkowo zastosowano kompresję. &lt;/p&gt; 
&lt;p&gt;
Podobnie sprawa ma się z pamięcią. Przydział kilkuset niewielkich porcji pamięci, jest znacznie mniej wydajny niż jednorazowe wywołanie funkcji przydzielającej pamięć dla większego bloku danych. &lt;br&gt;
Dzięki operatorowi &lt;a href="http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.10"&gt;placement new&lt;/a&gt;, możliwe jest przydzielanie pamięci pod wskazany adres. Co nam to daje? Przydzielamy określony blok pamięci (ustalony z góry, lub obliczony) i posługując się wskaźnikiem na ową pamięć wywołujemy wyżej wspomniany placement new, który przydzieli zasoby pod określonym mu adresem. Następnie (po wcześniejszym rzutowaniu na char*), zwiększamy ten wskaźnik o rozmiar zablokowanego obiektu (operator sizeof()), by podczas kolejnego przydziału nie nadpisać istniejących danych. Dzięki temu dodawanie kolejnych obiektów będzie odbywało się znacznie mniejszym kosztem. Pamiętać należy tylko o tym, że wcześniej zaalokowana pamięć nie jest elastyczna - kiedyś się wyczerpie. Najlepiej, jeśli wcześniej posiadamy informacjie o ostatecznym rozmiarze ładowanych danych i dla niego przydzielimy pamięć. &lt;/p&gt;
&lt;p&gt;
Przedstawione sposoby, mimo, że bardzo proste, potrafią czasem dość znacząco przyśpieszyć działanie naszych superwydajnych aplikacji ;).&lt;p/&gt; 

W następnych notkach postaram napisać coś o optymalizacji obliczeń matematycznych ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8323132172904612534-7788862984248359486?l=www.bsmechanik.pl' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Bsmechanikdevblog/~4/gdcg554ODlI" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Bsmechanikdevblog/~3/gdcg554ODlI/zarzdzanie-pamici.html</link><author>bs.mechanik@gmail.com (bs.mechanik)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.bsmechanik.pl/2008/12/zarzdzanie-pamici.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-6293644399009906101</guid><pubDate>Wed, 19 Nov 2008 16:53:00 +0000</pubDate><atom:updated>2008-11-19T18:22:20.086+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Visual Studio</category><title>Visual Studio 2010</title><description>Microsoft udostępnił wersję pre-release Visual Studio 2010. Do nowości zapowiadanych w tej wersji należały obsługa procesorów wielordzeniowych, co ma znacząco przyśpieszyć działanie pakietu, ulepszenie systemu pomocy, możliwoścc tworzenia programów dla Window 7, .Net Framework 4.0, a także wykorzystanie wielu monitorów, dzięki czemu konfort pracy będzie jeszcze wyższy. 
Poprawieniu miał ulec także systema autouzupełniania kodu intelliSense dla C++, które jak wiadomo, w poprzednich wersjach czasem działało niepoprawnie. 

Informacje o produkcie można znaleźć &lt;a href="http://www.microsoft.com/visualstudio/2010/overview.mspx"&gt;tu&lt;/a&gt;, zaś download możliwy jest pod &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=922B4655-93D0-4476-BDA4-94CF5F8D4814&amp;displaylang=en#filelist"&gt;tym&lt;/a&gt; adresem.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8323132172904612534-6293644399009906101?l=www.bsmechanik.pl' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Bsmechanikdevblog/~4/GanO5bjrb5M" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Bsmechanikdevblog/~3/GanO5bjrb5M/visual-studio-2010.html</link><author>bs.mechanik@gmail.com (bs.mechanik)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.bsmechanik.pl/2008/11/visual-studio-2010.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-8740030354455822739</guid><pubDate>Thu, 23 Oct 2008 20:50:00 +0000</pubDate><atom:updated>2008-10-23T23:10:10.475+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Ogólne</category><title>Joystick 2 Mouse</title><description>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_YlcK27LLDCs/SQDn12bm6PI/AAAAAAAAAO4/ODWaK0XYQ74/s1600-h/Joy2Mouse3Shot.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 200px; height: 220px;" src="http://4.bp.blogspot.com/_YlcK27LLDCs/SQDn12bm6PI/AAAAAAAAAO4/ODWaK0XYQ74/s320/Joy2Mouse3Shot.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5260459277099133170" /&gt;&lt;/a&gt;
Aplikacja, której nazwa jest w tylule niniejszej notki, jest bardzo użyteczna - potrafi oddać kursor myszy pod władzę podłączonego pada. Za pomocą wcześniej skonfigurowanych przycisków możemy poruszać kursorem. Niby nic nadzwyczajnego, jednak w pewnych sytuacjach bardzo praktyczne. Podstawowa zaleta, z punktu widzenia programisty gier, to możliwość przetestowania nowego rodzaju sterowania, bez konieczności implementacji obsługi pada. Wystarczy uruchomić Joystick 2 Mouse i już na wstępie podjąć decyzję o dodaniu nowej funkcjonalności. Oczywiście nie zawsze się to sprawdza, szczególnie gdy nasza gra nie jest sterowana za pomocą myszy :).

Strona projektu: &lt;a href="http://atzitznet.no-ip.org/Joy2Mouse3/"&gt;http://atzitznet.no-ip.org/Joy2Mouse3/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8323132172904612534-8740030354455822739?l=www.bsmechanik.pl' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Bsmechanikdevblog/~4/VEuk-YyL6W4" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Bsmechanikdevblog/~3/VEuk-YyL6W4/joystick-2-mouse.html</link><author>bs.mechanik@gmail.com (bs.mechanik)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_YlcK27LLDCs/SQDn12bm6PI/AAAAAAAAAO4/ODWaK0XYQ74/s72-c/Joy2Mouse3Shot.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.bsmechanik.pl/2008/10/joystick-2-mouse.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-4909351371258461229</guid><pubDate>Tue, 14 Oct 2008 21:04:00 +0000</pubDate><atom:updated>2008-10-15T00:38:40.606+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Visual Studio</category><title>Zaplanowane zadania</title><description>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_YlcK27LLDCs/SPUQsJ4xLxI/AAAAAAAAAOk/OyEKRBeGh3g/s1600-h/taskList.JPG"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_YlcK27LLDCs/SPUQsJ4xLxI/AAAAAAAAAOk/OyEKRBeGh3g/s320/taskList.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5257126490779234066" /&gt;&lt;/a&gt;
Tworzenie kodu źródłowego zazwyczaj odbywa się według określonego przez nas porządku. Wprowadzamy zmiany do istniejącej implementacji, dodajemy nową funkcjonalność... Całość pracy, mimo że podzielona na określone okresy czasu, musi zachować ciągłość. 
Jednak, jak to zazwyczaj bywa, najsłabszym ogniwem jest człowiek. Ile to razy zdarzyło się, że zapomnieliśmy poprawić działanie jakieś metody, której ostateczną implementację zostawilśmy na sam koniec? :)
Przydatnym narzędziem są tzw. listy TODO - posortowana według priorytetu lista zadań, jakie należy wykonać w implementacji. Najprostszym tego typu rozwiązaniem może być zwykła kartka papieru lub plik txt. 
MS Visual Studio też oferuje dość proste, choć wystarczające rozwiazanie. 

Otwieramy menu View-&gt;Other Windows-&gt; Task List. Pokazuje nam sie niewielkie okno. 
Dodawanie zadań dobywa się w dwojaki sposób: bezpośrednio w oknie zadań, lub jako komentarze w kodzie - wystarczy tylko wybrać opcję Comments lub User Tasks.
Komentarze będące elementami listy zadan muszą zaczynać się od słowa TODO lub HACK. IDE natychmiast wykrywa taki komentarz, dodając go do listy. Mamy także informacje o numerze linii i nazwie pliku źródłowego. Niestety w przeciwieństwie do User Tasks nie możemy ustalać ich priorytetu. Jeśli wykonamy określone zadanie, zaznaczamy stojącego obok niego checkbox'a - misja wykonana :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8323132172904612534-4909351371258461229?l=www.bsmechanik.pl' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Bsmechanikdevblog/~4/sbjZKtwyF7k" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Bsmechanikdevblog/~3/sbjZKtwyF7k/zaplanowane-zadania.html</link><author>bs.mechanik@gmail.com (bs.mechanik)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_YlcK27LLDCs/SPUQsJ4xLxI/AAAAAAAAAOk/OyEKRBeGh3g/s72-c/taskList.JPG" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://www.bsmechanik.pl/2008/10/zaplanowane-zadania.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-1813767026418431697</guid><pubDate>Fri, 10 Oct 2008 22:21:00 +0000</pubDate><atom:updated>2009-03-13T03:01:07.964+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">c++</category><title>Fizyczność logiki</title><description>Projektowanie kodu aplikacji jest z pewnością procesem niezwykle złożonym i pracochłonnym. Aplikacja cechująca się wysoka jakością, nie ogranicza się tylko do odpowiedniej funkcjonalności, stabilności i wydajności. Niezwykle ważną cechą jest także możliwość łatwej konserwacji a także ponownego użycia niektórych jej elementów. Oczywiście z pomocą przychodzi nam projektowanie zorientowane obiektowo. 
Podział kodu na logiczne części (klasy) i opisanie ich poziomu abstrakcji znacznie zwiększa czytelność projektu. Dodatkowo, do dyspozycji mamy też wyspecjalizowane narzędzia temu służące, jak np. UML. 
&lt;p&gt;
Projekt programu może być dwojaki: logiczny lub fizyczny. 
Projekt logiczny opisuje problemy występujące na poziomie implementacji. Decyzja o tym, czy dany operator będzie członkiem klasy lub czy dana klasa powinna mieć konstruktor domyślny, zapada na etapie projektu logicznego.  
Projekt fizyczny zaś, określa zależności pomiędzy poszczególnymi komponentami programu. 
Wbrew pozorom, obydwa rodzaje są ze sobą ściśle powiązane i często nieświadomie projektujemy aplikacje od strony fizycznej.&lt;/p&gt; 
&lt;p&gt;
Podstawowym elementem projektu fizycznego jest komponent, czyli spójna i niezależna jednostka będąca zazwyczaj klasą (lub zbiorem klas określonej funkcjonalności) zdefiniowaną w pliku nagłówkowym i zaimplementowaną w pliku cpp.
Załóżmy, że tworzymy klasę przechowującą punkty na płaszczyźnie dwuwymiarowej. 
Klasa ta udostępnia pewną podstawową funkcjonalność (dodawanie, usuwanie,sortowanie punktów). Interesuje nas także możliwość przeglądania listy punktów, jednak przy wykorzystaniu iteratora. Tworzona przez nas klasa iteratora powinna znajdować się w tych samych plikach co główna klasa będąca kontenerem punktów. Fizycznie (a także logicznie) stanowią one jeden komponent udostępniający określoną z góry funkcjonalność (przechowywanie i przeglądanie danych).&lt;/p&gt;
&lt;p&gt;
Pomiędzy komponentami mogą występować określone relacje:
&lt;ul&gt;
 &lt;li&gt;Jest&lt;/li&gt;
 &lt;li&gt;Używa-W-Interfejsie&lt;/li&gt;
 &lt;li&gt;Używa-W-Implementacji&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
Relacja &lt;span style="font-weight:bold;"&gt;Jest&lt;/span&gt;  bezpośrednio wynika z dziedziczenia. Klasa A jest Klasą B, jeśli klasa A publicznie dziedziczy po klasie B. 

&lt;span style="font-weight:bold;"&gt;Używa-W-Interfejsie&lt;/span&gt; oznacza, że dany typ jest wykorzystywany w interfejsie danej klasy. Kiedy tak się dzieje? Gdy typ jest zwracany przez jedną z metod klasy, przyjmowany na liście argumentów lub znajduje się w sekcji prywatnej. Ogólnie rozróżnia się dwa przypadki tej zależności: pełna i z nazwy. Przypadek pierwszy, mówi o tym, że do kompilacji klasy wymagana jest znajomość całej definicji obiektu (dołączenie jej za pomocą #include). Jest to najczęściej spotykany przypadek. 
Zależność Tylko-Z-Nazwy jest wykorzystywana tam, gdzie mamy do czynienia ze wskaźnikami lub referencjami na obiekt. Wtedy potrzebujemy tylko nazwy obiektu - korzystamy z &lt;a href="http://pl.wikibooks.org/wiki/C/Powszechne_praktyki"&gt;deklaracji wyprzedzającej&lt;/a&gt;.   

Ostatnia z relacji, czyli &lt;span style="font-weight:bold;"&gt;Używa-W-Implementacji&lt;/span&gt;, jak sama nazwa wskazuje, mówi o tym, że dany typ używany jest w implementacji funkcjonalności klasy. Wszystkie pliki nagłówkowe, niezbędne do kompilacji, należy dodać poleceniem #include w pliku cpp klasy (nie w pliku nagłówkowym).  

Odpowiednie wykorzystanie wyżej zaprezentowanych relacji pozwoli nam na bardziej przejrzyste zaprojektowanie naszej aplikacji, a także skrócenie czasu kompilacji lub nawet linkowania.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8323132172904612534-1813767026418431697?l=www.bsmechanik.pl' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Bsmechanikdevblog/~4/AXk2yz_p3Qs" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Bsmechanikdevblog/~3/AXk2yz_p3Qs/fizyczno-logiki.html</link><author>bs.mechanik@gmail.com (bs.mechanik)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://www.bsmechanik.pl/2008/10/fizyczno-logiki.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-2697160836861405064</guid><pubDate>Thu, 09 Oct 2008 18:31:00 +0000</pubDate><atom:updated>2008-10-10T00:04:58.205+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Ogólne</category><title>Opera 9.6</title><description>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_YlcK27LLDCs/SO6ABNgh6ZI/AAAAAAAAAOc/mKnLXcsZjGU/s1600-h/opera96.jpeg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_YlcK27LLDCs/SO6ABNgh6ZI/AAAAAAAAAOc/mKnLXcsZjGU/s320/opera96.jpeg" border="0" alt=""id="BLOGGER_PHOTO_ID_5255278573482273170" /&gt;&lt;/a&gt;
Wczoraj, 8 października, Opera Software wypuściła finalną wersję, kolejnej generacji, swojej przeglądarki internetowej. Z podstawowych zmian o jakich należy wspomnieć to ulepszenia w kliencie pocztowym Opera Mail, polegające na dodaniu trybu "połączenia o niskiej przepustowości". Ciekawą funkcjonalnością jest także możliwość przejrzenia kanału informacyjnego RSS przed dodaniem go do Kanałów. 
Ciekawa jest także Opera Link, umożliwiająca zschynchronizowanie swojej przeglądarki z Operą zainstalowaną na innym komputerze  - wystarczy zarejestrować się w serwisie &lt;a href="http://my.opera.com"&gt;my.opera.com&lt;/a&gt; i wybrać opcję z menu Plik-&gt;Synchronizuj Operę. Wybrane ustawienia zostaną zapisane na serwerach Opera Software.

&lt;a href="http://www.opera.com/download/"&gt;Tutaj&lt;/a&gt; możemy sciągnąć pakiet instalacyjny przeglądarki.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8323132172904612534-2697160836861405064?l=www.bsmechanik.pl' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Bsmechanikdevblog/~4/IDHh7w3GQCk" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Bsmechanikdevblog/~3/IDHh7w3GQCk/opera-96.html</link><author>bs.mechanik@gmail.com (bs.mechanik)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_YlcK27LLDCs/SO6ABNgh6ZI/AAAAAAAAAOc/mKnLXcsZjGU/s72-c/opera96.jpeg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://www.bsmechanik.pl/2008/10/opera-96.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-667468765499874767</guid><pubDate>Sun, 21 Sep 2008 18:26:00 +0000</pubDate><atom:updated>2008-09-21T23:54:59.241+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Visual Studio</category><title>różności w kopiowaniu ;)</title><description>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_YlcK27LLDCs/SNa_G1et06I/AAAAAAAAAOU/CN4-w96LsKQ/s1600-h/vscopy.JPG"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_YlcK27LLDCs/SNa_G1et06I/AAAAAAAAAOU/CN4-w96LsKQ/s320/vscopy.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5248592539902923682" /&gt;&lt;/a&gt;
Operacja dość często wykonywana podczas edycji tekstu (w tym także i kodu źródłowego), to kopiuj/wklej. Sekwencja stara, jak pojęcie "edytor tekstu", więc przez te kilka lat istnienia, powstało kilka rozwiazań, które rozbudowywują tą dość ubogą kolekcję - także w środowisku Visual Studio.
Pierwsza ze znanych mi opcji to clipboard ring, czyli możliwość wklejenia kilku ostatnio kopiowanych fragmentów kodu. Użycie bardzo proste: Ctrl+Shift+Ins. Wielokrotne skorzystanie z tej kombinacji powoduje przeskok, do wcześniejszych fragmentów.
Drugie udogodnienie jest bardziej wizualne. Otwieramy zakładkę Toolbox (View-&gt;Toolbox), zaznaczamy tekst i przenosimy go do Toolboxa. Tylko tyle ;) Wklejenie wiąże się z operacją odwrotną: "wyciągnięcie" fragmentu do edytowanego tekstu. Interesujące jest to, że możemy przechować w ten sposób więcej niż jeden fragment kodu, a znajdujące się tam dane pozostaja nawet po zamknięciu Visuala.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8323132172904612534-667468765499874767?l=www.bsmechanik.pl' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Bsmechanikdevblog/~4/HeSrSosr62w" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Bsmechanikdevblog/~3/HeSrSosr62w/rnoci-w-kopiowaniu.html</link><author>bs.mechanik@gmail.com (bs.mechanik)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_YlcK27LLDCs/SNa_G1et06I/AAAAAAAAAOU/CN4-w96LsKQ/s72-c/vscopy.JPG" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.bsmechanik.pl/2008/09/rnoci-w-kopiowaniu.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-976198511510953418</guid><pubDate>Wed, 17 Sep 2008 21:54:00 +0000</pubDate><atom:updated>2009-05-04T21:10:24.998+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">c++</category><title>deklaracja a definicja</title><description>Przeglądając fora internetowe lub kursy dotyczące programowania, 
wiele razy spotkałem się z błędnym używaniem pojęć "deklaracja" i "definicja".
Autorzy powyższych tekstów często nie zwracali uwagi na drobne, aczkolwiek
istotne szczegóły, różniące te dwa pojęcia.

Jak wygląda to w praktyce?
Deklaracja wprowadza do zakresu informacje dotyczące wyłącznie nazwy danego typu.
W jednym zakresie może wystąpić kilka deklaracji określonej nazwy, jednak muszą
być one indentyczne. Wyjątkiem są tutaj deklaracje metod i statycznych
pól składowych klas - mogą wystąpić tylko raz.
W wielu przypadkach, deklaracja jest jednocześnie definicją, 
wyłączając:
&lt;ul&gt;
&lt;li&gt;deklaracje wyprzedzające&lt;/li&gt;
&lt;li&gt;prototypy funkcji&lt;/li&gt;
&lt;li&gt;instrukcje typedef, tworzące alias dla istniejącego typu&lt;/li&gt;
&lt;li&gt;deklaracje statycznych składowych klas&lt;/li&gt;
&lt;li&gt;zmienne zadeklarowane z użyciem modyfikatora extern&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8323132172904612534-976198511510953418?l=www.bsmechanik.pl' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Bsmechanikdevblog/~4/2sejHepp-Q0" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Bsmechanikdevblog/~3/2sejHepp-Q0/deklaracja-definicja.html</link><author>bs.mechanik@gmail.com (bs.mechanik)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.bsmechanik.pl/2008/09/deklaracja-definicja.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-3769157481079917872</guid><pubDate>Fri, 12 Sep 2008 16:53:00 +0000</pubDate><atom:updated>2008-09-12T19:09:47.355+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Ogólne</category><title>wszystkiego najlepszego!</title><description>Prawie każda grupa zawodowa ma dzień, w którym obchodzi swoje święto. Szczególnie popularne było to w czasach PRL, kiedy to urządzano wiece i pochody na których chwalono się najnowszymi osiągnięciami gospodarki. 
Te czasy jednak bezpowrotnie (miejmy nadzieje ;) ) minęły, jednak niektóre tradycje zachowały się do dziś. 
Górnik, hutnik, nauczyciel... To czemu nie programista? ;)
Jak podaje &lt;a href="http://pl.wikipedia.org/wiki/Dzień_programisty"&gt;Wikipedia&lt;/a&gt; dziś przypada nam dzień programisty - 256 dzień roku kalendarzowego. 

Życzę więc wszystkim świętującym udanych kodów i jak najmniej bugów!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8323132172904612534-3769157481079917872?l=www.bsmechanik.pl' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Bsmechanikdevblog/~4/IUoAZa6IB90" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Bsmechanikdevblog/~3/IUoAZa6IB90/wszystkiego-najlepszego.html</link><author>bs.mechanik@gmail.com (bs.mechanik)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://www.bsmechanik.pl/2008/09/wszystkiego-najlepszego.html</feedburner:origLink></item></channel></rss>
