<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-9977539741480046</id><updated>2012-01-21T00:57:33.809+11:00</updated><title type='text'>Zach Saw's Blog</title><subtitle type='html'>A software engineer's daily encounters</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>52</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-7060703387297491951</id><published>2011-07-28T19:53:00.001+10:00</published><updated>2011-07-28T19:53:51.686+10:00</updated><title type='text'>StreamReader.Peek can block - Another .NET framework bug</title><content type='html'>There are so many bugs in the .NET framework that existed since the very first version and remains not fixed as of version 4.0 (see some of my other blog posts). Here's another one that I discovered a long time ago but did not have time to write about - &lt;span style="font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;StreamReader.Peek&lt;/span&gt;&lt;/span&gt; can block for &lt;span style="font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Process.StandardOutput&lt;/span&gt;&lt;/span&gt; / &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: small;"&gt;Process.StandardError&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;There's even a &lt;a href="https://connect.microsoft.com/VisualStudio/feedback/details/96484/streamreader-peek-can-block"&gt;Microsoft Connect entry&lt;/a&gt; that has been filed since September 2005! And a several blog/forum posts &lt;a href="http://jrwren.wrenfam.com/blog/2005/08/09/streamreaderpeek-can-block/"&gt;[1: Jay R. Wren]&lt;/a&gt; &lt;a href="http://social.msdn.microsoft.com/Forums/en/vblanguage/thread/5914afc3-0656-48ff-b995-b274bf0e1729"&gt;[2: MSDN]&lt;/a&gt; &lt;a href="http://stackoverflow.com/questions/4557591/alternative-to-streamreader-peek-and-thread-interrupt/"&gt;[3: StackOverflow]&lt;/a&gt; about it. What has Microsoft done about it? &lt;b&gt;&lt;i&gt;Nothing!&lt;/i&gt;&lt;/b&gt; Is it surprising? Not at all - none of the bugs I've blogged about has been fixed so far, critical or not. All they did was whinge about how hard/expensive it is to fix.&lt;br /&gt;&lt;br /&gt;So here it is Microsoft, I've come up with a solution for you (feel free to rip me off).&lt;br /&gt;&lt;br /&gt;Essentially, what Microsoft needs to do is change &lt;code&gt;Process.StartWithCreateProcess&lt;/code&gt; such that &lt;code&gt;standardOutput&lt;/code&gt; and &lt;code&gt;standardError&lt;/code&gt; are both assigned a specialised type of &lt;code&gt;StreamReader&lt;/code&gt; (e.g. &lt;code&gt;PipeStreamReader&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;In this &lt;code&gt;PipeStreamReader&lt;/code&gt;, they need to override both &lt;code&gt;ReadBuffer&lt;/code&gt; overloads (i.e. need to change both overloads to virtual in &lt;code&gt;StreamReader&lt;/code&gt; first) such that prior to a read, &lt;code&gt;PeekNamedPipe&lt;/code&gt; is called to do the actual peek. As it is at the moment, &lt;code&gt;FileStream.Read()&lt;/code&gt; (called by &lt;code&gt;Peek()&lt;/code&gt;) will block on pipe reads when no data is available for read. While a &lt;code&gt;FileStream.Read()&lt;/code&gt;  with 0 bytes works well on files, it doesn't work all that well on  pipes! In fact, the .NET team missed an important part of the pipe  documentation - &lt;a href="http://msdn.microsoft.com/en-us/library/aa365779%28v=vs.85%29.aspx" rel="nofollow"&gt;PeekNamedPipe&lt;/a&gt; WinAPI.&lt;br /&gt;&lt;br /&gt;&lt;blockquote style="background-color: #eeeeee;"&gt;The PeekNamedPipe function is similar to the ReadFile function with the following exceptions:&lt;br /&gt;...&lt;br /&gt;The function always returns immediately in a single-threaded application, &lt;b&gt;&lt;i&gt;even if there is no data in the pipe&lt;/i&gt;&lt;/b&gt;. The wait mode of a named pipe handle (blocking or nonblocking) has no effect on the function.&lt;/blockquote&gt;&lt;br /&gt;There you go. It looks like Microsoft forgot about the &lt;a href="http://msdn.microsoft.com/en-us/library/aa365779%28v=vs.85%29.aspx" rel="nofollow"&gt;PeekNamedPipe&lt;/a&gt; WinAPI that &lt;i&gt;the other &lt;/i&gt;Microsoft team wrote. Wow! That's &lt;i&gt;embarrassing&lt;/i&gt;!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-7060703387297491951?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/7060703387297491951/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=7060703387297491951' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/7060703387297491951'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/7060703387297491951'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2011/07/streamreaderpeek-can-block-another-net.html' title='StreamReader.Peek can block - Another .NET framework bug'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-2226001567862505616</id><published>2011-07-06T22:17:00.002+10:00</published><updated>2011-07-07T23:17:23.186+10:00</updated><title type='text'>Website Moved</title><content type='html'>To all my followers,&lt;br /&gt;&lt;br /&gt;I've moved my website across to &lt;a href="http://www.zachsaw.com/"&gt;www.zachsaw.com&lt;/a&gt; from the .co.cc domain which Google has banned from their index. So please update your bookmarks.&lt;br /&gt;&lt;blockquote&gt;Website: &lt;a href="http://www.zachsaw.com/"&gt;http://www.zachsaw.com &lt;/a&gt;&lt;br /&gt;Forum: &lt;a href="http://forum.zachsaw.com/"&gt;http://forum.zachsaw.com&lt;/a&gt;&lt;br /&gt;Blog: &lt;a href="http://blog.zachsaw.com/"&gt;http://blog.zachsaw.com&lt;/a&gt;&lt;/blockquote&gt;Thanks everyone for your continued support.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-2226001567862505616?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/2226001567862505616/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=2226001567862505616' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/2226001567862505616'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/2226001567862505616'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2011/07/website-moved.html' title='Website Moved'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-4529938009705359045</id><published>2011-02-23T23:03:00.005+11:00</published><updated>2011-07-16T22:40:58.508+10:00</updated><title type='text'>Win7 SP1 OS bug - Do we need Windows 8 now?</title><content type='html'>It's the same &lt;a href="http://zachsaw.blogspot.com/2010/11/wow64-bug-getthreadcontext-may-return.html"&gt;Windows 7 x64 (WOW64) bug I reported&lt;/a&gt; in November last year (2010) - &lt;a href="http://connect.microsoft.com/VisualStudio/feedback/details/621594/getthreadcontext-may-return-stale-contents-from-previous-call-out-to-long-mode"&gt;see the entry in Microsoft Connect&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;And the new Windows 7 Service Pack 1 &lt;i&gt;&lt;b&gt;*HASN'T*&lt;/b&gt;&lt;/i&gt; fixed it! It doesn't only affect Windows 7 though, it goes back all the way to the very first version of x64 Windows - XP 64-bit.&lt;br /&gt;&lt;br /&gt;There's no way to workaround this problem in user code. It is a fundamental design flaw in the very first version of 64-bit Windows. This makes it very hard (expensive) for Microsoft to fix - a proper fix requires a redesign of the whole emulation layer of 32-bit apps on 64-bit Windows. Microsoft charges a minimal sum for their OSes&lt;i&gt; (sarcasm)&lt;/i&gt;, so it's not like they have the resources to work on anything that doesn't affect everyone. It's very likely that Windows 7 will be forever plagued with this bug as it would seem to be easier (cheaper) to start from a clean sheet with Windows 8. Then again, why bother? It's not as if Microsoft has any real competition at all in the x64 OS market - they own more than 80% of the pie!&lt;br /&gt;&lt;br /&gt;From the feedback of my previous post, the problem appears more widespread than Microsoft would want to acknowledge - see &lt;span class="citation web"&gt;&lt;a class="external text" href="http://comments.gmane.org/gmane.comp.programming.garbage-collection.boehmgc/4188" rel="nofollow"&gt;Discussions about the Boehm Garbage Collector (Boehm GC)&lt;/a&gt;&lt;/span&gt;. Hopefully this bug gets fixed sooner rather than later.&lt;br /&gt;&lt;br /&gt;In the meantime, if you want to test it out yourself, you can &lt;a href="http://www.zachsaw.com/downloads/GcTester_trap_12_11_2010.zip"&gt;download this&lt;/a&gt; (extract all and run Tester.exe). Usually running it for a few minutes will get it to crash on x64. Give it 30 minutes if it doesn't. If it doesn't crash (i.e. on 32-bit OS), you'll have to kill the app via task manager after you've tested it though (an unrelated bug in the tester application prevents it from shutting down completely - the app will appear closed but the process remains running).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-4529938009705359045?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/4529938009705359045/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=4529938009705359045' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/4529938009705359045'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/4529938009705359045'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2011/02/win7-sp1-os-bug-do-we-need-windows-8.html' title='Win7 SP1 OS bug - Do we need Windows 8 now?'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-2049601906813556596</id><published>2010-11-24T23:15:00.000+11:00</published><updated>2010-11-24T23:15:28.953+11:00</updated><title type='text'>Fast memcpy for large blocks</title><content type='html'>Memory copy of 8MB blocks can be quite slow.&lt;br /&gt;&lt;br /&gt;I found that both memcpy and CopyMemory won't utilize the full bandwidth of your RAM due to memory controller bottlenecks (I suspect the memory controller isn't smart enough to prefetch the right data). So&lt;a href="http://williamchan.ca/portfolio/assembly/ssememcpy/source/viewsource.php?id=ssememcpy.c"&gt; this implementation by William Chan&lt;/a&gt; issues SSE2 prefetch instructions and gets the memory controller to literally stream the data back and forth from RAM in the fastest manner.&lt;br /&gt;&lt;br /&gt;Note though, that you'll need to give it 16-byte aligned memory and it copies in 128-byte blocks.&lt;br /&gt;&lt;br /&gt;The result is here (on my Core2Duo Wolfdale CPU @ 3.6GHz, dual channel DDR2 @ 800MHz):&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;memcpy/CopyMemory:&lt;br /&gt;1871.775MB/sec&lt;br /&gt;&lt;br /&gt;William Chan's SSE2 memcpy:&lt;br /&gt;3540.471MB/sec&lt;/blockquote&gt;&lt;br /&gt;That's nearly double the speed of the naive memcpy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-2049601906813556596?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/2049601906813556596/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=2049601906813556596' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/2049601906813556596'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/2049601906813556596'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2010/11/fast-memcpy-for-large-blocks.html' title='Fast memcpy for large blocks'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-5900267693336229646</id><published>2010-11-13T21:26:00.005+11:00</published><updated>2010-11-19T23:18:38.990+11:00</updated><title type='text'>Reporting a bug against Windows OS - possible?</title><content type='html'>Is Microsoft so arrogant that they think their OS is bug-free and that no one should ever need to report a bug against their OS?&lt;br /&gt;&lt;br /&gt;There doesn't seem to be a way to report a bug against the Windows OS (no such category in Microsoft Connect). 2 years ago, I tried to report a bug against Vista - &lt;a href="https://connect.microsoft.com/VisualStudio/feedback/details/352843/treeview-indent-in-vista-causes-hittest-to-fail"&gt;TreeView Indent in Vista causes HitTest to fail&lt;/a&gt;. The closest way would be to report it against VisualStudio. Surprise surprise, the VS product team closed it as external and did absolutely &lt;span style="font-weight: bold;"&gt;*nothing*&lt;/span&gt; after that. Sure, they redirected me to a non-existent website, which was supposed to be the MSDN forums, but that was where I was redirected to MS Connect in the first place! Talk about going around in circles... This really reminds me of Telstra (the ex-government owned now privatized biggest telco in Australia).&lt;br /&gt;&lt;br /&gt;With regards to the &lt;a href="https://connect.microsoft.com/VisualStudio/feedback/details/621594/getthreadcontext-may-return-stale-contents-from-previous-call-out-to-long-mode"&gt;bug that I've just reported&lt;/a&gt;, I'd expect them to do the same, and close it as external, not knowing which department they need to talk to. Microsoft is so &lt;span style="font-style: italic; font-weight: bold;"&gt;big, dumb and slow&lt;/span&gt; that its right hand really have no idea what the left hand is doing! &lt;span style="font-style: italic;"&gt;Sad &lt;/span&gt;really... &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;* Edit: Looks like I'm &lt;i&gt;not&lt;/i&gt; the only one complaining:&lt;br /&gt;&lt;blockquote&gt;&lt;a href="http://social.msdn.microsoft.com/forums/en-US/windowsgeneraldevelopmentissues/thread/699cfb6a-d88a-47f5-896d-1d999cb64201"&gt;Reporting a bug in Vista 64 WOW64&lt;/a&gt;&lt;br /&gt;&lt;a href="http://superuser.com/questions/67131/how-do-you-file-a-bug-report-for-windows"&gt;How do you file a bug report for Windows?&lt;/a&gt;&lt;br /&gt;&lt;a href="http://social.msdn.microsoft.com/forums/en-US/winforms/thread/cca8cd09-823b-478b-a1ca-2f6d3c72d74b"&gt;Problems with comdlg32.ocx, Windows Vista and long file names/extension´s&lt;/a&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-5900267693336229646?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/5900267693336229646/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=5900267693336229646' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/5900267693336229646'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/5900267693336229646'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2010/11/reporting-bug-against-windows-os.html' title='Reporting a bug against Windows OS - possible?'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-7241651645001504439</id><published>2010-11-13T17:07:00.004+11:00</published><updated>2011-02-23T23:31:42.206+11:00</updated><title type='text'>WOW64 bug: GetThreadContext() may return stale contents</title><content type='html'>My &lt;a href="http://zachsaw.blogspot.com/2010/01/fastmm-slow-in-multithreaded-apps-on.html"&gt;GC app&lt;/a&gt; runs perfectly fine under native x86 OS's starting from XP.&lt;br /&gt;&lt;br /&gt;I've installed Windows 7 x64 recently (I've always used Win7-x86 due to 64-bit being in its infancy yet for the stuff that I do on my desktop) and to my dismay the app fails after a few minutes of running.&lt;br /&gt;&lt;br /&gt;After hours of debugging (GC is never easy to debug, let alone a hypothesis that involves a bug in WOW64 which has been used by millions since XP-64), I found that WOW64 clobbers the ESP value (as returned by &lt;span style="font-family: courier new;"&gt;GetThreadContext()&lt;/span&gt;, of which the the GC thread in the app relies upon to get the current stack pointer of mutator threads) when it does a call out to &lt;a href="http://en.wikipedia.org/wiki/Long_mode"&gt;long mode&lt;/a&gt;. I also found that ESP is always restored upon returning.&lt;br /&gt;&lt;br /&gt;Prior to calling &lt;span style="font-family: courier new;"&gt;GetThreadContext()&lt;/span&gt;, the GC thread suspends all mutator threads. If it just so happens to suspend the mutator thread while it's running long mode code in user mode, the ESP value gets changed to a value indicating a higher address than the actual stack pointer (remember on IA, stack 'grows' downwards). I've seen this happen for &lt;span style="font-family: courier new;"&gt;SetEvent()&lt;/span&gt; and &lt;span style="font-family: courier new;"&gt;SwitchToThread()&lt;/span&gt; (as these are the most frequently called kernel functions in the app).&lt;br /&gt;&lt;br /&gt;This means that either SuspendThread is suspending a thread in an incompatible way to native x86, or the thread's context in WOW64 is not being protected when the code jumps to &lt;a href="http://www.nynaeve.net/?p=129"&gt;translation mode&lt;/a&gt;. Either way, I was sure it's a bug.&lt;br /&gt;&lt;br /&gt;I then found &lt;a href="http://www.nynaeve.net/?p=131"&gt;this article&lt;/a&gt; (difference between WOW64 and native x86 system DLLs) and while the article isn't exactly addressing the issue I'm facing, I found it very useful because this guy (&lt;a href="http://www.nynaeve.net/?page_id=2"&gt;Skywing&lt;/a&gt; from Microsoft) certainly knows WOW64 very well. I proceeded to email him and he replied with the following:&lt;br /&gt;&lt;blockquote&gt;[...] there’s an issue with get and set context operations against amd64 Wow64 threads returning bad information in circumstances when the thread is running long mode code in user mode.  This relates to us [Microsoft] pulling the Wow64 context from the TLS slot (as described in &lt;a href="http://www.nynaeve.net/?p=191"&gt;the [this] article&lt;/a&gt;) before that context structure has been updated with current contents.&lt;/blockquote&gt;&lt;br /&gt;That sounded very much like the issue here. So, I decided to dig deeper and put a few software traps to try and catch it in the act.&lt;br /&gt;&lt;br /&gt;This is what I found.&lt;br /&gt;&lt;br /&gt;The stale contents from &lt;span style="font-family: courier new;"&gt;GetThreadContext()&lt;/span&gt; actually came from the previous system call out (a &lt;span style="font-style: italic;"&gt;looong &lt;/span&gt;way up the stack really - it's not as if it's a few instructions ago). It should've returned contents from the &lt;span style="font-style: italic;"&gt;*current*&lt;/span&gt; system call out instead (or to be precise, just before the call out to long mode took place). Like Skywing said, they pulled the context before it's updated with the current contents.&lt;br /&gt;&lt;br /&gt;With that said, we can now conclude that it is &lt;span style="font-weight: bold;"&gt;indeed&lt;/span&gt; an OS bug (&lt;a href="http://zachsaw.blogspot.com/2011/02/win7-sp1-os-bug-do-we-need-windows-8.html"&gt;Win7 SP1 hasn't fixed it&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 85%;"&gt;&lt;span style="font-style: italic;"&gt;* I'd like to thank Skywing for his effort in assisting me to root cause this issue.&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-7241651645001504439?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/7241651645001504439/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=7241651645001504439' title='33 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/7241651645001504439'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/7241651645001504439'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2010/11/wow64-bug-getthreadcontext-may-return.html' title='WOW64 bug: GetThreadContext() may return stale contents'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>33</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-5879409647057408721</id><published>2010-10-21T22:48:00.010+11:00</published><updated>2010-11-18T21:51:44.678+11:00</updated><title type='text'>BCC32 the Optimizing Compiler?</title><content type='html'>We all know asking the bcc32 compiler team to do put more effort into making the codegen generate more efficient / optimized asm is a *BIG ASK*, seeing how they haven't even got the basics (compiler bugs that Microsoft VC++ compiler fixed since MSVC 2005) working correctly. VC++ 6 was worse than C++ Builder 6, but since then, Microsoft have worked hard and fixed up their compiler, made it fully optimizing and generate one of the fastest and most efficient code in the world. It is also now one of the most compliant C++ compilers of all.&lt;br /&gt;&lt;br /&gt;Let's compare the following code sample.&lt;br /&gt;&lt;br /&gt;For the uninformed, the following usage pattern is found in a lot of expanded template code (I'm using it a lot in my GC framework and Boost uses it too).&lt;br /&gt;&lt;blockquote&gt;&lt;pre style="background: none repeat scroll 0% 0% rgb(255, 255, 255); color: black;"&gt;&lt;span style="color: #7f0055;"&gt;#&lt;/span&gt;&lt;span style="color: #7f0055;"&gt;include &lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f3fbf;"&gt;tchar.h&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;struct&lt;/span&gt; foo&lt;br /&gt;{&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;    inline&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;operator&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;bool&lt;/span&gt;() &lt;span style="color: #7f0055; font-weight: bold;"&gt;const&lt;/span&gt;&lt;br /&gt;    {&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;        return&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;false&lt;/span&gt;;&lt;br /&gt;    }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt; _tmain(&lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt; argc, _TCHAR* argv[])&lt;br /&gt;{&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;    if&lt;/span&gt; (foo())&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;        return&lt;/span&gt; 0; &lt;span style="color: #3f7f59;"&gt;// *see footnote&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;    return&lt;/span&gt; 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;*footnote: usually this is something more meaningful, but here I'm trying to illustrate how massively unintelligent bcc32&lt;br /&gt;is.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;bcc32 (C++ Builder XE) command line:&lt;/span&gt;&lt;br /&gt;&lt;pre style="background: none repeat scroll 0% 0% rgb(255, 255, 255); color: black;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bcc32 -O2 -Hs- -C8 -v- -vi test8.cpp&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;generated asm:&lt;br /&gt;&lt;pre style="background: none repeat scroll 0% 0% rgb(255, 255, 255); color: black;"&gt;push ebp&lt;br /&gt;mov ebp,esp&lt;br /&gt;add esp,-$08&lt;br /&gt;push edi&lt;br /&gt;lea edi,[ebp-$08]&lt;br /&gt;xor eax,eax&lt;br /&gt;mov ecx,$00000008&lt;br /&gt;rep stosb&lt;br /&gt;lea eax,[ebp-$08]&lt;br /&gt;xor edx,edx&lt;br /&gt;test dl,dl&lt;br /&gt;jz $00401201&lt;br /&gt;xor eax,eax&lt;br /&gt;jmp $00401203&lt;br /&gt;xor eax,eax&lt;br /&gt;pop edi&lt;br /&gt;pop ecx&lt;br /&gt;pop ecx&lt;br /&gt;pop ebp&lt;br /&gt;ret&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;cl command line:&lt;/span&gt;&lt;br /&gt;&lt;pre style="background: none repeat scroll 0% 0% rgb(255, 255, 255); color: black;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cl /Ox /Ot test8.cpp&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;generated asm:&lt;br /&gt;&lt;pre style="background: none repeat scroll 0% 0% rgb(255, 255, 255); color: black;"&gt;xor eax,eax&lt;br /&gt;ret&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;BCC32 generated 18 lines of useless opcodes when really only 2 are required. With BCC32, your code would be a few hundred times slower (taking into account of memory access latencies).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-5879409647057408721?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/5879409647057408721/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=5879409647057408721' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/5879409647057408721'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/5879409647057408721'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2010/10/bcc32-optimizing-compiler.html' title='BCC32 the Optimizing Compiler?'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-23463613886501141</id><published>2010-07-06T12:26:00.016+10:00</published><updated>2010-11-18T22:15:11.100+11:00</updated><title type='text'>SerialPort IOException Workaround in C#</title><content type='html'>As promised, I've whipped up a quick workaround to fix the problem as &lt;a href="http://zachsaw.blogspot.com/2010/07/net-serialport-woes.html"&gt;described here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Here's the code:&lt;br /&gt;&lt;br /&gt;&lt;div style="height: 400px; overflow: scroll; white-space: nowrap; width: 530px;"&gt;&lt;pre style="background: none repeat scroll 0% 0% rgb(255, 255, 255); color: black;"&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;using&lt;/span&gt; System;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;using&lt;/span&gt; System.IO;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;using&lt;/span&gt; System.IO.Ports;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;using&lt;/span&gt; System.Runtime.InteropServices;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;using&lt;/span&gt; System.Text;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;using&lt;/span&gt; Microsoft.Win32.SafeHandles;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;namespace&lt;/span&gt; SerialPortTester&lt;br /&gt;{&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;    public&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;class&lt;/span&gt; SerialPortFixer : IDisposable&lt;br /&gt;    {&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;        public&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;static&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;void&lt;/span&gt; Execute(&lt;span style="color: #7f0055; font-weight: bold;"&gt;string&lt;/span&gt; portName)&lt;br /&gt;        {&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            using&lt;/span&gt; (&lt;span style="color: #7f0055; font-weight: bold;"&gt;new&lt;/span&gt; SerialPortFixer(portName))&lt;br /&gt;            {&lt;br /&gt;            }&lt;br /&gt;        }&lt;/pre&gt;&lt;pre style="background: none repeat scroll 0% 0% rgb(255, 255, 255); color: black;"&gt;&lt;/pre&gt;&lt;pre style="background: none repeat scroll 0% 0% rgb(255, 255, 255); color: black;"&gt;&amp;nbsp;       #region IDisposable Members&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;    &lt;/span&gt;    &lt;span style="color: #7f0055; font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;void&lt;/span&gt; Dispose()&lt;br /&gt;        {&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            if&lt;/span&gt; (m_Handle != &lt;span style="color: #7f0055; font-weight: bold;"&gt;null&lt;/span&gt;)&lt;br /&gt;            {&lt;br /&gt;                m_Handle.Close();&lt;br /&gt;                m_Handle = &lt;span style="color: #7f0055; font-weight: bold;"&gt;null&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;&lt;br /&gt;        #region Implementation&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;        private&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;const&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt; DcbFlagAbortOnError = 14;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;        private&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;const&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt; CommStateRetries = 10;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;        private&lt;/span&gt; SafeFileHandle m_Handle;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;        private&lt;/span&gt; SerialPortFixer(&lt;span style="color: #7f0055; font-weight: bold;"&gt;string&lt;/span&gt; portName)&lt;br /&gt;        {&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            const&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt; dwFlagsAndAttributes = 0x40000000;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            const&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt; dwAccess = &lt;span style="color: #7f0055; font-weight: bold;"&gt;unchecked&lt;/span&gt;((&lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt;) 0xC0000000);&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: none repeat scroll 0% 0% rgb(255, 255, 255); color: black;"&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background: none repeat scroll 0% 0% rgb(255, 255, 255); color: black;"&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            if&lt;/span&gt; ((portName == &lt;span style="color: #7f0055; font-weight: bold;"&gt;null&lt;/span&gt;) || !portName.StartsWith(&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;COM&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;, StringComparison.OrdinalIgnoreCase))&lt;br /&gt;            {&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;                throw&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;new&lt;/span&gt; ArgumentException(&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;Invalid Serial Port&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;, &lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;portName&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;);&lt;br /&gt;            }&lt;br /&gt;            SafeFileHandle hFile = CreateFile(@"\\.\" + portName, dwAccess, 0, IntPtr.Zero, 3, dwFlagsAndAttributes,&lt;br /&gt;                                              IntPtr.Zero);&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            if&lt;/span&gt; (hFile.IsInvalid)&lt;br /&gt;            {&lt;br /&gt;                WinIoError();&lt;br /&gt;            }&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            try&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;                int&lt;/span&gt; fileType = GetFileType(hFile);&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;                if&lt;/span&gt; ((fileType != 2) &amp;amp;&amp;amp; (fileType != 0))&lt;br /&gt;                {&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;                     throw&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;new&lt;/span&gt; ArgumentException(&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;Invalid Serial Port&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;, &lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;portName&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;);&lt;br /&gt;                }&lt;br /&gt;                m_Handle = hFile;&lt;br /&gt;                InitializeDcb();&lt;br /&gt;            }&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            catch&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;                hFile.Close();&lt;br /&gt;                m_Handle = &lt;span style="color: #7f0055; font-weight: bold;"&gt;null&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;                throw&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        [DllImport(&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;kernel32.dll&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;, CharSet = CharSet.Auto, SetLastError = &lt;span style="color: #7f0055; font-weight: bold;"&gt;true&lt;/span&gt;)]&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;        private&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;static&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;extern&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt; FormatMessage(&lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt; dwFlags, HandleRef lpSource, &lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt; dwMessageId, &lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt; dwLanguageId,&lt;br /&gt;                                                StringBuilder lpBuffer, &lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt; nSize, IntPtr arguments);&lt;br /&gt;&lt;br /&gt;        [DllImport(&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;kernel32.dll&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;, CharSet = CharSet.Auto, SetLastError = &lt;span style="color: #7f0055; font-weight: bold;"&gt;true&lt;/span&gt;)]&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;        private&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;static&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;extern&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;bool&lt;/span&gt; GetCommState(SafeFileHandle hFile, &lt;span style="color: #7f0055; font-weight: bold;"&gt;ref&lt;/span&gt; Dcb lpDcb);&lt;br /&gt;&lt;br /&gt;        [DllImport(&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;kernel32.dll&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;, CharSet = CharSet.Auto, SetLastError = &lt;span style="color: #7f0055; font-weight: bold;"&gt;true&lt;/span&gt;)]&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;        private&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;static&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;extern&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;bool&lt;/span&gt; SetCommState(SafeFileHandle hFile, &lt;span style="color: #7f0055; font-weight: bold;"&gt;ref&lt;/span&gt; Dcb lpDcb);&lt;br /&gt;&lt;br /&gt;        [DllImport(&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;kernel32.dll&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;, CharSet = CharSet.Auto, SetLastError = &lt;span style="color: #7f0055; font-weight: bold;"&gt;true&lt;/span&gt;)]&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;        private&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;static&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;extern&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;bool&lt;/span&gt; ClearCommError(SafeFileHandle hFile, &lt;span style="color: #7f0055; font-weight: bold;"&gt;ref&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt; lpErrors, &lt;span style="color: #7f0055; font-weight: bold;"&gt;ref&lt;/span&gt; Comstat lpStat);&lt;br /&gt;&lt;br /&gt;        [DllImport(&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;kernel32.dll&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;, CharSet = CharSet.Auto, SetLastError = &lt;span style="color: #7f0055; font-weight: bold;"&gt;true&lt;/span&gt;)]&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;        private&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;static&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;extern&lt;/span&gt; SafeFileHandle CreateFile(&lt;span style="color: #7f0055; font-weight: bold;"&gt;string&lt;/span&gt; lpFileName, &lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt; dwDesiredAccess, &lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt; dwShareMode,&lt;br /&gt;                                                        IntPtr securityAttrs, &lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt; dwCreationDisposition,&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;                                                        int&lt;/span&gt; dwFlagsAndAttributes, IntPtr hTemplateFile);&lt;br /&gt;&lt;br /&gt;        [DllImport(&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;kernel32.dll&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;, SetLastError = &lt;span style="color: #7f0055; font-weight: bold;"&gt;true&lt;/span&gt;)]&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;        private&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;static&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;extern&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt; GetFileType(SafeFileHandle hFile);&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;        private&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;void&lt;/span&gt; InitializeDcb()&lt;br /&gt;        {&lt;br /&gt;            Dcb dcb = &lt;span style="color: #7f0055; font-weight: bold;"&gt;new&lt;/span&gt; Dcb();&lt;br /&gt;            GetCommStateNative(&lt;span style="color: #7f0055; font-weight: bold;"&gt;ref&lt;/span&gt; dcb);&lt;br /&gt;            dcb.Flags &amp;amp;= ~(1u &amp;lt;&amp;lt; DcbFlagAbortOnError);&lt;br /&gt;            SetCommStateNative(&lt;span style="color: #7f0055; font-weight: bold;"&gt;ref&lt;/span&gt; dcb);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;        private&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;static&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;string&lt;/span&gt; GetMessage(&lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt; errorCode)&lt;br /&gt;        {&lt;br /&gt;            StringBuilder lpBuffer = &lt;span style="color: #7f0055; font-weight: bold;"&gt;new&lt;/span&gt; StringBuilder(0x200);&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            if&lt;/span&gt; (&lt;br /&gt;                FormatMessage(0x3200, &lt;span style="color: #7f0055; font-weight: bold;"&gt;new&lt;/span&gt; HandleRef(&lt;span style="color: #7f0055; font-weight: bold;"&gt;null&lt;/span&gt;, IntPtr.Zero), errorCode, 0, lpBuffer, lpBuffer.Capacity,&lt;br /&gt;                              IntPtr.Zero) != 0)&lt;br /&gt;            {&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;                return&lt;/span&gt; lpBuffer.ToString();&lt;br /&gt;            }&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            return&lt;/span&gt; &lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;Unknown Error&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;        private&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;static&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt; MakeHrFromErrorCode(&lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt; errorCode)&lt;br /&gt;        {&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            return&lt;/span&gt; (&lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt;) (0x80070000 | (&lt;span style="color: #7f0055; font-weight: bold;"&gt;uint&lt;/span&gt;) errorCode);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;        private&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;static&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;void&lt;/span&gt; WinIoError()&lt;br /&gt;        {&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            int&lt;/span&gt; errorCode = Marshal.GetLastWin32Error();&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            throw&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;new&lt;/span&gt; IOException(GetMessage(errorCode), MakeHrFromErrorCode(errorCode));&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;        private&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;void&lt;/span&gt; GetCommStateNative(&lt;span style="color: #7f0055; font-weight: bold;"&gt;ref&lt;/span&gt; Dcb lpDcb)&lt;br /&gt;        {&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            int&lt;/span&gt; commErrors = 0;&lt;br /&gt;            Comstat comStat = &lt;span style="color: #7f0055; font-weight: bold;"&gt;new&lt;/span&gt; Comstat();&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            for&lt;/span&gt; (&lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt; i = 0; i &amp;lt; CommStateRetries; i++)&lt;br /&gt;            {&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;                if&lt;/span&gt; (!ClearCommError(m_Handle, &lt;span style="color: #7f0055; font-weight: bold;"&gt;ref&lt;/span&gt; commErrors, &lt;span style="color: #7f0055; font-weight: bold;"&gt;ref&lt;/span&gt; comStat))&lt;br /&gt;                {&lt;br /&gt;                     WinIoError();&lt;br /&gt;                }&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;                if&lt;/span&gt; (GetCommState(m_Handle, &lt;span style="color: #7f0055; font-weight: bold;"&gt;ref&lt;/span&gt; lpDcb))&lt;br /&gt;                {&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;                     break&lt;/span&gt;;&lt;br /&gt;                }&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;                if&lt;/span&gt; (i == CommStateRetries - 1)&lt;br /&gt;                {&lt;br /&gt;                     WinIoError();&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: none repeat scroll 0% 0% rgb(255, 255, 255); color: black;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: none repeat scroll 0% 0% rgb(255, 255, 255); color: black;"&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;        private&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;void&lt;/span&gt; SetCommStateNative(&lt;span style="color: #7f0055; font-weight: bold;"&gt;ref&lt;/span&gt; Dcb lpDcb)&lt;br /&gt;        {&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            int&lt;/span&gt; commErrors = 0;&lt;br /&gt;            Comstat comStat = &lt;span style="color: #7f0055; font-weight: bold;"&gt;new&lt;/span&gt; Comstat();&amp;nbsp;&lt;/pre&gt;&lt;pre style="background: none repeat scroll 0% 0% rgb(255, 255, 255); color: black;"&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="background: none repeat scroll 0% 0% rgb(255, 255, 255); color: black;"&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            for&lt;/span&gt; (&lt;span style="color: #7f0055; font-weight: bold;"&gt;int&lt;/span&gt; i = 0; i &amp;lt; CommStateRetries; i++)&lt;br /&gt;            {&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;                 if&lt;/span&gt; (!ClearCommError(m_Handle, &lt;span style="color: #7f0055; font-weight: bold;"&gt;ref&lt;/span&gt; commErrors, &lt;span style="color: #7f0055; font-weight: bold;"&gt;ref&lt;/span&gt; comStat))&lt;br /&gt;                 {&lt;br /&gt;                     WinIoError();&lt;br /&gt;                 }&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;                 if&lt;/span&gt; (SetCommState(m_Handle, &lt;span style="color: #7f0055; font-weight: bold;"&gt;ref&lt;/span&gt; lpDcb))&lt;br /&gt;                 {&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;                     break&lt;/span&gt;;&lt;br /&gt;                 }&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;                 if&lt;/span&gt; (i == CommStateRetries - 1)&lt;br /&gt;                 {&lt;br /&gt;                     WinIoError();&lt;br /&gt;                 }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        #region Nested type: COMSTAT&lt;br /&gt;&lt;br /&gt;        [StructLayout(LayoutKind.Sequential)]&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;        private&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;struct&lt;/span&gt; Comstat&lt;br /&gt;        {&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            public&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;readonly&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;uint&lt;/span&gt; Flags;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            public&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;readonly&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;uint&lt;/span&gt; cbInQue;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            public&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;readonly&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;uint&lt;/span&gt; cbOutQue;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;&lt;br /&gt;        #region Nested type: DCB&lt;br /&gt;&lt;br /&gt;        [StructLayout(LayoutKind.Sequential)]&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;        private&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;struct&lt;/span&gt; Dcb&lt;br /&gt;        {&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            public&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;readonly&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;uint&lt;/span&gt; DCBlength;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            public&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;readonly&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;uint&lt;/span&gt; BaudRate;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            public&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;uint&lt;/span&gt; Flags;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            public&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;readonly&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;ushort&lt;/span&gt; wReserved;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            public&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;readonly&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;ushort&lt;/span&gt; XonLim;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            public&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;readonly&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;ushort&lt;/span&gt; XoffLim;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            public&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;readonly&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;byte&lt;/span&gt; ByteSize;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            public&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;readonly&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;byte&lt;/span&gt; Parity;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            public&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;readonly&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;byte&lt;/span&gt; StopBits;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            public&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;readonly&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;byte&lt;/span&gt; XonChar;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            public&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;readonly&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;byte&lt;/span&gt; XoffChar;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            public&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;readonly&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;byte&lt;/span&gt; ErrorChar;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            public&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;readonly&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;byte&lt;/span&gt; EofChar;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            public&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;readonly&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;byte&lt;/span&gt; EvtChar;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            public&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;readonly&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;ushort&lt;/span&gt; wReserved1;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;    internal&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;class&lt;/span&gt; Program&lt;br /&gt;    {&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;        private&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;static&lt;/span&gt; &lt;span style="color: #7f0055; font-weight: bold;"&gt;void&lt;/span&gt; Main(&lt;span style="color: #7f0055; font-weight: bold;"&gt;string&lt;/span&gt;[] args)&lt;br /&gt;        {&lt;br /&gt;            SerialPortFixer.Execute(&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;COM1&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: #7f0055; font-weight: bold;"&gt;            using&lt;/span&gt; (SerialPort port = &lt;span style="color: #7f0055; font-weight: bold;"&gt;new&lt;/span&gt; SerialPort(&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;COM1&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;))&lt;br /&gt;            {&lt;br /&gt;                port.Write(&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;test&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&lt;/span&gt;);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;/pre&gt;&lt;pre style="background: none repeat scroll 0% 0% rgb(255, 255, 255); color: black;"&gt;} &lt;/pre&gt;&lt;pre style="background: none repeat scroll 0% 0% rgb(255, 255, 255); color: black;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;* Use Firefox to copy and paste the code above. Formatting won't be preserved if you use IE (IE bug).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-23463613886501141?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/23463613886501141/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=23463613886501141' title='34 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/23463613886501141'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/23463613886501141'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2010/07/serialport-ioexception-workaround-in-c.html' title='SerialPort IOException Workaround in C#'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>34</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-292217628128956261</id><published>2010-07-01T18:23:00.008+10:00</published><updated>2010-07-06T13:22:54.214+10:00</updated><title type='text'>.NET SerialPort Woes</title><content type='html'>&lt;strong&gt;Preface&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;This is a very long post articulating the .NET SerialPort bug and the proposed fix for Microsoft to implement in its post .NET 4.0 framework. An interim fix that doesn't involve Microsoft is also available.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The built-in serial port support in .NET has been a major let down (which has remained largely unchanged since its introduction in v2.0 to the latest v4.0). Posts on MSDN have suggested that a lot of people (both C# and VB users alike) are in fact facing some form of difficulties using System.IO.Ports.SerialPort:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;a href="http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/2021f5b5-5414-4b01-84b3-bfb4c0ebf631"&gt;IOException when reading serial port using .NET 2.0 SerialPort.Read&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://social.msdn.microsoft.com/forums/en-US/netfxbcl/thread/bc9be51b-c810-4672-bc05-182a3008e4b9"&gt;Port IOException&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://social.msdn.microsoft.com/Forums/en-US/netfxcompact/thread/9f6f5405-e590-40be-a330-c7493ca5395c"&gt;SerialPort.Close throws IOException&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://social.msdn.microsoft.com/Forums/en-US/netfxcompact/thread/866f435a-af18-411d-8f5f-6f381778d527"&gt;IOException when SerialPort.Open()&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://social.msdn.microsoft.com/Forums/en/vssmartdevicesvbcs/thread/9745471b-55b4-4518-8fcf-f0ccbda320be"&gt;WinCE 5.0 - IOException when serialPort.Open()&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://social.msdn.microsoft.com/Forums/en-US/Vsexpressvb/thread/3e64f562-e74b-4213-8019-e69f54fc0d74"&gt;WARNING! SerialPort in .NET 3.5&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;... and many more, but take the last one with a grain of salt.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Yet Microsoft could't seem to be able to reproduce the bug, or worse, brushed it aside thinking it's a problem with users' code. That is likely due to the noise (i.e. incorrect answers accepted as correct answers) introduced by the forum's serial port expert pretenders (a lot of them Microsoft support staffs) - so far none of the posts were answered correctly, yet were all marked as correctly answered! Yay to the quality of MSDN forum - a forum where n00bs answer questions by other n00bs. The truth is, there's only one similarity in all of the posts - they all encountered IOException.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The Problem - IOException&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;To understand why IOException occurs in SerialPort (or rather, SerialStream to be exact), one would only need to look as far as the WinAPI Comm functions. SerialStream calls several comm APIs to get the real job done and when the API functions fail and return an error, SerialStream simply throws an IOException with the message returned by FormatMessage with the error code from GetLastError.&lt;br /&gt;&lt;br /&gt;So why does the WinAPI function fail? From the posts, they all have a common error message:&lt;br /&gt;&lt;blockquote&gt;"The I/O operation has been aborted because of either a thread exit or an application request." (error code 995)&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;While a thread exit will also cause an overlapped (asynchronous) function to implicitly abort, in this case it's aborted because the serial port is in a mode where any errors encountered by the UART chip would trigger the abort flag causing all current and subsequent serial port related calls to abort. Errors include parity error, buffer overrun, etc. &lt;br /&gt;&lt;br /&gt;Some developers have even encountered IOException as soon as they call SerialPort.Open(), especially in slow devices such as handhelds running .NET CE. Some encounter it when the garbage collector disposes the serial port. Some encounter it when they call SerialPort.Read(). &lt;br /&gt;&lt;br /&gt;They're all due to a mistake in .NET's SerialStream implementation - neglecting to set the fAbortOnError flag in the DCB structure when initializing the serial port.&lt;br /&gt;&lt;br /&gt;This negligence on Microsoft's part means every time you run your application you could potentially encounter a different behavior (this flag is persistent across app runs and the default is determined by BIOS and/or UART hardware vendor). Some claim that it only happens in one machine and not others. This also explains why it has remained such a pesky problem for both developers and Microsoft since the first incarnation of the SerialPort class.&lt;br /&gt;&lt;br /&gt;When fAbortOnError flag is set to true, this is indeed the expected behavior - but is this the desired behavior Microsoft intended for its users? No. System.IO.Ports.SerialStream was never meant to work with fAbortOnError set to true, because the ClearCommError WinAPI function that goes hand-in-hand was nowhere to be found among its methods. Clearly, whoever wrote SerialStream made a mistake &lt;em&gt;(and needs to be shot)&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The Solution&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;It took me an entire day to root cause this problem. Luckily the solution is much simpler.&lt;br /&gt;Here's what Microsoft needs to do to fix the problems (in reference to the .NET 4.0 source):&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;1) In InitializeDCB, SetDcbFlag for bit 14 to zero - this sets fAbortOnError to false. Also, retry GetCommState and SetCommState if it fails with error 995 (call ClearCommError() before retrying).&lt;br /&gt;&lt;br /&gt;2) In SerialStream's c'tor, move InitializeDCB to the line before GetCommProperties. This fixes the problem for the folks who've been getting IOException when calling SerialPort.Open(). The reason SerialPort.Open() only failed on slow devices because between the port's CreateFile and the time GetCommProperties() is called, a comm port physical error might have already occurred.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;The reason some people have claimed that their app simply crashes out when their application terminates is due to DiscardInBuffer() in SerialStream.Dispose() throwing IOException because PurgeComm failed with error 995, likely because of buffer overrun as their serial devices would've been sending and filling up the input buffer before user closes the app. And mind you, Dispose() at that point would've been called by the garbage collector thread - hence a try-catch would've been ineffective, unless of course, you've manually disposed the object prior to closing the app - causing the app to hard crash with unhandled exception.&lt;br /&gt;&lt;br /&gt;How do you fix it in the interim? Simple. Before you call SerialPort.Open(), simply open the serial port by calling CreateFile and SetCommState's fAbortOnError to false. Now you can safely open the serial port without worrying that it might throw an IOException. I've whipped up a &lt;a href="http://zachsaw.blogspot.com/2010/07/serialport-ioexception-workaround-in-c.html"&gt;sample workaround in C#&lt;/a&gt; that you could use as a reference.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-292217628128956261?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/292217628128956261/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=292217628128956261' title='21 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/292217628128956261'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/292217628128956261'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2010/07/net-serialport-woes.html' title='.NET SerialPort Woes'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>21</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-5670886382326387601</id><published>2010-05-23T11:25:00.005+10:00</published><updated>2010-05-23T15:50:28.135+10:00</updated><title type='text'>Anonymous methods / Lambda expression variable capture scope in C#</title><content type='html'>Let's face it, at some point or another, we've come across the problem in C# where you pass a for-loop variable into an anonymous method without redeclaring it and find that it doesn't behave expectedly. Once we get used to the idea of always redeclaring a variable you're going to use in your lambda expression though, you tend to ignore the fact that there is actually no reason why it should be the way it is.&lt;br /&gt;&lt;br /&gt;At least, I find it hard to explain to a junior team member the reason behind this implementation where the compiler would not consider a for-loop variable as a local variable to its scope when it comes to anonymous methods. In case you're wondering, this is the reason why we need to redeclare 'var s' in the following example:&lt;br /&gt;&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;foreach&lt;/span&gt; (var s &lt;span style='color:#7f0055; font-weight:bold; '&gt;in&lt;/span&gt; Names)&lt;br /&gt;{&lt;br /&gt;    var temp = s; &lt;span style='color:#3f7f59; '&gt;// redeclaration&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    criteria = criteria.Or(x =&gt; x.Name == temp);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The above example is very obvious, no doubt. But, throw in some code refactoring (out to a separate method and merging inline again etc.) and more complex lambda expression, you'll find that it is quite easy to forget that 'temp' variable. A bad language is one that requires you to 'tip toe around a field of land mine' when you're using it - which defeats the whole selling point of C# (or at least what Eric Gunnerson was selling when he first introduced C# to the world).&lt;br /&gt;&lt;br /&gt;Like I said, there's really no reason why the compiler shouldn't consider 'var s' as the local variable of the foreach block - there's no way you could access variable 's' outside of it anyway. In this case, variable 's' isn't local enough to be captured by the lambda expression, but isn't any more global than that either!&lt;br /&gt;&lt;br /&gt;My suggestion to Microsoft is to have the compiler automatically insert the redeclaration (as a quick and simple fix). I really can't think of a genuine use-case where one would actually desire the behavior without the redeclaration. In fact, if that is truly what is intended, then wouldn't this make more sense and a LOT more readable (read: maintainable)?&lt;br /&gt;&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;var s = Names[Names.Length-1];&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;for&lt;/span&gt; (&lt;span style='color:#7f0055; font-weight:bold; '&gt;int&lt;/span&gt; i=0; i&amp;lt;Names.Length; i++)&lt;br /&gt;{&lt;br /&gt;    criteria = criteria.Or(x =&gt; x.Name == s);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;rather than,&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#7f0055; font-weight:bold; '&gt;foreach&lt;/span&gt; (var s &lt;span style='color:#7f0055; font-weight:bold; '&gt;in&lt;/span&gt; Names)&lt;br /&gt;{&lt;br /&gt;    criteria = criteria.Or(x =&gt; x.Name == s);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-5670886382326387601?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/5670886382326387601/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=5670886382326387601' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/5670886382326387601'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/5670886382326387601'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2010/05/anonymous-methods-lambda-expression.html' title='Anonymous methods / Lambda expression variable capture scope in C#'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-756067062642546281</id><published>2010-01-26T19:07:00.005+11:00</published><updated>2010-01-26T22:58:20.671+11:00</updated><title type='text'>Rad Studio IDE Changes System Wide Timer Resolution</title><content type='html'>This one had me scratching my head for a &lt;span style="font-weight: bold;"&gt;long&lt;/span&gt; time. Apparently, the CodeGear / Embarcadero RAD Studio IDEs (I've tested 2007 and 2010) exhibit this behavior - it calls &lt;a href="http://msdn.microsoft.com/en-us/library/dd757624%28VS.85%29.aspx"&gt;timeBeginPeriod&lt;/a&gt; to change system wide timer resolution to 1ms when it starts and &lt;a href="http://msdn.microsoft.com/en-us/library/dd757626%28VS.85%29.aspx"&gt;timeEndPeriod&lt;/a&gt; when it quits.&lt;br /&gt;&lt;br /&gt;What's the problem then?&lt;br /&gt;&lt;br /&gt;For starters, this means that simple code such as:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;"&gt;while&lt;/span&gt; (!Terminated)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (Poll())&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DoSomething();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Sleep(1);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;will behave very differently with and without the IDE running. You may end up polling a lot slower than you expected when you deploy your applications and may cause DoSomething() to not get called in-time. The evil is in the fact that when you are developing the application, DoSomething() always gets called as you would have expected. But when you deploy your application (or hands it over to the testers for testing), you'd soon realize something is amiss. Everyone knows Windows is not a real-time OS, so no one would expect Sleep(1) to actually sleep for 1ms. But while developing the application, you had found that it is actually quite close.&lt;br /&gt;&lt;br /&gt;Well, surprise, surprise! Without the IDE running, Sleep(1) would actually wait for 15.625ms by default - that's more than 15 times slower than what you were expecting.&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://msdn.microsoft.com/en-us/library/ms686298%28VS.85%29.aspx"&gt;Sleep Function documentation from MSDN&lt;/a&gt; really doesn't do a good job at explaining the Sleep function. In DOS, I would've expected the system ticks to be at a default of 15.7ms. But I had expected Windows starting from Windows 95 to have a default system tick of 1ms. I was wrong (well, not really, see my comment #1).&lt;br /&gt;&lt;br /&gt;Regardless, this is a serious problem with all of RAD Studio's IDEs. I am sure hardly anyone knows about this and at one point or another, you would've been bitten by this, even if you didn't know it - except that your application failed on the day of demo at your client's site. Just your luck again.&lt;br /&gt;&lt;br /&gt;Microsoft's Visual Studio IDEs (tested 6, 2005, 2008) don't do this.&lt;br /&gt;&lt;br /&gt;Also, it's never a good idea to change the system tick resolution - from MSDN, &lt;span style="font-style: italic;"&gt;"&lt;/span&gt;&lt;span style="font-style: italic;"&gt;(The timeBeginPeriod)&lt;/span&gt;&lt;span style="font-style: italic;"&gt; function affects a global Windows setting. Windows uses the lowest value (that is, highest resolution) requested by any process. Setting a higher resolution can improve the accuracy of time-out intervals in wait functions. However, it can also reduce overall system performance, because the thread scheduler switches tasks more often. High resolutions can also prevent the CPU power management system from entering power-saving modes. Setting a higher resolution does not improve the accuracy of the high-resolution performance counter."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Perhaps the OS should have simply fixed it at 1ms. To allow processes to change system timer resolution that affects global system settings does not make much sense in a multitasking environment.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-756067062642546281?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/756067062642546281/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=756067062642546281' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/756067062642546281'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/756067062642546281'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2010/01/rad-studio-ide-changes-system-wide.html' title='Rad Studio IDE Changes System Wide Timer Resolution'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-4336852302306157104</id><published>2010-01-20T18:18:00.004+11:00</published><updated>2010-01-20T18:23:05.717+11:00</updated><title type='text'>Component / Control with TPropertyEditor in DesignEditors</title><content type='html'>If you include &amp;lt;designeditor.hpp&amp;gt; and try to use TPropertyEditor in C++ Builder, you'll run into BCC32 errors complaining about &lt;span style="font-style: italic;"&gt;multiple declaration for 'IPropertyDescription'&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;ambiguity between 'IPropertyDescription' and 'Designintf::IPropertyDescription'&lt;/span&gt;. This is true for every version post-BCB6, including the latest CB2010.&lt;br /&gt;&lt;br /&gt;The namespace ambiguity problem is an inherent problem with C++ Builder because every HPP file that is generated from Delphi includes the namespace in the header file. We all know that's *BAD* now, but it's a decision that dates back to the first version where even the std namespace was implicit included. Now that we've found ourselves too deep in the rabbit hole, there's really no easy way out as far as backward compatibility is concerned.&lt;br /&gt;&lt;br /&gt;But, for this particular problem, there's a solution.&lt;br /&gt;&lt;br /&gt;Before you include DesignEditors.hpp, you should first include PropSys.hpp, such as,&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 102, 102);font-family:courier new;" &gt;#include &amp;lt;propsys.hpp&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 102, 102);font-family:courier new;" &gt;#include &amp;lt;designeditors.hpp&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);"&gt;class &lt;/span&gt;PACKAGE TMyComponentEditor: &lt;span style="font-weight: bold; color: rgb(51, 51, 255);"&gt;public &lt;/span&gt;TPropertyEditor&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// ...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Perhaps the better way would be for DesignEditors.hpp to include PropSys.hpp at the very top of the file, so anyone who uses DesignEditors.hpp doesn't need to remember including PropSys.hpp explicitly. That one's for Embarcadero to decide.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-4336852302306157104?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/4336852302306157104/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=4336852302306157104' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/4336852302306157104'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/4336852302306157104'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2010/01/component-control-with-tpropertyeditor.html' title='Component / Control with TPropertyEditor in DesignEditors'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-5739135702469719845</id><published>2010-01-20T18:14:00.002+11:00</published><updated>2010-01-20T18:17:54.567+11:00</updated><title type='text'>Upgrading VCL Apps to C++ Builder 2010</title><content type='html'>If you run into the following error, here's what you need to do.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;[ILINK32 Error] Error: Unresolved external 'wWinMain' referenced from C:\PROGRAM FILES\EMBARCADERO\RAD STUDIO\7.0\LIB\C0W32W.OBJ&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Open your main cpp file and look for this line,&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, &lt;span style="font-weight: bold; color: rgb(51, 51, 255);"&gt;int&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Change it to,&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;br /&gt;WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);"&gt;int&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is to do with the Unicode support in the new IDE (starting from CB2009).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-5739135702469719845?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/5739135702469719845/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=5739135702469719845' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/5739135702469719845'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/5739135702469719845'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2010/01/upgrading-vcl-apps-to-c-builder-2010.html' title='Upgrading VCL Apps to C++ Builder 2010'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-3174076966268299929</id><published>2010-01-20T18:08:00.001+11:00</published><updated>2010-01-20T18:13:53.784+11:00</updated><title type='text'>IDE Regex Replace: char to wchar_t string literals</title><content type='html'>While upgrading your apps to use &lt;span style="font-family: courier new;"&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);"&gt;wchar_t&lt;/span&gt;*&lt;/span&gt; instead of &lt;span style="font-family: courier new; color: rgb(51, 51, 255); font-weight: bold;"&gt;char&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;*&lt;/span&gt; string literals, you'll find that you need to change a string such as &lt;span style="font-family: courier new; color: rgb(51, 51, 255);"&gt;"This is a string"&lt;/span&gt; to &lt;span style="font-family: courier new;"&gt;_T(&lt;span style="color: rgb(51, 51, 255);"&gt;"This is a string"&lt;/span&gt;)&lt;/span&gt;, as well as character literals such as &lt;span style="font-family: courier new; color: rgb(153, 51, 153);"&gt;'c'&lt;/span&gt; to &lt;span style="font-family: courier new;"&gt;_T(&lt;span style="color: rgb(153, 51, 153);"&gt;'c'&lt;/span&gt;)&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Well the good news is there's a quick way of doing this.&lt;br /&gt;&lt;br /&gt;The C++ Builder IDE has always have a Regex (Regular Expression) based search and replace function. All you have to do is enable it in the Replace Text dialog, under &lt;span style="font-style: italic;"&gt;Options | Regular expressions&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;These are the corresponding Regex you'll need.&lt;br /&gt;&lt;br /&gt;For &lt;span style="font-style: italic;"&gt;string &lt;/span&gt;literals,&lt;br /&gt;&lt;br /&gt;Text to find: &lt;span style="font-family: courier new; color: rgb(51, 51, 255);"&gt;"{(\\"|[^"])*}"&lt;/span&gt; (include the double quotes)&lt;br /&gt;Replace with: &lt;span style="font-family: courier new; color: rgb(51, 51, 255);"&gt;_T("\0")&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For &lt;span style="font-style: italic;"&gt;char &lt;/span&gt;literals,&lt;br /&gt;&lt;br /&gt;Text to find: &lt;span style="font-family: courier new; color: rgb(51, 51, 255);"&gt;\'{\\[^']|[^']}\'&lt;/span&gt;&lt;br /&gt;Replace with: &lt;span style="font-family: courier new; color: rgb(51, 51, 255);"&gt;_T('\0')&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;* Note:&lt;/span&gt; &lt;span style="font-style: italic;"&gt;Do not&lt;/span&gt; blindly replace all. You may end up replacing the text inside a string, such as &lt;span style="color: rgb(51, 51, 255); font-family: courier new;"&gt;"I can see 'u' from here"&lt;/span&gt;. If anyone has any suggestions on how to correct this, I'd appreciate it (note that the IDE regex replacer does not support backreference). You may end up replacing strings that aren't string literals, such as &lt;span style="font-family: courier new; color: rgb(51, 153, 153);"&gt;#include "myfile.h"&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;The reason you'd want to use the _T(x) macro is because it's faster when you do an assignment to UnicodeString (which is typedef'd to String). The _T(x) macro maps to L##x - i.e. &lt;span style="font-family: courier new;"&gt;_T(&lt;span style="color: rgb(51, 51, 255);"&gt;"text"&lt;/span&gt;) == L&lt;span style="color: rgb(51, 51, 255);"&gt;"text"&lt;/span&gt;&lt;/span&gt;. The String and _T(x) macro pair is compatible going from a compiler that supports Unicode to one that doesn't as String will map to UnicodeString in the former and AnsiString in the latter, which is the same for the _T(x) macro mapping to L (&lt;span style="font-family: courier new; color: rgb(51, 51, 255);"&gt;L"string"&lt;/span&gt;) and nothing (&lt;span style="font-family: courier new; color: rgb(51, 51, 255);"&gt;"string"&lt;/span&gt;) respectively.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;String fromAnsi = &lt;span style="color: rgb(51, 51, 255);"&gt;"text"&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;_&lt;span style="font-style: italic;"&gt;UStrFromPChar&lt;/span&gt;, which ends up calling &lt;span style="font-style: italic;"&gt;MultiByteToWideChar&lt;/span&gt;. It is a Windows API that converts Ansi strings to Unicode strings, and as fast as it may be, it's bound to be slower than a straight memory copy.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;String fromUnicode = &lt;span style="color: rgb(51, 51, 255);"&gt;L"text"&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;All else being equal (allocate memory and finding string length), this is much faster as it's basically just a straight memory copy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-3174076966268299929?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/3174076966268299929/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=3174076966268299929' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/3174076966268299929'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/3174076966268299929'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2010/01/ide-regex-replace-char-to-wchart-string.html' title='IDE Regex Replace: char to wchar_t string literals'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-691983715319914071</id><published>2010-01-15T17:58:00.019+11:00</published><updated>2011-07-06T21:36:19.884+10:00</updated><title type='text'>FastMM - Slow in multithreaded apps on multicore CPUs</title><content type='html'>There's something wrong with FastMM4's (i.e. the default memory manager of Delphi / C++ Builder starting BDS2006) usability on multicore systems, especially running multithreaded apps in a GC/managed environment. The result of this is that when multicore is enabled,&lt;span style="font-style: italic;"&gt; &lt;span style="font-weight: bold;"&gt;performance suffers by up to 5 folds&lt;/span&gt;&lt;/span&gt;. So, not only that &lt;a href="http://zachsaw.blogspot.com/2008/11/fastmms-multicore-performance-scaling.html"&gt;FastMM would not scale&lt;/a&gt;, your multithreaded apps will run tremendously slower on a multicore system - up to &lt;span style="font-style: italic;"&gt;5 times slower on a dual-core machine&lt;/span&gt; vs a single-core one at the same clock speed of the same architecture.&lt;br /&gt;&lt;br /&gt;That's 500% performance drop going from single-core to dual-core! Comparing the dual-core performance of FastMM4 and TBBMM, the latter is &lt;span style="font-style: italic;"&gt;9 times faster&lt;/span&gt;!&lt;br /&gt;&lt;br /&gt;This test is meant to show just that. &lt;a href="http://www.zachsaw.com/downloads/gctester_27012010.zip"&gt;Download Test (updated 27/01/2010)&lt;/a&gt; (see readme.txt for instructions) &lt;span style="font-style: italic; font-weight: bold;"&gt;*** WARNING:&lt;/span&gt; Incompatible with x64 OS due to &lt;a href="http://zachsaw.blogspot.com/2010/11/wow64-bug-getthreadcontext-may-return.html"&gt;an OS bug&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;It runs through a variety of algorithms in multiple threads (in a threadpool of the framework, similar to .NET's ThreadPool) consisting of a mix of GC list, GC dictionary, and GC string unit-tests.&lt;br /&gt;&lt;br /&gt;Keep in mind that this is an app written using &lt;a href="http://zachsaw.blogspot.com/2009/12/precise-garbage-collector-for-c-builder.html"&gt;a GC framework&lt;/a&gt;, which means allocations usually happen in multiple threads concurrently while de-allocations are done in specialized garbage collector threads. This may be the reason FastMM breaks down (a general-purpose memory manager shouldn't break down given any usage patterns).&lt;br /&gt;&lt;br /&gt;Notice that when you run the FastMM Test with &lt;span style="font-style: italic;"&gt;CPU Affinity&lt;/span&gt; set to just one CPU, you'll end up with nearly the same performance as TBBMM. Once you enable multicores though, you'd immediately lose performance once again, running slower than with just one core.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Note:&lt;/span&gt; You'll find that the FastMM BorlndMM.dll is different from the default Rad Studio 2010 one. This is due to the changes added to support the GC framework, but at its heart, it's simply making calls to &lt;span style="font-style: italic;"&gt;GetMemory&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;ReallocMemory &lt;/span&gt;and &lt;span style="font-style: italic;"&gt;FreeMemory &lt;/span&gt;(as oppose to WinMM's version of &lt;span style="font-style: italic;"&gt;HeapAlloc&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;HeapRealloc &lt;/span&gt;and &lt;span style="font-style: italic;"&gt;HeapFree &lt;/span&gt;respectively, with all else&lt;br /&gt;being equal). The WinMM version is initialized with the LFH &lt;span style="font-style: italic;"&gt;(low fragmentation heap) &lt;/span&gt;flag.&lt;br /&gt;&lt;br /&gt;Here are some results from my own tests:&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family: courier new;"&gt;Test results in &lt;span style="font-style: italic;"&gt;ops/second&lt;/span&gt; (10sec average), listed in the following order:&lt;br /&gt;1) TBBMM&lt;/span&gt; &lt;a href="http://www.zachsaw.com/?pg=borlndmm_tbbmm"&gt;(what is TBBMM?)&lt;/a&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;2) WinMM&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;3) FastMM&lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;Core2Duo E6550 2.33GHz (Conroe)&lt;/span&gt; - XP SP3&lt;br /&gt;&lt;span style="font-family: courier new; font-style: italic;"&gt;Both cores enabled&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;1) &lt;/span&gt;&lt;span style="font-family: courier new;"&gt;1785&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;2) 1230&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;3) &lt;span style="color: red; font-weight: bold;"&gt;250&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-style: italic;"&gt;Single core (via CPU affinity mask)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;1) 930&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;2) 650&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;3) &lt;span style="color: #3333ff; font-weight: bold;"&gt;950&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;Core2Duo E6550 throttled to 1.33GHz&lt;/span&gt; - XP SP3&lt;br /&gt;&lt;span style="font-family: courier new; font-style: italic;"&gt;Both cores enabled&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;1) 730&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;2) 520&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;3) &lt;span style="color: red; font-weight: bold;"&gt;180&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-style: italic;"&gt;Single core (via CPU affinity mask)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;1) 410&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;2) 275&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;3) &lt;span style="color: #3333ff; font-weight: bold;"&gt;395&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;Pentium M 1.2GHz (Banias)&lt;/span&gt; - XP SP3&lt;br /&gt;&lt;span style="font-family: courier new; font-style: italic;"&gt;CPU is Single core&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;1) 395&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;2) 340&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;3) &lt;span style="color: #3333ff; font-weight: bold;"&gt;395&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;Core2Duo E7200 3.6GHz (Wolfdale)&lt;/span&gt; - Vista&lt;br /&gt;&lt;span style="font-family: courier new; font-style: italic;"&gt;Both cores enabled&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;1) &lt;/span&gt;&lt;span style="font-family: courier new;"&gt;2595&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;2) 2080&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;3) &lt;span style="color: red; font-weight: bold;"&gt;290&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-style: italic;"&gt;Single core (via CPU affinity mask)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;1) 1450&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;2) 1180&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;3) &lt;span style="color: #3333ff; font-weight: bold;"&gt;1405&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;As you can see, the results are quite consistent. On a dual core machine, the performance of FastMM is terrible. From 2.33GHz to 3.6GHz, there's virtually no increase at all in speed! In fact, when the test was running, the CPU wasn't even fully utilized (with more than 50% of CPU spent in kernel time), whereas the other memory managers had the CPU pegged at 100% and nearly no kernel time.&lt;br /&gt;&lt;br /&gt;If you wish to try it out on your system, &lt;a href="http://www.zachsaw.com/downloads/gctester_27012010.zip"&gt;download this GC speed tester (updated 27/01/2010)&lt;/a&gt; and unzip it to a folder of your choice. Then, run &lt;span style="font-style: italic;"&gt;"Run All Tests.bat" &lt;/span&gt;and follow the on-screen instructions. Note that the GC Speed Test app will run indefinitely, so once you take note of the speed (ops/sec), you can quit the app to move on to the next test.&lt;br /&gt;&lt;br /&gt;I'd appreciate it if you could post your results here in the comments in the same format as the ones above - i.e. CPU make (I'd love to see how AMD CPUs fare) and model number as well as the frequency, OS / service pack, and the results.&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;My advice? For an all-rounded memory manager, use the Windows default one. It may be a little slower than FastMM on a single core, but it certainly scales very well on multicore systems. Alternatively, the Intel TBB allocator has a near perfect scaling and is the fastest memory managers around. Only thing is, it consumes more RAM.&lt;br /&gt;&lt;br /&gt;Regardless, &lt;span style="font-style: italic;"&gt;I'd stay away from FastMM4 &lt;/span&gt;(thus the default memory manager of Delphi / C++ Builder).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-691983715319914071?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/691983715319914071/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=691983715319914071' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/691983715319914071'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/691983715319914071'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2010/01/fastmm-slow-in-multithreaded-apps-on.html' title='FastMM - Slow in multithreaded apps on multicore CPUs'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-4368897961979841708</id><published>2010-01-14T18:22:00.007+11:00</published><updated>2010-01-14T19:07:53.905+11:00</updated><title type='text'>C++ Builder 2010 Optimizing C++ Compiler</title><content type='html'>I'm pleasantly surprised after giving C++ Builder 2010 a quick spin. It's much better at optimizing code than its predecessor CB2007 (I skipped CB2009 altogether as it was and still is completely broken).&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;"&gt;CB2010&lt;/span&gt; vs &lt;span style="font-weight: bold; color: rgb(0, 153, 0);"&gt;CB2007&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;AnsiString test:&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;"&gt;6938ms&lt;/span&gt; vs &lt;span style="font-weight: bold; color: rgb(0, 153, 0);"&gt;6765ms&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;GcString test:&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);"&gt;420ms&lt;/span&gt; vs &lt;span style="font-weight: bold; color: rgb(0, 153, 0);"&gt;1734ms&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;(yes, that's 420ms, it's not a typo)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In the AnsiString test, things got &lt;span style="font-style: italic;"&gt;just a bit &lt;/span&gt;slower (about 2% - nothing to worry about). But the big surprise here is my GcString test, which is &lt;span style="font-style: italic; font-weight: bold;"&gt;over 400% FASTER!&lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-weight: bold;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Code for the test above (executed on Core2Duo 2.33GHz with &lt;a href="http://www.zachsaw.co.cc/?pg=borlndmm_tbbmm"&gt;TBBMM&lt;/a&gt;):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color:#ff6633;"&gt;void&lt;/span&gt; __fastcall RunTest&lt;b&gt;&lt;span style="color:#663300;"&gt;()&lt;br /&gt;{&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#990000;"&gt;&lt;br /&gt;   const&lt;/span&gt;&lt;span style="color:#ff6633;"&gt; int&lt;/span&gt; TEST_COUNT&lt;b&gt;&lt;span style="color:#663300;"&gt; =&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#999900;"&gt; 10&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt;;&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#990000;"&gt;&lt;br /&gt;   const&lt;/span&gt;&lt;span style="color:#ff6633;"&gt; int&lt;/span&gt; TEST_SIZE&lt;b&gt;&lt;span style="color:#663300;"&gt; =&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#999900;"&gt; 10000&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt;;&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#990000;"&gt;&lt;br /&gt;   const&lt;/span&gt;&lt;span style="color:#ff6633;"&gt; int&lt;/span&gt; LOOP_COUNT&lt;b&gt;&lt;span style="color:#663300;"&gt; =&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#999900;"&gt; 1000&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt;;&lt;br /&gt;&lt;br /&gt;   {&lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color:#999999;"&gt;&lt;br /&gt;       // RefCounted String Test&lt;br /&gt;&lt;/span&gt;&lt;/i&gt;        AnsiString strings&lt;b&gt;&lt;span style="color:#663300;"&gt;[&lt;/span&gt;&lt;/b&gt;TEST_SIZE&lt;b&gt;&lt;span style="color:#663300;"&gt;];&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#ff0000;"&gt;&lt;br /&gt;       for&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt; (&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#ff6633;"&gt;int&lt;/span&gt; i&lt;b&gt;&lt;span style="color:#663300;"&gt;=&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#999900;"&gt;0&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt;;&lt;/span&gt;&lt;/b&gt; i&lt;b&gt;&lt;span style="color:#663300;"&gt;&lt;&lt;/span&gt;&lt;/b&gt;TEST_SIZE&lt;b&gt;&lt;span style="color:#663300;"&gt;;&lt;/span&gt;&lt;/b&gt; i&lt;b&gt;&lt;span style="color:#663300;"&gt;++)&lt;br /&gt;       {&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;           strings&lt;b&gt;&lt;span style="color:#663300;"&gt;[&lt;/span&gt;&lt;/b&gt;i&lt;b&gt;&lt;span style="color:#663300;"&gt;] =&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#009900;"&gt; "test"&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt;;&lt;br /&gt;       }&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;       DWORD start&lt;b&gt;&lt;span style="color:#663300;"&gt; =&lt;/span&gt;&lt;/b&gt; GetTickCount&lt;b&gt;&lt;span style="color:#663300;"&gt;();&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#ff0000;"&gt;&lt;br /&gt;       for&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt; (&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#ff6633;"&gt;int&lt;/span&gt; x&lt;b&gt;&lt;span style="color:#663300;"&gt;=&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#999900;"&gt;0&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt;;&lt;/span&gt;&lt;/b&gt; x&lt;b&gt;&lt;span style="color:#663300;"&gt;&lt;&lt;/span&gt;&lt;/b&gt;LOOP_COUNT&lt;b&gt;&lt;span style="color:#663300;"&gt;;&lt;/span&gt;&lt;/b&gt; x&lt;b&gt;&lt;span style="color:#663300;"&gt;++)&lt;br /&gt;       {&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;           AnsiString temp&lt;b&gt;&lt;span style="color:#663300;"&gt;;&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#ff0000;"&gt;&lt;br /&gt;           for&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt; (&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#ff6633;"&gt;int&lt;/span&gt; j&lt;b&gt;&lt;span style="color:#663300;"&gt;=&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#999900;"&gt;0&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt;;&lt;/span&gt;&lt;/b&gt; j&lt;b&gt;&lt;span style="color:#663300;"&gt;&lt;&lt;/span&gt;&lt;/b&gt;TEST_COUNT&lt;b&gt;&lt;span style="color:#663300;"&gt;;&lt;/span&gt;&lt;/b&gt; j&lt;b&gt;&lt;span style="color:#663300;"&gt;++)&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#ff0000;"&gt;&lt;br /&gt;           for&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt; (&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#ff6633;"&gt;int&lt;/span&gt; i&lt;b&gt;&lt;span style="color:#663300;"&gt;=&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#999900;"&gt;0&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt;;&lt;/span&gt;&lt;/b&gt; i&lt;b&gt;&lt;span style="color:#663300;"&gt;&lt;&lt;/span&gt;&lt;/b&gt;TEST_SIZE&lt;b&gt;&lt;span style="color:#663300;"&gt;/&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#999900;"&gt;2&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt;;&lt;/span&gt;&lt;/b&gt; i&lt;b&gt;&lt;span style="color:#663300;"&gt;++)&lt;br /&gt;           {&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;               temp&lt;b&gt;&lt;span style="color:#663300;"&gt; =&lt;/span&gt;&lt;/b&gt; strings&lt;b&gt;&lt;span style="color:#663300;"&gt;[&lt;/span&gt;&lt;/b&gt;i&lt;b&gt;&lt;span style="color:#663300;"&gt;];&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;               strings&lt;b&gt;&lt;span style="color:#663300;"&gt;[&lt;/span&gt;&lt;/b&gt;i&lt;b&gt;&lt;span style="color:#663300;"&gt;] =&lt;/span&gt;&lt;/b&gt; strings&lt;b&gt;&lt;span style="color:#663300;"&gt;[&lt;/span&gt;&lt;/b&gt;TEST_SIZE&lt;b&gt;&lt;span style="color:#663300;"&gt;-&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#999900;"&gt;1&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt;-&lt;/span&gt;&lt;/b&gt;i&lt;b&gt;&lt;span style="color:#663300;"&gt;];&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;               strings&lt;b&gt;&lt;span style="color:#663300;"&gt;[&lt;/span&gt;&lt;/b&gt;TEST_SIZE&lt;b&gt;&lt;span style="color:#663300;"&gt;-&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#999900;"&gt;1&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt;-&lt;/span&gt;&lt;/b&gt;i&lt;b&gt;&lt;span style="color:#663300;"&gt;] =&lt;/span&gt;&lt;/b&gt; temp&lt;b&gt;&lt;span style="color:#663300;"&gt;;&lt;br /&gt;           }&lt;br /&gt;       }&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;       ShowMessage&lt;b&gt;&lt;span style="color:#663300;"&gt;(&lt;/span&gt;&lt;/b&gt;IntToStr&lt;b&gt;&lt;span style="color:#663300;"&gt;((&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#ff6633;"&gt;int&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt;)&lt;/span&gt;&lt;/b&gt;GetTickCount&lt;b&gt;&lt;span style="color:#663300;"&gt;() - (&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#ff6633;"&gt;int&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt;)&lt;/span&gt;&lt;/b&gt;start&lt;b&gt;&lt;span style="color:#663300;"&gt;));&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   {&lt;/span&gt;&lt;/b&gt;&lt;i&gt;&lt;span style="color:#999999;"&gt;&lt;br /&gt;       // GcString Test&lt;br /&gt;&lt;/span&gt;&lt;/i&gt;        GcString strings&lt;b&gt;&lt;span style="color:#663300;"&gt;[&lt;/span&gt;&lt;/b&gt;TEST_SIZE&lt;b&gt;&lt;span style="color:#663300;"&gt;];&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#ff0000;"&gt;&lt;br /&gt;       for&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt; (&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#ff6633;"&gt;int&lt;/span&gt; i&lt;b&gt;&lt;span style="color:#663300;"&gt;=&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#999900;"&gt;0&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt;;&lt;/span&gt;&lt;/b&gt; i&lt;b&gt;&lt;span style="color:#663300;"&gt;&lt;&lt;/span&gt;&lt;/b&gt;TEST_SIZE&lt;b&gt;&lt;span style="color:#663300;"&gt;;&lt;/span&gt;&lt;/b&gt; i&lt;b&gt;&lt;span style="color:#663300;"&gt;++)&lt;br /&gt;       {&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;           strings&lt;b&gt;&lt;span style="color:#663300;"&gt;[&lt;/span&gt;&lt;/b&gt;i&lt;b&gt;&lt;span style="color:#663300;"&gt;] =&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#009900;"&gt; "test"&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt;;&lt;br /&gt;       }&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;       DWORD start&lt;b&gt;&lt;span style="color:#663300;"&gt; =&lt;/span&gt;&lt;/b&gt; GetTickCount&lt;b&gt;&lt;span style="color:#663300;"&gt;();&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#ff0000;"&gt;&lt;br /&gt;       for&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt; (&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#ff6633;"&gt;int&lt;/span&gt; x&lt;b&gt;&lt;span style="color:#663300;"&gt;=&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#999900;"&gt;0&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt;;&lt;/span&gt;&lt;/b&gt; x&lt;b&gt;&lt;span style="color:#663300;"&gt;&lt;&lt;/span&gt;&lt;/b&gt;LOOP_COUNT&lt;b&gt;&lt;span style="color:#663300;"&gt;;&lt;/span&gt;&lt;/b&gt; x&lt;b&gt;&lt;span style="color:#663300;"&gt;++)&lt;br /&gt;       {&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;           GcString temp&lt;b&gt;&lt;span style="color:#663300;"&gt;;&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#ff0000;"&gt;&lt;br /&gt;           for&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt; (&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#ff6633;"&gt;int&lt;/span&gt; j&lt;b&gt;&lt;span style="color:#663300;"&gt;=&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#999900;"&gt;0&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt;;&lt;/span&gt;&lt;/b&gt; j&lt;b&gt;&lt;span style="color:#663300;"&gt;&lt;&lt;/span&gt;&lt;/b&gt;TEST_COUNT&lt;b&gt;&lt;span style="color:#663300;"&gt;;&lt;/span&gt;&lt;/b&gt; j&lt;b&gt;&lt;span style="color:#663300;"&gt;++)&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#ff0000;"&gt;&lt;br /&gt;           for&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt; (&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#ff6633;"&gt;int&lt;/span&gt; i&lt;b&gt;&lt;span style="color:#663300;"&gt;=&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#999900;"&gt;0&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt;;&lt;/span&gt;&lt;/b&gt; i&lt;b&gt;&lt;span style="color:#663300;"&gt;&lt;&lt;/span&gt;&lt;/b&gt;TEST_SIZE&lt;b&gt;&lt;span style="color:#663300;"&gt;/&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#999900;"&gt;2&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt;;&lt;/span&gt;&lt;/b&gt; i&lt;b&gt;&lt;span style="color:#663300;"&gt;++)&lt;br /&gt;           {&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;               temp&lt;b&gt;&lt;span style="color:#663300;"&gt; =&lt;/span&gt;&lt;/b&gt; strings&lt;b&gt;&lt;span style="color:#663300;"&gt;[&lt;/span&gt;&lt;/b&gt;i&lt;b&gt;&lt;span style="color:#663300;"&gt;];&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;               strings&lt;b&gt;&lt;span style="color:#663300;"&gt;[&lt;/span&gt;&lt;/b&gt;i&lt;b&gt;&lt;span style="color:#663300;"&gt;] =&lt;/span&gt;&lt;/b&gt; strings&lt;b&gt;&lt;span style="color:#663300;"&gt;[&lt;/span&gt;&lt;/b&gt;TEST_SIZE&lt;b&gt;&lt;span style="color:#663300;"&gt;-&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#999900;"&gt;1&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt;-&lt;/span&gt;&lt;/b&gt;i&lt;b&gt;&lt;span style="color:#663300;"&gt;];&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;               strings&lt;b&gt;&lt;span style="color:#663300;"&gt;[&lt;/span&gt;&lt;/b&gt;TEST_SIZE&lt;b&gt;&lt;span style="color:#663300;"&gt;-&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#999900;"&gt;1&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt;-&lt;/span&gt;&lt;/b&gt;i&lt;b&gt;&lt;span style="color:#663300;"&gt;] =&lt;/span&gt;&lt;/b&gt; temp&lt;b&gt;&lt;span style="color:#663300;"&gt;;&lt;br /&gt;           }&lt;br /&gt;       }&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;       ShowMessage&lt;b&gt;&lt;span style="color:#663300;"&gt;(&lt;/span&gt;&lt;/b&gt;IntToStr&lt;b&gt;&lt;span style="color:#663300;"&gt;((&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#ff6633;"&gt;int&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt;)&lt;/span&gt;&lt;/b&gt;GetTickCount&lt;b&gt;&lt;span style="color:#663300;"&gt;() - (&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#ff6633;"&gt;int&lt;/span&gt;&lt;b&gt;&lt;span style="color:#663300;"&gt;)&lt;/span&gt;&lt;/b&gt;start&lt;b&gt;&lt;span style="color:#663300;"&gt;));&lt;br /&gt;   }&lt;br /&gt;}&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As you may have noticed, it is simply an array reversal test. And yes, the GcString version was 4 times faster even in CB2007. In CB2010, &lt;span style="font-weight: bold; font-style: italic;"&gt;GcString is now a staggering 16.5 times&lt;/span&gt;&lt;span style="font-weight: bold;"&gt; &lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-weight: bold;"&gt;faster than AnsiString!&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-4368897961979841708?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/4368897961979841708/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=4368897961979841708' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/4368897961979841708'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/4368897961979841708'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2010/01/c-builder-2010-optimizing-c-compiler.html' title='C++ Builder 2010 Optimizing C++ Compiler'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-3425796167483013417</id><published>2010-01-14T18:18:00.001+11:00</published><updated>2010-01-14T18:22:16.741+11:00</updated><title type='text'>Internal Compiler Error (ICE) in BCC32 of C++ Builder 2010</title><content type='html'>An excellent write-up of &lt;a href="http://blogs.embarcadero.com/ddean/2009/02/13/34818"&gt;‘What is an Internal Compiler Error?’ by David Dean (an Embarcadero C++ QA Engineer)&lt;/a&gt; is a must-read if you do not know what an ICE is, apart from it giving you error message such as this, “[BCC32 Fatal Error] FileA.cpp(56): F1004 Internal compiler error at 0x59650a1 with base 0x5900000”.&lt;br /&gt;&lt;br /&gt;CB2010 seems to be more prone to encountering ICE, for reasons which are beyond my understanding. However, with a lot of struggle and time spent to get my projects compiled, I’ve found a few settings that are vital to avoid ICE.&lt;br /&gt;&lt;br /&gt;The first thing I’d do is &lt;span style="font-style: italic;"&gt;disable smart cached precompiled headers&lt;/span&gt; (command line: &lt;span style="font-weight: bold;"&gt;-Hs-&lt;/span&gt;). I’ve found that this option, combined with &lt;span style="font-style: italic;"&gt;Debugging | Expand inline functions&lt;/span&gt; and/or &lt;span style="font-style: italic;"&gt;Optimizations | Expand common intrinsic functions (implicit via Generate fastest possible code)&lt;/span&gt; is the root of all evil. Disabling the former will allow the latter two to be enabled, thus taking advantage of the new optimization featured in BCC32 v6.21 of CB2010. In fact, I’ve made all my projects default to this configuration. If you still get ICE, then start disabling the other two as well. Even if you get it to compile after disabling either or both of them, you’d still want to submit a QC entry (a bug report). To do this, follow the instructions in the above link &lt;a href="http://blogs.embarcadero.com/ddean/2009/02/13/34818"&gt;(David Dean’s page about ICE)&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-3425796167483013417?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/3425796167483013417/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=3425796167483013417' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/3425796167483013417'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/3425796167483013417'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2010/01/internal-compiler-error-ice-in-bcc32-of.html' title='Internal Compiler Error (ICE) in BCC32 of C++ Builder 2010'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-1959852323948999534</id><published>2010-01-07T23:39:00.003+11:00</published><updated>2010-01-07T23:54:53.805+11:00</updated><title type='text'>ATI DXVA with Arcsoft - Still Behind nVidia with Anything</title><content type='html'>Happy New Year 2010 to all my readers!&lt;br /&gt;&lt;br /&gt;First post of the year. And it's &lt;span style="font-weight: bold;"&gt;bad news for ATI&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;yet again&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;*note: this post is a follow-up to my &lt;a href="http://zachsaw.blogspot.com/2009/08/watching-hd-video-in-mpc-hc-dxva-for.html"&gt;post here&lt;/a&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;With the recent changes (additions) to the popular open-sourced H.264 encoder, x264, encoding at ref 16 with b-pyramid normal and weighted-p 2 (which is default), playback on ATI cards with the Arcsoft decoder will exhibit bad artifacts, as if using MPC-HC's internal DXVA decoder on ref 16 encodes. Meanwhile, it's all well and dandy over at the green camp. nVidia owners will find that their cards can decode these streams without even the slightest artifact, and with just about any DXVA decoders you could get your hands on - even the Win7 &lt;em&gt;Microsoft&lt;/em&gt; DTV-DVD. If you intend to encode with b-pyramid normal + weighted-p 2, you should reduce the ref to 12 (haven't tried anything in between) to ensure artifact-free DXVA playback with ATI+Arcsoft.&lt;br /&gt;&lt;br /&gt;So there you go, even with the best combo, ATI still looses out to nVidia. So again, my advice is, sell your ATI cards and stick to nVidia.&lt;br /&gt;&lt;br /&gt;Let's see if this is the year ATI catches up (My bet is on &lt;span style="font-style: italic;"&gt;NO&lt;/span&gt;. Perhaps &lt;span style="font-style: italic;"&gt;never&lt;/span&gt;. Frankly, ATI doesn't care about the HTPC scene).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-1959852323948999534?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/1959852323948999534/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=1959852323948999534' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/1959852323948999534'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/1959852323948999534'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2010/01/ati-dxva-with-arcsoft-still-behind.html' title='ATI DXVA with Arcsoft - Still Behind nVidia with Anything'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-2700085283888029248</id><published>2009-12-04T17:44:00.007+11:00</published><updated>2010-02-19T17:55:57.739+11:00</updated><title type='text'>A Precise Garbage Collector for C++ Builder</title><content type='html'>Ahh... Nothing rivals the &lt;span style="font-style: italic;"&gt;feeling of success&lt;/span&gt;!&lt;br /&gt;&lt;br /&gt;I've finally devised a precise garbage collector &lt;span style="font-style: italic;"&gt;(note: a precise GC is very different from conventional GCs such as BoehmGC - a precise GC does not suffer from ambiguities) &lt;/span&gt;for C++ Builder that is faster than boost's shared_ptr.&lt;br /&gt;&lt;br /&gt;That's a &lt;span style="font-weight: bold; font-style: italic;"&gt;bold claim &lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;indeed! And, by claiming that it is faster than shared_ptr, I'm also claiming that I can create a String class that is similarly faster than Delphi string, which is also reference counted like shared_ptr. And yes, the gc_ptr is thread-safe too.&lt;br /&gt;&lt;br /&gt;The trick is in the pointer assignment. In my precise GC, a pointer assign is no more expensive than its native equivalent - both are a single instruction operation, whereas a ref counted pointer requires a locked instruction and a refcount check, both of which are &lt;span style="font-style: italic;"&gt;*very*&lt;/span&gt; expensive on any processors, especially modern multicore ones. Most precise GC source codes you can freely download from the net get the assignment operator correct. However, the part where they lose out big time is in the gc_ptr's constructor and destructor with lock instructions and what not for multithread support (note that some don't even support multithread). These are often non-trivial and is the biggest cause of performance bottleneck.&lt;br /&gt;&lt;br /&gt;With a minimal c'tor and d'tor for my gc_ptr, I end up with an insanely fast precise GC engine which runs a .NET like framework in pure native mode. How about that - a managed framework that runs natively. None of the pain (both literally and performance-wise) of pinning objects and marshaling data going in and out of the managed world (anything that interfaces with the real world cannot have a non-fixed address - e.g. it's impossible to write a driver that allocates a .NET managed non-fixed buffer and let your system's DMA fill it up). Looks like .NET's GC team is paying the price of betting on the Stop-And-Copy algo (yes, the .NET GC is nothing more than an advanced version of the Stop-And-Copy GC) - &lt;span style="font-style:italic;"&gt;Update:&lt;/span&gt; *Correction, I was wrong. &lt;a href="http://vineetgupta.spaces.live.com/?_c11_BlogPart_BlogPart=blogview&amp;_c=BlogPart&amp;partqs=cat%3DCLR"&gt;The CLR GC&lt;/a&gt; is very similar to what I have implemented - in fact, even more so now that I have finished the generational version of the GC. Only notable thing is that my GC does not compact the heap after the sweep phase and does not support weak references or resurrection. Also, it relies on an external memory allocator.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Update 1: &lt;/span&gt;GcString is 16.5 times faster than AnsiString in an array reversal test in CB2010 - &lt;a href="http://zachsaw.blogspot.com/2010/01/c-builder-2010-optimizing-c-compiler.html"&gt;more info here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Update 2:&lt;/span&gt; FastMM (Rad Studio's default memory manager) is excruciatingly slow in a GC / managed app in multicore systems - &lt;a href="http://zachsaw.blogspot.com/2010/01/fastmm-slow-in-multithreaded-apps-on.html"&gt;more info here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-2700085283888029248?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/2700085283888029248/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=2700085283888029248' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/2700085283888029248'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/2700085283888029248'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2009/12/precise-garbage-collector-for-c-builder.html' title='A Precise Garbage Collector for C++ Builder'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-6427562848705109071</id><published>2009-11-10T17:28:00.004+11:00</published><updated>2011-07-06T21:39:32.374+10:00</updated><title type='text'>LANBench - Network Benchmark</title><content type='html'>Folks,&lt;br /&gt;&lt;br /&gt;I've just released the first version of LANBench here - &lt;a href="http://www.zachsaw.com/?pg=lanbench_tcp_network_benchmark"&gt;http://www.zachsaw.com/?pg=lanbench_tcp_network_benchmark&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/__HXL2AtXUkk/SvkKWNDvqiI/AAAAAAAAABs/vwXYGh2djTQ/s1600-h/lanbench_small.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5402360604586388002" src="http://3.bp.blogspot.com/__HXL2AtXUkk/SvkKWNDvqiI/AAAAAAAAABs/vwXYGh2djTQ/s400/lanbench_small.png" style="cursor: pointer; height: 317px; width: 300px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;Created it very quickly recently to find the maximum bandwidth of my gigabit switch / NICs in my LAN. LANBench mainly tests your network bandwith, but also to a certain extent gives you an idea of how much CPU is being spent in just transferring data back and forth between your machines.&lt;/div&gt;&lt;br /&gt;LANBench takes the HDD subsystem out of the equation and lets you test the raw speed of your network.&lt;br /&gt;&lt;br /&gt;Head over and check it out for more info.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-6427562848705109071?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/6427562848705109071/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=6427562848705109071' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/6427562848705109071'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/6427562848705109071'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2009/11/lanbench-network-benchmark.html' title='LANBench - Network Benchmark'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/__HXL2AtXUkk/SvkKWNDvqiI/AAAAAAAAABs/vwXYGh2djTQ/s72-c/lanbench_small.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-2985160587058920245</id><published>2009-10-16T16:16:00.003+11:00</published><updated>2009-10-16T17:07:43.334+11:00</updated><title type='text'>DynamicArray causing memory leak in C++ Builder</title><content type='html'>Recently I came across a memory leak which CodeGuard reported was due to DynamicArray&lt;foo&gt;.set_length(...).&lt;br /&gt;&lt;br /&gt;Well, DynamicArrays are referenced counted, exactly the same way as AnsiStrings / UnicodeStrings so really there's no way you could've missed free-ing it... ... &lt;span style="font-weight: bold; font-style: italic;"&gt;or is there?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;From experience, the first thing that came to mind was that since it's a referenced-counted container - and as with the rest, it's prone to circular-references.&lt;br /&gt;&lt;br /&gt;Consider the following code:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: rgb(0, 0, 153);"&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);"&gt;#include &amp;lt;vcl.h&amp;gt;&lt;br /&gt;#pragma hdrstop&lt;br /&gt;&lt;br /&gt;#include &amp;lt;iostream.h&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;&lt;br /&gt;&lt;br /&gt;struct&lt;/span&gt; TCircularRef&lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt;&lt;br /&gt;{&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;    DynamicArray&lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt;&amp;lt;&lt;/span&gt;&lt;/b&gt;TCircularRef&lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt;&amp;gt;&lt;/span&gt;&lt;/b&gt; refs&lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;    &lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt;~&lt;/span&gt;&lt;/b&gt;TCircularRef&lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt;() {&lt;/span&gt;&lt;/b&gt; cout&lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt; &amp;lt;&amp;lt;&lt;/span&gt;&lt;/b&gt;&lt;span style="color: rgb(0, 153, 0);"&gt; "here"&lt;/span&gt;&lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt; &amp;lt;&amp;lt;&lt;/span&gt;&lt;/b&gt; endl&lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt;; }&lt;br /&gt;};&lt;/span&gt;&lt;/b&gt;&lt;span style="color: rgb(0, 0, 153);"&gt;&lt;br /&gt;&lt;br /&gt;#pragma argsused&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(255, 102, 51);"&gt;int&lt;/span&gt;&lt;span style="color: rgb(153, 0, 0);"&gt; main&lt;/span&gt;&lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt;(&lt;/span&gt;&lt;/b&gt;&lt;span style="color: rgb(255, 102, 51);"&gt;int&lt;/span&gt; argc&lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt;,&lt;/span&gt;&lt;/b&gt;&lt;span style="color: rgb(255, 102, 51);"&gt; char&lt;/span&gt;&lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt;*&lt;/span&gt;&lt;/b&gt; argv&lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt;[])&lt;br /&gt;{&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;    DynamicArray&lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt;&amp;lt;&lt;/span&gt;&lt;/b&gt;TCircularRef&lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt;&amp;gt;&lt;/span&gt;&lt;/b&gt; base&lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt;;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;    base&lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt;.&lt;/span&gt;&lt;/b&gt;set_length&lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt;(&lt;/span&gt;&lt;/b&gt;&lt;span style="color: rgb(153, 153, 0);"&gt;1&lt;/span&gt;&lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt;);&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;    base&lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt;[&lt;/span&gt;&lt;/b&gt;&lt;span style="color: rgb(153, 153, 0);"&gt;0&lt;/span&gt;&lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt;].&lt;/span&gt;&lt;/b&gt;refs&lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt; =&lt;/span&gt;&lt;/b&gt; base&lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt;;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;    base&lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt;.&lt;/span&gt;&lt;/b&gt;set_length&lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt;(&lt;/span&gt;&lt;/b&gt;&lt;span style="color: rgb(153, 153, 0);"&gt;0&lt;/span&gt;&lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt;);&lt;/span&gt;&lt;/b&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;    &lt;span style="color: rgb(255, 0, 0);"&gt;return&lt;/span&gt;&lt;span style="color: rgb(153, 153, 0);"&gt; 0&lt;/span&gt;&lt;b&gt;&lt;span style="color: rgb(102, 51, 0);"&gt;;&lt;br /&gt;}&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;/pre&gt;With the&lt;span style="font-style: italic;"&gt; 'refs'&lt;/span&gt; member of &lt;span style="font-style: italic;"&gt;DynamicArray&amp;lt;TCircularRef&amp;gt; base &lt;/span&gt;referring back to itself &lt;span style="font-style: italic;"&gt;(base[0].refs = base),&lt;/span&gt; we ended up with a circular-ref. Yes, the cirular-ref in the above example is easy to spot and would probably never occur in the real world as well. In reality though, the circular-refs are much harder to spot and assignments change during run-time, depending on the code branch and/or timing. What's worse is that the reference could be held by an object of which you pass to another library written by someone else...&lt;br /&gt;&lt;br /&gt;Notice that the above sample code tries to break the circular-ref such that it would get cleaned-up with the line &lt;span style="font-style: italic;"&gt;base.set_length(0)&lt;/span&gt;? Alas, that was to no avail as its ref-count prior to set_length would be 2, which leaves us with a ref-count of 1 after that. Can we call &lt;span style="font-style: italic;"&gt;set_length(0) &lt;/span&gt;again then? No. Why? Because&lt;span style="font-style: italic;"&gt; 'base'&lt;/span&gt; no longer knows about the object it once held as the first &lt;span style="font-style: italic;"&gt;set_length(0)&lt;/span&gt; would've set it to point to the new memory location allocated by &lt;span style="font-style: italic;"&gt;set_length(0)&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Is there a way out? There're a few. But none to my liking. (You could Google for 'circular-reference' if you're interested to find a solution to this but it's not the intention of this article).&lt;br /&gt;As I have a garbage collector library ready to be used in any projects I create with C++ Builder, that was the solution I took. I simply replaced all DynamicArray with gc_array and allocated it with gcnew_array. With that, I no longer had to care about the hairy problem of who owns the object, who's responsible to free it and whether there's a potential circular reference problem in my code. What's more, &lt;span style="font-style: italic;"&gt;it's thread-safe&lt;/span&gt;, unlike DynamicArray. But that's a topic for another day.&lt;br /&gt;&lt;br /&gt;In short, this is my advice: &lt;span style="font-weight: bold;"&gt;Avoid DynamicArray at all costs!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/foo&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-2985160587058920245?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/2985160587058920245/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=2985160587058920245' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/2985160587058920245'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/2985160587058920245'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2009/10/dynamicarray-causing-memory-leak-in-c.html' title='DynamicArray causing memory leak in C++ Builder'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-2181780681741040981</id><published>2009-10-14T13:59:00.007+11:00</published><updated>2009-10-14T16:37:16.481+11:00</updated><title type='text'>Stepping into a Delphi package while debugging in C++ Builder</title><content type='html'>Well, you really should debug a Delphi package in Delphi. But once every so often, you'll find yourself using the Delphi package (controls / components) in C++ Builder and in need of tracing into the package while you're debugging your main application. By default, even if you compile the Delphi package in Debug mode, you won't be able to step into the Delphi source codes. These are the settings which will enable that (this guide is for CB2007 but it shouldn't be too different for other versions of C++ Builder):&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Go to the project options of the Delphi package.&lt;br /&gt;&lt;br /&gt;Select the &lt;span style="font-style: italic;"&gt;Compiler&lt;/span&gt; view on the left pane.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/__HXL2AtXUkk/StVAf7cMi6I/AAAAAAAAABU/SE9GNTQTTTA/s1600-h/stepping_delphi_package_compiler_options.png"&gt;&lt;img style="cursor: pointer; width: 333px; height: 250px;" src="http://3.bp.blogspot.com/__HXL2AtXUkk/StVAf7cMi6I/AAAAAAAAABU/SE9GNTQTTTA/s400/stepping_delphi_package_compiler_options.png" alt="" id="BLOGGER_PHOTO_ID_5392287046122113954" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Set the build config to &lt;span style="font-style: italic;"&gt;Debug mode&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Code generation:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Optimization = off&lt;/li&gt;&lt;li&gt;Stack frames = on&lt;/li&gt;&lt;/ul&gt;Debugging:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Debug information = on&lt;/li&gt;&lt;li&gt;Local symbols = on&lt;/li&gt;&lt;li&gt;Assertions = on&lt;/li&gt;&lt;li&gt;Use debug DCUs = on&lt;/li&gt;&lt;/ul&gt;Now select the &lt;span style="font-style: italic;"&gt;Linker &lt;/span&gt;view on the left pane.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/__HXL2AtXUkk/StVAgG0p7zI/AAAAAAAAABc/8bY7E2kTPPo/s1600-h/stepping_delphi_package_linker_options.png"&gt;&lt;img style="cursor: pointer; width: 333px; height: 250px;" src="http://1.bp.blogspot.com/__HXL2AtXUkk/StVAgG0p7zI/AAAAAAAAABc/8bY7E2kTPPo/s400/stepping_delphi_package_linker_options.png" alt="" id="BLOGGER_PHOTO_ID_5392287049177493298" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Map file:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Off&lt;/li&gt;&lt;/ul&gt;EXE and DLL options:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Include TD32 debug info = on&lt;/li&gt;&lt;li&gt;Include remote debug symbols = on&lt;/li&gt;&lt;/ul&gt;Linker output:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Generate all C++Builder files (you should already have this selected)&lt;/li&gt;&lt;/ul&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;br /&gt;You're done with the settings.&lt;br /&gt;&lt;br /&gt;Rebuild your package and your main app and you should now be able to step into the Delphi source.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-2181780681741040981?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/2181780681741040981/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=2181780681741040981' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/2181780681741040981'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/2181780681741040981'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2009/10/stepping-into-delphi-package-while.html' title='Stepping into a Delphi package while debugging in C++ Builder'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/__HXL2AtXUkk/StVAf7cMi6I/AAAAAAAAABU/SE9GNTQTTTA/s72-c/stepping_delphi_package_compiler_options.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-5319913587912860270</id><published>2009-08-18T17:22:00.007+10:00</published><updated>2009-10-20T18:40:14.019+11:00</updated><title type='text'>Watching HD Video in MPC-HC DXVA for ATI HD 4000 Series Card Owners</title><content type='html'>It's widely known that ATI card owners do not have the luxury of Nvidia card owners when it comes to playing HD video in MPC-HC in DXVA mode. With the built-in H.264/AVC video decoder, HD video such as 1920x800 with reference frames of 6 and above (i.e. L5.0 / L5.1 AVC streams) won't play (actually, it usually plays but with corrupted blocks and/or video freezing after a few seconds).&lt;br /&gt;&lt;br /&gt;What I've gathered from the comments of the readers of my &lt;a href="http://zachsaw.blogspot.com/2009/06/ati-hd-hardware-accelerated-dxva-for.html"&gt;original post about this issue&lt;/a&gt; and from months of testing using a plethora of mixing and matching on my own HTPC, I thought it'll save everyone some time for me to post a summary of what settings worked with Media Player Classic - Home Cinema. I previously said it's necessary to use PowerDVD 9 for DXVA with ATI HD 4000 series (such as my ATI HD 4350) but that is no longer true and that a better combination has been found thanks to those who contributed in my previous blog post. This is only for ATI card owners with UVD 2 (or newer) though. HD3000 series owners, you guys are out of luck unfortunately (you have AMD / ATI to thank).&lt;br /&gt;&lt;br /&gt;Here are some settings I've tested and their results:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Common settings:&lt;/span&gt;&lt;br /&gt;Pentium 4 HT 3.0GHz (underclocked to 2.0GHz, DDR2@222MHz (444MHz effective), HT disabled)&lt;br /&gt;ATI HD 4350 (Asus) - 512MB RAM @ 400MHz DDR2 (800MHz effective)&lt;br /&gt;Windows XP SP3 (latest Windows Update as of 18 August 2009)&lt;br /&gt;ATI Catalyst 9.7&lt;br /&gt;Media Player Classic - Home Cinema Build 1237 x86 (&lt;a href="http://aleksoid.tosei.ru/Dist/MPCHC_1237_x86.7z"&gt;download here&lt;/a&gt;)&lt;br /&gt;Haali Media Splitter externally installed (i.e. not using MPC-HC's one)&lt;br /&gt;DirectVobSub&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Here's what I've found.&lt;br /&gt;&lt;br /&gt;So long as you have the DXVA decoder output pin &lt;span style="font-style: italic; font-weight: bold;"&gt;directly connected to the renderer&lt;/span&gt;, you'll get proper working DXVA decode with up to 16 ref-frames for full HD streams (1920x1080) regardless of the renderer&lt;span style="font-style: italic;"&gt; (well, almost)&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;VMR7 (Windowed) = OK&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;VMR9 (Windowed) = &lt;/span&gt;&lt;span style="font-style: italic; color: rgb(255, 0, 0);"&gt;failed (pink vertical stripes with Motion Vectors)&lt;/span&gt;&lt;br /&gt;VMR7 Renderless = OK&lt;br /&gt;VMR9 Renderless = OK&lt;br /&gt;&lt;br /&gt;For the sake of discussion, let's use the VMR7 (Windowed) renderer. It has been proven to work with both Cyberlink's PDVD8 AVC decoder and ArcSoft's Video Decoder. With MPC's DXVA decoder, video with ref-frames of 12 and above will freeze after a few seconds of playback. Cyberlink's decoder suffers from occassional judder while ArcSoft's Video Decoder plays up to 16&lt;br /&gt;ref-frames in DXVA mode perfectly. The results vary when other renderers are used. For example, the combo of VMR9 Renderless + MPC's DXVA decoder yielded the same pink vertical stripes.&lt;br /&gt;&lt;br /&gt;I still have not found a combination that would get subtitles working without causing issues with DXVA decode. Under VMR9 Renderless + ArcSoft + MPC-HC internal subtitles renderer, the video would playback in like half the speed! Frames are decoded and rendered correctly though. If anyone has any idea how to solve that, I'd be all ears!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; font-weight: bold;"&gt;Update:&lt;/span&gt; With ATI Catalyst 9.8, the combo of "VMR9 Renderless + ArcSoft + MPC-HC internal subtitles renderer" now works properly. Although with DirectVobSub, the half-frame-rate playback issue is still there.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; font-weight: bold;"&gt;Update 2:&lt;/span&gt; It appears that, in order to get the results I've published here, you'll need to 'initialize' the ATI driver for proper operation of DirectX by opening the Catalyst Control Center each time you start / restart your PC (not sure about stand-by / hibernate). I was taken by surprise yesterday for not doing so - I got a blank white screen instead of the normal proper video playback. Once I opened the CCC (and closed it), reopening MPC-HC and the video then worked fine. &lt;span style="font-style: italic;"&gt;*Bravo ATI!* You've got my standing ovation.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Anyway, this is the settings that I've found to work under MPC-HC without subtitles:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;MPC-HC settings:&lt;/span&gt;&lt;br /&gt;Renderer - VMR7 (Windowed)&lt;br /&gt;Auto load subtitles - false (see &lt;span style="font-style: italic;"&gt;Update&lt;/span&gt; above)&lt;br /&gt;DirectVobSub options - disable autoload subtitles&lt;br /&gt;Use ArcSoft Video Decoder as your AVC/H.264 decoder&lt;br /&gt;Use AC3Filter directshow decoder&lt;br /&gt;&lt;br /&gt;Again, make sure your DXVA decoder's output pin is connected directly to the renderer's input pin. This means under your DirectVobSub filter options, make sure it never loads subtitles and that it is &lt;span style="font-style: italic;"&gt;blocked &lt;/span&gt;under your MPC-HC external filters page. The following is what I've configured under that page:&lt;br /&gt;&lt;br /&gt;Arcsoft video decoder - &lt;span style="font-style: italic;"&gt;preferred&lt;/span&gt;.&lt;br /&gt;AC3Filter - &lt;span style="font-style: italic;"&gt;preferred&lt;/span&gt;.&lt;br /&gt;DirectVobSub - &lt;span style="font-style: italic;"&gt;blocked&lt;/span&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-5319913587912860270?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/5319913587912860270/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=5319913587912860270' title='37 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/5319913587912860270'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/5319913587912860270'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2009/08/watching-hd-video-in-mpc-hc-dxva-for.html' title='Watching HD Video in MPC-HC DXVA for ATI HD 4000 Series Card Owners'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>37</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-8234117336409199575</id><published>2009-06-10T18:24:00.004+10:00</published><updated>2009-06-10T22:41:08.301+10:00</updated><title type='text'>NTFS A Journaling File System</title><content type='html'>If NTFS &lt;span style="font-weight: bold;"&gt;is&lt;/span&gt; a &lt;a href="http://en.wikipedia.org/wiki/Journaling_file_system"&gt;journaling file system&lt;/a&gt; &lt;span style="font-style: italic;"&gt;(if you don't know what it is, I suggest you read it up first before continuing)&lt;/span&gt; then why do we have to perform such an extensive chkdsk (checkdisk or scandisk) every time the system does not shutdown cleanly (due to a power or system failure)?&lt;br /&gt;&lt;br /&gt;A journaling file system should always have their file system in a consistent state. For example, the MFT (Master File Table) should never indicate a cluster as being occupied while it in fact isn't. But so often when we don't cleanly shut Windows (2k or XP for that matter) down, the checkdisk that runs when Windows boots up again will find the exact inconsistency as described above.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Q: So is NTFS a journaling file system?&lt;/span&gt;&lt;br /&gt;A: Yes.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Q: Then why is NTFS inconsistent?&lt;/span&gt;&lt;br /&gt;A: NTFS is &lt;span style="font-style: italic; font-weight: bold;"&gt;ONLY&lt;/span&gt; inconsistent (or unsafe) when an unclean shutdown occurs if you are running Windows 2K or XP. Microsoft for some reason (most likely performance related) chose not to enable the journaling function for non-server version of Windows. Windows Vista, however, enables it by default (I'm assuming Windows 7 does as well).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Q: Should I enable NTFS journals then?&lt;/span&gt;&lt;br /&gt;A: It's up to you really, but personally I have a higher preference for the safety of my data, and I can't tell the speed difference between having it enabled / disabled on my hard drives, so it's a definite &lt;span style="font-style: italic;"&gt;Yes&lt;/span&gt; for me.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Q: How do I enable NTFS journals?&lt;/span&gt;&lt;br /&gt;A: Go to command prompt and run the following command for each NTFS partition:&lt;br /&gt;&lt;blockquote style="color: rgb(102, 102, 204);"&gt;fsutil usn createjournal m=1000 a=100 C:&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;span style="font-style: italic;"&gt;Q: How do I check if my NTFS partition has journals enabled?&lt;/span&gt;&lt;br /&gt;A: Run the following command:&lt;br /&gt;&lt;blockquote style="color: rgb(102, 102, 204);"&gt;fsutil usn queryjournal C:&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;span style="font-style: italic;"&gt;Q: Does that mean I don't have to run chkdsk any more?&lt;/span&gt;&lt;br /&gt;A: Not really. Just that you don't have to do it every time you fail to shutdown your computer properly. You should still do it occasionally (like defrag).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Q: How do I disable chkdsk on start-up?&lt;/span&gt;&lt;br /&gt;A: &lt;a href="http://www.raymond.cc/blog/archives/2008/02/23/disable-or-stop-auto-chkdsk-during-windows-startup/"&gt;http://www.raymond.cc/blog/archives/2008/02/23/disable-or-stop-auto-chkdsk-during-windows-startup/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-8234117336409199575?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/8234117336409199575/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=8234117336409199575' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/8234117336409199575'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/8234117336409199575'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2009/06/ntfs-journaling-file-system.html' title='NTFS A Journaling File System'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-3371353355967815603</id><published>2009-06-10T18:07:00.004+10:00</published><updated>2009-06-10T18:18:17.359+10:00</updated><title type='text'>Catalyst 9.6 ATI 4000 HD Series Still Behind NVIDIA For HTPC</title><content type='html'>ATI is still behind NVIDIA for HTPC even with the latest leaked Catalyst 9.6 - It still fails to decode L5.0 / L5.1 high profile AVC video in DXVA mode (using MPC-HC for example). This means that for HTPC, a NVidia 8600GT / 9400GT would be the better choice over ATI HD 4800 / 4700 / 4600 / 4500 / 4300 series.&lt;br /&gt;&lt;br /&gt;If you're looking to build a HTPC, go for NVIDIA.&lt;br /&gt;&lt;br /&gt;While ATI heavily promotes its HTPC capabilities, the truth is it is still very far behind NVIDIA.&lt;br /&gt;&lt;br /&gt;NVIDIAusers have been enjoying this for about 6 months.&lt;br /&gt;&lt;br /&gt;@NVIDIA marketing, you could consider starting a "The way it's meant to be watched" program. Doesn't look like ATI has anything left in them to pose a threat whatsoever.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-3371353355967815603?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/3371353355967815603/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=3371353355967815603' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/3371353355967815603'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/3371353355967815603'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2009/06/catalyst-96-ati-4000-hd-series-still.html' title='Catalyst 9.6 ATI 4000 HD Series Still Behind NVIDIA For HTPC'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-5976343472525794376</id><published>2009-06-02T14:40:00.019+10:00</published><updated>2010-01-10T14:35:12.759+11:00</updated><title type='text'>ATI HD Hardware Accelerated DXVA for H.264 AVC L5.0 / L5.1</title><content type='html'>&lt;span style="font-weight: bold;"&gt;HOW TO:&lt;/span&gt; Get hardware accelerated DXVA playback of HD AVC High Profile L5.0 / L5.1 MKV / MP4 Files on ATI HD Series.&lt;br /&gt;&lt;br /&gt;Well, technically speaking, not DXVA, but hardware accelerated playback of L5.0 / L5.1 files nevertheless. &lt;span style="font-style: italic;"&gt;(update: it *is* DXVA - not sure just yet why some decoders work and some don't - possibly because some decoders send more compliant bitstream?)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I've recently built a HTPC from an old Pentium 4 HT. I know it has not enough grunt to decode AVC High Profile video, so I bought an ATI 4350 HD in the hope that it'll do all video decoding on its GPU (or UVD).&lt;br /&gt;&lt;br /&gt;To my disappointment, I found this (&lt;a href="http://forums.amd.com/game/messageview.cfm?catid=279&amp;amp;threadid=106911&amp;amp;enterthread=y"&gt;ATI does not support AVC with High Profile above L4.1&lt;/a&gt;) &lt;span style="font-style: italic;"&gt;after &lt;/span&gt;I bought the card. All my encodes are done with L5.1 as my other PC is a Core 2 Duo which has an NVidia 9600GT. For some reason, the NVidia driver is able to support DXVA for AVC High Profile L5.1, so I simply assumed ATI would be the same. Turns out that the maximum the ATI would do is L4.1 (There's a Quantum of Solace trailer encoded at L5 to test here - &lt;a href="http://nunnally.ahmygoddess.net/watching-h264-videos-using-dxva/"&gt;http://nunnally.ahmygoddess.net/watching-h264-videos-using-dxva/&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;Regardless of which decoder I use, my P4 HT simply isn't powerful enough to playback these files (CPU hits 100% all the time and frames drop very frequently).&lt;br /&gt;&lt;br /&gt;Luckily for us ATI owners,&lt;span style="font-size:100%;"&gt; &lt;/span&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;there &lt;span style="font-style: italic;"&gt;is &lt;/span&gt;a solution&lt;/span&gt;. With &lt;span style="font-weight: bold;font-size:100%;" &gt;PowerDVD9 and Catalyst 9.5&lt;/span&gt;, I finally found a combination that would get 1920x1080 HD videos with ref-frames &gt; 4 to play without taxing my CPU. In fact, I was pleasantly surprised when I reran the Quantum of Solace test video -- my CPU remained at 2% utilization!&lt;br /&gt;&lt;br /&gt;I recommend the following setup for ATI users:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;PowerDVD 9 &lt;span style="font-weight: bold; font-style: italic;"&gt;build 1530&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(255, 102, 102);"&gt;==&gt; Must be this build! Other builds will not work&lt;/span&gt;&lt;/li&gt;&lt;li&gt;ATI Catalyst 9.5 (non-hotfix version)&lt;/li&gt;&lt;li&gt;AC3Filter&lt;/li&gt;&lt;li&gt;Haali Media Splitter (to playback MKV files) &lt;span style="color: rgb(255, 102, 102);"&gt;==&gt; version 1.9.42.1 (or later)&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;*** New:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;If you prefer to &lt;a href="http://zachsaw.blogspot.com/2009/08/watching-hd-video-in-mpc-hc-dxva-for.html"&gt;use Media Player Classic - Home Cinema (MPC-HC), see this&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;*** Note1:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Rename .MKV to .MP4 to get PowerDVD to playback MKV files.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;*** Note2:&lt;/span&gt; &lt;span style="font-weight: bold; font-style: italic;"&gt;&lt;br /&gt;&lt;br /&gt;Important &lt;/span&gt;- No other filters (e.g. FFDShow / CoreAVC / Codec Packs) should be installed in your system!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Try it out yourself (you could download the trial version of PowerDVD 9).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;MAKE SURE &lt;/span&gt;&lt;/span&gt;you &lt;span style="font-weight: bold;"&gt;DO NOT&lt;/span&gt; have any other filters installed (for example, CoreAVC or FFDShow which may have a higher merit than PowerDVD's own filter) or PowerDVD will not use its internal H264 decoder. Also, when opening MKV files, PowerDVD will complain that &lt;a href="http://www.dll-files.com/dllindex/dll-files.shtml?xvidcore"&gt;&lt;span style="font-style: italic;"&gt;xvidcore.dll&lt;/span&gt;&lt;/a&gt; could not be found, but will continue playing the video just fine. If you want to suppress the error message, simply download &lt;a href="http://www.dll-files.com/dllindex/dll-files.shtml?xvidcore"&gt;&lt;span style="font-style: italic;"&gt;xvidcore.dll&lt;/span&gt;&lt;/a&gt; and put it in the same folder as the PowerDVD executable (e.g. &lt;em&gt;c:\Program Files\CyberLink\PowerDVD\)&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Leave a comment to let me know if it does / doesn't work for you with your card's configuration and OS, for example:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;HD 4350 PCIe x16 512MB&lt;/li&gt;&lt;li&gt;WinXP SP3&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;*** Update 1:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://rapidshare.com/files/82525583/killa.sampla.x264.mkv.html"&gt;This clip (the 'Bird Scene' from Planet Earth)&lt;/a&gt; is the ultimate L5.1 super high bitrate MKV sample. On my nVidia 9600GT setup with a E7200 CPU @ 3.6GHz, it uses 50% of the CPU (playback using MPC - Home Cinema with driver supporting L5.1 bitstream DXVA). On my Pentium 4 HT (single core CPU) and the HD 4350 setup, I get 25% CPU usage. That is simply mind-boggling! What can we conclude? ATI is A LOT better at decoding H264 streams?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;*** Update 2:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I've found that PowerDVD has a problem with H264 encoded files that have been tagged with the wrong IDC. For example, if the file actually contains a high profile L5.1 bitstream but its IDC tag is marked incorrectly (e.g. L4.1), you will get stuttering problems. If that happens, you'll have to change the file's IDC tag back to L5.1 using &lt;a href="http://www.mediafire.com/?mc2dbsdgzvg"&gt;IDC Multi Changer&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;*** Update 3:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;While testing my configuration with a ref-frame 12 encode at 1920x800, I found that certain scenes (usually panning slowly) would judder (i.e. a couple of frames get dropped) and they always happen at the exact same time code. I tried remuxing the .mkv file to .ts / .m2ts but to no avail. I also increased the input buffer size to 100000KB from 8192KB in the Haali Media Splitter settings, which also did not help. Having spent a few hours on it, I finally decided to look at PowerDVD's settings itself. Apparently, under Advanced Video Preferences (Right-click Main Screen, click on Configuration, select the &lt;em&gt;Video&lt;/em&gt; tab, click &lt;em&gt;Advanced&lt;/em&gt;...), there's a group box called &lt;span style="font-style: italic;"&gt;Video Quality&lt;/span&gt;. I had &lt;span style="font-style: italic;"&gt;Normal Mode &lt;/span&gt;selected from before when I was using PowerDVD without AVIVO. Setting it to &lt;span style="font-style: italic;"&gt;Best Mode&lt;/span&gt; solves the problem. GPU and CPU usages remain unchanged at 6-8% and ~12% (DTS is being decoded in software) respectively.&lt;br /&gt;&lt;br /&gt;I can only make an educated guess on the reason behind the judder. Video Quality relates to the post processing / de-interlacing / pulldown settings. The judder which I picked up on slow panning scenes are probably due to the lack of pulldown under &lt;span style="font-style: italic;"&gt;Normal Mode&lt;/span&gt;. When set to Best Mode, pulldown (&lt;a href="http://en.wikipedia.org/wiki/24p#Conversion_of_24p_to_NTSC-based_frame.2Ffield_rates"&gt;what is this?&lt;/a&gt;) is activated to match the 24fps source to my 1080i LCD panel (1920x1080 at 30Hz).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;*** Update 4:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A full update on this topic has been &lt;a href="http://zachsaw.blogspot.com/2009/08/watching-hd-video-in-mpc-hc-dxva-for.html"&gt;posted here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-5976343472525794376?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/5976343472525794376/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=5976343472525794376' title='89 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/5976343472525794376'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/5976343472525794376'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2009/06/ati-hd-hardware-accelerated-dxva-for.html' title='ATI HD Hardware Accelerated DXVA for H.264 AVC L5.0 / L5.1'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>89</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-1428398745157511982</id><published>2009-03-25T18:35:00.007+11:00</published><updated>2011-07-06T21:40:40.342+10:00</updated><title type='text'>Cracking Signed ActiveX Controls</title><content type='html'>Ever come across an ActiveX control you can't afford to buy but wish to use for your own little pet project? Especially those readily available for download, but annoys the hell out of you when you try to use it as it keeps painting "Evaluation Version" all over itself?&lt;br /&gt;&lt;br /&gt;Well, from time to time, I develop pet projects to keep myself entertained. Being a perfectionist, I just can't stand to see the "Eval Version" message appearing on my applications. Yes, the sole purpose of these apps are just so I could marvel at myself when I finish them, but how would I be able to do that if I leave the "Eval Version" message lying around? I want that newly polished, super shiny feeling you get when you finish something you can be proud of.&lt;br /&gt;&lt;br /&gt;So I set out with a mission - to crack the ActiveX control that is sprinkling all those "Eval Version" on itself.&lt;br /&gt;&lt;br /&gt;Surprisingly, cracking the several ActiveX controls I've used isn't all that hard - so long as you know a little x86 ASM and have the right tools (such as the &lt;a href="http://www.zachsaw.com/downloads/W32DSM89.zip"&gt;W32Dasm for Windows&lt;/a&gt;). Most ActiveX controls are smart enough to prevent simple cracks such as looking up the "Eval Version" message and skipping them via a jmp, but in order to draw the text on the screen, the message would still have to be decrypted somehow and placed in the memory. And, THAT is usually the weakest link. What I usually do is, I'd change the opcodes directly in the memory while I step through the ASM in an IDE (I use CodeGear RAD Studio 2007) so I could see the effects immediately. If things go wrong, I'd simply break out of the debug session and restart.&lt;br /&gt;&lt;br /&gt;Once you have cracked it, use a hex editor to change the bytes you've changed in the IDE - you'll have to note down a few instructions before and after the ones you're about to change when you were debugging in the IDE, as there may be more than one occurrence of the bytes you search for. For example, there could be numerous occurrences of "33C9" hex, which translates to "xor ecx,ecx".&lt;br /&gt;&lt;br /&gt;For normal exe / dll files, patching the file and then doing a final test would've been the end of it. With a signed ActiveX file, however, you'd find that if you try to use the ActiveX in your IDE, it'll complain that the ActiveX cannot be loaded. That simply means that the hash (usually SHA1) in the ActiveX no longer matches the file - and rightly so! This is easily circumvented though - all you need to do is re-sign the file, and then re-import that into your IDE.&lt;br /&gt;&lt;br /&gt;Lucky for us, there's no need to un-sign the ActiveX file before re-signing it with our own cert. Here's a link with step-by-step guide for signing an ActiveX file - &lt;a href="http://www.pantaray.com/signcode.html"&gt;http://www.pantaray.com/signcode.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In the next installment, I'd probably blog about cracking signed .NET assemblies, if responses are good for this one.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-1428398745157511982?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/1428398745157511982/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=1428398745157511982' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/1428398745157511982'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/1428398745157511982'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2009/03/cracking-signed-activex-controls.html' title='Cracking Signed ActiveX Controls'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-194555922084028017</id><published>2009-03-18T10:49:00.001+11:00</published><updated>2009-03-18T10:53:02.263+11:00</updated><title type='text'>WinAPI functions and GetLastError / WSAGetLastError</title><content type='html'>Having been using WinAPI for more than a decade, I was surprised with myself for not being more careful with the return value and GetLastError's error code following a WinAPI call. Granted the bug I was facing was not easy to root cause, but that was no excuse as I should've been more careful when coding. We all make mistakes but the difference between a good and bad programmer is that the former is constantly alert of the pitfalls when coding &lt;span style="font-style: italic;"&gt;(read: edging toward paranoia)&lt;/span&gt; while the latter simply hacks away hoping things will work out fine.&lt;br /&gt;&lt;br /&gt;The thing to keep in mind is WinAPI functions don't set Last Error Code unless the function's return value is FALSE (zero) even if GetLastError sometimes returns ERROR_SUCCESS (e.g. TlsGetValue) - it does &lt;span style="font-weight: bold;"&gt;NOT &lt;/span&gt;mean that WinAPI functions will set Last Error Code to ERROR_SUCCESS regardless. If you've made the assumption that all WinAPI function calls will reset Last Error Code to ERROR_SUCCESS (or NO_ERROR) following a call, then chances are your code will work fine so long as the function has not encountered an error, but will fail as soon as it does, because subsequent calls to the function will appear like an error if you rely on just GetLastError for the result. You should &lt;span style="font-weight: bold;"&gt;ALWAYS read the documentation&lt;/span&gt; of each function as their Return Value varies and remember that there will be one scenario where Last Error Code won't be set.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-194555922084028017?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/194555922084028017/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=194555922084028017' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/194555922084028017'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/194555922084028017'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2009/03/winapi-functions-and-getlasterror.html' title='WinAPI functions and GetLastError / WSAGetLastError'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-3404154512869257892</id><published>2009-02-22T18:25:00.003+11:00</published><updated>2009-02-22T18:56:17.539+11:00</updated><title type='text'>Avoid AMD at all costs (and Gigabyte too)</title><content type='html'>This goes for everything - GPU / graphics cards, CPU, software, and even shares.&lt;br /&gt;&lt;br /&gt;I recently got my first AMD graphics card and found it to be extremely bad in quality - both the hardware itself as well as the drivers.&lt;br /&gt;&lt;br /&gt;My first card was from MSY (VIC Australia) - it was a Gigabyte 4350 (AMD / ATI card). Plug it in to my old machine which was sidelined recently due to an upgrade, but had been running ECS nVidia 9600, I found that the GDDR2 chips are defective. In fact, booting into Vista caused the graphics card to lock-up entirely. After some investigations, I discovered that there are a few frequencies that the card chooses depending on the state of the card - it boots up with a 200MHz GDDR2 RAM frequency (400MHz effective) and runs 3D (load) with a 500MHz (max default) frequency.&lt;br /&gt;&lt;br /&gt;Keep in mind that this is the default frequencies (read: NON-OC'ed) from Gigabyte. Just to get a closure and confirm that it is in fact defective RAM as I had suspected, I flashed the video card BIOS with one that runs the RAM at a lower speed and found that it worked. The maximum speed I could get it to run at was 300MHz - a far cry from the advertised 500MHz (1000MHz effective)! Heck, 300MHz? My OLD machine is running 800MHz DDR2 (1600MHz effective). And to put that into perspective, my nVidia 9600GT works perfectly with an overclocked GDDR2 at 1200MHz (2400MHz effective)! Gigabyte and AMD - shame on you!&lt;br /&gt;&lt;br /&gt;I'd also avoid Gigabyte at all costs. So far I've owned 5 Gigabyte motherboards - none of which I could go to the shop, purchase it, and plonk in a CPU and install OS. Gigabyte = troublesome. I'd have to return it and get it exchanged for a new one. It's not the 2nd board that'll work but the 3rd! Most won't even get past POST. Apparently, it's no different with a graphics card.&lt;br /&gt;&lt;br /&gt;Back to the graphics card issue - this time the shop ran out of the graphics card - so I got to the 2nd, and that did not work either. Eventually we settled for a refund. I immediately drop by Centrecom and got myself an Asus 4350. Dropping it into my system and it immediately worked - 3DMark06 ran flawlessly (discounting the performance of course).&lt;br /&gt;&lt;br /&gt;Then, I decided to watch some blu-ray contents and to my surprise, it stuttered like mad. Why? Because it's using my old CPU to decode in software - no UVD! Keep in mind this is with Media Player Classic - HC, which used to accelerate blu-ray with my nVidia 9600GT (which was running a BETA driver, as opposed to the AMD 4350 which was running the official Catalyst 9.1).&lt;br /&gt;&lt;br /&gt;After spending days reinstalling Windows and drivers, I still had no luck. Eventually, I stumbled upon AMD's own forum while looking for solutions and found that people have been complaining about the same thing - Catalyst 9.1 broke all DXVA support in Windows XP! I immediately did a driver feedback via their website and told them the issue.&lt;br /&gt;&lt;br /&gt;A month later, Catalyst 9.2 was released. Still broken!&lt;br /&gt;&lt;br /&gt;I bought this card for the sole purpose of accelerating HD contents - if the card can't do it, then stop advertising it! At least in Australia, the law protects consumers in this regard - we can return it if we find that it does not do what it's advertised to. I'm sure in US consumers have no rights whatsoever and get lied to with false advertisements.&lt;br /&gt;&lt;br /&gt;My advice, stick with Intel and nVidia. Heck, even Intel's G45 integrated gfx would've been a LOT better - yes there're some issues with 24Hz playback (1920x1080p 24Hz that is, and not all TVs support that) but for all other modes, it accelerates HD contents flawlessly, just as advertised.&lt;br /&gt;&lt;br /&gt;But, with that said, I'd like people (read fanboys) to continue buying AMD just to keep Intel and nVidia in check (quality, performance and price). :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-3404154512869257892?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/3404154512869257892/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=3404154512869257892' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/3404154512869257892'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/3404154512869257892'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2009/02/avoid-amd-at-all-costs.html' title='Avoid AMD at all costs (and Gigabyte too)'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-6812980065477962225</id><published>2009-02-17T18:47:00.002+11:00</published><updated>2009-02-17T18:54:29.252+11:00</updated><title type='text'>Performance Monitor / Counters not working in XP</title><content type='html'>Strangely enough, the XP machine I use in the office has never had the performance counters working.&lt;br /&gt;&lt;br /&gt;If you tried running SysInternal's pslist (I use it mostly so I could do pskill for the issue I &lt;a href="http://zachsaw.blogspot.com/2009/02/windows-hangs-while-debugging-how-to.html"&gt;blogged about here&lt;/a&gt;), you'll get a message saying, &lt;span style="font-style: italic;"&gt;"Processor performance object not found on &lt;machine&gt; Run Exctrlst from the Windows Resource Kit to repair the performance counters."&lt;/machine&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Or, if you try running the Performance MMC snap-in (In XP it's under &lt;span style="font-style: italic;"&gt;Control Panel --&amp;gt; Administrative Tools --&amp;gt; Performance&lt;/span&gt;), you'll get no response for a minute or two, and when the window appears, the red line in the graph will not move (and you won't be able to add any graphs for monitoring either).&lt;br /&gt;&lt;br /&gt;Or, if you try to use performance counters in .NET (e.g. for CPU Usage monitoring), you'll get an exception complaining performance counters are not available.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; font-weight: bold;"&gt;What's the problem?&lt;/span&gt; To be honest, I don't know and I don't care enough to find out, but I do care enough to make it work.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Here's how:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Install Windows Support Tools which could be found on Microsoft's website (here's the XP SP2 version which will also run in SP3 - &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=49ae8576-9bb9-4126-9761-ba8011fabf38&amp;amp;displaylang=en"&gt;http://www.microsoft.com/downloads/details.aspx?FamilyID=49ae8576-9bb9-4126-9761-ba8011fabf38&amp;amp;displaylang=en&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;Once you've installed it, run &lt;span style="font-style: italic;"&gt;exctrlst.exe&lt;/span&gt;&lt;/li&gt;&lt;li&gt;Make sure that &lt;span style="font-style: italic;"&gt;PerfProc &lt;/span&gt;and &lt;span style="font-style: italic;"&gt;PerfOS &lt;/span&gt;have their Performance Counters enabled (select the entry and verify that the "Performance Counters Enabled" option is checked)&lt;/li&gt;&lt;li&gt;Once you've done that, close the window and run PsList again to see if it works&lt;/li&gt;&lt;li&gt;If not, continue reading. You'll need a copy of Windows installation CD for the following steps&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;PsList is still not working:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What we'll be doing is manually replace some of the files with the original ones (I'm guessing at some point, Microsoft released a hotfix which broke the files).&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Go to the &lt;span style="font-style: italic;"&gt;I386 &lt;/span&gt;folder on your Windows CD&lt;/li&gt;&lt;li&gt;Make a backup of &lt;span style="font-style: italic;"&gt;C:\Windows\System32\perfc009.dat&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;C:\Windows\System32\perfh009.dat&lt;/span&gt; (we'll be overwriting them)&lt;/li&gt;&lt;li&gt;Expand &lt;span style="font-style: italic;"&gt;perfc009.da_&lt;/span&gt; to &lt;span style="font-style: italic;"&gt;C:\Windows\System32\perfc009.dat&lt;/span&gt; (&lt;span style="font-style: italic;"&gt;expand perfc009.da_ C:\Windows\System32\perfc009.dat&lt;/span&gt;)&lt;/li&gt;&lt;li&gt;Expand &lt;span style="font-style: italic;"&gt;perfh009.da_&lt;/span&gt; to &lt;span style="font-style: italic;"&gt;C:\Windows\System32\perfh009.dat&lt;/span&gt; (&lt;span style="font-style: italic;"&gt;expand perfh009.da_ C:\Windows\System32\perfh009.dat&lt;/span&gt;)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Try running PsList again - it should work now.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;If all of the above failed, there's one other resource you could read up - &lt;a href="http://support.microsoft.com/kb/300956"&gt;How to manually rebuild Performance Counter Library values&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-6812980065477962225?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/6812980065477962225/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=6812980065477962225' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/6812980065477962225'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/6812980065477962225'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2009/02/performance-monitor-counters-not.html' title='Performance Monitor / Counters not working in XP'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-1410641550049847162</id><published>2009-02-17T18:32:00.004+11:00</published><updated>2009-02-17T18:46:39.020+11:00</updated><title type='text'>Windows hangs while debugging - How to regain Windows GUI responsiveness</title><content type='html'>Following up on the issue I blogged about a while ago about &lt;a href="http://zachsaw.blogspot.com/2009/02/debugging-multithreaded-applications-in.html"&gt;Windows locking up while debugging multithreaded applications&lt;/a&gt; under CodeGear RAD Studio, someone from the CodeGear IDE forum suggested that Command Prompt would still work responsively. Some guessed that it could be due to Windows running out of GDI handles (how that is related to the debugger is beyond me, so if someone cares to explain, I'm all ears) and this proves to be quite correct.&lt;br /&gt;&lt;br /&gt;Apparently, this problem has been confirmed on Microsoft Visual C++ 6 up to Visual Studio 2003 (have yet to heard anyone commenting about 2005 or 2008, so they could also be affected) and Borland C++ Builder 6 up to CodeGear C++ Builder 2009. So far I've gathered that this happens on both Windows Server 2003 and XP, regardless of the level of service pack installed.&lt;br /&gt;&lt;br /&gt;In order to get your machine responsive again, you'd have to kill the debugger (which is BDS.exe / BCB.exe for CodeGear / Borland and MSDEV.exe / DevEnv.exe for Microsoft). The painful way is to bring up Windows Task Manager (Ctrl+Shift+ESC to save you a few minutes of right-clicking on the taskbar and waiting for the GUI to appear) and select the process to terminate. Going through that process will take you somewhere around 5 to 10 minutes. There's a simpler way though (courtesy of Ingo Zettl - thanks!), which requires less than 5 seconds if you have everything setup before starting your debug session:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Install SysInternals PsTools which could be found here &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb896649.aspx"&gt;http://technet.microsoft.com/en-us/sysinternals/bb896649.aspx&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Start command prompt, go to the PsTools folder and leave the command window open&lt;/li&gt;&lt;li&gt;Start debugging&lt;/li&gt;&lt;li&gt;Once you hit the OS+debugger bug, Alt+TAB straight to the command window (beware: if you inadvertently Alt+TAB to the wrong window, you'll waste a few minutes waiting for Windows to respond)&lt;/li&gt;&lt;li&gt;Run PsList - you should get a list of processes running on your machine&lt;/li&gt;&lt;li&gt;Lookup the Pid (Process ID) of your debugger (e.g. BDS.exe)&lt;/li&gt;&lt;li&gt;Run PsKill e.g. - pskill -t &lt;span style="font-style: italic;"&gt;[pid]&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;At this point, your machine should regain responsiveness.&lt;br /&gt;&lt;br /&gt;We all have Microsoft to thank for this &lt;span style="font-style: italic;"&gt;'little'&lt;/span&gt; inconvenience which makes life &lt;span style="font-style: italic;"&gt;'fun'&lt;/span&gt; for us Win32 software developers.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-1410641550049847162?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/1410641550049847162/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=1410641550049847162' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/1410641550049847162'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/1410641550049847162'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2009/02/windows-hangs-while-debugging-how-to.html' title='Windows hangs while debugging - How to regain Windows GUI responsiveness'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-7471772219983801940</id><published>2009-02-05T11:42:00.005+11:00</published><updated>2009-02-06T16:27:07.860+11:00</updated><title type='text'>Debugging multithreaded applications in CodeGear hangs Windows XP Kernel</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/__HXL2AtXUkk/SYo2bGqHtTI/AAAAAAAAAA8/NunhAz2px4I/s1600-h/XP_CodeGear_Debugging.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 320px;" src="http://4.bp.blogspot.com/__HXL2AtXUkk/SYo2bGqHtTI/AAAAAAAAAA8/NunhAz2px4I/s400/XP_CodeGear_Debugging.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5299107750826456370" /&gt;&lt;/a&gt;&lt;br /&gt;When debugging a multithreaded application in CodeGear under Windows XP, users have found that the debugger locks up the Windows kernel frequently (twice a day for me). When the Windows kernel locks up (actually slows to a crawl), if you hit CTRL+SHIFT+ESC to bring up the task manager, it will not come up until after a few minutes. While waiting, hit CTRL+SHIFT+ESC say 50 times. You'll get 50 task managers appearing after the first one pops up.&lt;br /&gt;&lt;br /&gt;At this point, Windows XP kernel is still painfully slow - Task Manager shows no CPU usage, kernel's just 99.9% locked up. With that 0.1% responsiveness, you'll be able to slowly terminate bds.exe and again, wait ages for the confirmation window to pop up. Once bds.exe is terminated, your system will be fully responsive again. You'll be left with the above screen shot.&lt;br /&gt;&lt;br /&gt;Good job CodeGear, for your ability to bring XP kernel to its knees...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;* Update: Just upgraded to XP SP3 from SP2, and problem persists.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-7471772219983801940?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/7471772219983801940/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=7471772219983801940' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/7471772219983801940'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/7471772219983801940'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2009/02/debugging-multithreaded-applications-in.html' title='Debugging multithreaded applications in CodeGear hangs Windows XP Kernel'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/__HXL2AtXUkk/SYo2bGqHtTI/AAAAAAAAAA8/NunhAz2px4I/s72-c/XP_CodeGear_Debugging.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-7534890739757038473</id><published>2009-01-23T18:27:00.002+11:00</published><updated>2009-01-23T18:57:54.435+11:00</updated><title type='text'>Turning C++ into C#</title><content type='html'>Can you really turn C++ into C#?&lt;br /&gt;&lt;br /&gt;The answer is yes to a certain extent, but you'll need certain C++ keyword extensions which are readily available in C++ compilers such as BCC (Borland / CodeGear C++ Compiler), namely indexed properties (VC++ does support properties via the __declspec(property) extension but does not support indexed ones).&lt;br /&gt;&lt;br /&gt;What I've found really interesting is that it is quite possible to write templates and turn C++ objects into fully 'managed' - e.g. garbage collected, arrays are range checked and pointers are checked for null reference.&lt;br /&gt;&lt;br /&gt;I've even went as far as to create templates for keywords such as C#'s 'using', 'foreach' and 'lock'. They behave exactly the same as their counterparts in C#, albeit with a little syntax difference for the 'using' and 'foreach' keyword.&lt;br /&gt;&lt;br /&gt;The advantage of having a C# like C++ library will be greatly appreciated by programmers who love C# but would like their target application to run on non-dotnet platforms such as an embedded XP with limited RAM for cost reasons. Apart from that, applications based on this library will always outperform any C# applications since it's basically C++ with a garbage collector behind it. There are no managed / unmanaged switching penalty when pinvoking and the garbage collector is definitely more deterministic. I've made it such that it such that the code could temporarily disable the garbage collector. This makes real-time systems much more reliable than those using .NET.&lt;br /&gt;&lt;br /&gt;With this library, it is a lot simpler to write high performance applications - glue logic could be written in C#Lib, and the core in pure C/C++ or ASM. With clear separation between managed and non-managed object within the same source code, the non managed part runs per usual, while the object itself could still be managed by C#Lib. The garbage collector also does not relocate objects - they rely on a low-fragmentation memory manager for memory allocations. The GC is a double edged sword in that it is faster and is also easier on the library user as calling into legacy code / APIs / code written in other languages for high performance as the objects always have a permanent address.&lt;br /&gt;&lt;br /&gt;There are a few subtle things which C++ can't do but C# (or in a more generic term, .NET) can. For example, the multiple inheritance feature in C++ is rather limited. You can't explicitly override a method for a specific base class (even if it's implemented as an interface).&lt;br /&gt;&lt;br /&gt;But the most important thing which C++ lacks is the garbage collector, which proved extremely useful in design patterns for the asynchronous (read multi/many core) future (actually, now). C#Lib bridges the gap and has proven to be extremely useful for me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-7534890739757038473?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/7534890739757038473/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=7534890739757038473' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/7534890739757038473'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/7534890739757038473'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2009/01/turning-c-into-c.html' title='Turning C++ into C#'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-7712794225487191683</id><published>2008-11-17T14:53:00.009+11:00</published><updated>2011-07-06T21:49:36.534+10:00</updated><title type='text'>FastMM's Multicore Performance Scaling</title><content type='html'>Having used .NET's asynchronous socket, filestream, WinForm's Invoke / BeginInvoke and fell in love with its design and knowing that it uses IOCP / threadpool WinAPI underneath the hood, I decided to write my own in C++, using C++ Builder. Everything went well until I started testing. I realised that my dual core machine doesn't seem to get full utilization when I'm running some of the most intensive tests, which easily causes the threadpool to spawn extra threads to serve the load.&lt;br /&gt;I started investigating and eventually managed to reproduce the issue with just the following code:&lt;blockquote&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;void __fastcall TAnsiStringTesterThread::Execute()&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;{&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;    AnsiString str;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;    &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;    for (int i=0; i&amp;lt;10000000; i++)&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;    &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;            str = " something ";&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;}&lt;/span&gt;&lt;/blockquote&gt;Delphi doesn't seem to suffer the same problem at first sight when I ran the above in its Delphi equivalent. That is until I tried the following (instead of assigning straight to a literal string, I did an IntToStr): procedure TAnsiStringTesterThread.Execute; var   i: Integer;   str: string; begin   for i := 0 to 10000000 - 1 do     str := IntToStr(10000000); end; The similarity in both these codes is that they both call LStrFromPCharLen, which eventually leads to a call to GetMem and when the string's ref count goes back to zero, a call to FreeMem. Could GetMem and FreeMem be the culprit? As it turns out, yes. To put the hypothesis to the test, I did a tight GetMemory / FreeMemory loop in 2 threads and observed the CPU usage. Unsurprisingly, only 50% of my dual cores are utilized, even though the utilization spreads across both quite evenly. In my search for a better memory manager, I came across the Intel Threading Building Block library. Among other useful things like parallel loops, concurrent hash maps and lock-free queue, it has a scalable memory manager. With that, I wrote a BorlndMM.dll wrapper and called it TBBMM. Here's the result:&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/__HXL2AtXUkk/SSDzQS_N2SI/AAAAAAAAAA0/huGjia1PwyI/s1600-h/tbbmm_fastmm_perf_scale.png"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/__HXL2AtXUkk/SSDzQS_N2SI/AAAAAAAAAA0/huGjia1PwyI/s400/tbbmm_fastmm_perf_scale.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/__HXL2AtXUkk/SSDzQS_N2SI/AAAAAAAAAA0/huGjia1PwyI/s1600-h/tbbmm_fastmm_perf_scale.png"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;/div&gt;In the single-threaded test, the TBBMM is only faster than FastMM by 20%. However, from 2 to 8 threads on a Dual Core machine, the improvements are from 2.25x to a staggering 2.5x.&lt;br /&gt;For more information / to download TBBMM, &lt;a href="http://www.zachsaw.com/?pg=borlndmm_tbbmm"&gt;visit my TBBMM webpage&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-7712794225487191683?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/7712794225487191683/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=7712794225487191683' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/7712794225487191683'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/7712794225487191683'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2008/11/fastmms-multicore-performance-scaling.html' title='FastMM&apos;s Multicore Performance Scaling'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/__HXL2AtXUkk/SSDzQS_N2SI/AAAAAAAAAA0/huGjia1PwyI/s72-c/tbbmm_fastmm_perf_scale.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-1453306959135111539</id><published>2008-10-24T20:41:00.003+11:00</published><updated>2008-10-24T20:57:42.801+11:00</updated><title type='text'>C++ Builder 2009 Compiler Bug Fixes... Finally!</title><content type='html'>Came across this &lt;a href="http://dn.codegear.com/article/38715"&gt;http://dn.codegear.com/article/38715&lt;/a&gt; today and found that CodeGear has finally fixed all the compiler bugs I've filed in 2005 (3 years ago). Heck, if you do a search for "Zach Saw", you'll find that one of the entries has a path to my "My Documents" ;)&lt;br /&gt;&lt;br /&gt;Anyway, kudos to Embarcadero to let the team work on these C++ compiler bugs which turned most of us away to the clutches of Microsoft Visual Studio / C# back then. These compiler bugs were by no means trivial - they were so nasty that they simply rendered any effort to create a stable 24/7 server impossible.&lt;br /&gt;&lt;br /&gt;With all these bugs fixed, C++ Builder would now be the definitive tool to create a proper server (especially versus C#) - low memory usage, blistering fast and it shares most of its the design patterns with .NET (in fact, one would argue that C# is heavily inspired by Delphi / C++ Builder). I spent just 3 days writing a framework which is intimately similar to .NET's asynchronous IO design and its Control.BeginInvoke / Control.Invoke design. In case of the latter, I found that with C++, you get more type checking than you would with C# in passing parameters to the callback. In fact, even the return type for EndInvoke could be type checked with RTTI (during run-time unfortunately, but in any case, is automatic unlike .NET).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-1453306959135111539?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/1453306959135111539/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=1453306959135111539' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/1453306959135111539'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/1453306959135111539'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2008/10/c-builder-2009-compiler-bug-fixes.html' title='C++ Builder 2009 Compiler Bug Fixes... Finally!'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-2553550947551773476</id><published>2008-10-24T20:15:00.002+11:00</published><updated>2008-10-24T20:40:40.373+11:00</updated><title type='text'>[ILINK32 Error] Fatal: Unable to open file .obj</title><content type='html'>If you have been playing around with Delphi packages compiled for C++ Builder in Borland Developer Studio or CodeGear RAD Studio, you'll have undoubtedly run into this error message. You could also run into that if you are not dealing with Delphi packages (e.g. using a run-time package, static library).&lt;br /&gt;&lt;br /&gt;Let's start with Delphi packages.&lt;br /&gt;&lt;br /&gt;What is suspicious is the way the linker reports the error - such as [ILINK32 Error] Fatal: Unable to open file MyComponent.obj. You search the entire hard drive for MyComponent.obj only to find the closest thing to be MyComponent.dcu, which is compiled in Delphi from MyComponent.pas. So how and where do you get MyComponent.obj?&lt;br /&gt;&lt;br /&gt;The answer is, this .obj file is actually in a container with the extension of .LIB. If your package with MyComponent.pas is called MyPackage.bpl, then you need to look for MyPackage.lib. While an installed package should get automatically added to the default list of included packages when you create a new project file, it doesn't always happen (i.e. bug). All you have to do then is manually open up your current project file (.cbproj) in a text editor and add MyPackage.lib into the &lt;AllPackageLibs&gt; tag. Reload your project and you should be able to link successfully.&lt;br /&gt;&lt;br /&gt;If you are not dealing with Delphi packages and you get that error message, that means you're trying to use a static library, or a run-time package (and some times even design-time package which are not dropped onto a form / data module). This could easily be fixed and is the expected way linkers work. There are 2 ways you can fix this:&lt;br /&gt;&lt;br /&gt;1) Add the lib file to the project (I don't like this, as you rely on the user of the static library to remember to add the lib file every time they use it in a new project)&lt;br /&gt;2) Add the following line to a header file which is guaranteed to be included when the static library is used:&lt;br /&gt;#pragma comment(lib, "your library name.lib")&lt;br /&gt;&lt;br /&gt;That's it.&lt;br /&gt;&lt;br /&gt;I haven't tried C++ Builder 2009, but I hope CodeGear have found a better way to do this. Actually, I'd suggest that they simply make all Delphi compiler generated C++ Builder files include that #pragma comment(lib, ...) line so that we never have to muck around with the .cbproj files any more. In fact, this would also mean that there will be no annoying messages that prompts you to remove packages you don't need when you create and try to save a new project.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-2553550947551773476?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/2553550947551773476/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=2553550947551773476' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/2553550947551773476'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/2553550947551773476'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2008/10/ilink32-error-fatal-unable-to-open-file.html' title='[ILINK32 Error] Fatal: Unable to open file .obj'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-2480840581980916049</id><published>2008-10-08T16:37:00.003+11:00</published><updated>2008-10-08T16:47:02.642+11:00</updated><title type='text'>BUG: April 08 Hotfix for CodeGear RAD Studio Skips Update</title><content type='html'>I've run into &lt;span style="font-style:italic;"&gt;yet another Borland / CodeGear bug&lt;/span&gt; - this time with the April 08 Hotfix installer. It says it has successfully applied the Hotfix but it really hasn't and you would have noticed that on the installation summary screen, it says "Current Hotfix Level: 1", instead of 0.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/__HXL2AtXUkk/SOxIY_iXbtI/AAAAAAAAAAk/93Uc4ezlq7E/s1600-h/hotfix.PNG"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/__HXL2AtXUkk/SOxIY_iXbtI/AAAAAAAAAAk/93Uc4ezlq7E/s320/hotfix.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5254654459444162258" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;What happened?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Well, to begin with, you'll always run into this issue everytime you have applied this hotfix and then reinstalled CodeGear RAD Studio (i.e. uninstall and reinstall from the original DVD). The registry settings for the HotfixLevel doesn't get cleared.&lt;br /&gt;&lt;br /&gt;Workaround is simple. Go to your registry (plenty of registry actions with Borland / CodeGear - I'm sure all of you are used to it by now), and open the following key:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;HKEY_LOCAL_MACHINE\SOFTWARE\Borland\BDS\5.0&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;(&lt;span style="font-weight:bold;"&gt;Note:&lt;/span&gt; Assuming you installed RAD Studio for all users. If you've installed it for current user only, look into HKEY_CURRENT_USER and look for this key as well)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In there, you'll find an entry called &lt;span style="font-style:italic;"&gt;HotfixLevel&lt;/span&gt; and it'll have 1 as its value. Change it to 0 and restart the hotfix. It now correctly detect that it hasn't updated the files and proceed to update them.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-2480840581980916049?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/2480840581980916049/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=2480840581980916049' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/2480840581980916049'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/2480840581980916049'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2008/10/bug-april-08-hotfix-for-codegear-rad.html' title='BUG: April 08 Hotfix for CodeGear RAD Studio Skips Update'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/__HXL2AtXUkk/SOxIY_iXbtI/AAAAAAAAAAk/93Uc4ezlq7E/s72-c/hotfix.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-4814335659462102885</id><published>2008-10-08T14:52:00.002+11:00</published><updated>2008-10-08T15:03:37.625+11:00</updated><title type='text'>Delphi Packages not appearing in C++ Builder personality</title><content type='html'>One of the new features in CodeGear RAD Studio 2007 (actually Borland Developer Studio which is the 2006 version of RAD Studio) is the ability to get the Delphi compiler / linker to generate all the files required by C++ Builder (.hpp, .obj, .lib etc.) for a Delphi package, without having to create the equivalent C++ Builder package.&lt;br /&gt;&lt;br /&gt;Unfortunately, there's one ugly bug that has plagued this feature - you may find that the components in the package that you've installed does not come up in the designer's Tool Palette. This bug was first reported by yours truly against BDS 2006 and it appears that it hasn't been and won't be fixed even for RAD Studio 2009. That's &lt;span style="font-weight:bold;"&gt;more than 3 years&lt;/span&gt; since I've reported it in QC! Wow!&lt;br /&gt;&lt;br /&gt;If you have left all settings to the default when you create a package in Delphi (which you most likely will), you will find that the components you've registered in the package won't appear in a C++ Builder project. That is simply because you have not specifically told the linker to "Generate all C++Builder files". So you would go back to the Delphi package and select that option in the Linker output and recompile / reinstall. This time, however, you would expect the installed components to appear in the Tool Palette when you try to use it in C++ Builder... Surprise surprise, it's not there!&lt;br /&gt;&lt;br /&gt;It's as though once the IDE has decided that it is a Delphi-only package, it will remain a Delphi-only package forever. Note that if you uninstall and recreate and then reinstall the entire package, it will still be invisible to C++ Builder - that is, until you've renamed the package. That's because the IDE remembers the package name!&lt;br /&gt;&lt;br /&gt;The other cleaner workaround would be to go to your registry via Regedit.exe and remove all the following entries to your package (say, MyPackage.bpl).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Key:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;HKEY_CURRENT_USER\Software\Borland\BDS\5.0\Known Packages\&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Entry:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Look for the entry with [path]\MyPackage.bpl and remove it&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Key:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;HKEY_CURRENT_USER\Software\Borland\BDS\5.0\Package Cache\&lt;br /&gt;Look for the key called MyPackage.bpl and remove the entire sub-key&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Key:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;HKEY_CURRENT_USER\Software\Borland\BDS\5.0\Palette\Cache\&lt;br /&gt;Look for the key called MyPackage.bpl and remove the entire sub-key&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Remember to &lt;span style="font-style:italic;"&gt;first shut down CodeGear RAD Studio before changing the registry keys&lt;/span&gt;. Once you have removed the entries, restart RAD Studio and this time, remember to select &lt;span style="font-style:italic;"&gt;"Generate all C++Builder files" for all build configurations&lt;/span&gt; (e.g. Debug and Release) before you install the Delphi package.&lt;br /&gt;&lt;br /&gt;And in the future, keep in mind to always set the linker to "Generate all C++Builder files" or set that as your default for all build configurations.&lt;br /&gt;&lt;br /&gt;ps. Yup, they haven't rebranded it to CodeGear in the registry - it's still Borland as we know it! :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-4814335659462102885?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/4814335659462102885/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=4814335659462102885' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/4814335659462102885'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/4814335659462102885'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2008/10/delphi-packages-not-appearing-in-c.html' title='Delphi Packages not appearing in C++ Builder personality'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-6896723487324624063</id><published>2008-10-01T18:44:00.004+10:00</published><updated>2011-07-06T21:51:48.139+10:00</updated><title type='text'>QuickPHP v1.4 Adds Apache Mod Capabilities</title><content type='html'>Those who are familiar with Apache mods will welcome this new addition to QuickPHP. What sets QuickPHP apart though, is that it uses PHP itself to implement the mods.&lt;br /&gt;I've detailed its inner workings before on this blog &lt;a href="http://zachsaw.blogspot.com/2008/09/using-php-script-as-plugin.html"&gt;here&lt;/a&gt;.&lt;br /&gt;You can &lt;a href="http://www.zachsaw.com/?pg=quickphp_php_tester_debugger"&gt;download QuickPHP here&lt;/a&gt; and &lt;a href="http://forum.zachsaw.com/viewtopic.php?f=11&amp;amp;t=28&amp;amp;p=103"&gt;read the mod documentation here&lt;/a&gt;.&lt;br /&gt;While I've made the interface to create mods available, there isn't any mods available yet. This is the time QuickPHP could really use your contributions. Someone to write the equivalent of mod_rewrite, mod_log_referrer, mod_log etc. in PHP. Anything that might be useful to you, is potentially useful to others too. So don't be shy to &lt;a href="http://forum.zachsaw.com/viewforum.php?f=11"&gt;contribute your code in the forum!&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-6896723487324624063?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/6896723487324624063/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=6896723487324624063' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/6896723487324624063'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/6896723487324624063'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2008/10/quickphp-v14-adds-apache-mod.html' title='QuickPHP v1.4 Adds Apache Mod Capabilities'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-5143529919096387031</id><published>2008-09-11T16:55:00.001+10:00</published><updated>2008-09-11T17:45:04.962+10:00</updated><title type='text'>Project Offset will be Larrabee Exclusive</title><content type='html'>It's been officially confirmed by one of the developers in the &lt;a href="http://www.projectoffset.com"&gt;Project Offset&lt;/a&gt; Team (&lt;a href="http://www.freewebs.com/paultozour/index.htm"&gt;Paul Tozour&lt;/a&gt;) that Project Offset will be exclusive to a &lt;span style="font-style:italic;"&gt;"select Intel-based platform"&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;From &lt;a href="http://www.projectoffset.com/forums/viewtopic.php?f=9&amp;t=7&amp;st=0&amp;sk=t&amp;sd=a&amp;start=30#p747"&gt;Project Offset's Forum&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;"Right now, I can only pass on the official word:&lt;br /&gt;&lt;br /&gt;Offset will be exclusive to select Intel-based platforms.&lt;br /&gt;&lt;br /&gt;We look forward to being able to discuss more details in the future."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What this means is that Project Offset has been specifically designed to run only on Larrabee - utilizing every bit of the massive VPU to do graphics and physics that are traditionally impossible without heavy tweaking on the DirectX API.&lt;br /&gt;&lt;br /&gt;But how is this game important? It's only one game. And more importantly - why is Project Offset a key player in the success of Larrabee?&lt;br /&gt;&lt;br /&gt;Project Offset is firstly a game development tool / package with its own engine and secondly a game, much like the Unreal 3 Engine. Ageia employed the same strategy with its Physx and while its card has not been much of a success, the strategy worked - at the time of this post, there are 100 over games supporting Physx, with the majority of them based on Unreal engine. Intel has bought everything they need to own a game engine outright - first, they bought Havok, and early this year (February 2008), they bought Project Offset.&lt;br /&gt;&lt;br /&gt;Larrabee was seen as a saviour for Project Offset's developers -- they were constantly wrestling with the DirectX API to get the effects they desire. They have also worked very closely with other renowned developers in the field to try and solve some of the problems they encountered but none came up with any good answers. This simply proves that there are more developers hitting the walls of limitations imposed by the DirectX API than we previously thought. Larrabee frees them of this struggle and gives them the freedom to implement anything they could imagine. While it is easy to see that the whole game industry is behind DirectX at the moment, you are completely restricted to the feature set it gives you. Even with the shaders becoming more powerful, it is nowhere near the prowess, flexbility and maturity of x86. Perhaps you could be arguing that nVidia's CUDA could accomplish the same thing. Maybe. But nVidia hasn't bought / started to develop its own game engine yet. Yes, they have the Unreal 3 Engine which uses Physx but it's bound by DirectX. A quick visit to the CUDA forum can confirm that no one has even started working on a custom graphics engine based on CUDA. So on the one hand, we have a plethora of DirectX games - almost every game engines out there are based on this API. Smaller game studios simply buy games engines to create games. We exclude these from the equation as they will adopt which ever standards the underlying engine relies on. So this leaves us with the major players - those who are creating their own engines and sell them for a profit. They're the ones who're being limited by the DirectX API at the moment. They're the ones hitting the walls of creativity set by nVidia, ATI / AMD and Microsoft. They spend years coming out with techniques that utilize the API to do forefront, eye-popping graphics engines. Imagine if they're thrown a life line. Imagine the day they don't have to trick the API to perform something clever. That's where Larrabee comes in.&lt;br /&gt;&lt;br /&gt;Don't be fooled by the statement made by the architect of GTX 280. He said they've considered creating something like Larrabee but found that it's not a viable design. That could be true a few years ago or even now, but by next year, nVidia could be heading down an opposite path but ending up with the same design as Larrabee. GTX 280 contains a fair bit of general purpose cores, which sets it apart from the generations before. Larrabee's design is basically the natural progression of GTX 280.&lt;br /&gt;&lt;br /&gt;Come next year, I wouldn't be surprised if nVidia's successor to the GTX 280 is somewhat similar to Larrabee - except perhaps the most obvious: it is not x86.&lt;br /&gt;&lt;br /&gt;In any case, Intel's strategy at this point is nothing to scoff at - they've built a solid foundation for Larrabee. If anything, they're &lt;span style="font-style:italic;"&gt;ahead &lt;/span&gt;of nVidia/CUDA at this stage of the game.&lt;br /&gt;&lt;br /&gt;For those who are interested, reading through Project Offset's developer &lt;a href="http://www.projectoffset.com/blog.php"&gt;blogs&lt;/a&gt; and &lt;a href="http://www.projectoffset.com/forums"&gt;forums&lt;/a&gt; will give you an insight into the life as a graphics engine developer.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-5143529919096387031?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/5143529919096387031/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=5143529919096387031' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/5143529919096387031'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/5143529919096387031'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2008/09/project-offset-will-be-larrabee.html' title='Project Offset will be Larrabee Exclusive'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-6198968992029187722</id><published>2008-09-05T17:40:00.004+10:00</published><updated>2011-07-06T21:52:45.318+10:00</updated><title type='text'>Using PHP Script as a Plugin</title><content type='html'>A discussion in my &lt;a href="http://forum.zachsaw.com/viewtopic.php?f=11&amp;amp;t=15"&gt;QuickPHP forum&lt;/a&gt; has resulted in this new idea where PHP Script can simply be used to create a plugin. Rather than the conventional DLL plugins, we simply get the host to call into the PHP script and get the results back from it.&lt;br /&gt;Of course, a DLL plugin has its advantages (i.e. compiled and runs faster), but in cases that require you to allow your user to configure part of your software with great flexibility, instead of using INI / XML files, a PHP file is definitely not a bad idea. That would bridge the chasm between a DLL plugin and a simple config file. What's more - you only need to deploy the php DLL file &lt;span style="font-style: italic;"&gt;(e.g. php5ts.dll)&lt;/span&gt; along your software and that's it! You get PHP's powerful regular expression out of the box!&lt;br /&gt;In the discussion, I suggested that PHP could be used to implement the entire &lt;a href="http://httpd.apache.org/docs/1.3/mod/mod_rewrite.html"&gt;Apache's mod_rewrite module&lt;/a&gt;, without the need for an external INI file with an input and output regular expression. Users would simply need to write PHP script to manipulate the client request info and return it back to the server. This also means that QuickPHP's mod_rewrite functionality could be so much more powerful than Apache's. In fact, I think one main PHP file is all I need - the main file, in turn could simply call into other modules to work its magic if it's required. If &lt;span style="font-style: italic;"&gt;QuickPHP_ReqMod.php&lt;/span&gt; is not found, QuickPHP reverts back to its basic mode. No additional DLLs - no unnecessary memory usage.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-6198968992029187722?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/6198968992029187722/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=6198968992029187722' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/6198968992029187722'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/6198968992029187722'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2008/09/using-php-script-as-plugin.html' title='Using PHP Script as a Plugin'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-6150576886412285606</id><published>2008-08-29T14:52:00.001+10:00</published><updated>2011-07-06T21:58:31.005+10:00</updated><title type='text'>Testing PHP on Windows - in 5 seconds!  Without installing Apache, IIS or even PHP.</title><content type='html'>Testing PHP on Windows in less than 5 seconds without installing Apache, IIS or even PHP. Is this possible?&lt;br /&gt;Yes it certainly is - and it's&lt;span style="font-style: italic; font-weight: bold;"&gt; FREE&lt;/span&gt;.&lt;br /&gt;QuickPHP is designed spefically for this purpose.&lt;br /&gt;Here are the steps to test PHP on Windows in less than 5 seconds:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Download QuickPHP WebServer (&lt;span style="font-style: italic;"&gt;quickphp_webserver.zip&lt;/span&gt;)  from &lt;a href="http://www.zachsaw.com/?pg=quickphp_php_tester_debugger"&gt;http://www.zachsaw.com/?pg=quickphp_php_tester_debugger&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Unzip the file into C:\QuickPHP&lt;/li&gt;&lt;li&gt;Run QuickPHP.exe from the folder&lt;/li&gt;&lt;li&gt;Hit Start.&lt;/li&gt;&lt;/ol&gt;&lt;blockquote&gt;&lt;div style="text-align: left;"&gt;&lt;a href="http://3.bp.blogspot.com/__HXL2AtXUkk/SLeCq3we6sI/AAAAAAAAAAc/bB2T-F3iufI/s1600-h/quickphp.PNG" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5239800364502280898" src="http://3.bp.blogspot.com/__HXL2AtXUkk/SLeCq3we6sI/AAAAAAAAAAc/bB2T-F3iufI/s320/quickphp.PNG" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;That's it!&lt;br /&gt;You can now test your PHP webpages by browsing to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;http://127.0.0.1:5723&lt;/span&gt; and QuickPHP will run 'index.php' in 'C:\' folder (of course, make sure you have a file called 'C:\index.php' - if not, copy and paste the following code and put them into 'C:\index.php').&lt;br /&gt;If you wish, you can change the webserver's root to your local webpage folder and the default document name to point to your own index file.&lt;br /&gt;index.php:&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;lt;?php&lt;/span&gt; &lt;span style="font-family: courier new;"&gt;phpinfo(); &lt;/span&gt;&lt;span style="font-family: courier new;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  &lt;/span&gt;&lt;span style="font-family: courier new;"&gt; &lt;span style="font-family: courier new;"&gt; &lt;span style="font-family: courier new;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;If you need any help, you can &lt;a href="http://forum.zachsaw.co.cc/viewforum.php?f=11"&gt;visit the QuickPHP forum&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-6150576886412285606?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/6150576886412285606/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=6150576886412285606' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/6150576886412285606'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/6150576886412285606'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2008/08/testing-php-on-windows-in-5-seconds.html' title='Testing PHP on Windows - in 5 seconds!  Without installing Apache, IIS or even PHP.'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/__HXL2AtXUkk/SLeCq3we6sI/AAAAAAAAAAc/bB2T-F3iufI/s72-c/quickphp.PNG' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-7434680832649387818</id><published>2008-08-20T15:35:00.000+10:00</published><updated>2008-08-20T15:36:19.136+10:00</updated><title type='text'>Larrabee with FPGA pledge</title><content type='html'>Following up on my pledge to Intel for including a real-time reprogrammable highspeed FPGA on Larrabee, it looks like it's definitely very useful in a number of applications. With texture filtering being done in hardware with Larrabee running as a GPU, we could reprogram the FPGA to do motion search for H264 encoding. We're now going into a new era where computer engineers are very good in both software and hardware design.&lt;br /&gt;&lt;br /&gt;I suggested the idea of including an FPGA as part of the CPU to a fellow employee / manager back in Intel but unfortunately, it never got any attention. That was back in year 2001. 7 years following that, we're now seeing companies making full use of FPGAs to accelerate applications that aren't efficient to be run on a CPU. Larrabee solves some of the things I said an FPGA would solve, but there are definitely several other applications out there that would benefit from an FPGA. I also pointed out that Intel should come up with a library (i.e. hardware design) that developers can simply load into the FPGA to accelerate specific types of algos.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://forum.doom9.org/archive/index.php/t-137459.html"&gt;Take a look at this.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-7434680832649387818?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/7434680832649387818/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=7434680832649387818' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/7434680832649387818'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/7434680832649387818'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2008/08/larrabee-with-fpga-pledge.html' title='Larrabee with FPGA pledge'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-9204263119912979251</id><published>2008-08-20T14:50:00.000+10:00</published><updated>2008-08-20T14:51:49.423+10:00</updated><title type='text'>Larrabee picks it up where CUDA fails</title><content type='html'>Having read most of the &lt;a href="http://s08.idav.ucdavis.edu/"&gt;publications by nVidia, ATI/AMD and Intel made available to SIGGRAPH&lt;/a&gt;, I have to say, I'm a believer in Larrabee. Most of the problems that plagued CUDA involves having to design and offload only certain parts of the algo which can be suited for GPU and which is small enough in terms of bandwidth utilization across PCIe over to the GPU, and then getting the results back from it via the same path.&lt;br /&gt;&lt;br /&gt;The reason this is even being discussed lies in the fault of the whole GPGPU concept. The GPU is good at one thing - being fed textures (compressed) and command that are then pumped through its fat pipelines to get results (rendered image). Use it for something more generic, we have to deal with issues such as the PCIe bandwidth and having to feed the onboard frame buffer with enough contiguous data to work with. Say we have infinite video RAM. Even then, we'll still have to do some parts of the algo on the CPU as the GPU is just incapable of doing things like scalar operations and sequential branching algos (namely tree algos - heck, CUDA doesn't even do recursion) effectively. With a measly PCIe between CPU and GPU, any performance gained will most likely be offset.&lt;br /&gt;&lt;br /&gt;CUDA is at best, a DSP SDK. nVidia's attempt at using its GPU as a very basic DSP. Nothing more. Yes, you may find that offloading some parts of, say, a H264 encoder will give you some gains. But if you go further, and implement say, anything beyond the baseline profile, you'll run into troubles. You'll get some gains no doubt, since the GPU is always a free agent if it's not being utilized. Is it worth the effort though? Hardly. The x264 developer has gone out to say CUDA is the worst API / language he's ever encountered (particularly with the threading model).&lt;br /&gt;&lt;br /&gt;Larrabee, however, will change the landscape quite a bit. All the above mentioned problems, are exactly what Larrabee seeks out to solve. OpenMP for threading model, much higher level of abstraction between CPU and Larrabee (it's capable of running Pentium x86 instruction sets, so there's no need to go back to the CPU as frequently as GeForce / Radeon), and SSE vector instruction sets -- these are all directly targeted at the downfalls of CUDA!&lt;br /&gt;&lt;br /&gt;When Pat Gelsinger said CUDA will just be a footnote in computing history, nVidia was a fool to laugh it off. It's already happening. Perhaps Wiki should start deleting their CUDA pages and start footnoting GPGPU pages with a short and sweet "meanwhile, there's CUDA" line. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-9204263119912979251?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/9204263119912979251/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=9204263119912979251' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/9204263119912979251'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/9204263119912979251'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2008/08/larrabee-picks-it-up-where-cuda-fails.html' title='Larrabee picks it up where CUDA fails'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-237787010449493616</id><published>2008-08-14T15:41:00.000+10:00</published><updated>2008-08-14T15:51:44.430+10:00</updated><title type='text'>Larrabee and TFLOPS SP / DP - the TFLOPS race BEGINS!</title><content type='html'>There's much confusion over the upcoming Larrabee chip from Intel. It seems that most people who've tried to calculate the peak performance of the chip in terms of TFLOPS couldn't come up with the 2 TFLOPS Intel claimed Larrabee would achieve.&lt;br /&gt;&lt;br /&gt;Larrabee's in-order cores are capable of processing a peak of 16 SP (single precision floating point) data per clock (512-bit VPU, hence 16 SP or 8 DP). At 2GHz, 32 cores, you only get 1.024TFLOPS SP (2GHz * 32 * 16SP). So how come Intel is claiming it is capable of 2 TFLOPS at that configuration?&lt;br /&gt;&lt;br /&gt;Well, here goes. 1.024TFLOPS is the peak for most SIMD instructions, but if we take the MULTIPLY-ADD instruction into account (which Intel implemented recently in its SSSE3 - or SSE4 for the non-informed) then we would multiply 1.024TFLOPS by 2 - hence giving Larrabee a peak performance of 2.048 TFLOPs SP. Yes, it's Single Precision Floating Point (i.e. 32-bit) and not Double Precision (i.e. 64-bit) as some people are claiming it is. For DP, Larrabee would get a peak of 1.024 TFLOPs.&lt;br /&gt;&lt;br /&gt;Before you go saying that Intel's cheating, the 4870 HD also implements the same instruction and its 1.2 TFLOPs SP performance is calculated for this specific instruction as well (same as Larrabee). A high end 48 core Larrabee would give a peak performance of 3 TFLOPs at 2GHz.&lt;br /&gt;&lt;br /&gt;Interesting thing about the MULTIPLY-ADD instruction really - it's patented by 2 Japanese persons. This is a single cycle instruction that does multiplication and add - it's obviously very beneficial to vector calculations and applications like GPUs largely depends on this particular instruction.&lt;br /&gt;&lt;br /&gt;I can see things shaping up quite nicely for Larrabee. Now that the GHz-race era is behind us, let the TFLOPS race begin!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-237787010449493616?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/237787010449493616/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=237787010449493616' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/237787010449493616'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/237787010449493616'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2008/08/larrabee-and-tflops-sp-dp-tflops-race.html' title='Larrabee and TFLOPS SP / DP - the TFLOPS race BEGINS!'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-4777244747636411872</id><published>2008-08-14T15:39:00.002+10:00</published><updated>2008-08-14T15:52:10.360+10:00</updated><title type='text'>nVidia gives Larrabee its blessing for CUDA and Physx</title><content type='html'>Just a thought - nVidia has said that its CUDA will run on x86 too (duh, that would be simply an x86 C compiler wouldn't it?) and since Physx runs on CUDA, that means nVidia has (probably inadvertently) given its blessing to get Physx running on Larrabee. Now that wouldn't be a bad thing at all.&lt;br /&gt;&lt;br /&gt;Very generous of nVidia. ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-4777244747636411872?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/4777244747636411872/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=4777244747636411872' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/4777244747636411872'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/4777244747636411872'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2008/08/nvidia-gives-larrabee-its-blessing-for.html' title='nVidia gives Larrabee its blessing for CUDA and Physx'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-2953911394821368302</id><published>2008-08-14T15:39:00.001+10:00</published><updated>2008-08-14T15:55:08.663+10:00</updated><title type='text'>Highspeed FPGA to complement Larrabee</title><content type='html'>Before I joined Intel, I've always had this idea in my mind - to have a highspeed FPGA as a coprocessor. I think this is a much better time to propose this solution to the world than it's ever been. With the buzz going around Larrabee and its need for a fixed function unit such as the rasterization unit for GPU, it would be so much more flexible if this is implemented as a block of FPGA. The driver is then responsible for converting this block into whatever the application sees fit. Anything that could not fit in that cGPU paradigm can be hardware accelerated via the FPGA block.&lt;br /&gt;&lt;br /&gt;Any take on this, Intel?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-2953911394821368302?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/2953911394821368302/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=2953911394821368302' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/2953911394821368302'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/2953911394821368302'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2008/08/highspeed-fpga-to-complement-larrabee.html' title='Highspeed FPGA to complement Larrabee'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-5333004308728443330</id><published>2008-08-14T15:24:00.000+10:00</published><updated>2008-08-14T15:27:43.125+10:00</updated><title type='text'>About Intel Larrabee</title><content type='html'>About Larrabee and Larrabee vs GeForce / CUDA or ATI / CTM (without repeating what you could look up on other sites):&lt;br /&gt;&lt;br /&gt;1) Michael Abrash, Tim Sweeney and John Carmack are all on board Intel's software team for Larrabee. This should give them a pretty solid team (understatement) for driver development.&lt;br /&gt;&lt;br /&gt;2) A quote from GCDC'08: multi-thread your DirectX code and drivers. "3. Direct 3D runtimes and drivers account for 25-40 percent of CPU cycles per frame. This needs to be reduced in order to push performance!"&lt;br /&gt;&lt;br /&gt;The freedom of offloading these 24-40 percent to Larrabee and leave the CPU to process everything else is something quite significant. This is, however, something they're still working on, as some calls involve the OS kernel and is not the natural way things happen as it stands with Larrabee on PCIe. Again, the ultimate goal is to get Larrabee sitting on your motherboard running as a co-processor, in which case scheduling will be done by the OS just as it would for a normal processor. The design decision to use software task scheduling is obviously two-folds.&lt;br /&gt;&lt;br /&gt;3) CUDA does not support recursion (among several other things) - and will not likely be implemented in the near future due to hardware limitation - and not unless they implement a sophisticated prefetch hardware like Larrabee, it will most likely never happen.&lt;br /&gt;&lt;br /&gt;Developers look for free-lunch. CUDA doesn't seem to provide that very well as it requires the algo to be completely rewritten - see &lt;a href="http://www.gpuchess.com/"&gt;www.gpuchess.com&lt;/a&gt; for example. With that said, it doesn't mean that nVidia can't emulate some of these features through other means like what &lt;a href="http://www.gpuchess.com/"&gt;GpuChess &lt;/a&gt;has done in its compiler. But, that leads me to the next point.&lt;br /&gt;&lt;br /&gt;4) CUDA is a C-like language. That's good - but, how do you get C++ / C# / VB / Delphi / Java etc. developers to code for it? Not unless nVidia starts writing their own .NET IL runtime libraries, and VCL runtimes for their hardware (read: doesn't make sense financially and impossible in the limited time frame before Larrabee debuts). Larrabee gets all of these, for free.&lt;br /&gt;&lt;br /&gt;The final point is what I'm excited about - because you're not restricted to just CUDA-C. You're free to develop in whatever language you're most familiar with. The best part is, with the binaries compiled for Larrabee (if you don't go for the exotic mnemonics of course), it'll be possible to run it on a machine without Larrabee, albeit much slower - but, at least it will run. I don't see any developers (bar hobbyists) getting excited over writing the same algo 3 different ways - CUDA, CTM and x86.&lt;br /&gt;&lt;br /&gt;I don't know about the rest of you, but this looks like a very good idea to me. When I was working in Intel, I was going to propose something similar to Larrabee, but a more hardware solution. Maybe it's still possible. I'll leave that for the next post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-5333004308728443330?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/5333004308728443330/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=5333004308728443330' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/5333004308728443330'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/5333004308728443330'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2008/08/about-larrabee-and-larrabee-vs-geforce.html' title='About Intel Larrabee'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-4620107026676487376</id><published>2008-07-29T14:41:00.000+10:00</published><updated>2008-07-29T15:45:55.348+10:00</updated><title type='text'>DotNUTs Framework - DirectoryInfo.GetFiles and DirectoryInfo.GetDirectories Callback / Event</title><content type='html'>The .NET framework is far from a refined / polished framework. It's nearly everything that I do in the .NET world, I run into a brick wall which eventually leads to writing my own wrapper around Win32.&lt;br /&gt;&lt;br /&gt;Recently, I had to write a file searcher which is mainly used to look for files on USB hard drives. Each folder in the drive is made up of several tens of thousands of files and the drive is usually extremely fragmented (we're not talking about your conventional PC hard drive setup here). Using DirectoryInfo.GetFiles has a fatal flaw when it comes to enumerating files in a folder - it does not have a callback to report its progress, which means there's no way to cancel the search.&lt;br /&gt;&lt;br /&gt;The Directory.GetFiles method works well for folders with not too many files but my case, enumeration can take up to a few minutes on a USB 1 connection. It doesn't matter if you implement this in the foreground or background thread - either way, your user will be forced to sit through the enumeration without any progress report or means to cancel the enumeration (unless you want to force a thread abort - still, there's no way to report progress).&lt;br /&gt;&lt;br /&gt;So, WinAPI to the rescue, yet again. Using FindFirstFile and FindNextFile, we can easily achieve the same thing. The problem, however, is that in C#, you'll need to pinvoke these functions and the painful part is, you'll need to define everything that is simply a header file include away in C++. If that's not enough, you'll then need to verify that your definitions are correct in that it marshals the arguments back and forth properly.&lt;br /&gt;&lt;br /&gt;Finally with all that out of the way, I stumbled upon yet another .NET framework bug in my unit test: DirectoryInfo.LastAccessTime LIES! (although I admit I don't need the LastAccessTime of a directory - but a bug's a bug)&lt;br /&gt;&lt;br /&gt;Directory: C:\Windows\assembly&lt;br /&gt;Date Accessed, as reported by Windows Explorer: 29/07/2008 2:08 PM&lt;br /&gt;Date Accessed, as reported by WinAPI: 29/07/2008 2:08 PM (29/07/2008 2:08:38 PM)&lt;br /&gt;Date Accessed, as reported by dotNUTs framework (DirectoryInfo.LastAccessTime): 29/07/2008 2:30:08 PM&lt;br /&gt;&lt;br /&gt;It's not the LastWriteTime nor the CreationTime - that leads me to think that dotNUTs must have pulled the value out of its arse - which is not surprising given my experience with dotNUTs.&lt;br /&gt;&lt;br /&gt;Does anyone else feel that the .NET framework is plagued with bugs? Or am I just a bug-magnet?&lt;br /&gt;&lt;br /&gt;Or maybe someone should help Microsoft with their unit tests?&lt;br /&gt;&lt;br /&gt;p.s. I'm not the first to coin the word dotNUTs.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-4620107026676487376?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/4620107026676487376/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=4620107026676487376' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/4620107026676487376'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/4620107026676487376'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2008/07/dotnuts-framework-directoryinfogetfiles.html' title='DotNUTs Framework - DirectoryInfo.GetFiles and DirectoryInfo.GetDirectories Callback / Event'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-3272379055000855022</id><published>2008-07-13T17:25:00.001+10:00</published><updated>2011-07-06T22:00:18.782+10:00</updated><title type='text'>Borland / CodeGear Delphi / C++ Builder</title><content type='html'>It's sad really to finally see Borland closing a chapter on its very successful product - the VCL.&lt;br /&gt;VCL has been the foundation of the .NET framework Windows Forms portion and in many ways still does a much better job - such as subclassing common controls, wrapping it into a 'drag-drop'-able control. Amazingly, Borland's core controls in the VCL has remained mainly unchanged since Version 5. With a few tweaks and additions to make it use Vista theme, it was made theme-aware in Vista.&lt;br /&gt;What can we say about the .NET framework then? Well, as of Orcas (VS 2008 for the less informed), most controls are still not Vista themed - and most of the controls are around about VCL's version 3 standards in terms of features, bugs, and extensibility (ease of derivation, subclassing etc.).&lt;br /&gt;Yeah yeah, there's WPF, but heck, some controls in WPF are even worse than their Windows Forms counterparts. And, using WPF simply means shooting yourself in the foot when it comes to finding the lowest common denominator - heck, I can't even run WPF apps at a decent speed on my 3 year-old laptop.&lt;br /&gt;Microsoft's solutions - WPF or Windows Forms - are very half-hearted. They are neither very usable, or completely unusable. Most of the time, you'll have to invest a lot of your own time and resources into making something useful out of it.&lt;br /&gt;Just for example, the TreeView control - both Borland (CodeGear) and Microsoft have it. Which is better? Borland (CodeGear) hands down (I expect Borland fan boys to cheer and Microsoft fan boys to boo now -- Darn those people - get a life!).&lt;br /&gt;I worked with a guy with MCSE creditation last year (typical Microsoft fan-boy) and was told that anything I could do with Borland (CodeGear), I could do with Visual Studio / .NET framework. Sure. Try creating a multiselect TreeView that works in both Vista and XP, natively themed (i.e. Vista explorer mode theme and in XP, fall back to the active XP theme). In Borland (CodeGear), you'd simply drag-n-drop and set the multiselect property to true. Zero lines of code. I dare you - you know who you are, you Microsoft fan-boy - try doing that in Visual Studio and see how long it would take you to do something similar.&lt;br /&gt;Yeah, sure, I did it eventually - &lt;a href="http://www.zachsaw.com/?pg=advanced_treeview"&gt;check out my Advanced TreeView Control here&lt;/a&gt; - but it took me some time. And sure, the fan-boy could've simply said, well, I told ya, it could be done. And my reply would have been, "Yeah, it could've also been done in pure ASM!"&lt;br /&gt;Good on ya Microsoft!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-3272379055000855022?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/3272379055000855022/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=3272379055000855022' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/3272379055000855022'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/3272379055000855022'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2008/07/borland-codegear-delphi-c-builder.html' title='Borland / CodeGear Delphi / C++ Builder'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-2227453889665012718</id><published>2008-07-10T12:30:00.001+10:00</published><updated>2008-07-10T12:30:37.742+10:00</updated><title type='text'>The Online Vultures</title><content type='html'>I think I'm going to coin a new term here - The Online Vultures.&lt;br /&gt;&lt;br /&gt;There are quite a few companies out there waiting for a domain, particularly a very highly ranked domain (in search engines) to&lt;br /&gt;&lt;br /&gt;expire, and if the owner does not renew it, these companies pound on the domains, analogous to vultures ripping apart a dead&lt;br /&gt;&lt;br /&gt;carcus. If you even try to get the domain back, you'll face the wrath of these vultures pecking you to death! Not that you should&lt;br /&gt;&lt;br /&gt;let your domain expire, but that's a tale for another day.&lt;br /&gt;&lt;br /&gt;How do these companies get money off sites like these?&lt;br /&gt;&lt;br /&gt;Simple. They park a website on the expired domain, with a link oh-so-visible to "Enquire about the Domain". Following the link,&lt;br /&gt;&lt;br /&gt;you'll be presented with a form which asks you for your contact details and the most important question of all, "How much are you&lt;br /&gt;&lt;br /&gt;willing to pay for the domain?" (all these are provided by Domain Parking service).&lt;br /&gt;&lt;br /&gt;Companies like the following is an example:&lt;br /&gt;&lt;br /&gt;created-date: 2007-05-04 18:16:31&lt;br /&gt;updated-date: 2007-09-06 13:48:52&lt;br /&gt;registration-expiration-date: 2009-05-04 00:00:00&lt;br /&gt;&lt;br /&gt;owner-contact: WA-VirtualStockLtd&lt;br /&gt;owner-organization: Virtual Stock House LTD&lt;br /&gt;owner-fname: Andrew&lt;br /&gt;owner-lname: Waggins&lt;br /&gt;owner-street: Midtown Building, 625, D.R. Walwyn Square&lt;br /&gt;owner-city: Charlestown&lt;br /&gt;owner-state:&lt;br /&gt;owner-zip: 001&lt;br /&gt;owner-country: SAINT KITTS AND NEVIS&lt;br /&gt;owner-phone: +18696124652805&lt;br /&gt;owner-fax: +18696124652805&lt;br /&gt;owner-email: vsh.ltd@googlemail.com&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This 'company' (whether or not it's real) owns 3,557 other domains.&lt;br /&gt;&lt;br /&gt;Try www.micrusoft.com and www.micrasoft.com, or even www.iApple.com - they are all domain parked. Amazing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-2227453889665012718?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/2227453889665012718/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=2227453889665012718' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/2227453889665012718'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/2227453889665012718'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2008/07/online-vultures.html' title='The Online Vultures'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9977539741480046.post-5169715539669148030</id><published>2008-07-08T12:02:00.000+10:00</published><updated>2008-07-08T13:24:35.563+10:00</updated><title type='text'>Application Data - The WinForms Cookies</title><content type='html'>The application data folder (%USERPROFILE%\Local Settings\Application Data) is guaranteed to be read-writable and furthermore, it is user specific. Compounded by the ease of use via the IsolatedStorage class in the .NET framework,  this sounds like the ideal place to save all your user settings doesn't it?&lt;br /&gt;&lt;br /&gt;It is. Just an example, Microsoft Visual Studio caches all your project assemblies there. If Microsoft does it, it has to be correct, right? Yes and no.&lt;br /&gt;&lt;br /&gt;While this is one of the most convenient storage locations, there is, however, the issue of - when and how do we remove the data we have stored in app data folder?&lt;br /&gt;&lt;br /&gt;Microsoft Visual Studio suffers from this exact problem with its project assemblies - it really shouldn't, but it does. And when that happens, it will drive you nuts. What am I talking about? Here goes.&lt;br /&gt;&lt;br /&gt;When a solution is loaded, all the referenced assemblies which have their property "Copy Local" enabled will be cached in %USERPROFILE%\Local Settings\Application Data\Microsoft\VisualStudio\&lt;version&gt;\ProjectAssemblies\&lt;unique&gt;. The next time you open the solution, Visual Studio will check the cache for the assemblies and will not recopy the assemblies even if they are out of date. This happens very frequently if you use any third party components / controls with designer support - every time you upgrade to a newer version, your solution breaks as you now have an older version of the assembly in your cache, while the designer expects to work with the version it gets installed with.&lt;br /&gt;&lt;br /&gt;The problem arises simply because Visual Studio does not remove the cache when the user closes the solution. It really should not retain the cached assemblies simply because these files will then remain indefinitely in your application data. Imagine every single time you create a little application to test out the behavior of certain components / controls (be it built-in or third party), VS caches all the assemblies. If Microsoft insist on not deleting the files, at least have the courtesy of doing it properly - this is analogous to Intel's Nehalem processor (the successor of Core processor) using stale data from its L3 cache!&lt;br /&gt;&lt;br /&gt;In the case of VS, the solution is simple - recopy the assemblies each time the solution is reloaded.&lt;br /&gt;&lt;br /&gt;Users of IsolatedStorage though, have a bit more problem in that if we use IsolatedStorage for application settings, when do we clean it up? When the software is uninstalled? Seems like quite a hassle - in the uninstaller, figure out which subfolder is for the application we have installed, enumerate through all the user profiles and delete the data files.&lt;br /&gt;&lt;br /&gt;OK. Before we go any further, how do we figure out the subfolder of which our application has used for IsolatedStorage? Is this relative location even the same for all the users? Where's the documentation for this?&lt;br /&gt;&lt;br /&gt;Too much hassle means one thing - most developers / companies will simply leave the files in IsolatedStorage after the application gets uninstalled. I suppose that's a bit better than leaving the data in your Windows registry back in the old days.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9977539741480046-5169715539669148030?l=zachsaw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zachsaw.blogspot.com/feeds/5169715539669148030/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9977539741480046&amp;postID=5169715539669148030' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/5169715539669148030'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9977539741480046/posts/default/5169715539669148030'/><link rel='alternate' type='text/html' href='http://zachsaw.blogspot.com/2008/07/application-data-winforms-cookies.html' title='Application Data - The WinForms Cookies'/><author><name>Zach Saw</name><uri>http://www.blogger.com/profile/02019604928253273845</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
