<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Netrix&#039;s devBlog</title>
	<atom:link href="http://netrix.org.pl/index.php/feed/" rel="self" type="application/rss+xml" />
	<link>http://netrix.org.pl</link>
	<description>Code or die</description>
	<lastBuildDate>Mon, 12 Sep 2011 20:20:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Raytracer</title>
		<link>http://netrix.org.pl/index.php/2011/07/30/raytracer/</link>
		<comments>http://netrix.org.pl/index.php/2011/07/30/raytracer/#comments</comments>
		<pubDate>Sat, 30 Jul 2011 21:07:03 +0000</pubDate>
		<dc:creator>Netrix</dc:creator>
				<category><![CDATA[Programy]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Grafika]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Raytracer]]></category>
		<category><![CDATA[Sockets]]></category>
		<category><![CDATA[Threads]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://netrix.org.pl/?p=1032</guid>
		<description><![CDATA[Jak zwykle po długiej nieobecności w końcu pojawia się kolejna notka. Tym razem chciałbym zaprezentować Raytracer, który napisałem w ramach laboratorium z Zaawansowanej grafiki komputerowej. Program oprócz standardowego śledzenia promieni potrafi również generować teksturę proceduralną cegły dla podanego atrybutu (tę część napisałem z kolegą Adamem Jordankiem) oraz prowadzić obliczenia na wielu komputerach wykorzystując model klient-serwer. [...]]]></description>
			<content:encoded><![CDATA[<p>Jak zwykle po długiej nieobecności w końcu pojawia się kolejna notka. Tym razem chciałbym zaprezentować Raytracer, który napisałem w ramach laboratorium z <em>Zaawansowanej grafiki komputerowej</em>. Program oprócz standardowego śledzenia promieni potrafi również generować teksturę proceduralną cegły dla podanego atrybutu (tę część napisałem z kolegą Adamem Jordankiem) oraz prowadzić obliczenia na wielu komputerach wykorzystując model klient-serwer.</p>
<p><img class="size-medium wp-image-1039 alignright" style="margin: 10px;" title="night_v3" src="http://netrix.org.pl/wp-content/2011/07/night_v3-300x225.png" alt="" width="300" height="225" /></p>
<p>Aplikacja do renderowania grafiki wykorzystuje między innymi moją własną biblioteczkę matematyczną, proste kontenery, a oprócz tego &#8211; do obsługi klienta i serwera &#8211;  sockety i wątki (w zależności od systemu ich odpowiednie implementacje).  Implementacja Raytracera wykorzystuje algorytm przecięcia promienia z trójkątem oraz implementację kd-tree znalezioną na <a href="http://www.devmaster.net/articles/raytracing_series/part1.php">tej</a> stronie, które według mojego przekonania są na tyle wydajne i stabilne, że nie było sensu tego modyfikować. Wykorzystywany model oświetlenia jest efektem prób i błędów, ale myślę że wygląda całkiem znośnie. Zaimplementowane są wszystkie podstawowe elementy takie jak cienie, odbicia czy refrakcja.</p>
<p>Z ciekawszych rzeczy, które można znaleźć w kodzie to:</p>
<ul>
<li>obsługa linii poleceń, która opiera się przede wszystkim na liście poleceń, gdzie każde polecenie zawiera nazwę i opis parametru oraz wskaźnik do funkcji, która implementuje jego obsługę.</li>
<li>implementacja klienta i serwera w oparciu o stany oraz przydział zadań do poszczególnych klientów</li>
<li>wczytywanie plików oparte o stany (łatwość dodawania nowych elementów)</li>
</ul>
<p>Więcej informacji i paczkę można znaleźć <strong><a href="http://netrix.org.pl/index.php/programy/raytracer/">tutaj</a></strong>.</p>
]]></content:encoded>
			<wfw:commentRss>http://netrix.org.pl/index.php/2011/07/30/raytracer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Optymalizacja aplikacji C++ z wykorzystaniem AMD CodeAnalyst</title>
		<link>http://netrix.org.pl/index.php/2011/04/13/optymalizacja-aplikacji-c-z-wykorzystaniem-amd-codeanalyst/</link>
		<comments>http://netrix.org.pl/index.php/2011/04/13/optymalizacja-aplikacji-c-z-wykorzystaniem-amd-codeanalyst/#comments</comments>
		<pubDate>Wed, 13 Apr 2011 21:15:50 +0000</pubDate>
		<dc:creator>Netrix</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Algorytm ewolucyjny]]></category>
		<category><![CDATA[Assembler]]></category>
		<category><![CDATA[CodeAnalyst]]></category>
		<category><![CDATA[Optymalizacje]]></category>
		<category><![CDATA[std::set]]></category>
		<category><![CDATA[std::vector]]></category>
		<category><![CDATA[Źródła]]></category>

		<guid isPermaLink="false">http://netrix.org.pl/?p=879</guid>
		<description><![CDATA[W tej notce opiszę moją pierwszą porządną styczność z programem CodeAnalyst i przy okazji pokażę, w jaki sposób udało mi się nieco zoptymalizować napisaną przeze mnie aplikację implementującą rozwiązywanie problemu kolorowania grafu za pomocą algorytmu genetycznego. CodeAnalyst jest programem służącym do profilowania aplikacji. Jego zadaniem jest zbieranie różnego rodzaju próbek w trakcie działania testowanej aplikacji, [...]]]></description>
			<content:encoded><![CDATA[<p>W tej notce opiszę moją pierwszą porządną styczność z programem CodeAnalyst i przy okazji pokażę, w jaki sposób udało mi się nieco zoptymalizować napisaną przeze mnie aplikację implementującą rozwiązywanie problemu kolorowania grafu za pomocą algorytmu genetycznego.</p>
<p><a href="http://netrix.org.pl/wp-content/2011/04/code_analyst.png"><img class="alignright size-medium wp-image-885" title="code_analyst" src="http://netrix.org.pl/wp-content/2011/04/code_analyst-300x215.png" alt="CodeAnalyst - Okno główne programu" width="198" height="141" /></a>CodeAnalyst jest programem służącym do profilowania aplikacji. Jego zadaniem jest zbieranie różnego rodzaju próbek w trakcie działania testowanej aplikacji, które są następnie przedstawiane w formie wykresu lub tabeli. Dzięki temu widać od razu, które miejsca aplikacji mają największy wpływ na badany parametr z dokładnością do wykonywanych instrukcji Assemblera. Program ten można znaleźć na <a href="http://developer.amd.com/cpu/codeanalyst/Pages/default.aspx"><strong>stronie producenta</strong></a>. Jego główne okienko jest przedstawione na obrazku obok.</p>
<p>Jak już wspomniałem badaną aplikacją jest moja implementacja algorytmu ewolucyjnego użytego do rozwiązania problemu kolorowania grafu. Kod tej aplikacji wraz z przykładowym grafem znajduje się <a href="http://netrix.org.pl/content/blog/ea_gcp_src.zip"><strong>tutaj</strong></a>. Jest to kod, od którego wychodzę w tej notce, zatem nie uwzględnia on żadnych poprawek. Poniższa tabela zawiera średnie wyniki pomiaru cykli i czasu jakie zabiera główna pętla programu na dwóch maszynach:</p>
<table style="margin-bottom: 10px; width: 100%; border-collapse: collapse; border-width: 1px; border-style: inset">
<tr>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">Procesor</th>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">System</th>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">Kompilator</th>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">Częstotliwość zegara</th>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">Liczba cykli</th>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">Czas</th>
</tr>
<tr>
<td style="border-width: 1px; border-style: inset">AMD Turion64 2 GHz</td>
<td style="border-width: 1px; border-style: inset">MS Windows 7</td>
<td style="border-width: 1px; border-style: inset">msvc</td>
<td style="border-width: 1px; border-style: inset">25 MHz (QPF)</td>
<td style="border-width: 1px; border-style: inset">4111926149 cykli (QPC)</td>
<td style="border-width: 1px; border-style: inset">164,48 s</td>
</tr>
<tr>
<td style="border-width: 1px; border-style: inset">Intel Pentium 4 2,66 GHz</td>
<td style="border-width: 1px; border-style: inset">Linux</td>
<td style="border-width: 1px; border-style: inset">g++</td>
<td style="border-width: 1px; border-style: inset">2659,98 MHz (cpuinfo)</td>
<td style="border-width: 1px; border-style: inset">268359191768 cykli (__rdtsc())</td>
<td style="border-width: 1px; border-style: inset">100,89 s</td>
</tr>
</table>
<p>Optymalizacja będzie dotyczyć głównie tej pierwszej platformy, ale postanowiłem z ciekawości sprawdzić jak zmiany będą wpływać na czas wykonywania się kodu również na drugiej platformie.</p>
<p>Analiza programu będzie polegać na szukaniu miejsc, w których spędza on najwięcej czasu. Zatem na początek należy uruchomić program CodeAnalyst, a następnie utworzyć projekt wybierając profil <em>Time-based profile</em>. Według mnie dobrze jest również zaznaczyć opcje <em>Stop data collection when app exits</em> oraz <em>Profile the duration of the app execution</em>. Dzięki temu CodeAnalyst poczeka z analizą wyników aż badana aplikacja skończy działanie. Po utworzeniu projektu można przystąpić do testów. Zatem po wyciszeniu/wyłączeniu niepotrzebnych aplikacji można wybrać z menu <em>Profile -&gt; Start</em> lub kliknąć zieloną strzałkę.</p>
<p>Po zakończeniu działania aplikacji zostanie wyświetlone podsumowanie, które wygląda mniej więcej tak:<br />
<a href="http://netrix.org.pl/wp-content/2011/04/ca_systemdata.png"><img class="size-medium wp-image-892" title="ca_systemdata" src="http://netrix.org.pl/wp-content/2011/04/ca_systemdata-300x215.png" alt="CodeAnalyst - System data" width="198" height="141" /></a><a href="http://netrix.org.pl/wp-content/2011/04/ca_systemgraph.png"><img class="alignnone size-medium wp-image-893" title="ca_systemgraph" src="http://netrix.org.pl/wp-content/2011/04/ca_systemgraph-300x215.png" alt="CodeAnalyst - System graph" width="198" height="141" /></a></p>
<p>Obie te zakładki przedstawiają dokładnie to samo, czyli procentowy udział próbek w każdej aplikacji/bibliotece/module, różnica występuje tylko w formie przedstawienia danych. Co w tym podsumowaniu jest interesującego? W tym widoku jeszcze nic, ale CodeAnalyst umożliwia podgląd szczegółów każdego z wymienionych wcześniej bytów, nawet dowolnego procesu wybranego z zakładki <em>Processes</em>. Jednak ponieważ ta notka obejmuje tylko jedną aplikacje, w dodatku tę, która zebrała najwięcej próbek, zatem przejdę teraz do niej. Oto co pokazuje się po dwukrotnym kliknięciu na jej proces:<br />
<a href="http://netrix.org.pl/wp-content/2011/04/ca_tested_app.png"><img class="alignnone size-medium wp-image-898" title="ca_tested_app" src="http://netrix.org.pl/wp-content/2011/04/ca_tested_app1-300x215.png" alt="CodeAnalyst - Testowana aplikacja" width="198" height="141" /></a></p>
<p>W tym widoku widać już nieco więcej. Są tu pokazane funkcje, które zabierały najwięcej czasu. Na samej górze widać jedną, która zabiera aż 40% próbek, jest to funkcja <em>EvaluateConflicts(</em>), która zlicza konflikty dla każdego osobnika w całej populacji. Warto się jej przyjrzeć z bliska:<br />
<a href="http://netrix.org.pl/wp-content/2011/04/ca_evaluateConflicts.png"><img src="http://netrix.org.pl/wp-content/2011/04/ca_evaluateConflicts-300x181.png" alt="CodeAnalysy - Podgląd funkcji EvaluateConflicts()" title="ca_evaluateConflicts" width="198" height="141" class="alignnone size-medium wp-image-924" /></a></p>
<p>CodeAnalyst, wykorzystując dane zawarte w pliku .pdb, który powinien znajdować się obok pliku wykonywalnego, potrafi wyświetlić i dopasować próbki do odpowiedniego miejsca w kodzie. Można również podejrzeć wykonywany w tym miejscu kod Assemblera, co jest bardzo przydatne (żeby nie powiedzieć kluczowe) przy profilowaniu aplikacji. Co zatem widać na powyższym screenie? Jest tam coś co tak naprawdę powinno znajdować się tylko i wyłącznie w aplikacji kompilowanej w trybie Debug. To sprawdzanie poprawności odwołania się do elementu tablicy w klasie <em>std::vector</em>. Jest to nieco dziwne, ponieważ jest tam używany <em>operator[]</em>, a standardowo ta wersja odwołania nie powinna być sprawdzana, w przeciwieństwie do funkcji <em>at()</em>.<br />
Okazuje się jednak, że implementacja STL dostarczana z kompilatorem <em>msvc</em> ma zaimplementowane takie sprawdzenie, które można co prawda wyłączyć flagą <em>_SECURE_SCL</em> ustawioną na 0, ale domyślnie ta opcja jest włączona. Więcej informacji można znaleźć <a href="http://stackoverflow.com/questions/1290396/how-to-make-stdvectors-operator-compile-doing-bounds-checking-in-debug-but-n"><strong>tu</strong></a> lub bezpośrednio <a href="http://msdn.microsoft.com/en-us/library/aa985965%28v=VS.80%29.aspx"><strong>tutaj</strong></a>.</p>
<p>Poniższa tabela zawiera wyniki pomiarów cykli i czasu z wyłączeniem tego sprawdzania:</p>
<table style="margin-bottom: 10px; width: 100%; border-collapse: collapse; border-width: 1px; border-style: inset">
<tr>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">Procesor</th>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">System</th>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">Kompilator</th>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">Częstotliwość zegara</th>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">Liczba cykli</th>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">Czas</th>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">Zysk</th>
</tr>
<tr>
<td style="border-width: 1px; border-style: inset">AMD Turion64 2 GHz</td>
<td style="border-width: 1px; border-style: inset">MS Windows 7</td>
<td style="border-width: 1px; border-style: inset">msvc</td>
<td style="border-width: 1px; border-style: inset">25 MHz (QPF)</td>
<td style="border-width: 1px; border-style: inset">3191994350 cykli (QPC)</td>
<td style="border-width: 1px; border-style: inset">127,68 s</td>
<td style="border-width: 1px; border-style: inset">22,37%</td>
</tr>
<tr>
<td style="border-width: 1px; border-style: inset">Intel Pentium 4 2,66 GHz</td>
<td style="border-width: 1px; border-style: inset">Linux</td>
<td style="border-width: 1px; border-style: inset">g++</td>
<td style="border-width: 1px; border-style: inset">2659,98 MHz (cpuinfo)</td>
<td style="border-width: 1px; border-style: inset">269220460226 cykli (__rdtsc())</td>
<td style="border-width: 1px; border-style: inset">101,21 s</td>
<td style="border-width: 1px; border-style: inset">-0.32%</td>
</tr>
</table>
<p>W przypadku <em>msvc</em> widać, że jest już lepiej, a przypadek <em>gcc</em> został praktycznie nietknięty, zatem nie posiada on domyślnie tego typu sprawdzania. Na poniższych screenach widnieją wyniki ponownego próbkowania aplikacji.<br />
<a href="http://netrix.org.pl/wp-content/2011/04/ca_tested_app2.png"><img src="http://netrix.org.pl/wp-content/2011/04/ca_tested_app2-300x181.png" alt="CodeAnalysy - Próbki w programie po pierwszej poprawce" title="ca_tested_app2" width="198" height="141" class="alignnone size-medium wp-image-939" /></a><a href="http://netrix.org.pl/wp-content/2011/04/ca_evaluateConflicts2.png"><img src="http://netrix.org.pl/wp-content/2011/04/ca_evaluateConflicts2-300x181.png" alt="CodeAnalyst - Funkcja EvaluateConflicts po wprowadzeniu pierwszych poprawek" title="ca_evaluateConflicts2" width="198" height="141" class="alignnone size-medium wp-image-940" /></a></p>
<p>Jak można zauważyć, ta drobna poprawka pozwoliła kompilatorowi zinline&#8217;ować całą funkcję EvaluateConflicts(). Dzięki temu aplikacja wykonuje się szybciej o ok. 22 %. Kod tej wersji znajduje się pod <a href="http://netrix.org.pl/content/blog/ea_gcp_src2.zip"><strong>tym</strong></a> linkiem.</p>
<p>Jednak na tym nie koniec poprawek, ponieważ jest jeszcze jedno miejsce, z którym da się coś zrobić. Otóż jeśli się przyjrzeć podsumowaniu całej aplikacji jeszcze raz, można zauważyć, że spędza ona dużo czasu w funkcji <em>insert()</em> drzewa <em>std::_Tree</em>, które jest implementacją zbioru (<em>std::set</em>) w bibliotece standardowej. Klasa ta jest używana w operatorze selekcji w celu wybrania losowych i niepowtarzających się osobników do turnieju. Co za tym idzie, funkcja <em>insert()</em> jest wywoływana minimum raz dla każdego wolnego miejsca w turnieju (w przypadku testowym jest 50 miejsc), aż do wypełnienia całej nowej populacji (tutaj 5000), czyli krótko mówiąc &#8211; dość często.</p>
<p>Rozwiązaniem, które przyjąłem w tym miejscu było całkowite pozbycie się klasy <em>std::set</em> na rzecz własnego sposobu wybierania losowych i różnych osobników do turnieju. Wynikiem tego jest taka oto klasa:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">template</span><span style="color: #000080;">&lt;</span>uint RANGE<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">class</span> RandomSet    <span style="color: #666666;">// singleton</span>
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    RandomSet<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span> 
        <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span>uint i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> RANGE<span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span> m_aSet<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> i<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">const</span> uint<span style="color: #000040;">*</span> GetRandomSet<span style="color: #008000;">&#40;</span>uint uCount, uint uInnerRange<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        uint uTemp, uRand<span style="color: #008080;">;</span>
        <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span>uint i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> uCount<span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            uRand <span style="color: #000080;">=</span> <span style="color: #0000dd;">rand</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">%</span> <span style="color: #008000;">&#40;</span>uInnerRange <span style="color: #000040;">-</span> i<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            uTemp <span style="color: #000080;">=</span> m_aSet<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
            m_aSet<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> m_aSet<span style="color: #008000;">&#91;</span>i <span style="color: #000040;">+</span> uRand<span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
            m_aSet<span style="color: #008000;">&#91;</span>i <span style="color: #000040;">+</span> uRand<span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> uTemp<span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
        <span style="color: #0000ff;">return</span> m_aSet<span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
    uint m_aSet<span style="color: #008000;">&#91;</span>RANGE<span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Klasa ta wykorzystuje tablicę, w której zapisane są kolejno indeksy wszystkich osobników. Przy każdym wywołaniu funkcji <em>GetRandomSet()</em> tablica ta jest ponownie mieszana tak, by na jej początku znalazły się w miarę losowe wartości. Dzięki temu, że wybierane wartości są zamieniane z wartościami z początku tablicy, zbiór pozostaje pełny ale jest on stopniowo mieszany, przy czym największa różnorodność występuje zawsze na początku tablicy. To ostatnie nie ma tak naprawdę większego znaczenia, ponieważ najważniejsze jest to, żeby funkcja zwracała za każdym razem różne wartości.</p>
<p>Kolejna tabela zawiera wyniki testów po wprowadzeniu tych zmian:</p>
<table style="margin-bottom: 10px; width: 100%; border-collapse: collapse; border-width: 1px; border-style: inset">
<tr>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">Procesor</th>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">System</th>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">Kompilator</th>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">Częstotliwość zegara</th>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">Liczba cykli</th>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">Czas</th>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">Zysk</th>
</tr>
<tr>
<td style="border-width: 1px; border-style: inset">AMD Turion64 2 GHz</td>
<td style="border-width: 1px; border-style: inset">MS Windows 7</td>
<td style="border-width: 1px; border-style: inset">msvc</td>
<td style="border-width: 1px; border-style: inset">25 MHz (QPF)</td>
<td style="border-width: 1px; border-style: inset">1144922576 cykli (QPC)</td>
<td style="border-width: 1px; border-style: inset">45,8 s</td>
<td style="border-width: 1px; border-style: inset">64,13 %</td>
</tr>
<tr>
<td style="border-width: 1px; border-style: inset">Intel Pentium 4 2,66 GHz</td>
<td style="border-width: 1px; border-style: inset">Linux</td>
<td style="border-width: 1px; border-style: inset">g++</td>
<td style="border-width: 1px; border-style: inset">2659,98 MHz (cpuinfo)</td>
<td style="border-width: 1px; border-style: inset">105596054178 cykli (__rdtsc())</td>
<td style="border-width: 1px; border-style: inset">39,7 s</td>
<td style="border-width: 1px; border-style: inset">60,78 %</td>
</tr>
</table>
<p>W przypadku tej poprawki można już zaobserwować znaczny zysk i to na obu platformach (Windows &#8211; 64%, Linux &#8211; 61 %). Na poniższych obrazkach kolejne zrzuty z CodeAnalyst.<br />
<a href="http://netrix.org.pl/wp-content/2011/04/ca_tested_app3.png"><img src="http://netrix.org.pl/wp-content/2011/04/ca_tested_app3-300x215.png" alt="CodeAnalyst - Poprawka GetRandomSet - podsumowanie aplikacji" title="ca_tested_app3" width="198" height="141" class="alignnone size-medium wp-image-960" /></a><a href="http://netrix.org.pl/wp-content/2011/04/ca_GetRandomSet.png"><img src="http://netrix.org.pl/wp-content/2011/04/ca_GetRandomSet-300x181.png" alt="CodeAnalyst - Poprawka GetRandomSet - funkcja" title="ca_GetRandomSet" width="198" height="141" class="alignnone size-medium wp-image-961" /></a></p>
<p>Widać tutaj, że ilość próbkowanego kodu znacznie zmalała, a proporcje między funkcjami znów się zróżnicowały. Dzięki temu można zobaczyć, że funkcja <em>GetRandomSet()</em> zabiera znacznie mniej próbek niż <em>EvaluateGeneration()</em>. Kod tej wersji można pobrać <a href="http://netrix.org.pl/content/blog/ea_gcp_src3.zip"><strong>stąd</strong></a>.</p>
<p>Pozostaje teraz ponownie zapytać, czy można coś tu jeszcze zoptymalizować? Może i można, ale prawdopodobnie zajmie to już trochę więcej czasu niż poprzednie poprawki. Jednym z oczywistych kroków jakie można tutaj wykonać to zastąpienie <em>std::vector</em> zwykłymi tablicami dynamicznymi, ale w tym przypadku zysk jest osiągalny tylko na Linuksie co pokazuje kolejna tabela:</p>
<table style="margin-bottom: 10px; width: 100%; border-collapse: collapse; border-width: 1px; border-style: inset">
<tr>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">Procesor</th>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">System</th>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">Kompilator</th>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">Częstotliwość zegara</th>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">Liczba cykli</th>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">Czas</th>
<th style="border-width: 1px; border-style: outset; background-color: #CCCCCC">Zysk</th>
</tr>
<tr>
<td style="border-width: 1px; border-style: inset">AMD Turion64 2 GHz</td>
<td style="border-width: 1px; border-style: inset">MS Windows 7</td>
<td style="border-width: 1px; border-style: inset">msvc</td>
<td style="border-width: 1px; border-style: inset">25 MHz (QPF)</td>
<td style="border-width: 1px; border-style: inset">1144922576 cykli (QPC)</td>
<td style="border-width: 1px; border-style: inset">46,2 s</td>
<td style="border-width: 1px; border-style: inset">-0.89 %</td>
</tr>
<tr>
<td style="border-width: 1px; border-style: inset">Intel Pentium 4 2,66 GHz</td>
<td style="border-width: 1px; border-style: inset">Linux</td>
<td style="border-width: 1px; border-style: inset">g++</td>
<td style="border-width: 1px; border-style: inset">2659,98 MHz (cpuinfo)</td>
<td style="border-width: 1px; border-style: inset">105596054178 cykli (__rdtsc())</td>
<td style="border-width: 1px; border-style: inset">37 s</td>
<td style="border-width: 1px; border-style: inset">6,78 %</td>
</tr>
</table>
<p>Kod tego przypadku znajduje się <a href="http://netrix.org.pl/content/blog/ea_gcp_src4.zip"><strong>tutaj</strong></a>.</p>
<p>I to właściwie tyle, wnioski? CodeAnalyst jest bardzo dobrym narzędziem do profilowania aplikacji, jest łatwy w obsłudze, a co najważniejsze jest za darmo. Oprócz tego warto zwracać uwagę na implementacje biblioteki standardowej w używanym kompilatorze, ponieważ można się nieco zdziwić, tak jak to miało miejsce w przypadku <em>std::vector</em> w tym przykładzie. Dodatkowo warto czasami poszukać innych rozwiązań dla niektórych problemów, ponieważ wyniki mogą okazać się całkiem zaskakujące.</p>
<p>Na koniec jeszcze taka małą dygresja odnośnie algorytmu ewolucyjnego &#8211; operator mutacji powinien testować prawdodpobieństwo dla każdego genu osobnika (czyli koloru węzła), a nie tak jak w tej implementacji, dla całego osobnika :).</p>
]]></content:encoded>
			<wfw:commentRss>http://netrix.org.pl/index.php/2011/04/13/optymalizacja-aplikacji-c-z-wykorzystaniem-amd-codeanalyst/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Operacje na systemie plików w systemach Windows i Linux w C++</title>
		<link>http://netrix.org.pl/index.php/2011/04/03/operacje-na-systemie-plikow-w-systemach-windows-i-linux-w-c/</link>
		<comments>http://netrix.org.pl/index.php/2011/04/03/operacje-na-systemie-plikow-w-systemach-windows-i-linux-w-c/#comments</comments>
		<pubDate>Sun, 03 Apr 2011 02:15:45 +0000</pubDate>
		<dc:creator>Netrix</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Files]]></category>
		<category><![CDATA[FindFirstFile]]></category>
		<category><![CDATA[getcwd]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[opendir]]></category>
		<category><![CDATA[stat]]></category>
		<category><![CDATA[WinAPI]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://netrix.org.pl/?p=856</guid>
		<description><![CDATA[Tym razem notka o tym, w jaki sposób można wykonywać różne operacje w systemie plików w wymienionych w temacie systemach. Oczywiście każdy programista C/C++ zna funkcje wykonujące podstawowe operacje na plikach, takie jak: odczyt, modyfikacja, zapis (funkcja fopen i poboczne oraz klasy fstream) zmiana nazwy pliku lub katalogu (funkcja rename()) usunięcie pliku (funkcja remove()) Nieco [...]]]></description>
			<content:encoded><![CDATA[<p>Tym razem notka o tym, w jaki sposób można wykonywać różne operacje w systemie plików w wymienionych w temacie systemach. Oczywiście każdy programista C/C++ zna funkcje wykonujące podstawowe operacje na plikach, takie jak:</p>
<ul>
<li>odczyt, modyfikacja, zapis (funkcja <a href="http://www.cplusplus.com/reference/clibrary/cstdio/fopen/">fopen</a> i poboczne oraz klasy <a href="http://www.cplusplus.com/reference/iostream/fstream/">fstream</a>)</li>
<li>zmiana nazwy pliku lub katalogu (funkcja <a href="http://www.cplusplus.com/reference/clibrary/cstdio/rename/">rename()</a>)</li>
<li>usunięcie pliku (funkcja <a href="http://www.cplusplus.com/reference/clibrary/cstdio/remove/">remove()</a>)</li>
</ul>
<p>
Nieco więcej problemów sprawiają pozostałe operacje, takie jak np. pobranie pełnej ścieżki do pliku czy przeglądanie listy plików w katalogu, ponieważ w bibliotece standardowej nie ma do tego celu odpowiednich funkcji, zatem należy ich szukać w API systemu. Niestety co API to różne funkcje, ale zdarzają się i takie, które istnieją w obu systemach.</p>
<p>Na początek pobieranie pełnej ścieżki do bieżącego katalogu, czyli funkcja <strong>getcwd</strong>. Jej prototyp w systemie Windows jest następujący:

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;direct.h&gt;</span>
<span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> _getcwd<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> _DstBuf, <span style="color: #0000ff;">int</span> _SizeInBytes<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></div></div>

<p>a w systemie Linux:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;unistd.h&gt;</span>
<span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> getcwd<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> _DstBuf, <span style="color: #0000ff;">int</span> _SizeInBytes<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></div></div>

<p>
Jak widać prototyp obu funkcji jest identyczny, więc nic nie stoi na przeszkodzie utworzenia sobie odpowiedniego aliasu nazwy za pomocą <strong>typedef</strong>.</p>
<p>
Trochę lepiej jest z funkcją <a href="http://publib.boulder.ibm.com/infocenter/zos/v1r10/index.jsp?topic=/com.ibm.zos.r10.bpxbd00/rtsta.htm">stat()</a> i jej strukturą o tej samej nazwie (thx C&#8230;, typedef needed), która istnieje w obu systemach. Funkcja ta służy do pobierania pełnych informacji o pliku, czyli np. daty modyfikacji, typu czy rozmiaru. Jej przykładowe użycie wygląda następująco:
</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;sys/stat.h&gt;</span>
<span style="color: #0000ff;">typedef</span> <span style="color: #0000ff;">struct</span> stat FileStatus<span style="color: #008080;">;</span> <span style="color: #666666;">// thx C</span>
&nbsp;
<span style="color: #ff0000; font-style: italic;">/*...*/</span>
FileStatus fileStatus<span style="color: #008080;">;</span>
<span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>stat<span style="color: #008000;">&#40;</span>szFullPath.<span style="color: #007788;">c_str</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, <span style="color: #000040;">&amp;</span>fileStatus<span style="color: #008000;">&#41;</span> <span style="color: #000080;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">unsigned</span> <span style="color: #0000ff;">int</span> uFileSize <span style="color: #000080;">=</span> fileStatus.<span style="color: #007788;">st_size</span><span style="color: #008080;">;</span>	<span style="color: #666666;">// Pobranie rozmiaru pliku</span></pre></td></tr></table></div>

<p>
Nieco gorzej jest z wyciąganiem listy plików w katalogu, ponieważ w tym przypadku oba systemy mają do tego różne funkcje. W przypadku systemu Windows wygląda to tak:
</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;windows.h&gt;</span>
<span style="color: #ff0000; font-style: italic;">/*...*/</span>
&nbsp;
WIN32_FIND_DATA info<span style="color: #008080;">;</span>
HANDLE hFind <span style="color: #000080;">=</span> FindFirstFile<span style="color: #008000;">&#40;</span>szDirPath, <span style="color: #000040;">&amp;</span>info<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>INVALID_HANDLE_VALUE <span style="color: #000080;">==</span> hFind<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;Error&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">do</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>info.<span style="color: #007788;">dwFileAttributes</span> <span style="color: #000040;">&amp;</span> FILE_ATTRIBUTE_DIRECTORY<span style="color: #008000;">&#41;</span> <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;Directory: %s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, info.<span style="color: #007788;">cFileName</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">else</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;File: %s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, info.<span style="color: #007788;">cFileName</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">while</span><span style="color: #008000;">&#40;</span>FindNextFile<span style="color: #008000;">&#40;</span>hFind, <span style="color: #000040;">&amp;</span>info<span style="color: #008000;">&#41;</span> <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
FindClose<span style="color: #008000;">&#40;</span>hFind<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>A w systemie Linux tak:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;dirent.h&gt;</span>
<span style="color: #339900;">#include &lt;string.h&gt; // c-string operations</span>
<span style="color: #0000ff;">typedef</span> <span style="color: #0000ff;">struct</span> dirent DirEntry<span style="color: #008080;">;</span>
<span style="color: #0000ff;">typedef</span> <span style="color: #0000ff;">struct</span> stat DirEntryStat<span style="color: #008080;">;</span> <span style="color: #666666;">// thx C again</span>
&nbsp;
DIR<span style="color: #000040;">*</span> pDir<span style="color: #008080;">;</span>
pDir <span style="color: #000080;">=</span> opendir<span style="color: #008000;">&#40;</span>szDirPath<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>pDir <span style="color: #000080;">==</span> null<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;Error&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
DirEntry<span style="color: #000040;">*</span> pDirent<span style="color: #008080;">;</span>
DirEntryStat dirEntryStat<span style="color: #008080;">;</span>
<span style="color: #0000ff;">while</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>pDirent <span style="color: #000080;">=</span> readdir<span style="color: #008000;">&#40;</span>pDir<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">!</span><span style="color: #000080;">=</span> null<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">char</span> buffer<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">255</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">strcpy</span><span style="color: #008000;">&#40;</span>buffer, szDirPath<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">strcat</span><span style="color: #008000;">&#40;</span>buffer, pDirent<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>d_name<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>	<span style="color: #666666;">// Do ponizszej funkcji potrzebna jest sciezka z biezacego katalogu</span>
&nbsp;
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>stat<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>buffer, <span style="color: #000040;">&amp;</span>dirEntryStat<span style="color: #008000;">&#41;</span> <span style="color: #000080;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;Error&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">continue</span><span style="color: #008080;">;</span>	<span style="color: #666666;">// file corrupted... NEXT!</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>dirEntryStat.<span style="color: #007788;">st_mode</span> <span style="color: #000040;">&amp;</span> S_IFDIR<span style="color: #008000;">&#41;</span> <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span>	<span style="color: #666666;">// Katalog</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;Directory: %s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, pDirent<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>d_name<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>dirEntryStat.<span style="color: #007788;">st_mode</span> <span style="color: #000040;">&amp;</span> S_IFREG<span style="color: #008000;">&#41;</span> <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span>	<span style="color: #666666;">// Plik</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;File: %s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, info.<span style="color: #007788;">pDirent</span><span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>d_name<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
closedir<span style="color: #008000;">&#40;</span>pDir<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>
Można zauważyć, że funkcja z WinAPI jest nieco przyjaźniejsza, ponieważ operuje na uchwycie do żądanego katalogu, w przeciwieństwie do funkcji Linuksowej, która po prostu zwraca nazwę tego co siedzi w katalogu i nic więcej.</p>
]]></content:encoded>
			<wfw:commentRss>http://netrix.org.pl/index.php/2011/04/03/operacje-na-systemie-plikow-w-systemach-windows-i-linux-w-c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Komunikacja za pomocą JSON z serwerem PHP w Javie</title>
		<link>http://netrix.org.pl/index.php/2011/03/13/komunikacja-za-pomoca-json-z-serwerem-php-w-javie/</link>
		<comments>http://netrix.org.pl/index.php/2011/03/13/komunikacja-za-pomoca-json-z-serwerem-php-w-javie/#comments</comments>
		<pubDate>Sun, 13 Mar 2011 16:05:48 +0000</pubDate>
		<dc:creator>Netrix</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[HttpURLConnection]]></category>
		<category><![CDATA[JSON]]></category>

		<guid isPermaLink="false">http://netrix.org.pl/?p=848</guid>
		<description><![CDATA[Jakiś czas temu pisałem pewną aplikację w Javie, która wykorzystywała format JSON do komunikacji z serwerem i wywoływania na nim pewnych procedur. Można rzec, że była to bardzo uboga wersja JSON-RPC czyli oficjalnego protokołu wywoływania procedur na zdalnej maszynie. JSON, podobnie jak w XML, jest formatem przesyłu danych w postaci tekstu (czyli postaci odpowiedniej dla [...]]]></description>
			<content:encoded><![CDATA[<p>Jakiś czas temu pisałem pewną aplikację w Javie, która wykorzystywała format JSON do komunikacji z serwerem i wywoływania na nim pewnych procedur. Można rzec, że była to bardzo uboga wersja <a href="http://json-rpc.org/">JSON-RPC</a> czyli oficjalnego protokołu wywoływania procedur na zdalnej maszynie. </p>
<p><a href="http://www.json.org/">JSON</a>, podobnie jak w <a href="http://pl.wikipedia.org/wiki/XML">XML</a>, jest formatem przesyłu danych w postaci tekstu (czyli postaci odpowiedniej dla człowieka), ale w przeciwieństwie do niego jest lżejszy, co widać chociażby po tym, że sam jest opisywany za pomocą tylko kilku znaków. Pomimo tego, że format ten pochodzi z języka Java Script, istnieje masa bibliotek, które umożliwiają jego wykorzystanie w wielu językach, w tym właśnie w języku Java.</p>
<p>W przypadku aplikacji, którą pisałem, jednym z jej zadań było łączenie się z serwerem napisanym PHP i wywoływaniem odpowiednich procedur, które udostępniały jakieś dane. Format procedur był następujący:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">“sessid”: “id”
”action”: “akcja”
”data”: “dane”</pre></div></div>

<p>Przy czym dane również były zapisane w formacie JSON, ale były zorganizowane w odpowiednie struktury, które rozpoznawał serwer. Biblioteką, którą użyłem do wysyłania i odbierania danych była <a href="http://www.json.org/java/index.html">org.json</a>, czyli pierwsza z dostępnych dla języka JAVA. W przypadku mojego kodu jej użycie ograniczyło się do użyciu tylko dwóch klas – <em>JSONObject</em> oraz <em>JSONArray</em>, z których za pomocą metody <em>toString()</em>, można wyciągnąć całą zapisaną hierarchię i następnie wysłać ją za pomocą odpowiedniego strumienia połączonego z serwerem.</p>
<p>Teraz przedstawię trochę kodu pokazującego w jaki sposób połączyć się z serwerem za pomocą <em>HttpURLConnection</em> oraz jak wykorzystać to połączenie do przesłania danych w formacie JSON. Na początek kod wysyłający zapytanie i odbierający odpowiedź serwera:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
</pre></td><td class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.*</span><span style="color: #339933;">;</span>		<span style="color: #666666; font-style: italic;">// BufferedReader, BufferedWriter, IOException, InputStreamReader, OutputStreamWriter</span>
<span style="color: #000000; font-weight: bold;">import</span>.<span style="color: #006633;">java</span>.<span style="color: #006633;">net</span>.<span style="color: #339933;">*;</span>		<span style="color: #666666; font-style: italic;">// HttpURLConnection, URL</span>
&nbsp;
<span style="color: #666666; font-style: italic;">/*
...
*/</span>
&nbsp;
<span style="color: #003399;">URL</span> url <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">URL</span><span style="color: #009900;">&#40;</span>“http<span style="color: #339933;">:</span><span style="color: #666666; font-style: italic;">//mysweet.phpserver.com/”);</span>
<span style="color: #003399;">HttpURLConnection</span> conn <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">HttpURLConnection</span><span style="color: #009900;">&#41;</span>url.<span style="color: #006633;">openConnection</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
conn.<span style="color: #006633;">setDoOutput</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>			<span style="color: #666666; font-style: italic;">// Bo chcemy wysyłać</span>
conn.<span style="color: #006633;">setRequestMethod</span><span style="color: #009900;">&#40;</span>“POST”<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>		<span style="color: #666666; font-style: italic;">// np. jako zapytanie POST</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Request</span>
<span style="color: #003399;">BufferedWriter</span> out <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">BufferedWriter</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">OutputStreamWriter</span><span style="color: #009900;">&#40;</span>conn.<span style="color: #006633;">getOutputStream</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
out.<span style="color: #006633;">write</span><span style="color: #009900;">&#40;</span>“Some post data<span style="color: #339933;">/</span>query”<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
out.<span style="color: #006633;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Response</span>
<span style="color: #003399;">BufferedReader</span> in <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">BufferedReader</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">InputStreamReader</span><span style="color: #009900;">&#40;</span>conn.<span style="color: #006633;">getInputStream</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003399;">String</span> inputLine, answer <span style="color: #339933;">=</span> “”<span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">while</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>inputLine <span style="color: #339933;">=</span> in.<span style="color: #006633;">readLine</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    answer <span style="color: #339933;">+=</span> inputLine<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
in.<span style="color: #006633;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
conn.<span style="color: #006633;">disconnect</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Jak widać nie ma tutaj zbyt dużo roboty, więcej zapewne dzieje się wewnątrz tych klas, ale przecież po to one są żeby się tym z grubsza nie przejmować. Kolejny kod przedstawia sposób tworzenia zapytań za pomocą wspomnianej biblioteki <strong>org.json</strong>:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.json.*</span><span style="color: #339933;">;</span>	<span style="color: #666666; font-style: italic;">//JSONArray, JSONException, JSONObject</span>
&nbsp;
<span style="color: #666666; font-style: italic;">/*
...
*/</span>
&nbsp;
JSONObject root <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> JSONObject<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    .<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span>“sesid”, sesid<span style="color: #009900;">&#41;</span>
    .<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span>“action”, action<span style="color: #009900;">&#41;</span>
    .<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span>“data”, data<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>			 <span style="color: #666666; font-style: italic;">// data może być liczbą, stringiem lub obiektem JSONObject</span>
&nbsp;
string query <span style="color: #339933;">=</span> “json<span style="color: #339933;">=</span>” <span style="color: #339933;">+</span> root.<span style="color: #006633;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Ostatecznie obiekt <em>query</em> zostanie przekazany jako zapytanie do wcześniej wspomnianego obiektu klasy <em>BufferedWriter</em>, dzięki któremu poleci do serwera. Odbieranie odpowiedzi jest równie proste:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">string answer<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">/* Odbieranie odpowiedzi
...
*/</span>
&nbsp;
JSONObject object <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> JSONObject<span style="color: #009900;">&#40;</span>answer<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000066; font-weight: bold;">int</span> status <span style="color: #339933;">=</span> object.<span style="color: #006633;">getInt</span><span style="color: #009900;">&#40;</span>“status”<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
string text <span style="color: #339933;">=</span> object.<span style="color: #006633;">getString</span><span style="color: #009900;">&#40;</span>“some_text”<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
JSONObject node <span style="color: #339933;">=</span> object.<span style="color: #006633;">getJSONObject</span><span style="color: #009900;">&#40;</span>“some_struct”<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
JSONArray array <span style="color: #339933;">=</span> object.<span style="color: #006633;">getJSONArray</span><span style="color: #009900;">&#40;</span>“some_array”<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>I generalnie tak to wygląda, nie trzeba nic samemu parsować, ponieważ wszystko zapewnia kilka gotowych już klas – największa zaleta obiektowych języków programowania.</p>
]]></content:encoded>
			<wfw:commentRss>http://netrix.org.pl/index.php/2011/03/13/komunikacja-za-pomoca-json-z-serwerem-php-w-javie/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Visual Editor dla Eclipse</title>
		<link>http://netrix.org.pl/index.php/2011/03/04/visual-editor-dla-eclipse-2/</link>
		<comments>http://netrix.org.pl/index.php/2011/03/04/visual-editor-dla-eclipse-2/#comments</comments>
		<pubDate>Fri, 04 Mar 2011 20:54:00 +0000</pubDate>
		<dc:creator>Netrix</dc:creator>
				<category><![CDATA[Ciekawostki]]></category>
		<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Swing]]></category>
		<category><![CDATA[Visual Editor]]></category>

		<guid isPermaLink="false">http://netrix.org.pl/index.php/2011/03/04/visual-editor-dla-eclipse-2/</guid>
		<description><![CDATA[Swego czasu do pisania aplikacji okienkowych w Javie (głównie z musu) korzystałem z NetBeans i jego edytora graficznego, jednak w przypadku ostatniego projektu na laboratoria postanowiłem przetestować pewną alternatywę, czyli Visual Editor dla Eclipse. Visual Editor jest (jak większość dodatków do Eclipse) wtyczką, która ma na celu automatyczne generowanie kodu wykorzystującego bibliotekę okienek Swing. Niestety [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://netrix.org.pl/wp-content/2011/03/visual_editor.png"><img style="background-image: none; border-right-width: 0px; margin: 5px 5px 5px 10px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="visual_editor" border="0" alt="visual_editor" align="right" src="http://netrix.org.pl/wp-content/2011/03/visual_editor_thumb.png" width="210" height="133" /></a>Swego czasu do pisania aplikacji okienkowych w Javie (głównie z musu) korzystałem z NetBeans i jego edytora graficznego, jednak w przypadku ostatniego projektu na laboratoria postanowiłem przetestować pewną alternatywę, czyli <a href="http://www.eclipse.org/vep/">Visual Editor</a> dla Eclipse. </p>
<p>Visual Editor jest (jak większość dodatków do Eclipse) wtyczką, która ma na celu automatyczne generowanie kodu wykorzystującego bibliotekę okienek Swing. Niestety okazuje się, że mimo wersji 1.5 dla Eclipse Helios jest to raczej prototyp działający trochę na siłę niż poprawna wersja Release. </p>
<p>Jego największą wadą jest dość wysoka niestabilność, co potrafi owocować widokiem okienek jak na obrazku obok niemal co chwila (tak, korzystałem z wersji x64). Drugą rzeczą, która boli jest to, że zagnieżdżone <a href="http://netrix.org.pl/wp-content/2011/03/ve_error.png"><img style="background-image: none; border-right-width: 0px; margin: 5px 10px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="ve_error" border="0" alt="ve_error" align="left" src="http://netrix.org.pl/wp-content/2011/03/ve_error_thumb.png" width="196" height="129" /></a>okienko zostawia swoja kotwiczkę jako osobny proces, który siedzi sobie jako zupełnie osobna aplikacja w pasku zadań i skutecznie blokuje możliwość użycia skrótu alt+tab, a w przypadku zmiany edytowanych okienek, powoduje wymienione crashe. Kolejną wadą, trochę drobniejszą, jest generowany kod, który, dla większej ilości komponentów i ich właściwości, niestety wygląda jak makaron&#160; (chociaż organizacja na zasadzie statycznych wartości, tudzież singletonów jest dość fajnym rozwiązaniem. </p>
<p>Z zalet Visual Editora mogę wymienić chyba głównie to że jest, a co do samego wyglądu i integracji z Eclipse, to oprócz osobnego procesu dla okienka i crashów, komponuje się to w miarę wygodnie.</p>
<p>Tak przy okazji narzekania na tworzenie okienek w Javie – dlaczego nikt nie wymyślił obliczania minimalnego rozmiaru okna na podstawie minimalnych rozmiarów zawartych w nim komponentów, to naprawdę ułatwiłoby życie.</p>
]]></content:encoded>
			<wfw:commentRss>http://netrix.org.pl/index.php/2011/03/04/visual-editor-dla-eclipse-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Własne repozytorium Gita na Linuksie</title>
		<link>http://netrix.org.pl/index.php/2011/02/16/wlasne-repozytorium-gita-na-linuksie/</link>
		<comments>http://netrix.org.pl/index.php/2011/02/16/wlasne-repozytorium-gita-na-linuksie/#comments</comments>
		<pubDate>Tue, 15 Feb 2011 23:17:58 +0000</pubDate>
		<dc:creator>Netrix</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[authorized_key]]></category>
		<category><![CDATA[CVS]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[repozytorium]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[Slackware]]></category>
		<category><![CDATA[ssh]]></category>

		<guid isPermaLink="false">http://netrix.org.pl/?p=821</guid>
		<description><![CDATA[W tej notce postaram się opisać w jaki sposób, krok po kroku, postawić główne repozytorium Gita na własnym serwerze z zainstalowanym systemem linux (na przykładzie Slackware, z którego korzystam, ale myślę, że nie będzie problemów na innych dystrybucjach). Repozytorium nie będzie wykorzystywać interfejsu webowego i nie będzie uwzględniać podziału na konta, ale będzie wystarczającą alternatywą [...]]]></description>
			<content:encoded><![CDATA[<p>W tej notce postaram się opisać w jaki sposób, krok po kroku, postawić główne repozytorium Gita na własnym serwerze z zainstalowanym systemem linux (na przykładzie Slackware, z którego korzystam, ale myślę, że nie będzie problemów na innych dystrybucjach). Repozytorium nie będzie wykorzystywać interfejsu webowego i nie będzie uwzględniać podziału na konta, ale będzie wystarczającą alternatywą dla publicznego repozytorium w serwisie GitHub. Jednak zaczynając od początku wypadałoby powiedzieć kilka słów o tym czym jest Git.</p>
<p>Git jest jednym z kilku systemów kontroli wersji (SVN, Mercurial), czyli narzędzi służących do śledzenia zmian w kodzie źródłowym. Jego głównym zadaniem jest łączenie i modyfikacja zmian, a w razie błędu, umożliwienie przywrócenia poprzedniej, działającej wersji. Jedną z bardzo ważnych cech Gita jest to, że wszystkie zmiany są przechowywane lokalnie, dzięki czemu nie wymaga on do działania połączenia z głównym repozytorium. W porównaniu do Subversion, z którego do tej pory korzystałem, jest również szybszy i nie występują w nim problemy z łączeniem równoległych wersji (branchy).</p>
<p>Wracając jednak do tematu, na początek wypadałoby się upewnić czy na komputerze, na którym chcemy zainstalować Gita jest jedna z jego nowszych wersji. Ma to związek z przeniesieniem wewnętrznych plików wykonywalnych z katalogu <em>/usr/bin/</em> do <em>/usr/libexec/git-core/</em>. </p>
<h4>Instalacja Gita</h4>
<p>Tak więc na początek pobieramy paczkę z git-core z <strong><a href="http://git-scm.com/download">tej</a></strong> strony, za pomocą polecenia:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">wget</span> http:<span style="color: #000000; font-weight: bold;">//</span>kernel.org<span style="color: #000000; font-weight: bold;">/</span>pub<span style="color: #000000; font-weight: bold;">/</span>software<span style="color: #000000; font-weight: bold;">/</span>scm<span style="color: #000000; font-weight: bold;">/</span>git<span style="color: #000000; font-weight: bold;">/</span>git-1.7.4.1.tar.bz2</pre></div></div>

<p>i ją rozpakowujemy:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">tar</span> –xvf git-1.7.4.1.tar.bz2</pre></div></div>

<p>następnie przechodzimy do tego katalogu i (po przeczytaniu README oraz INSTALL), wykonujemy następujące polecenia:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">.<span style="color: #000000; font-weight: bold;">/</span>configure <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #c20cb9; font-weight: bold;">make</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #c20cb9; font-weight: bold;">make</span> <span style="color: #007800;">prefix</span>=<span style="color: #000000; font-weight: bold;">/</span>usr <span style="color: #c20cb9; font-weight: bold;">install</span> install-doc install-html install-info</pre></div></div>

<p>Tutaj można napotkać problem przy instalowaniu dokumentacji, jak to miało miejsce u mnie. Rozwiązanie tego problemu znajduje się na <strong><a href="http://stackoverflow.com/questions/897477/installing-git-on-os-x">tej</a></strong> stronie.</p>
<p>W tym momencie Git powinien być już zainstalowany, w przypadku gdy mieliśmy na dysku starą wersję, która pliki wykonywalne przechowuje w katalogu <em>/usr/bin/</em>, należy je ręcznie skasować, żeby nie sprawiały problemu. Jeśli jest to możliwe, można je rozpoznać po datach modyfikacji, po czym na koniec powinny zostać tam następujące pliki:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">git
git-cvsserver
git-receive-pack
git-shell
git-upload-archive
git-upload-pack
gitk</pre></div></div>

<h4>Konto shellowe Git</h4>
</p>
<p>Kolejnym krokiem jest utworzenie odpowiedniego konta shellowego, dzięki któremu będzie można połączyć się z repozytorium za pomocą protokołu ssh. Konto należy utworzyć z <em>uid</em> i <em>gid</em> równymi <em>9418</em> oraz <em>git-shell</em> jako programem startowym:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">groupadd <span style="color: #c20cb9; font-weight: bold;">git</span> –g <span style="color: #000000;">9418</span>
useradd <span style="color: #c20cb9; font-weight: bold;">git</span> –u <span style="color: #000000;">9418</span> –g <span style="color: #c20cb9; font-weight: bold;">git</span> –c <span style="color: #c20cb9; font-weight: bold;">git</span> –d <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span><span style="color: #c20cb9; font-weight: bold;">git</span> –s <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>libexec<span style="color: #000000; font-weight: bold;">/</span>git-core<span style="color: #000000; font-weight: bold;">/</span><span style="color: #c20cb9; font-weight: bold;">git-shell</span>
<span style="color: #c20cb9; font-weight: bold;">passwd</span> –d <span style="color: #c20cb9; font-weight: bold;">git</span></pre></div></div>

<p>Istotna jest ostatnia komenda, ponieważ bez niej nie uda się nam połączyć z repozytorium. Następnie tworzymy repozytorium i nadajemy prawa:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">chown</span> <span style="color: #c20cb9; font-weight: bold;">git</span>:<span style="color: #c20cb9; font-weight: bold;">git</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>git<span style="color: #000000; font-weight: bold;">/</span>
<span style="color: #c20cb9; font-weight: bold;">chmod</span> <span style="color: #000000;">700</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>git<span style="color: #000000; font-weight: bold;">/</span>
<span style="color: #c20cb9; font-weight: bold;">mkdir</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>git<span style="color: #000000; font-weight: bold;">/</span>base<span style="color: #000000; font-weight: bold;">/</span>
<span style="color: #c20cb9; font-weight: bold;">chown</span> <span style="color: #c20cb9; font-weight: bold;">git</span>:<span style="color: #c20cb9; font-weight: bold;">git</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>git<span style="color: #000000; font-weight: bold;">/</span>base<span style="color: #000000; font-weight: bold;">/</span>
<span style="color: #c20cb9; font-weight: bold;">chmod</span> <span style="color: #000000;">775</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>git<span style="color: #000000; font-weight: bold;">/</span>base<span style="color: #000000; font-weight: bold;">/</span></pre></div></div>

<p>Kolejnym krokiem jest utworzenie właściwego repozytorium, robi się to za pomocą poleceń:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">mkdir</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>git<span style="color: #000000; font-weight: bold;">/</span>base<span style="color: #000000; font-weight: bold;">/</span>repo.git
<span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>git<span style="color: #000000; font-weight: bold;">/</span>base<span style="color: #000000; font-weight: bold;">/</span>repo.git
<span style="color: #c20cb9; font-weight: bold;">git</span> init –-bare -–shared
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">chmod</span> <span style="color: #660033;">-R</span> g+ws <span style="color: #000000; font-weight: bold;">*</span>
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">chgrp</span> <span style="color: #660033;">-R</span> <span style="color: #c20cb9; font-weight: bold;">git</span> <span style="color: #000000; font-weight: bold;">*</span></pre></div></div>

<p>Repozytorium jest już gotowe, niestety jeszcze nie można się z nim połączyć, ponieważ konto <em>git</em> nie posiada hasła. W celu umożliwienia łączenia się do repozytorium należy skorzystać mechanizmu autoryzacji sesji <em>ssh</em> za pomocą klucza prywatnego.</p>
<h4>Autoryzacja za pomocą klucza prywatnego</h4>
<p>W tym celu należy na każdej maszynie, z której będziemy się łączyć, utworzyć dwa klucze rsa, jeden publiczny drugi prywatny. Nie będę tego opisywał w tej notce, ponieważ jest to fajnie wyjaśnione na stronie GitHuba, w wersji dla systemu <a href="http://help.github.com/msysgit-key-setup/"><strong>windows</strong></a><strong>&#160;</strong>i<strong> </strong><a href="http://help.github.com/linux-key-setup/"><strong>linux</strong></a>. Opiszę natomiast w jaki sposób dodać te klucze do konta git na serwerze, umożliwiając tym autoryzację.</p>
<p>Na początek należy utworzyć w katalogu <em>/home/git/</em> katalog <em>.ssh</em>, w nim plik <em>authorized_keys</em> i nadać im odpowiednie prawa:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">mkdir</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>git<span style="color: #000000; font-weight: bold;">/</span>.ssh
<span style="color: #c20cb9; font-weight: bold;">chmod</span> <span style="color: #000000;">700</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>git<span style="color: #000000; font-weight: bold;">/</span>.ssh<span style="color: #000000; font-weight: bold;">/</span>
<span style="color: #c20cb9; font-weight: bold;">touch</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>git<span style="color: #000000; font-weight: bold;">/</span>.ssh<span style="color: #000000; font-weight: bold;">/</span>authorized_keys
<span style="color: #c20cb9; font-weight: bold;">chmod</span> <span style="color: #000000;">600</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>git<span style="color: #000000; font-weight: bold;">/</span>.ssh<span style="color: #000000; font-weight: bold;">/</span>authorized_keys
<span style="color: #c20cb9; font-weight: bold;">cat</span> id_rsa.pub <span style="color: #000000; font-weight: bold;">&gt;&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>git<span style="color: #000000; font-weight: bold;">/</span>.ssh<span style="color: #000000; font-weight: bold;">/</span>authorized_keys
<span style="color: #c20cb9; font-weight: bold;">chown</span> –R <span style="color: #c20cb9; font-weight: bold;">git</span>:<span style="color: #c20cb9; font-weight: bold;">git</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>git<span style="color: #000000; font-weight: bold;">/</span>.ssh<span style="color: #000000; font-weight: bold;">/</span></pre></div></div>

<p>Gdzie <em>id_rsa.pub</em> to klucz publiczny skopiowany z komputera klienckiego.</p>
<p>I to by było na tyle, w tym momencie można już wysyłać dane do repozytorium, którego adres jest następujący:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">git@adres_serwera:base/repo.git</pre></div></div>

<p>Źródła: <br />
[1] <a title="http://forums.freebsd.org/showthread.php?t=10810" href="http://forums.freebsd.org/showthread.php?t=10810">http://forums.freebsd.org/showthread.php?t=10810</a><br />
[2] <a title="http://stackoverflow.com/questions/897477/installing-git-on-os-x" href="http://stackoverflow.com/questions/897477/installing-git-on-os-x">http://stackoverflow.com/questions/897477/installing-git-on-os-x</a><br />
[3] <a title="https://wincent.com/wiki/Updating_to_Git_1.6.0.1" href="https://wincent.com/wiki/Updating_to_Git_1.6.0.1">https://wincent.com/wiki/Updating_to_Git_1.6.0.1</a><br />
[4] <a title="http://mapopa.blogspot.com/2009/10/git-insufficient-permission-for-adding.html" href="http://mapopa.blogspot.com/2009/10/git-insufficient-permission-for-adding.html">http://mapopa.blogspot.com/2009/10/git-insufficient-permission-for-adding.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://netrix.org.pl/index.php/2011/02/16/wlasne-repozytorium-gita-na-linuksie/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NIne 3 SceneGraph &#8211; paczka</title>
		<link>http://netrix.org.pl/index.php/2011/02/12/nine-3-scenegraph-paczka/</link>
		<comments>http://netrix.org.pl/index.php/2011/02/12/nine-3-scenegraph-paczka/#comments</comments>
		<pubDate>Sat, 12 Feb 2011 18:12:10 +0000</pubDate>
		<dc:creator>Netrix</dc:creator>
				<category><![CDATA[NIne]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[SceneGraph]]></category>

		<guid isPermaLink="false">http://netrix.org.pl/index.php/2011/02/12/nine-3-scenegraph-paczka/</guid>
		<description><![CDATA[Tym razem krótki wpis wraz z aplikacją przedstawiającą zaimplementowany SceneGraph. Różnica między tą a poprzednią wersją jest taka, że do obracającego modelu Tiny (postać) został podpięty model LandShark (statek) dzięki czemu zaczął on latać nad planszą zgodnie z obrotem Tiny. Dodatkowo pod ten ostatni można podpiąć kamerę, którą nie traci swobodnego ruchu, co pozwala poruszać [...]]]></description>
			<content:encoded><![CDATA[<p>Tym razem krótki wpis wraz z aplikacją przedstawiającą zaimplementowany SceneGraph. Różnica między tą a poprzednią wersją jest taka, że do obracającego modelu Tiny (postać) został podpięty model LandShark (statek) dzięki czemu zaczął on latać nad planszą zgodnie z obrotem Tiny. Dodatkowo pod ten ostatni można podpiąć kamerę, którą nie traci swobodnego ruchu, co pozwala poruszać się po nowym lokalnym układzie współrzędnych. Hierarchię modeli można zobaczyć na poniższym obrazku:</p>
<p><a href="http://netrix.org.pl/wp-content/2011/02/SceneGraphTree.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 5px auto; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top: 0px; border-right: 0px; padding-top: 0px" title="SceneGraphTree" border="0" alt="SceneGraphTree" src="http://netrix.org.pl/wp-content/2011/02/SceneGraphTree_thumb.png" width="412" height="265" /></a></p>
<p>Odnośnie sterowania odsyłam do ReadMe. Aplikację można pobrać <a href="http://netrix.org.pl/content/blog/NIne3_12_02_2011.7z">stąd</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://netrix.org.pl/index.php/2011/02/12/nine-3-scenegraph-paczka/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Data-Oriented-Design &#8211; SceneGraph proof of concept</title>
		<link>http://netrix.org.pl/index.php/2011/02/08/data-oriented-design-scenegraph-proof-of-concept/</link>
		<comments>http://netrix.org.pl/index.php/2011/02/08/data-oriented-design-scenegraph-proof-of-concept/#comments</comments>
		<pubDate>Tue, 08 Feb 2011 02:10:02 +0000</pubDate>
		<dc:creator>Netrix</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[DirectX]]></category>
		<category><![CDATA[DOD]]></category>
		<category><![CDATA[NIne]]></category>
		<category><![CDATA[OOP]]></category>
		<category><![CDATA[Optymalizacje]]></category>
		<category><![CDATA[SceneGraph]]></category>

		<guid isPermaLink="false">http://netrix.org.pl/?p=743</guid>
		<description><![CDATA[Jakiś czas temu postanowiłem do swojego silnika dołączyć SceneGraph, którego zadaniem byłaby hierarchizacja modeli (w relacji rodzic-dzieci) występujących na scenie oraz aktualizacja ich macierzy świata. Generalnie taki graf zawiera nieco więcej informacji, takich jak na przykład bryły otaczające wraz z drzewem ósemkowym, na podstawie których można odrzucić modele niebędące w zasięgu kamery, jeszcze przed renderowaniem [...]]]></description>
			<content:encoded><![CDATA[<p>Jakiś czas temu postanowiłem do swojego silnika dołączyć SceneGraph, którego zadaniem byłaby hierarchizacja modeli (w relacji rodzic-dzieci) występujących na scenie oraz aktualizacja ich macierzy świata. Generalnie taki graf zawiera nieco więcej informacji, takich jak na przykład bryły otaczające wraz z drzewem ósemkowym, na podstawie których można odrzucić modele niebędące w zasięgu kamery, jeszcze przed renderowaniem całej sceny. Jednak aktualnie zależało mi na zaimplementowaniu samej podstawy, czyli macierzy świata, ale w sposób zorientowany na dane, jak ma to miejsce w prezentacji <em><a href="http://research.scee.net/files/presentations/gcapaustralia09/Pitfalls_of_Object_Oriented_Programming_GCAP_09.pdf">Pitfalls of Object-Oriented Programming</a></em>. </p>
<p>Hierarchizacja sceny polega na zebraniu wszystkich elementów sceny i połączeniu ich w drzewo, które składa się z korzenia oraz węzłów potomnych. W takim drzewie każdy rodzic oddziałuje bezpośrednio na swoje dziecko, czyli w tym przypadku transformacja, którą przechowuje rodzic ma wpływ na transformację przechowywaną przez dziecko, dla D3DX wygląda to tak:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">D3DXMatrixMultiply<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>childWorldMatrix, <span style="color: #000040;">&amp;</span>childLocalMatrix, <span style="color: #000040;">&amp;</span>parentWorldMatrix<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></div></div>

<p>
Istnieje kilka sposobów na powiązanie węzłów SceneGraph z elementami sceny. Najprostszym z nich jest struktura SGNode, której instancję można umieścić w klasie reprezentującej jakiś element sceny. Taka struktura wygląda następująco:
</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">struct</span> SGNode
<span style="color: #008000;">&#123;</span>
   SGNode<span style="color: #000040;">*</span> pSibling, pChild<span style="color: #008080;">;</span>
   D3DXMATRIX localMatrix, worldMatrix<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Ponieważ sceny zwykle nie są statyczne, każdy taki węzeł powinien być aktualizowany co klatkę. Do tego celu powinna służyć odpowiednia funkcja klasy zarządzającej drzewem, której zadaniem będzie przejście rekursywnie po całym drzewie i zaktualizowanie danych. Oto przykład takiej funkcji:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> updateNodes<span style="color: #008000;">&#40;</span>SGNode<span style="color: #000040;">*</span> pRoot<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
   SGNode<span style="color: #000040;">*</span> pNode <span style="color: #000080;">=</span> pRoot<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>pChild<span style="color: #008080;">;</span>
&nbsp;
   <span style="color: #0000ff;">while</span><span style="color: #008000;">&#40;</span>pNode <span style="color: #000040;">!</span><span style="color: #000080;">=</span> null<span style="color: #008000;">&#41;</span>
   <span style="color: #008000;">&#123;</span>
      D3DXMatrixMultiply<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>pNode<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>worldMatrix, <span style="color: #000040;">&amp;</span>pNode<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>localMatrix, <span style="color: #000040;">&amp;</span>pRoot<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>worldMatrix<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
      updateNodes<span style="color: #008000;">&#40;</span>pNode<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
      pNode<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>pSibling<span style="color: #008080;">;</span>
   <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #666666;">// Wywołanie na korzeniu</span>
updateNodes<span style="color: #008000;">&#40;</span>m_pRoot<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Ten prosty przykład wystarczy by zauważyć problem, który został poruszony w wymienionej prezentacji. Chodzi przede wszystkim o skakanie po pamięci wskaźnikami, które są dość obficie używane w takiej implementacji. Powoduje to cache-missy, zwłaszcza w przypadku, gdy każdy węzeł jest alokowany osobno.</p>
<p>Rozwiązaniem tego, jak można się domyślić, jest umieszczenie tych danych w sposób liniowy, tak jak ma to miejsce w wymienionej prezentacji. Ważne jest również, aby dane były rozdzielone i uszeregowane w kolejności ich późniejszej aktualizacji.</p>
<p>W swoim silniku rozwiązałem to wykorzystując uchwyty, a węzły traktując jak każdy inny zasób, który można tworzyć i niszczyć. Wszystko to znajduje się w jednej klasie, która wygląda następująco:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> NSceneGraph
<span style="color: #008000;">&#123;</span>
   <span style="color: #0000ff;">struct</span> NSceneGraphNode
   <span style="color: #008000;">&#123;</span>
      NSize_t   uChild,
            uSibling<span style="color: #008080;">;</span>
      NSize_t uIndex<span style="color: #008080;">;</span>            <span style="color: #666666;">// Indeks do tablic danych</span>
      NSize_t uNext<span style="color: #008080;">;</span>             <span style="color: #666666;">// Indeks następnego węzła</span>
   <span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
   NRESULT InitSceneGraph<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   <span style="color: #0000ff;">void</span> Release<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   NRESULT CreateNode<span style="color: #008000;">&#40;</span>NHSceneGraphNode<span style="color: #000040;">&amp;</span> hNode<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   <span style="color: #0000ff;">void</span> ReleaseNode<span style="color: #008000;">&#40;</span>NHSceneGraphNode hNode<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   <span style="color: #0000ff;">void</span> ChangeParent<span style="color: #008000;">&#40;</span>NHSceneGraphNode hNode<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   <span style="color: #0000ff;">void</span> ChangeParent<span style="color: #008000;">&#40;</span>NHSceneGraphNode hNode, NHSceneGraphNode hParent<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   NMMatrixPP GetLocalMatrix<span style="color: #008000;">&#40;</span>NHSceneGraphNode hNode<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   <span style="color: #0000ff;">void</span> SetLocalMatrix<span style="color: #008000;">&#40;</span>NHSceneGraphNode hNode, NMMatrixPP matrix<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   NMMatrixPP GetWorldMatrix<span style="color: #008000;">&#40;</span>NHSceneGraphNode hNode<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   <span style="color: #0000ff;">const</span> NMMatrix<span style="color: #000040;">*</span> GetWorldMatrixPtr<span style="color: #008000;">&#40;</span>NHSceneGraphNode hNode<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   <span style="color: #666666;">// Funkcja aktualizuje macierze world i inne dane</span>
   <span style="color: #0000ff;">void</span> Update<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   <span style="color: #666666;">// Funkcja porządkuje drzewo tak, by przechodzenie wszerz było liniowe i cache-friendly</span>
   NRESULT ApplyChanges<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
   NRESULT ResizeArrays<span style="color: #008000;">&#40;</span>NSize_t uSize<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   <span style="color: #0000ff;">void</span> AddSubtree<span style="color: #008000;">&#40;</span>NSize_t uNode, NSize_t uNewParent<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   <span style="color: #0000ff;">void</span> RemoveSubtree<span style="color: #008000;">&#40;</span>NSize_t uNode<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   <span style="color: #0000ff;">void</span> SetChildIndex<span style="color: #008000;">&#40;</span>NSize_t uNode, NSize_t uChild<span style="color: #008000;">&#41;</span>
   <span style="color: #008000;">&#123;</span>
      m_aSceneNodes<span style="color: #008000;">&#91;</span>uNode<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">uChild</span> <span style="color: #000080;">=</span> uChild<span style="color: #008080;">;</span>
   <span style="color: #008000;">&#125;</span>
&nbsp;
   NSize_t GetChildIndex<span style="color: #008000;">&#40;</span>NSize_t uNode<span style="color: #008000;">&#41;</span>
   <span style="color: #008000;">&#123;</span>
      <span style="color: #0000ff;">return</span> m_aSceneNodes<span style="color: #008000;">&#91;</span>uNode<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">uChild</span><span style="color: #008080;">;</span>
   <span style="color: #008000;">&#125;</span>
&nbsp;
   <span style="color: #0000ff;">void</span> SetSiblingIndex<span style="color: #008000;">&#40;</span>NSize_t uNode, NSize_t uSibling<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   NSize_t GetSiblingIndex<span style="color: #008000;">&#40;</span>NSize_t uNode<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   <span style="color: #0000ff;">void</span> SetDataIndex<span style="color: #008000;">&#40;</span>NSize_t uNode, NUint32 uIndex<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   NSize_t GetDataIndex<span style="color: #008000;">&#40;</span>NSize_t uNode<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   <span style="color: #0000ff;">void</span> SetNextIndex<span style="color: #008000;">&#40;</span>NSize_t uNode, NSize_t uNext<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   NSize_t GetNextIndex<span style="color: #008000;">&#40;</span>NSize_t uNode<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   <span style="color: #0000ff;">bool</span> RemoveSubtree<span style="color: #008000;">&#40;</span>NSize_t uRoot, NSize_t uNode<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
   NStableDataVector<span style="color: #000080;">&lt;</span>NSceneGraphNode<span style="color: #000080;">&gt;</span> m_aSceneNodes<span style="color: #008080;">;</span>
&nbsp;
   <span style="color: #0000ff;">bool</span> m_bDirty<span style="color: #008080;">;</span>
   NSize_t m_uArraysSize<span style="color: #008080;">;</span>
   NAlignedDynamicTable<span style="color: #000080;">&lt;</span>NMMatrix<span style="color: #000080;">&gt;</span> m_aLocalMatrices<span style="color: #008080;">;</span>
   NAlignedDynamicTable<span style="color: #000080;">&lt;</span>NMMatrix<span style="color: #000080;">&gt;</span> m_aWorldMatrices<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>
Teraz przydałoby się wyjaśnienie co do tego kodu. Po pierwsze nie ma tutaj wskaźników, ponieważ jednym z założeń silnika jest wykorzystywanie większych obszarów pamięci zamiast pojedynczych alokacji. Z tego wynika założenie o uchwytach, co implikuje wykorzystanie w przedstawionym kodzie indeksów. <em>NStableDataVector</em> reprezentuje kontener, którego kluczowym założeniem jest niezmienność pozycji przechowywanych danych, dzięki czemu uchwyty pozostają ważne przez cały czas działania aplikacji. <em>NAlignedDynamicTable</em> jest natomiast klasą, która odpowiada za tworzenie i obsługę tablicy przechowującej różne dane (w tym przypadku macierze), które wymagają wyrównanego adresu.
</p>
<p>
Wracając jednak do samego drzewa sceny &#8211; ponieważ jego głównym założeniem jest implementacja rozwiązań z wymienionej prezentacji, dane zostały podzielone na  kilka odpowiednich tablic, a indeksy do tych tablic zostały dodane do węzła. Wszystkie nowo utworzone węzły są potomkami węzła głównego, a zmiana rodzica jest transakcją, która usuwa podany węzeł i od razu dodaje go jako dziecko nowego rodzica (funkcja <em>ChangeParent()</em>).
</p>
<p>
Kluczową funkcją tej klasy jest <em>ApplyChanges()</em>, jej zadaniem ułożenie danych w taki sposób, aby zredukować liczbę cache-missów do minimum, wygląda ona tak:
</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">NRESULT NSceneGraph<span style="color: #008080;">::</span><span style="color: #007788;">ApplyChanges</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
   NAssert<span style="color: #008000;">&#40;</span>m_bDirty <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000ff;">false</span>, <span style="color: #FF0000;">&quot;Needless call of this function&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   NRESULT result<span style="color: #008080;">;</span>
   <span style="color: #666666;">// Temp arrays</span>
   NDataQueue<span style="color: #000080;">&lt;</span>NSize_t<span style="color: #000080;">&gt;</span> tempQueue<span style="color: #008080;">;</span>
   NAlignedDynamicTable<span style="color: #000080;">&lt;</span>NMMatrix<span style="color: #000080;">&gt;</span> tempLocalMatrices<span style="color: #008080;">;</span>
   NAlignedDynamicTable<span style="color: #000080;">&lt;</span>NMMatrix<span style="color: #000080;">&gt;</span> tempWorldMatrices<span style="color: #008080;">;</span>
&nbsp;
   <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>NFAILED<span style="color: #008000;">&#40;</span>result <span style="color: #000080;">=</span> tempLocalMatrices.<span style="color: #007788;">Create</span><span style="color: #008000;">&#40;</span>m_aLocalMatrices.<span style="color: #007788;">GetSize</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, MATRIX_ALIGNMENT<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
   <span style="color: #000040;">||</span> NFAILED<span style="color: #008000;">&#40;</span>result <span style="color: #000080;">=</span> tempWorldMatrices.<span style="color: #007788;">Create</span><span style="color: #008000;">&#40;</span>m_aWorldMatrices.<span style="color: #007788;">GetSize</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, MATRIX_ALIGNMENT<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
   <span style="color: #000040;">||</span> NFAILED<span style="color: #008000;">&#40;</span>result <span style="color: #000080;">=</span> tempQueue.<span style="color: #007788;">Create</span><span style="color: #008000;">&#40;</span>m_uArraysSize <span style="color: #000040;">/</span> <span style="color: #0000dd;">2</span>, <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
   <span style="color: #008000;">&#123;</span>
      tempLocalMatrices.<span style="color: #007788;">Release</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
      tempWorldMatrices.<span style="color: #007788;">Release</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
      tempQueue.<span style="color: #007788;">Release</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
      <span style="color: #0000ff;">return</span> result<span style="color: #008080;">;</span>
   <span style="color: #008000;">&#125;</span>
&nbsp;
   tempLocalMatrices<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> m_aLocalMatrices<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
   tempWorldMatrices<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> m_aWorldMatrices<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
&nbsp;
   <span style="color: #666666;">// Główny algorytm</span>
   NSize_t uRootNode <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
   tempQueue.<span style="color: #007788;">PushElement</span><span style="color: #008000;">&#40;</span>GetChildIndex<span style="color: #008000;">&#40;</span>uRootNode<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   SetNextIndex<span style="color: #008000;">&#40;</span>uRootNode, GetChildIndex<span style="color: #008000;">&#40;</span>uRootNode<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   NSize_t uNext <span style="color: #000080;">=</span> uRootNode<span style="color: #008080;">;</span>
   <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span>NUint32 i <span style="color: #000080;">=</span> <span style="color: #0000dd;">1</span><span style="color: #008080;">;</span> <span style="color: #000040;">!</span>tempQueue.<span style="color: #007788;">IsEmpty</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#41;</span>
   <span style="color: #008000;">&#123;</span>
      NSize_t uNode <span style="color: #000080;">=</span> <span style="color: #000040;">*</span>tempQueue.<span style="color: #007788;">GetFront</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
      tempQueue.<span style="color: #007788;">PopElement</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
      <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span><span style="color: #008080;">;</span> uNode <span style="color: #000040;">!</span><span style="color: #000080;">=</span> NMAX_SIZE_T<span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span>
      <span style="color: #008000;">&#123;</span>
         SetNextIndex<span style="color: #008000;">&#40;</span>uNext, uNode<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
         tempLocalMatrices<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> m_aLocalMatrices<span style="color: #008000;">&#91;</span>GetDataIndex<span style="color: #008000;">&#40;</span>uNode<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
         tempWorldMatrices<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> m_aWorldMatrices<span style="color: #008000;">&#91;</span>GetDataIndex<span style="color: #008000;">&#40;</span>uNode<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
         SetDataIndex<span style="color: #008000;">&#40;</span>uNode, i<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
         <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>GetChildIndex<span style="color: #008000;">&#40;</span>uNode<span style="color: #008000;">&#41;</span> <span style="color: #000040;">!</span><span style="color: #000080;">=</span> NMAX_SIZE_T<span style="color: #008000;">&#41;</span>
         <span style="color: #008000;">&#123;</span>
            tempQueue.<span style="color: #007788;">PushElement</span><span style="color: #008000;">&#40;</span>GetChildIndex<span style="color: #008000;">&#40;</span>uNode<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
         <span style="color: #008000;">&#125;</span>
&nbsp;
         uNext <span style="color: #000080;">=</span> GetNextIndex<span style="color: #008000;">&#40;</span>uNext<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
         uNode <span style="color: #000080;">=</span> GetSiblingIndex<span style="color: #008000;">&#40;</span>uNode<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
      <span style="color: #008000;">&#125;</span>
   <span style="color: #008000;">&#125;</span>
   SetNextIndex<span style="color: #008000;">&#40;</span>uNext, NMAX_SIZE_T<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   m_aLocalMatrices.<span style="color: #007788;">Release</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
   m_aWorldMatrices.<span style="color: #007788;">Release</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
   tempQueue.<span style="color: #007788;">Release</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   m_aLocalMatrices <span style="color: #000080;">=</span> tempLocalMatrices<span style="color: #008080;">;</span>
   m_aWorldMatrices <span style="color: #000080;">=</span> tempWorldMatrices<span style="color: #008080;">;</span>
   m_bDirty <span style="color: #000080;">=</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
&nbsp;
   Update<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   <span style="color: #0000ff;">return</span> NRV_SUCCESS<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>
Powyższa funkcja została wyrwana prosto z pliku źródłowego. Jak widać przechodzi ona całe drzewo wszerz porządkując dane (macierze) oraz aktualizując indeks danych i następnego węzła. Najważniejszym faktem dotyczącym tej funkcji jest to, że powinna być wywołana po wszystkich czynnościach związanych z dodawaniem, usuwaniem lub przenoszeniem węzłów. Dane uporządkowane można później wielokrotnie uaktualniać za pomocą funkcji <em>Update()</em>, która nie będzie posiadać narzutu związanego ze skakaniem po danych (pozostaje tylko skakanie po węzłach, które same w sobie nie są duże).
</p>
<p>
Funkcja ta wygląda w tym przypadku tak:
</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> NSceneGraph<span style="color: #008080;">::</span><span style="color: #007788;">Update</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
   NAssert<span style="color: #008000;">&#40;</span>m_bDirty <span style="color: #000080;">==</span> <span style="color: #0000ff;">false</span>, <span style="color: #FF0000;">&quot;Call this function before running updates&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
   NSize_t uParentNode <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
&nbsp;
   <span style="color: #0000ff;">while</span><span style="color: #008000;">&#40;</span>uParentNode <span style="color: #000040;">!</span><span style="color: #000080;">=</span> NMAX_SIZE_T<span style="color: #008000;">&#41;</span>
   <span style="color: #008000;">&#123;</span>
      NSize_t uNode <span style="color: #000080;">=</span> GetChildIndex<span style="color: #008000;">&#40;</span>uParentNode<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
      <span style="color: #0000ff;">while</span><span style="color: #008000;">&#40;</span>uNode <span style="color: #000040;">!</span><span style="color: #000080;">=</span> NMAX_SIZE_T<span style="color: #008000;">&#41;</span>
      <span style="color: #008000;">&#123;</span>
         NSize_t uDataIndex <span style="color: #000080;">=</span> GetDataIndex<span style="color: #008000;">&#40;</span>uNode<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
         <span style="color: #666666;">// Macierze globalne</span>
         m_aWorldMatrices<span style="color: #008000;">&#91;</span>uDataIndex<span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> NMMatrixMul<span style="color: #008000;">&#40;</span>m_aLocalMatrices<span style="color: #008000;">&#91;</span>GetDataIndex<span style="color: #008000;">&#40;</span>uNode<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#93;</span>, m_aWorldMatrices<span style="color: #008000;">&#91;</span>GetDataIndex<span style="color: #008000;">&#40;</span>uParentNode<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
         uNode <span style="color: #000080;">=</span> GetSiblingIndex<span style="color: #008000;">&#40;</span>uNode<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
      <span style="color: #008000;">&#125;</span>
&nbsp;
      uParentNode <span style="color: #000080;">=</span> GetNextIndex<span style="color: #008000;">&#40;</span>uParentNode<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
   <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>
Cały algorytm przechodzenia po tym drzewie polega na aktualizacji każdego dziecka dla bieżącego rodzica. Dzięki informacji o następnym węźle przechodzenie po drzewie odbywa się poziom po poziomie.
</p>
<p>
Jak widać cały problem podejścia zorientowanego na dane udało się umieścić w jednej klasie, co więcej funkcja porządkująca dane nie wymaga częstego wywoływania, ponieważ najprawdopodobniej będzie to miało miejsce w przypadku ładowania/usuwania sceny. Narzut związany z korzystaniem z uchwytów i indeksacją również można zredukować przed dodanie funkcji zwracających wskaźnik na żądane dane, które po każdym wywołaniu <em>ApplyChanges()</em> należy zaktualizować.</p>
]]></content:encoded>
			<wfw:commentRss>http://netrix.org.pl/index.php/2011/02/08/data-oriented-design-scenegraph-proof-of-concept/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>SerialPort i nasłuchiwanie w C#</title>
		<link>http://netrix.org.pl/index.php/2011/01/31/serialport-i-nasluchiwanie-w-c/</link>
		<comments>http://netrix.org.pl/index.php/2011/01/31/serialport-i-nasluchiwanie-w-c/#comments</comments>
		<pubDate>Mon, 31 Jan 2011 22:43:00 +0000</pubDate>
		<dc:creator>Netrix</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[.NET Framework]]></category>
		<category><![CDATA[Threads]]></category>
		<category><![CDATA[Windows Forms]]></category>

		<guid isPermaLink="false">http://netrix.org.pl/?p=705</guid>
		<description><![CDATA[W poprzedniej notce zaprezentowałem prosty emulator Modbus, który niedawno napisałem. W tej notce postaram się napisać w jaki sposób zaimplementowałem obsługę portu szeregowego COM oraz nasłuchiwanie nieblokujące aplikację. Zaczynając od początku, SerialPort jest klasą z .NET Framework, która umożliwia obsługę portów szeregowych. Na początek przykład, w jaki sposób pobrać listę dostępnych w komputerze portów: string&#91;&#93; [...]]]></description>
			<content:encoded><![CDATA[<p>W poprzedniej notce zaprezentowałem prosty emulator Modbus, który niedawno napisałem. W tej notce postaram się napisać w jaki sposób zaimplementowałem obsługę portu szeregowego COM oraz nasłuchiwanie nieblokujące aplikację.</p>
<p>Zaczynając od początku, <a href="http://msdn.microsoft.com/en-us/library/system.io.ports.serialport%28v=VS.80%29.aspx">SerialPort</a> jest klasą z .NET Framework, która umożliwia obsługę portów szeregowych. Na początek przykład, w jaki sposób pobrać listę dostępnych w komputerze portów:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #6666cc; font-weight: bold;">string</span><span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span> ports <span style="color: #008000;">=</span> SerialPort<span style="color: #008000;">.</span><span style="color: #0000FF;">GetPortNames</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span></pre></div></div>

<p>I tyle, tablica stringów zawiera nazwy dostępnych portów. Ważniejszym krokiem jest ustanowienie połączenia (tu przykładowe dane):</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">SerialPort sp <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> SerialPort<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
sp<span style="color: #008000;">.</span><span style="color: #0000FF;">ReadTimeout</span> <span style="color: #008000;">=</span> <span style="color: #FF0000;">1000</span><span style="color: #008000;">;</span>
sp<span style="color: #008000;">.</span><span style="color: #0000FF;">WriteTimeout</span> <span style="color: #008000;">=</span> <span style="color: #FF0000;">1000</span><span style="color: #008000;">;</span>
sp<span style="color: #008000;">.</span><span style="color: #0000FF;">PortName</span> <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;COM1&quot;</span>	<span style="color: #008080; font-style: italic;">// Jeden z wylistowanych portów</span>
sp<span style="color: #008000;">.</span><span style="color: #0000FF;">BaudRate</span> <span style="color: #008000;">=</span> <span style="color: #FF0000;">115200</span><span style="color: #008000;">;</span>
sp<span style="color: #008000;">.</span><span style="color: #0000FF;">DataBits</span> <span style="color: #008000;">=</span> <span style="color: #FF0000;">8</span>
sp<span style="color: #008000;">.</span><span style="color: #0000FF;">Parity</span> <span style="color: #008000;">=</span> Parity<span style="color: #008000;">.</span><span style="color: #0000FF;">None</span><span style="color: #008000;">;</span>
sp<span style="color: #008000;">.</span><span style="color: #0000FF;">StopBits</span> <span style="color: #008000;">=</span> StopBits<span style="color: #008000;">.</span><span style="color: #0000FF;">One</span>
sp<span style="color: #008000;">.</span><span style="color: #0000FF;">Encoding</span> <span style="color: #008000;">=</span> Encoding<span style="color: #008000;">.</span><span style="color: #0000FF;">BigEndianUnicode</span><span style="color: #008000;">;</span>
&nbsp;
<span style="color: #0600FF; font-weight: bold;">try</span>
<span style="color: #008000;">&#123;</span>
    sp<span style="color: #008000;">.</span><span style="color: #0000FF;">Open</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0600FF; font-weight: bold;">catch</span> <span style="color: #008000;">&#40;</span>Exception err<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #008080; font-style: italic;">/* ... */</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>Skoro port został otwarty można już coś do niego wysłać:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #6666cc; font-weight: bold;">byte</span><span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span> data <span style="color: #008000;">=</span> <span style="color: #008080; font-style: italic;">/* jakieś dane */</span>
sp<span style="color: #008000;">.</span><span style="color: #0000FF;">Write</span><span style="color: #008000;">&#40;</span>data, <span style="color: #FF0000;">0</span>, data<span style="color: #008000;">.</span><span style="color: #0000FF;">Length</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span></pre></div></div>

<p>Odbieranie danych wygląda analogicznie:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #6666cc; font-weight: bold;">byte</span><span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span> data <span style="color: #008000;">=</span> <span style="color: #0600FF; font-weight: bold;">null</span><span style="color: #008000;">;</span>
<span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span>sp<span style="color: #008000;">.</span><span style="color: #0000FF;">BytesToRead</span> <span style="color: #008000;">&gt;</span> <span style="color: #FF0000;">0</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    data <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> <span style="color: #6666cc; font-weight: bold;">byte</span><span style="color: #008000;">&#91;</span>sp<span style="color: #008000;">.</span><span style="color: #0000FF;">BytesToRead</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">;</span>
    sp<span style="color: #008000;">.</span><span style="color: #0000FF;">Read</span><span style="color: #008000;">&#40;</span>data, <span style="color: #FF0000;">0</span>, data<span style="color: #008000;">.</span><span style="color: #0000FF;">Length</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>Troszkę większym problemem jest sprawienie, by aplikacja oczekiwała na nowe dane, a w razie czego je obsłużyła, nie powodując jednocześnie zastoju. Do tego celu należy użyć wątków, a dokładniej jednego, w którym należy wywołać taką funkcję:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF; font-weight: bold;">private</span> boolean bReceiving <span style="color: #008000;">=</span> <span style="color: #0600FF; font-weight: bold;">false</span><span style="color: #008000;">;</span>
&nbsp;
<span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">void</span> Receive<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #6666cc; font-weight: bold;">byte</span><span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span> data<span style="color: #008000;">;</span>
    <span style="color: #0600FF; font-weight: bold;">while</span> <span style="color: #008000;">&#40;</span>bReceiving<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span>sp<span style="color: #008000;">.</span><span style="color: #0000FF;">BytesToRead</span> <span style="color: #008000;">&gt;</span> <span style="color: #FF0000;">0</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            data <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> <span style="color: #6666cc; font-weight: bold;">byte</span><span style="color: #008000;">&#91;</span>sp<span style="color: #008000;">.</span><span style="color: #0000FF;">BytesToRead</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">;</span>
            sp<span style="color: #008000;">.</span><span style="color: #0000FF;">Read</span><span style="color: #008000;">&#40;</span>data, <span style="color: #FF0000;">0</span>, data<span style="color: #008000;">.</span><span style="color: #0000FF;">Length</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
            receiveHandler<span style="color: #008000;">.</span><span style="color: #0000FF;">DataReceivedEvent</span><span style="color: #008000;">&#40;</span>data<span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        Thread<span style="color: #008000;">.</span><span style="color: #0000FF;">Sleep</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">50</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span> <span style="color: #008080; font-style: italic;">// Żeby nie zużywać niepotrzebnie zasobów</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>Funkcja ta, jak widać zawiera pętle, która sprawdza czy istnieją dane do odczytu, jeśli tak to je odczytuje i przekazuje dalej do metody, która z nich skorzysta. Kod wywołania wątku oraz interfejs receiveHandler jest następujący:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #6666cc; font-weight: bold;">interface</span> IDataReceiveListener
<span style="color: #008000;">&#123;</span>
    <span style="color: #6666cc; font-weight: bold;">void</span> DataReceivedEvent<span style="color: #008000;">&#40;</span><span style="color: #6666cc; font-weight: bold;">byte</span><span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span> data<span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
Thread transmissionThread <span style="color: #008000;">=</span> <span style="color: #0600FF; font-weight: bold;">null</span><span style="color: #008000;">;</span>
&nbsp;
<span style="color: #6666cc; font-weight: bold;">void</span> Run<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    bReceiving <span style="color: #008000;">=</span> <span style="color: #0600FF; font-weight: bold;">true</span><span style="color: #008000;">;</span>
    transmissionThread <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> Thread<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">=&gt;</span> <span style="color: #008000;">&#123;</span> Receive<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span> <span style="color: #008000;">&#125;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
    transmissionThread<span style="color: #008000;">.</span><span style="color: #0000FF;">Start</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>Teraz najważniejsze, ponieważ korzystam w tym kodzie z dwóch wątków (głównego + dodatkowego), w tym miejscu należy zwrócić szczególną uwagę na dostęp do danych prze oba wątki. W mojej aplikacji założyłem, że drugi wątek obsługuje obiekt SerialPort (mimo że tworzę go w pierwszym wątku), zatem dostęp do tego obiektu z wątku głównego (tutaj w przypadku wysyłania) musi być opatrzony sekcją krytyczną:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">Thread<span style="color: #008000;">.</span><span style="color: #0000FF;">BeginCriticalRegion</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
sp<span style="color: #008000;">.</span><span style="color: #0000FF;">Write</span><span style="color: #008000;">&#40;</span>data, <span style="color: #FF0000;">0</span>, data<span style="color: #008000;">.</span><span style="color: #0000FF;">Length</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
Thread<span style="color: #008000;">.</span><span style="color: #0000FF;">EndCriticalRegion</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span></pre></div></div>

<p>Natomiast jest jeszcze przypadek gdy wątek drugi odbiera dane i odwołuje się do obiektów z wątku pierwszego. W tym przypadku należy skorzystać funkcji <a href="http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx">Invoke()</a> klasy Form, która przyjmuje obiekt typu delegate, a jego zadaniem jest wywołanie odpowiedniej funkcji z wątku pierwszego. Kod który to robi jest następujący:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF; font-weight: bold;">private</span> <span style="color: #6666cc; font-weight: bold;">delegate</span> <span style="color: #6666cc; font-weight: bold;">void</span> ProcessRequestDelegate<span style="color: #008000;">&#40;</span><span style="color: #6666cc; font-weight: bold;">byte</span><span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span> data<span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
<span style="color: #008080; font-style: italic;">/* funkcja interfejsu IDataReceiveListener */</span>
<span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">void</span> DataReceivedEvent<span style="color: #008000;">&#40;</span><span style="color: #6666cc; font-weight: bold;">byte</span><span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span> data<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Invoke</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">new</span> ProcessRequestDelegate<span style="color: #008000;">&#40;</span><span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">ProcessRequest</span><span style="color: #008000;">&#41;</span>, <span style="color: #008000;">new</span> <span style="color: #6666cc; font-weight: bold;">object</span><span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span> <span style="color: #008000;">&#123;</span> data <span style="color: #008000;">&#125;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0600FF; font-weight: bold;">private</span> <span style="color: #6666cc; font-weight: bold;">void</span> ProcessRequest<span style="color: #008000;">&#40;</span><span style="color: #6666cc; font-weight: bold;">byte</span><span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span> data<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #008080; font-style: italic;">// some stuff</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>I to wszystko na ten temat. Jak widać pisanie aplikacji okienkowych w C# jest banalnie proste.</p>
]]></content:encoded>
			<wfw:commentRss>http://netrix.org.pl/index.php/2011/01/31/serialport-i-nasluchiwanie-w-c/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Modbus Emulator</title>
		<link>http://netrix.org.pl/index.php/2011/01/31/emulator-modbus/</link>
		<comments>http://netrix.org.pl/index.php/2011/01/31/emulator-modbus/#comments</comments>
		<pubDate>Mon, 31 Jan 2011 03:07:36 +0000</pubDate>
		<dc:creator>Netrix</dc:creator>
				<category><![CDATA[Programy]]></category>
		<category><![CDATA[.NET Framework]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Modbus]]></category>
		<category><![CDATA[RS-232]]></category>
		<category><![CDATA[Windows Forms]]></category>
		<category><![CDATA[Źródła]]></category>

		<guid isPermaLink="false">http://netrix.org.pl/index.php/2011/01/31/emulator-modbus/</guid>
		<description><![CDATA[Jednym z ostatnich zadań na laboratorium Informatycznych Systemów Sterowania (i jednocześnie jedynym ciekawym) było zaimplementowanie protokołu Modbus w postaci aplikacji emulujących urządzenia master i slave, komunikujących się ze sobą bezpośrednio korzystając z portów szeregowych COM (RS-232). Zadanie to zrealizowałem minimalistycznie tworząc jedną aplikację, która emuluje oba urządzenia i implementuje 6 pierwszych publicznych funkcji wraz z [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://netrix.org.pl/wp-content/2011/01/modbusEmulator.png" target="_blank"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 5px 5px 6px 10px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top: 0px; border-right: 0px; padding-top: 0px" title="modbusEmulator" border="0" alt="modbusEmulator" align="right" src="http://netrix.org.pl/wp-content/2011/01/modbusEmulator_thumb.png" width="244" height="169" /></a>Jednym z ostatnich zadań na laboratorium Informatycznych Systemów Sterowania (i jednocześnie jedynym ciekawym) było zaimplementowanie protokołu <a href="http://pl.wikipedia.org/wiki/Modbus" target="_blank">Modbus</a> w postaci aplikacji emulujących urządzenia master i slave, komunikujących się ze sobą bezpośrednio korzystając z portów szeregowych COM (RS-232). Zadanie to zrealizowałem minimalistycznie tworząc jedną aplikację, która emuluje oba urządzenia i implementuje 6 pierwszych publicznych funkcji wraz z podglądem rejestrów.</p>
<p>Aplikacja jest napisana w C# i korzysta z Windows Forms oraz klasy SerialPort (która załatwia całą komunikację po porcie COM). Całość implementacji bazuje na specyfikacji Modbusa znajdującej się <a href="www.modbus.org/docs/Modbus_Application_Protocol_V1_1b.pdf" target="_blank">tutaj</a>. Oprócz tego podczas pisania wykorzystywałem również kilka aplikacji:</p>
<ul>
<li><a href="http://www.eterlogic.com/Products.VSPE.html" target="_blank">Virtual Serial Ports Emulator (VSPE)</a> – aplikacja emulująca pary portów COM,</li>
<li><a href="http://www.modbustools.com/modbus_poll.asp" target="_blank">Modbus Poll</a> – aplikacja emulująca urządzenie Master dla protokołu Modbus,</li>
<li><a href="http://www.modbustools.com/modbus_slave.asp" target="_blank">Modbus Slave</a> – aplikacja emulująca urządzenie Slave dla protokołu Modbus.</li>
</ul>
<p>Dwie ostatnie aplikacje posłużyły mi jako referencja implementacji protokołu, ponieważ sama specyfikacja nie zawiera informacji o sposobie liczenia CRC i LRC, więc trzeba było do tego dojść metodą prób, błędów i Google.</p>
<p>Sam program obsługuje (jak już wcześniej wspomniałem) 6 pierwszych, publicznych funkcji protokołu Modbus dla obu urządzeń (Master i Slave) przesyłając dane w trybie ASCII lub RTU. Urządzenie Slave posiada podgląd rejestrów Coils, Discrete Inputs, Input Registers oraz Holding Registers, po 4096 sztuk każdy (wszystkie Read-Only, generowane na podstawie seed = 0). Aplikacja posiada również podgląd wysyłanych i otrzymywanych ramek w postaci logu transmisji.</p>
<p>Program wraz z kodem źródłowym znajdują się <a href="http://netrix.org.pl/content/blog/ModbusEmulator.7z">tutaj</a> (wymaga .NET Framework 2.0) .</p>
]]></content:encoded>
			<wfw:commentRss>http://netrix.org.pl/index.php/2011/01/31/emulator-modbus/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

