tag:blogger.com,1999:blog-154439122024-03-13T15:27:11.213+01:00Delphi Code SnippetsThis blog will discuss various delphi snippets, written or found by Davy Landman (the author of the Blog). <a href="http://delphi-snippets.blogspot.com/2005/08/welcome.html">More...</a>Davy Landmanhttp://www.blogger.com/profile/06890346525536829946noreply@blogger.comBlogger6125tag:blogger.com,1999:blog-15443912.post-21656557144923857172007-01-28T12:07:00.001+01:002008-07-21T23:09:28.207+02:00Thread safe TStack (TThreadStack)<p><span class="Notice">I've moved my blog and it's post to my new blog, please go to <a href="http://landman-code.blogspot.com/2007/01/thread-safe-tstack-tthreadstack.html">Thread safe TStack (TThreadStack) on Landman Code</a></span> Recently i've been doing a lot of multithreading, and luckily Delphi provides with a handy bunch of classes to make the developers life easier. You've got some basic synchronization classes (TMutex, TEvent, TCriticalSection, TMultiReadExclusiveWriteSynchronizer...) and an basic data container (TThreadList). But for one program I needed a thread safe stack. In this post I will describe how I created my own. </p><p>There is not thread safe stack in Borland Turbo Delphi 2006, so off course I started with a Google for <a title="delphi TThreadStack" href="http://www.google.nl/search?q=delphi+TThreadStack">delphi TThreadStack</a>, which at this time gives zero results. Searching the newsgroups I found an interesting group called <a title="comp.programming.threads" href="http://groups.google.com/group/comp.programming.threads" target="blank_">comp.programming.threads</a>, searching that group I found one Pascal <a title="Lock-Free" href="http://en.wikipedia.org/wiki/Lock-free_and_wait-free_algorithms" target="blank_">Lock-Free</a> stack (which basically means not using a critical section, or any other mechanism, to lock the data). But after testing it, FastMM pointed out an memory leak. I provided the author with a test case to cause the memory leak, but after 5 months no reply. </p><p>But I'm a hard person to please, and although it is indeed lock free, I was wondering if in my situation this lock-free solution wasn't to complicated and perhaps slower. So I created an simple TThreadStack from looking at the principle of the TThreadList (Very simple!), and compared it with the lock-free solution. </p><p>The source demonstrates is the test project. </p><pre style="BORDER-RIGHT: 1px inset; PADDING-RIGHT: 6px; BORDER-TOP: 1px inset; PADDING-LEFT: 6px; PADDING-BOTTOM: 6px; MARGIN: 0px; OVERFLOW: auto; BORDER-LEFT: 1px inset; WIDTH: 440px; PADDING-TOP: 6px; BORDER-BOTTOM: 1px inset; HEIGHT: 600px"><code><span style="FONT: 10pt Courier New"><span class="pas1-reservedword">program</span><span class="pas1-space"> Project2</span><span class="pas1-symbol">;
</span><span class="pas1-preprocessor">{$APPTYPE CONSOLE}
</span><span class="pas1-reservedword">uses
</span><span class="pas1-space"> FastMM4</span><span class="pas1-symbol">,
</span><span class="pas1-space"> unThreadStack</span><span class="pas1-symbol">,
</span><span class="pas1-space"> FreeStack</span><span class="pas1-symbol">,</span><span class="pas1-space"> Math</span><span class="pas1-symbol">,
</span><span class="pas1-space"> Windows</span><span class="pas1-symbol">,</span><span class="pas1-space"> SysUtils</span><span class="pas1-symbol">,</span><span class="pas1-space"> Classes</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">const
</span><span class="pas1-space"> NumberOfAllocations </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-number">1000</span><span class="pas1-symbol">;
</span><span class="pas1-space"> PopTimeOut </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-number">1</span><span class="pas1-symbol">;
</span><span class="pas1-space"> PushTimeOut </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-number">1</span><span class="pas1-symbol">;
</span><span class="pas1-space"> NumberOfThreads </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-number">8</span><span class="pas1-symbol">;</span><span class="pas1-space"> </span><span class="pas1-comment">// must be an multiple of 4
</span><span class="pas1-space"> NumberOfTest </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-number">10</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">type
</span><span class="pas1-space"> TTestRec </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-reservedword">packed</span><span class="pas1-space"> </span><span class="pas1-reservedword">record
</span><span class="pas1-space"> BigField</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">array</span><span class="pas1-symbol">[</span><span class="pas1-number">0</span><span class="pas1-symbol">..</span><span class="pas1-number">254</span><span class="pas1-symbol">]</span><span class="pas1-space"> </span><span class="pas1-reservedword">of</span><span class="pas1-space"> Char</span><span class="pas1-symbol">;
</span><span class="pas1-space"> SmallerField</span><span class="pas1-symbol">:</span><span class="pas1-space"> Extended</span><span class="pas1-symbol">;
</span><span class="pas1-space"> SmallField</span><span class="pas1-symbol">:</span><span class="pas1-space"> Byte</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-space"> PTestRec </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-symbol">^</span><span class="pas1-identifier">TTestRec</span><span class="pas1-symbol">;
</span><span class="pas1-space"> TFreeStackThread </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-reservedword">class</span><span class="pas1-symbol">(</span><span class="pas1-identifier">TThread</span><span class="pas1-symbol">)
</span><span class="pas1-space"> FPopper</span><span class="pas1-symbol">:</span><span class="pas1-space"> Boolean</span><span class="pas1-symbol">;
</span><span class="pas1-space"> FDestination</span><span class="pas1-symbol">:</span><span class="pas1-space"> TFreeStack</span><span class="pas1-symbol">;
</span><span class="pas1-space"> FFinished</span><span class="pas1-symbol">:</span><span class="pas1-space"> THandle</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">protected
</span><span class="pas1-space"> </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> Execute</span><span class="pas1-symbol">;</span><span class="pas1-space"> </span><span class="pas1-reservedword">override</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">public
</span><span class="pas1-space"> </span><span class="pas1-reservedword">constructor</span><span class="pas1-space"> Create</span><span class="pas1-symbol">(</span><span class="pas1-identifier">ADestination</span><span class="pas1-symbol">:</span><span class="pas1-space"> TFreeStack</span><span class="pas1-symbol">;</span><span class="pas1-space"> APopper</span><span class="pas1-symbol">:</span><span class="pas1-space"> Boolean</span><span class="pas1-symbol">;</span><span class="pas1-space"> AFinished</span><span class="pas1-symbol">:</span><span class="pas1-space"> THandle</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-space"> TThreadStackThread </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-reservedword">class</span><span class="pas1-symbol">(</span><span class="pas1-identifier">TThread</span><span class="pas1-symbol">)
</span><span class="pas1-space"> FPopper</span><span class="pas1-symbol">:</span><span class="pas1-space"> Boolean</span><span class="pas1-symbol">;
</span><span class="pas1-space"> FDestination</span><span class="pas1-symbol">:</span><span class="pas1-space"> TThreadStack</span><span class="pas1-symbol">;
</span><span class="pas1-space"> FFinished</span><span class="pas1-symbol">:</span><span class="pas1-space"> THandle</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">protected
</span><span class="pas1-space"> </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> Execute</span><span class="pas1-symbol">;</span><span class="pas1-space"> </span><span class="pas1-reservedword">override</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">public
</span><span class="pas1-space"> </span><span class="pas1-reservedword">constructor</span><span class="pas1-space"> Create</span><span class="pas1-symbol">(</span><span class="pas1-identifier">ADestination</span><span class="pas1-symbol">:</span><span class="pas1-space"> TThreadStack</span><span class="pas1-symbol">;</span><span class="pas1-space"> APopper</span><span class="pas1-symbol">:</span><span class="pas1-space"> Boolean</span><span class="pas1-symbol">;</span><span class="pas1-space"> AFinished</span><span class="pas1-symbol">:</span><span class="pas1-space"> THandle</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-comment">{ TThreadStackThread }
</span><span class="pas1-reservedword">constructor</span><span class="pas1-space"> TThreadStackThread</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">(</span><span class="pas1-identifier">ADestination</span><span class="pas1-symbol">:</span><span class="pas1-space"> TThreadStack</span><span class="pas1-symbol">;
</span><span class="pas1-space"> APopper</span><span class="pas1-symbol">:</span><span class="pas1-space"> Boolean</span><span class="pas1-symbol">;</span><span class="pas1-space"> AFinished</span><span class="pas1-symbol">:</span><span class="pas1-space"> THandle</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> FDestination </span><span class="pas1-symbol">:=</span><span class="pas1-space"> ADestination</span><span class="pas1-symbol">;
</span><span class="pas1-space"> FPopper </span><span class="pas1-symbol">:=</span><span class="pas1-space"> APopper</span><span class="pas1-symbol">;
</span><span class="pas1-space"> FFinished </span><span class="pas1-symbol">:=</span><span class="pas1-space"> AFinished</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">inherited</span><span class="pas1-space"> Create</span><span class="pas1-symbol">(</span><span class="pas1-identifier">False</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TThreadStackThread</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Execute</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">var
</span><span class="pas1-space"> TempStack</span><span class="pas1-symbol">:</span><span class="pas1-space"> TStack</span><span class="pas1-symbol">;
</span><span class="pas1-space"> p</span><span class="pas1-symbol">:</span><span class="pas1-space"> PTestRec</span><span class="pas1-symbol">;
</span><span class="pas1-space"> counter</span><span class="pas1-symbol">:</span><span class="pas1-space"> Int64</span><span class="pas1-symbol">;
</span><span class="pas1-space"> temp</span><span class="pas1-symbol">:</span><span class="pas1-space"> LongWord</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> counter </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">while</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-reservedword">not</span><span class="pas1-space"> Terminated</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">and</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">counter </span><span class="pas1-symbol"><</span><span class="pas1-space"> NumberOfAllocations</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">do
</span><span class="pas1-space"> </span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> TempStack </span><span class="pas1-symbol">:=</span><span class="pas1-space"> FDestination</span><span class="pas1-symbol">.</span><span class="pas1-identifier">LockStack</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">try
</span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> FPopper </span><span class="pas1-reservedword">then
</span><span class="pas1-space"> </span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> TempStack</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Count </span><span class="pas1-symbol">></span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">then
</span><span class="pas1-space"> </span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> Dispose</span><span class="pas1-symbol">(</span><span class="pas1-identifier">PTestRec</span><span class="pas1-symbol">(</span><span class="pas1-identifier">TempStack</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Pop</span><span class="pas1-symbol">));
</span><span class="pas1-space"> inc</span><span class="pas1-symbol">(</span><span class="pas1-identifier">counter</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end
</span><span class="pas1-space"> </span><span class="pas1-reservedword">else
</span><span class="pas1-space"> </span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> New</span><span class="pas1-symbol">(</span><span class="pas1-identifier">p</span><span class="pas1-symbol">);
</span><span class="pas1-space"> TempStack</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Push</span><span class="pas1-symbol">(</span><span class="pas1-identifier">p</span><span class="pas1-symbol">);
</span><span class="pas1-space"> inc</span><span class="pas1-symbol">(</span><span class="pas1-identifier">counter</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">finally
</span><span class="pas1-space"> FDestination</span><span class="pas1-symbol">.</span><span class="pas1-identifier">UnlockStack</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> FPopper </span><span class="pas1-reservedword">then
</span><span class="pas1-space"> Sleep</span><span class="pas1-symbol">(</span><span class="pas1-identifier">PopTimeOut</span><span class="pas1-symbol">)
</span><span class="pas1-space"> </span><span class="pas1-reservedword">else
</span><span class="pas1-space"> Sleep</span><span class="pas1-symbol">(</span><span class="pas1-identifier">PushTimeOut</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-space"> ReleaseSemaphore</span><span class="pas1-symbol">(</span><span class="pas1-identifier">FFinished</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-number">1</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-symbol">@</span><span class="pas1-identifier">temp</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-comment">{ TFreeStackThread }
</span><span class="pas1-reservedword">constructor</span><span class="pas1-space"> TFreeStackThread</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">(</span><span class="pas1-identifier">ADestination</span><span class="pas1-symbol">:</span><span class="pas1-space"> TFreeStack</span><span class="pas1-symbol">;</span><span class="pas1-space"> APopper</span><span class="pas1-symbol">:</span><span class="pas1-space"> Boolean</span><span class="pas1-symbol">;</span><span class="pas1-space"> AFinished</span><span class="pas1-symbol">:</span><span class="pas1-space"> THandle</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> FDestination </span><span class="pas1-symbol">:=</span><span class="pas1-space"> ADestination</span><span class="pas1-symbol">;
</span><span class="pas1-space"> FPopper </span><span class="pas1-symbol">:=</span><span class="pas1-space"> APopper</span><span class="pas1-symbol">;
</span><span class="pas1-space"> FFinished </span><span class="pas1-symbol">:=</span><span class="pas1-space"> AFinished</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">inherited</span><span class="pas1-space"> Create</span><span class="pas1-symbol">(</span><span class="pas1-identifier">False</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TFreeStackThread</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Execute</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">var
</span><span class="pas1-space"> p</span><span class="pas1-symbol">:</span><span class="pas1-space"> PTestRec</span><span class="pas1-symbol">;
</span><span class="pas1-space"> counter</span><span class="pas1-symbol">:</span><span class="pas1-space"> Int64</span><span class="pas1-symbol">;
</span><span class="pas1-space"> temp</span><span class="pas1-symbol">:</span><span class="pas1-space"> LongWord</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> counter </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-symbol">;
</span><span class="pas1-space"> p </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-reservedword">nil</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">while</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-reservedword">not</span><span class="pas1-space"> Terminated</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">and</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">counter </span><span class="pas1-symbol"><</span><span class="pas1-space"> NumberOfAllocations</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">do
</span><span class="pas1-space"> </span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> FPopper </span><span class="pas1-reservedword">then
</span><span class="pas1-space"> </span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> FDestination</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Count </span><span class="pas1-symbol">></span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">then
</span><span class="pas1-space"> </span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> FDestination</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Pop</span><span class="pas1-symbol">(</span><span class="pas1-identifier">TObject</span><span class="pas1-symbol">(</span><span class="pas1-identifier">p</span><span class="pas1-symbol">))</span><span class="pas1-space"> </span><span class="pas1-reservedword">then
</span><span class="pas1-space"> </span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> Dispose</span><span class="pas1-symbol">(</span><span class="pas1-identifier">p</span><span class="pas1-symbol">);
</span><span class="pas1-space"> inc</span><span class="pas1-symbol">(</span><span class="pas1-identifier">counter</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end
</span><span class="pas1-space"> </span><span class="pas1-reservedword">else
</span><span class="pas1-space"> </span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> p </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-reservedword">nil</span><span class="pas1-space"> </span><span class="pas1-reservedword">then
</span><span class="pas1-space"> New</span><span class="pas1-symbol">(</span><span class="pas1-identifier">p</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> FDestination</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Push</span><span class="pas1-symbol">(</span><span class="pas1-identifier">TObject</span><span class="pas1-symbol">(</span><span class="pas1-identifier">p</span><span class="pas1-symbol">))</span><span class="pas1-space"> </span><span class="pas1-reservedword">then
</span><span class="pas1-space"> </span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> p </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-reservedword">nil</span><span class="pas1-symbol">;
</span><span class="pas1-space"> inc</span><span class="pas1-symbol">(</span><span class="pas1-identifier">counter</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> FPopper </span><span class="pas1-reservedword">then
</span><span class="pas1-space"> Sleep</span><span class="pas1-symbol">(</span><span class="pas1-identifier">PopTimeOut</span><span class="pas1-symbol">)
</span><span class="pas1-space"> </span><span class="pas1-reservedword">else
</span><span class="pas1-space"> Sleep</span><span class="pas1-symbol">(</span><span class="pas1-identifier">PushTimeOut</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-space"> ReleaseSemaphore</span><span class="pas1-symbol">(</span><span class="pas1-identifier">FFinished</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-number">1</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-symbol">@</span><span class="pas1-identifier">temp</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">var
</span><span class="pas1-space"> AThreadStacksTests</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">array</span><span class="pas1-symbol">[</span><span class="pas1-number">0</span><span class="pas1-symbol">..</span><span class="pas1-identifier">NumberOfThreads </span><span class="pas1-symbol">-</span><span class="pas1-space"> </span><span class="pas1-number">1</span><span class="pas1-symbol">]</span><span class="pas1-space"> </span><span class="pas1-reservedword">of</span><span class="pas1-space"> TThreadStackThread</span><span class="pas1-symbol">;
</span><span class="pas1-space"> AFreeStacksTests</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">array</span><span class="pas1-symbol">[</span><span class="pas1-number">0</span><span class="pas1-symbol">..</span><span class="pas1-identifier">NumberOfThreads </span><span class="pas1-symbol">-</span><span class="pas1-space"> </span><span class="pas1-number">1</span><span class="pas1-symbol">]</span><span class="pas1-space"> </span><span class="pas1-reservedword">of</span><span class="pas1-space"> TFreeStackThread</span><span class="pas1-symbol">;
</span><span class="pas1-space"> i</span><span class="pas1-symbol">,</span><span class="pas1-space"> j</span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">;
</span><span class="pas1-space"> Start</span><span class="pas1-symbol">,</span><span class="pas1-space"> Stop</span><span class="pas1-symbol">,</span><span class="pas1-space"> Freq</span><span class="pas1-symbol">:</span><span class="pas1-space"> Int64</span><span class="pas1-symbol">;
</span><span class="pas1-space"> ThreadStacks</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">array</span><span class="pas1-symbol">[</span><span class="pas1-number">0</span><span class="pas1-symbol">..</span><span class="pas1-number">1</span><span class="pas1-symbol">]</span><span class="pas1-space"> </span><span class="pas1-reservedword">of</span><span class="pas1-space"> TThreadStack</span><span class="pas1-symbol">;
</span><span class="pas1-space"> FreeStacks</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">array</span><span class="pas1-symbol">[</span><span class="pas1-number">0</span><span class="pas1-symbol">..</span><span class="pas1-number">1</span><span class="pas1-symbol">]</span><span class="pas1-space"> </span><span class="pas1-reservedword">of</span><span class="pas1-space"> TFreeStack</span><span class="pas1-symbol">;
</span><span class="pas1-space"> ResultThread</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">array</span><span class="pas1-symbol">[</span><span class="pas1-number">0</span><span class="pas1-symbol">..</span><span class="pas1-identifier">NumberOfTest </span><span class="pas1-symbol">-</span><span class="pas1-space"> </span><span class="pas1-number">1</span><span class="pas1-symbol">]</span><span class="pas1-space"> </span><span class="pas1-reservedword">of</span><span class="pas1-space"> Double</span><span class="pas1-symbol">;
</span><span class="pas1-space"> ResultFree</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">array</span><span class="pas1-symbol">[</span><span class="pas1-number">0</span><span class="pas1-symbol">..</span><span class="pas1-identifier">NumberOfTest </span><span class="pas1-symbol">-</span><span class="pas1-space"> </span><span class="pas1-number">1</span><span class="pas1-symbol">]</span><span class="pas1-space"> </span><span class="pas1-reservedword">of</span><span class="pas1-space"> Double</span><span class="pas1-symbol">;
</span><span class="pas1-space"> Finished</span><span class="pas1-symbol">:</span><span class="pas1-space"> THandle</span><span class="pas1-symbol">;
</span><span class="pas1-space"> Mean</span><span class="pas1-symbol">,</span><span class="pas1-space"> StdDev</span><span class="pas1-symbol">:</span><span class="pas1-space"> Extended</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> ThreadStacks</span><span class="pas1-symbol">[</span><span class="pas1-number">0</span><span class="pas1-symbol">]</span><span class="pas1-space"> </span><span class="pas1-symbol">:=</span><span class="pas1-space"> TThreadStack</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">;
</span><span class="pas1-space"> ThreadStacks</span><span class="pas1-symbol">[</span><span class="pas1-number">1</span><span class="pas1-symbol">]</span><span class="pas1-space"> </span><span class="pas1-symbol">:=</span><span class="pas1-space"> TThreadStack</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">;
</span><span class="pas1-space"> FreeStacks</span><span class="pas1-symbol">[</span><span class="pas1-number">0</span><span class="pas1-symbol">]</span><span class="pas1-space"> </span><span class="pas1-symbol">:=</span><span class="pas1-space"> TFreeStack</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">;
</span><span class="pas1-space"> FreeStacks</span><span class="pas1-symbol">[</span><span class="pas1-number">1</span><span class="pas1-symbol">]</span><span class="pas1-space"> </span><span class="pas1-symbol">:=</span><span class="pas1-space"> TFreeStack</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">;
</span><span class="pas1-space"> Finished </span><span class="pas1-symbol">:=</span><span class="pas1-space"> CreateSemaphore</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">nil</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-symbol">,</span><span class="pas1-space"> NumberOfThreads</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-string">'Thread runners'</span><span class="pas1-symbol">);
</span><span class="pas1-space"> Writeln</span><span class="pas1-symbol">(</span><span class="pas1-string">'Starting ThreadStack threads'</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">for</span><span class="pas1-space"> j </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">to</span><span class="pas1-space"> NumberOfTest </span><span class="pas1-symbol">-</span><span class="pas1-space"> </span><span class="pas1-number">1</span><span class="pas1-space"> </span><span class="pas1-reservedword">do
</span><span class="pas1-space"> </span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> QueryPerformanceCounter</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Start</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">for</span><span class="pas1-space"> I </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">to</span><span class="pas1-space"> NumberOfThreads </span><span class="pas1-symbol">-</span><span class="pas1-space"> </span><span class="pas1-number">1</span><span class="pas1-space"> </span><span class="pas1-reservedword">do
</span><span class="pas1-space"> AThreadStacksTests</span><span class="pas1-symbol">[</span><span class="pas1-identifier">i</span><span class="pas1-symbol">]</span><span class="pas1-space"> </span><span class="pas1-symbol">:=</span><span class="pas1-space"> TThreadStackThread</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">(</span><span class="pas1-identifier">ThreadStacks</span><span class="pas1-symbol">[</span><span class="pas1-identifier">i </span><span class="pas1-reservedword">mod</span><span class="pas1-space"> </span><span class="pas1-number">2</span><span class="pas1-symbol">],</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">i </span><span class="pas1-reservedword">mod</span><span class="pas1-space"> </span><span class="pas1-number">4</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-symbol">>=</span><span class="pas1-space"> </span><span class="pas1-number">2</span><span class="pas1-symbol">,</span><span class="pas1-space"> Finished</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">for</span><span class="pas1-space"> I </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">to</span><span class="pas1-space"> NumberOfThreads </span><span class="pas1-symbol">-</span><span class="pas1-space"> </span><span class="pas1-number">1</span><span class="pas1-space"> </span><span class="pas1-reservedword">do
</span><span class="pas1-space"> WaitForSingleObject</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Finished</span><span class="pas1-symbol">,</span><span class="pas1-space"> INFINITE</span><span class="pas1-symbol">);
</span><span class="pas1-space"> QueryPerformanceCounter</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Stop</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">for</span><span class="pas1-space"> I </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">to</span><span class="pas1-space"> NumberOfThreads </span><span class="pas1-symbol">-</span><span class="pas1-space"> </span><span class="pas1-number">1</span><span class="pas1-space"> </span><span class="pas1-reservedword">do
</span><span class="pas1-space"> AThreadStacksTests</span><span class="pas1-symbol">[</span><span class="pas1-identifier">i</span><span class="pas1-symbol">].</span><span class="pas1-identifier">Free</span><span class="pas1-symbol">;
</span><span class="pas1-space"> ResultThread</span><span class="pas1-symbol">[</span><span class="pas1-identifier">j</span><span class="pas1-symbol">]</span><span class="pas1-space"> </span><span class="pas1-symbol">:=</span><span class="pas1-space"> Stop </span><span class="pas1-symbol">-</span><span class="pas1-space"> Start</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-space"> Writeln</span><span class="pas1-symbol">(</span><span class="pas1-string">'ThreadStack done.'</span><span class="pas1-symbol">);
</span><span class="pas1-space"> Writeln</span><span class="pas1-symbol">(</span><span class="pas1-string">'Starting TFreeStack threads'</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">for</span><span class="pas1-space"> j </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">to</span><span class="pas1-space"> NumberOfTest </span><span class="pas1-symbol">-</span><span class="pas1-space"> </span><span class="pas1-number">1</span><span class="pas1-space"> </span><span class="pas1-reservedword">do
</span><span class="pas1-space"> </span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> QueryPerformanceCounter</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Start</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">for</span><span class="pas1-space"> I </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">to</span><span class="pas1-space"> NumberOfThreads </span><span class="pas1-symbol">-</span><span class="pas1-space"> </span><span class="pas1-number">1</span><span class="pas1-space"> </span><span class="pas1-reservedword">do
</span><span class="pas1-space"> AFreeStacksTests</span><span class="pas1-symbol">[</span><span class="pas1-identifier">i</span><span class="pas1-symbol">]</span><span class="pas1-space"> </span><span class="pas1-symbol">:=</span><span class="pas1-space"> TFreeStackThread</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">(</span><span class="pas1-identifier">FreeStacks</span><span class="pas1-symbol">[</span><span class="pas1-identifier">i </span><span class="pas1-reservedword">mod</span><span class="pas1-space"> </span><span class="pas1-number">2</span><span class="pas1-symbol">],</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">i </span><span class="pas1-reservedword">mod</span><span class="pas1-space"> </span><span class="pas1-number">4</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-symbol">>=</span><span class="pas1-space"> </span><span class="pas1-number">2</span><span class="pas1-symbol">,</span><span class="pas1-space"> Finished</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">for</span><span class="pas1-space"> I </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">to</span><span class="pas1-space"> NumberOfThreads </span><span class="pas1-symbol">-</span><span class="pas1-space"> </span><span class="pas1-number">1</span><span class="pas1-space"> </span><span class="pas1-reservedword">do
</span><span class="pas1-space"> WaitForSingleObject</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Finished</span><span class="pas1-symbol">,</span><span class="pas1-space"> INFINITE</span><span class="pas1-symbol">);
</span><span class="pas1-space"> QueryPerformanceCounter</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Stop</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">for</span><span class="pas1-space"> I </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">to</span><span class="pas1-space"> NumberOfThreads </span><span class="pas1-symbol">-</span><span class="pas1-space"> </span><span class="pas1-number">1</span><span class="pas1-space"> </span><span class="pas1-reservedword">do
</span><span class="pas1-space"> AFreeStacksTests</span><span class="pas1-symbol">[</span><span class="pas1-identifier">i</span><span class="pas1-symbol">].</span><span class="pas1-identifier">Free</span><span class="pas1-symbol">;
</span><span class="pas1-space"> ResultFree</span><span class="pas1-symbol">[</span><span class="pas1-identifier">j</span><span class="pas1-symbol">]</span><span class="pas1-space"> </span><span class="pas1-symbol">:=</span><span class="pas1-space"> Stop </span><span class="pas1-symbol">-</span><span class="pas1-space"> Start</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-space"> Writeln</span><span class="pas1-symbol">(</span><span class="pas1-string">'TFreeStack done.'</span><span class="pas1-symbol">);
</span><span class="pas1-space"> Writeln</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Format</span><span class="pas1-symbol">(</span><span class="pas1-string">'Calculating the mean and the standard deviation out of %d runs.'</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-symbol">[</span><span class="pas1-identifier">NumberOfTest</span><span class="pas1-symbol">]));
</span><span class="pas1-space"> QueryPerformanceFrequency</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Freq</span><span class="pas1-symbol">);
</span><span class="pas1-space"> MeanAndStdDev</span><span class="pas1-symbol">(</span><span class="pas1-identifier">ResultThread</span><span class="pas1-symbol">,</span><span class="pas1-space"> Mean</span><span class="pas1-symbol">,</span><span class="pas1-space"> StdDev</span><span class="pas1-symbol">);
</span><span class="pas1-space"> Writeln</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Format</span><span class="pas1-symbol">(</span><span class="pas1-string">'TThreadStack: %f (%f)'</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-symbol">[</span><span class="pas1-identifier">Mean</span><span class="pas1-symbol">,</span><span class="pas1-space"> StdDev</span><span class="pas1-symbol">]));
</span><span class="pas1-space"> Writeln</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Format</span><span class="pas1-symbol">(</span><span class="pas1-string">'TThreadStack: %fms (%fms)'</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-symbol">[</span><span class="pas1-identifier">Mean </span><span class="pas1-symbol">/</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">Freq </span><span class="pas1-symbol">/</span><span class="pas1-space"> </span><span class="pas1-number">1000</span><span class="pas1-symbol">),</span><span class="pas1-space"> StdDev </span><span class="pas1-symbol">/</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">Freq </span><span class="pas1-symbol">/</span><span class="pas1-space"> </span><span class="pas1-number">1000</span><span class="pas1-symbol">)]));
</span><span class="pas1-space"> MeanAndStdDev</span><span class="pas1-symbol">(</span><span class="pas1-identifier">ResultFree</span><span class="pas1-symbol">,</span><span class="pas1-space"> Mean</span><span class="pas1-symbol">,</span><span class="pas1-space"> StdDev</span><span class="pas1-symbol">);
</span><span class="pas1-space"> Writeln</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Format</span><span class="pas1-symbol">(</span><span class="pas1-string">'TFreeStack: %f (%f)'</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-symbol">[</span><span class="pas1-identifier">Mean</span><span class="pas1-symbol">,</span><span class="pas1-space"> StdDev</span><span class="pas1-symbol">]));
</span><span class="pas1-space"> Writeln</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Format</span><span class="pas1-symbol">(</span><span class="pas1-string">'TFreeStack: %fms (%fms)'</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-symbol">[</span><span class="pas1-identifier">Mean </span><span class="pas1-symbol">/</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">Freq </span><span class="pas1-symbol">/</span><span class="pas1-space"> </span><span class="pas1-number">1000</span><span class="pas1-symbol">),</span><span class="pas1-space"> StdDev </span><span class="pas1-symbol">/</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">Freq </span><span class="pas1-symbol">/</span><span class="pas1-space"> </span><span class="pas1-number">1000</span><span class="pas1-symbol">)]));
</span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> DebugHook </span><span class="pas1-symbol"><></span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">then
</span><span class="pas1-space"> Readln</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-comment">{ freeing everything}
</span><span class="pas1-space"> ThreadStacks</span><span class="pas1-symbol">[</span><span class="pas1-number">0</span><span class="pas1-symbol">].</span><span class="pas1-identifier">Free</span><span class="pas1-symbol">;
</span><span class="pas1-space"> ThreadStacks</span><span class="pas1-symbol">[</span><span class="pas1-number">1</span><span class="pas1-symbol">].</span><span class="pas1-identifier">Free</span><span class="pas1-symbol">;
</span><span class="pas1-space"> FreeStacks</span><span class="pas1-symbol">[</span><span class="pas1-number">0</span><span class="pas1-symbol">].</span><span class="pas1-identifier">Free</span><span class="pas1-symbol">;
</span><span class="pas1-space"> FreeStacks</span><span class="pas1-symbol">[</span><span class="pas1-number">1</span><span class="pas1-symbol">].</span><span class="pas1-identifier">Free</span><span class="pas1-symbol">;
</span><span class="pas1-space"> CloseHandle</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Finished</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">.
</span></span>
</code></pre>
<p>This one also creates the memory leak. Running the code on a P4 2.26 returns this result: </p><blockquote class="console">Starting ThreadStack threads<br />
ThreadStack done.<br />
Starting TFreeStack threads<br />
TFreeStack done.<br />
Calculating the mean and the standard deviation out of 10 runs.<br />
TThreadStack: 7152374,20 (26574,65)<br />
TThreadStack: 1998,12ms (7,42ms)<br />
TFreeStack: 7339945,80 (310570,01)<br />
TFreeStack: 2050,52ms (86,76ms)</blockquote><p>So the TFreestack is all most the same speed as the simple critical section based TThreadStack, although I know now the test isn't what you'd call regular, because it's constantly trying to push and pop. So perhaps a more normal situation would result differently. But in my program this situation was expected. </p><p>I also liked the simplicity of the TThreadStack above the complexity of the FreeStack, were you had to compile a piece TASM (containing the CAS) for it to work. Another show stopper was the memory leak. But actually I just wanted to post my simple TThreadStack so that next time I have to use it, I can just wander to my own blog. So without further ado, I bring you the following source. </p><pre style="BORDER-RIGHT: 1px inset; PADDING-RIGHT: 6px; BORDER-TOP: 1px inset; PADDING-LEFT: 6px; PADDING-BOTTOM: 6px; MARGIN: 0px; OVERFLOW: auto; BORDER-LEFT: 1px inset; WIDTH: 440px; PADDING-TOP: 6px; BORDER-BOTTOM: 1px inset; HEIGHT: 600px"><code><span style="FONT: 10pt Courier New"><span class="pas1-reservedword">unit</span><span class="pas1-space"> unThreadStack</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">interface
uses
</span><span class="pas1-space"> Windows</span><span class="pas1-symbol">,</span><span class="pas1-space"> Contnrs</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">type
</span><span class="pas1-space"> TStack </span><span class="pas1-symbol">=</span><span class="pas1-space"> Contnrs</span><span class="pas1-symbol">.</span><span class="pas1-identifier">TStack</span><span class="pas1-symbol">;
</span><span class="pas1-space"> TThreadStack </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-reservedword">class
</span><span class="pas1-space"> </span><span class="pas1-reservedword">private
</span><span class="pas1-space"> FStack</span><span class="pas1-symbol">:</span><span class="pas1-space"> TStack</span><span class="pas1-symbol">;
</span><span class="pas1-space"> FLock </span><span class="pas1-symbol">:</span><span class="pas1-identifier">TRTLCriticalSection</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">public
</span><span class="pas1-space"> </span><span class="pas1-reservedword">constructor</span><span class="pas1-space"> Create</span><span class="pas1-symbol">();
</span><span class="pas1-space"> </span><span class="pas1-reservedword">destructor</span><span class="pas1-space"> Destroy</span><span class="pas1-symbol">;</span><span class="pas1-space"> </span><span class="pas1-reservedword">override</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">function</span><span class="pas1-space"> LockStack </span><span class="pas1-symbol">:</span><span class="pas1-space"> TStack</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> UnlockStack</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">function</span><span class="pas1-space"> Count</span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">function</span><span class="pas1-space"> Push</span><span class="pas1-symbol">(</span><span class="pas1-identifier">AItem</span><span class="pas1-symbol">:</span><span class="pas1-space"> Pointer</span><span class="pas1-symbol">):</span><span class="pas1-space"> Pointer</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">function</span><span class="pas1-space"> Pop</span><span class="pas1-symbol">:</span><span class="pas1-space"> Pointer</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">function</span><span class="pas1-space"> Peek</span><span class="pas1-symbol">:</span><span class="pas1-space"> Pointer</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">implementation
</span><span class="pas1-comment">{ TThreadStack }
</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TThreadStack</span><span class="pas1-symbol">.</span><span class="pas1-identifier">LockStack</span><span class="pas1-symbol">:</span><span class="pas1-space"> TStack</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> EnterCriticalSection</span><span class="pas1-symbol">(</span><span class="pas1-identifier">FLock</span><span class="pas1-symbol">);
</span><span class="pas1-space"> Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> FStack</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TThreadStack</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Count</span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> EnterCriticalSection</span><span class="pas1-symbol">(</span><span class="pas1-identifier">FLock</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">try
</span><span class="pas1-space"> Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> FStack</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Count</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">finally
</span><span class="pas1-space"> LeaveCriticalSection</span><span class="pas1-symbol">(</span><span class="pas1-identifier">FLock</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">constructor</span><span class="pas1-space"> TThreadStack</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">();
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> </span><span class="pas1-reservedword">inherited</span><span class="pas1-space"> Create</span><span class="pas1-symbol">();
</span><span class="pas1-space"> InitializeCriticalSection</span><span class="pas1-symbol">(</span><span class="pas1-identifier">FLock</span><span class="pas1-symbol">);
</span><span class="pas1-space"> FStack </span><span class="pas1-symbol">:=</span><span class="pas1-space"> Contnrs</span><span class="pas1-symbol">.</span><span class="pas1-identifier">TStack</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">destructor</span><span class="pas1-space"> TThreadStack</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Destroy</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> DeleteCriticalSection</span><span class="pas1-symbol">(</span><span class="pas1-identifier">FLock</span><span class="pas1-symbol">);
</span><span class="pas1-space"> FStack</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Free</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">inherited</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TThreadStack</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Peek</span><span class="pas1-symbol">:</span><span class="pas1-space"> Pointer</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> EnterCriticalSection</span><span class="pas1-symbol">(</span><span class="pas1-identifier">FLock</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">try
</span><span class="pas1-space"> Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> FStack</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Peek</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">finally
</span><span class="pas1-space"> LeaveCriticalSection</span><span class="pas1-symbol">(</span><span class="pas1-identifier">FLock</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TThreadStack</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Pop</span><span class="pas1-symbol">:</span><span class="pas1-space"> Pointer</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> EnterCriticalSection</span><span class="pas1-symbol">(</span><span class="pas1-identifier">FLock</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">try
</span><span class="pas1-space"> Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> FStack</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Pop</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">finally
</span><span class="pas1-space"> LeaveCriticalSection</span><span class="pas1-symbol">(</span><span class="pas1-identifier">FLock</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TThreadStack</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Push</span><span class="pas1-symbol">(</span><span class="pas1-identifier">AItem</span><span class="pas1-symbol">:</span><span class="pas1-space"> Pointer</span><span class="pas1-symbol">):</span><span class="pas1-space"> Pointer</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> EnterCriticalSection</span><span class="pas1-symbol">(</span><span class="pas1-identifier">FLock</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">try
</span><span class="pas1-space"> Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> FStack</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Push</span><span class="pas1-symbol">(</span><span class="pas1-identifier">AItem</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">finally
</span><span class="pas1-space"> LeaveCriticalSection</span><span class="pas1-symbol">(</span><span class="pas1-identifier">FLock</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TThreadStack</span><span class="pas1-symbol">.</span><span class="pas1-identifier">UnlockStack</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> LeaveCriticalSection</span><span class="pas1-symbol">(</span><span class="pas1-identifier">FLock</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">.
</span></span>
</code></pre>
<p>If you use this source, I would like it if you just left a comment on this blog. </p>Davy Landmanhttp://www.blogger.com/profile/06890346525536829946noreply@blogger.comtag:blogger.com,1999:blog-15443912.post-1145618701790871332006-04-21T11:51:00.001+02:002008-07-21T23:10:47.872+02:00Fast reading of files using Memory Mapping<span class="Notice">I've moved my blog and it's post to my new blog, please go to <a href="http://landman-code.blogspot.com/2006/04/it-has-been-six-months-since-i-last.html">Fast reading of files using Memory Mapping on Landman Code</a>.</span> It has been six months since I last posted something. Lets just say things got a little busy J. And posting source code on Blogspot seemed to be a bitch because blogspot would filter out the enters. I solved that in the previous post by using an <br /> as an enter. But when copying and pasting from the page the newlines were lost (offcourse <a href="http://www.dow.wau.nl/aew/DelForExp.html">DelForExp</a> fixes that.. but still it sucked). <p></p>
<p>Now I have just a little bit of time, and a few articles I wanted to post. So after some testing I found out blogspot fixed the enter removal and now I’ll try to post more frequently.</p>
<p>Now let’s get ontopic, <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dngenlib/html/msdn_manamemo.asp">Memory Mapped Files</a> can be very helpful for reading large files. Looking through the internet you can find many advantages and disadvantages. The important thing is, think about what your doing, MMF can be very fast in one application. But slow in an other, it all depends on the situation, there are enough articles about the subject (for instance <a href="http://blogs.borland.com/dcc/archive/2004/03/19/2380.aspx">this</a> one by the Delphi Compiler Team)</p>
<p>I like MMF a lot when using binary files of a certain format. Let’s assume we have the following file format:</p>
<pre>
<code><span style="FONT: 10pt Courier New"><span class="pas1-identifier">TCustomerStruct = </span><span class="pas1-reservedword">packed</span><span class="pas1-space"> </span><span class="pas1-reservedword">record
</span><span class="pas1-space"> CustomerID: Longword;
CustomerName: </span><span class="pas1-reservedword">array</span><span class="pas1-symbol">[</span><span class="pas1-number">0</span><span class="pas1-symbol">..</span><span class="pas1-number">254</span><span class="pas1-symbol">] </span><span class="pas1-reservedword">of</span><span class="pas1-space"> Char;
CustomerBirthDay: TDateTime;
CustomerRate: Double;
AccountManagerID: Longword;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;</span></span></code></pre>
<p>You could read this using BlockRead:</p>
<pre style="BORDER-RIGHT: 1px inset; PADDING-RIGHT: 6px; BORDER-TOP: 1px inset; PADDING-LEFT: 6px; PADDING-BOTTOM: 6px; MARGIN: 0px; OVERFLOW: auto; BORDER-LEFT: 1px inset; WIDTH: 440px; PADDING-TOP: 6px; BORDER-BOTTOM: 1px inset; HEIGHT: 300px"><span style="FONT: 10pt Courier New"><span class="pas1-reservedword">var
</span><span class="pas1-space"> CustomerFile: </span><span class="pas1-reservedword">file</span><span class="pas1-space"> </span><span class="pas1-reservedword">of</span><span class="pas1-space"> TCustomerStruct;
Customers: </span><span class="pas1-reservedword">array</span><span class="pas1-space"> </span><span class="pas1-reservedword">of</span><span class="pas1-space"> TCustomerStruct;
i : integer;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> AssignFile(CustomerFile,</span><span class="pas1-string">'c:\customers.cus'</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">try
</span><span class="pas1-space"> Reset(CustomerFile); </span><span class="pas1-comment">// open the file for reading
</span><span class="pas1-space"> SetLength(Customers, FileSize(CustomerFile)); </span><span class="pas1-comment">// create the array
</span><span class="pas1-space"> BlockRead(CustomerFile, Customers, Length(Customers)); </span><span class="pas1-comment">// Read the hole party in to the array
</span><span class="pas1-space"> </span><span class="pas1-reservedword">for</span><span class="pas1-space"> i := </span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">to</span><span class="pas1-space"> High(Customers) </span><span class="pas1-reservedword">do
</span><span class="pas1-space"> </span><span class="pas1-comment">// List all the customers in a memo
</span><span class="pas1-space"> memCustomerList.Lines.Add(</span><span class="pas1-string">'Name: '</span><span class="pas1-symbol">+ Customers[i].CustomerName);
</span><span class="pas1-reservedword">finally
</span><span class="pas1-space"> CloseFile(CustomerFile);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;</span></span>
</pre>
<p>And now using MemoryMapping:</p>
<pre style="BORDER-RIGHT: 1px inset; PADDING-RIGHT: 6px; BORDER-TOP: 1px inset; PADDING-LEFT: 6px; PADDING-BOTTOM: 6px; MARGIN: 0px; OVERFLOW: auto; BORDER-LEFT: 1px inset; WIDTH: 440px; PADDING-TOP: 6px; BORDER-BOTTOM: 1px inset; HEIGHT: 300px"><span style="FONT: 10pt Courier New"><span class="pas1-reservedword">type</span>
<span class="pas1-space"> TCustomerStructArray = </span><span class="pas1-reservedword">array</span><span class="pas1-symbol">[</span><span class="pas1-number">0</span><span class="pas1-symbol">..MaxInt </span><span class="pas1-reservedword">div</span><span class="pas1-space"> SizeOf(TCustomerStruct) - </span><span class="pas1-number">1</span><span class="pas1-symbol">] </span><span class="pas1-reservedword">of</span><span class="pas1-space"> TCustomerStruct;
PCustomerStructArray = ^TCustomerStructArray;
</span><span class="pas1-reservedword">var
</span><span class="pas1-space"> CustomerFile : TMappedFile;
Customers: PCustomerStructArray;
i : integer;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> CustomerFile := TMappedFile.Create;
</span><span class="pas1-reservedword">try
</span><span class="pas1-space"> CustomerFile.MapFile(</span><span class="pas1-string">'c:\customers.cus'</span><span class="pas1-symbol">);
Customers := PCustomerStructArray(CustomerFile.Content); </span><span class="pas1-comment">// not needed, but handy
</span><span class="pas1-space"> </span><span class="pas1-reservedword">for</span><span class="pas1-space"> i := </span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">to</span><span class="pas1-space"> CustomerFile.Size </span><span class="pas1-reservedword">div</span><span class="pas1-space"> SizeOf(TCustomerStruct) -</span><span class="pas1-number">1</span><span class="pas1-space"> </span><span class="pas1-reservedword">do
</span><span class="pas1-space"> memCustomerList.Lines.Add(</span><span class="pas1-string">'Name: '</span><span class="pas1-symbol">+ Customers[i].CustomerName);
</span><span class="pas1-reservedword">finally
</span><span class="pas1-space"> CustomerFile.Free;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;</span></span></pre>
<p>The <span style="FONT: 10pt Courier New"><span class="pas1-symbol">MaxInt </span><span class="pas1-reservedword">div</span><span class="pas1-space"> SizeOf(TCustomerStruct) – </span><span class="pas1-number">1</span></span> is the maximum amount of records (thus memory) loaded at once.</p>
<p>The TMappedFile class is something I created myself so I can be lazy. Off course I will share that piece of code too.</p>
<pre style="BORDER-RIGHT: 1px inset; PADDING-RIGHT: 6px; BORDER-TOP: 1px inset; PADDING-LEFT: 6px; PADDING-BOTTOM: 6px; MARGIN: 0px; OVERFLOW: auto; BORDER-LEFT: 1px inset; WIDTH: 440px; PADDING-TOP: 6px; BORDER-BOTTOM: 1px inset; HEIGHT: 400px"><span style="FONT: 10pt Courier New"><span class="pas1-reservedword">unit</span><span class="pas1-space"> unFileMapping</span><span class="pas1-symbol">;
</span><span class="pas1-comment">{
Copyright (c) 2005-2006 by Davy Landman
See the file COPYING.FPC, included in this distribution,
for details about the copyright. Alternately, you may use this source under the provisions of MPL v1.x or later
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
}
</span><span class="pas1-reservedword">interface
uses
</span><span class="pas1-space"> Windows</span><span class="pas1-symbol">,</span><span class="pas1-space"> SysUtils</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">type
</span><span class="pas1-space"> TMappedFile </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-reservedword">class
</span><span class="pas1-space"> </span><span class="pas1-reservedword">private
</span><span class="pas1-space"> FMapping</span><span class="pas1-symbol">:</span><span class="pas1-space"> THandle</span><span class="pas1-symbol">;
</span><span class="pas1-space"> FContent</span><span class="pas1-symbol">:</span><span class="pas1-space"> Pointer</span><span class="pas1-symbol">;
</span><span class="pas1-space"> FSize</span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> MapFile</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> AFileName</span><span class="pas1-symbol">:</span><span class="pas1-space"> WideString</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">public
</span><span class="pas1-space"> </span><span class="pas1-reservedword">constructor</span><span class="pas1-space"> Create</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> AFileName</span><span class="pas1-symbol">:</span><span class="pas1-space"> WideString</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">destructor</span><span class="pas1-space"> Destroy</span><span class="pas1-symbol">;</span><span class="pas1-space"> </span><span class="pas1-reservedword">override</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">property</span><span class="pas1-space"> Content</span><span class="pas1-symbol">:</span><span class="pas1-space"> Pointer </span><span class="pas1-reservedword">read</span><span class="pas1-space"> FContent</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">property</span><span class="pas1-space"> Size</span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer </span><span class="pas1-reservedword">read</span><span class="pas1-space"> FSize</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">implementation
function</span><span class="pas1-space"> FileExistsLongFileNames</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> FileName</span><span class="pas1-symbol">:</span><span class="pas1-space"> WideString</span><span class="pas1-symbol">):</span><span class="pas1-space"> Boolean</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> Length</span><span class="pas1-symbol">(</span><span class="pas1-identifier">FileName</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-symbol"><</span><span class="pas1-space"> </span><span class="pas1-number">2</span><span class="pas1-space"> </span><span class="pas1-reservedword">then
</span><span class="pas1-space"> </span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> False</span><span class="pas1-symbol">;
</span><span class="pas1-space"> Exit</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> CompareMem</span><span class="pas1-symbol">(@</span><span class="pas1-identifier">FileName</span><span class="pas1-symbol">[</span><span class="pas1-number">1</span><span class="pas1-symbol">],</span><span class="pas1-space"> </span><span class="pas1-symbol">@WideString(</span><span class="pas1-string">'\\')</span><span class="pas1-symbol">[</span><span class="pas1-number">1</span><span class="pas1-symbol">],</span><span class="pas1-space"> </span><span class="pas1-number">2</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">then
</span><span class="pas1-space"> Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">GetFileAttributesW</span><span class="pas1-symbol">(</span><span class="pas1-identifier">PWideChar</span><span class="pas1-symbol">(</span><span class="pas1-identifier">FileName</span><span class="pas1-symbol">))</span><span class="pas1-space"> </span><span class="pas1-reservedword">and</span><span class="pas1-space"> FILE_ATTRIBUTE_DIRECTORY </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-symbol">)
</span><span class="pas1-space"> </span><span class="pas1-reservedword">else
</span><span class="pas1-space"> Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">GetFileAttributesW</span><span class="pas1-symbol">(</span><span class="pas1-identifier">PWideChar</span><span class="pas1-symbol">(</span><span class="pas1-identifier">WideString</span><span class="pas1-symbol">(</span><span class="pas1-string">'\\?\'</span><span class="pas1-space"> </span><span class="pas1-symbol">+</span><span class="pas1-space"> FileName</span><span class="pas1-symbol">)))</span><span class="pas1-space"> </span><span class="pas1-reservedword">and</span><span class="pas1-space"> FILE_ATTRIBUTE_DIRECTORY </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-symbol">)
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-comment">{ TMappedFile }
</span><span class="pas1-reservedword">constructor</span><span class="pas1-space"> TMappedFile</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> AFileName</span><span class="pas1-symbol">:</span><span class="pas1-space"> WideString</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> </span><span class="pas1-reservedword">inherited</span><span class="pas1-space"> Create</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> FileExistsLongFileNames</span><span class="pas1-symbol">(</span><span class="pas1-identifier">AFileName</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">then
</span><span class="pas1-space"> MapFile</span><span class="pas1-symbol">(</span><span class="pas1-identifier">AFileName</span><span class="pas1-symbol">)
</span><span class="pas1-space"> </span><span class="pas1-reservedword">else
</span><span class="pas1-space"> </span><span class="pas1-reservedword">raise</span><span class="pas1-space"> Exception</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">(</span><span class="pas1-string">'File "'</span><span class="pas1-space"> </span><span class="pas1-symbol">+</span><span class="pas1-space"> AFileName </span><span class="pas1-symbol">+</span><span class="pas1-space"> </span><span class="pas1-string">'" does not exists.'</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">destructor</span><span class="pas1-space"> TMappedFile</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Destroy</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> Assigned</span><span class="pas1-symbol">(</span><span class="pas1-identifier">FContent</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">then
</span><span class="pas1-space"> </span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> UnmapViewOfFile</span><span class="pas1-symbol">(</span><span class="pas1-identifier">FContent</span><span class="pas1-symbol">);
</span><span class="pas1-space"> CloseHandle</span><span class="pas1-symbol">(</span><span class="pas1-identifier">FMapping</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">inherited</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TMappedFile</span><span class="pas1-symbol">.</span><span class="pas1-identifier">MapFile</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> AFileName</span><span class="pas1-symbol">:</span><span class="pas1-space"> WideString</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">var
</span><span class="pas1-space"> FileHandle</span><span class="pas1-symbol">:</span><span class="pas1-space"> THandle</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> CompareMem</span><span class="pas1-symbol">(@(</span><span class="pas1-identifier">AFileName</span><span class="pas1-symbol">[</span><span class="pas1-number">1</span><span class="pas1-symbol">]),</span><span class="pas1-space"> </span><span class="pas1-symbol">@(</span><span class="pas1-string">'\\'</span><span class="pas1-symbol">[</span><span class="pas1-number">1</span><span class="pas1-symbol">]),</span><span class="pas1-space"> </span><span class="pas1-number">2</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">then
</span><span class="pas1-space"> </span><span class="pas1-comment">{ Allready an UNC path }
</span><span class="pas1-space"> FileHandle </span><span class="pas1-symbol">:=</span><span class="pas1-space"> CreateFileW</span><span class="pas1-symbol">(</span><span class="pas1-identifier">PWideChar</span><span class="pas1-symbol">(</span><span class="pas1-identifier">AFileName</span><span class="pas1-symbol">),</span><span class="pas1-space"> GENERIC_READ</span><span class="pas1-symbol">,</span><span class="pas1-space"> FILE_SHARE_READ </span><span class="pas1-reservedword">or
</span><span class="pas1-space"> FILE_SHARE_WRITE</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-reservedword">nil</span><span class="pas1-symbol">,</span><span class="pas1-space"> OPEN_EXISTING</span><span class="pas1-symbol">,</span><span class="pas1-space"> FILE_ATTRIBUTE_NORMAL</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-symbol">)
</span><span class="pas1-space"> </span><span class="pas1-reservedword">else
</span><span class="pas1-space"> FileHandle </span><span class="pas1-symbol">:=</span><span class="pas1-space"> CreateFileW</span><span class="pas1-symbol">(</span><span class="pas1-identifier">PWideChar</span><span class="pas1-symbol">(</span><span class="pas1-identifier">WideString</span><span class="pas1-symbol">(</span><span class="pas1-string">'\\?\'</span><span class="pas1-space"> </span><span class="pas1-symbol">+</span><span class="pas1-space"> AFileName</span><span class="pas1-symbol">)),</span><span class="pas1-space"> GENERIC_READ</span><span class="pas1-symbol">,</span><span class="pas1-space"> FILE_SHARE_READ </span><span class="pas1-reservedword">or
</span><span class="pas1-space"> FILE_SHARE_WRITE</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-reservedword">nil</span><span class="pas1-symbol">,</span><span class="pas1-space"> OPEN_EXISTING</span><span class="pas1-symbol">,</span><span class="pas1-space"> FILE_ATTRIBUTE_NORMAL</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> FileHandle </span><span class="pas1-symbol"><></span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">then
</span><span class="pas1-space"> </span><span class="pas1-reservedword">try
</span><span class="pas1-space"> FSize </span><span class="pas1-symbol">:=</span><span class="pas1-space"> GetFileSize</span><span class="pas1-symbol">(</span><span class="pas1-identifier">FileHandle</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-reservedword">nil</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> FSize </span><span class="pas1-symbol"><></span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">then
</span><span class="pas1-space"> </span><span class="pas1-reservedword">begin
</span><span class="pas1-space"> FMapping </span><span class="pas1-symbol">:=</span><span class="pas1-space"> CreateFileMappingW</span><span class="pas1-symbol">(</span><span class="pas1-identifier">FileHandle</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-reservedword">nil</span><span class="pas1-symbol">,</span><span class="pas1-space"> PAGE_READONLY</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-reservedword">nil</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-comment">//Win32Check(FMapping <> 0);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">finally
</span><span class="pas1-space"> CloseHandle</span><span class="pas1-symbol">(</span><span class="pas1-identifier">FileHandle</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> FSize </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">then
</span><span class="pas1-space"> FContent </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-reservedword">nil
</span><span class="pas1-space"> </span><span class="pas1-reservedword">else
</span><span class="pas1-space"> FContent </span><span class="pas1-symbol">:=</span><span class="pas1-space"> MapViewOfFile</span><span class="pas1-symbol">(</span><span class="pas1-identifier">FMapping</span><span class="pas1-symbol">,</span><span class="pas1-space"> FILE_MAP_READ</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-symbol">);
</span><span class="pas1-space"> </span><span class="pas1-comment">//Win32Check(FContent <> nil);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">.
</span></span></span></pre>
<p>The big advantage is, that with BlockRead you can either read the whole content of the file in the array, or buffering the file in blocks. With MMF there is no need to worry about it (unless you get very big files), Windows automatically arranges the memory when requested.</p>Davy Landmanhttp://www.blogger.com/profile/06890346525536829946noreply@blogger.comtag:blogger.com,1999:blog-15443912.post-1124401277637569602005-08-18T23:41:00.001+02:002008-07-21T23:12:54.958+02:00Getting (possibly) 500% speed gain on divisions<span class="Notice">I've moved my blog and it's post to my new blog, please go to <a href="http://landman-code.blogspot.com/2005/08/getting-possibly-500-speed-gain-on.html">Getting (possibly) 500% speed gain on divisions on Landman Code</a>.</span>One of my fellow students once made a remark about the old days when a division was much faster if it was written as multiplication. </p><p>This means, instead of devising with a 100, you multiply with 0.01 (1/100). Because some programs of mine have a lot of divisions in their core loops, I investigated the difference.</p><p>I created the following test program.</p><pre style="margin:0px; padding:6px; border:1px inset; width: 440px; height: 600px; overflow:auto"><div dir="ltr" style="text-align:left;"><span style="font: 10pt Courier New;"><span class="pas1-reservedword">program</span><span class="pas1-space"> DivVsMult</span><span class="pas1-symbol">; <br /> <br /></span><span class="pas1-preprocessor">{$APPTYPE CONSOLE} <br /> <br /></span><span class="pas1-reservedword">uses <br /></span><span class="pas1-space"> SysUtils</span><span class="pas1-symbol">, <br /></span><span class="pas1-space"> Windows</span><span class="pas1-symbol">; <br /> <br /></span><span class="pas1-reservedword">var <br /></span><span class="pas1-space"> Start</span><span class="pas1-symbol">,</span><span class="pas1-identifier">Stop</span><span class="pas1-symbol">,</span><span class="pas1-space"> Start2</span><span class="pas1-symbol">,</span><span class="pas1-space"> Stop2</span><span class="pas1-symbol">,</span><span class="pas1-space"> Freq</span><span class="pas1-symbol">:</span><span class="pas1-identifier">int64</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> i </span><span class="pas1-symbol">:</span><span class="pas1-space"> integer</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> t </span><span class="pas1-symbol">:</span><span class="pas1-space"> real</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> CpuSpeed </span><span class="pas1-symbol">:</span><span class="pas1-space"> integer</span><span class="pas1-symbol">; <br /></span><span class="pas1-reservedword">begin <br /></span><span class="pas1-space"> </span><span class="pas1-comment">{ TODO -oUser -cConsole Main : Insert code here } <br /></span><span class="pas1-space"> </span><span class="pas1-comment">{ Cpu Speed fastes cpu = 1 slower => 10 <br /> it's just to determin the number of time to do the loop <br /> Maxint div CpuSpeed is calculated } <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> ParamCount </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-number">1</span><span class="pas1-space"> </span><span class="pas1-reservedword">then <br /></span><span class="pas1-space"> CpuSpeed </span><span class="pas1-symbol">:=</span><span class="pas1-space"> StrToIntDef</span><span class="pas1-symbol">(</span><span class="pas1-identifier">ParamStr</span><span class="pas1-symbol">(</span><span class="pas1-number">1</span><span class="pas1-symbol">),</span><span class="pas1-number">1</span><span class="pas1-symbol">) <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">else <br /></span><span class="pas1-space"> CpuSpeed </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-number">10</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> Writeln</span><span class="pas1-symbol">(</span><span class="pas1-string">'Simple Number division:'</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> Writeln</span><span class="pas1-symbol">(</span><span class="pas1-string">'Calculating'</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> QueryPerformanceFrequency</span><span class="pas1-symbol">(</span><span class="pas1-identifier">freq</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> QueryPerformanceCounter</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Start</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">for</span><span class="pas1-space"> i</span><span class="pas1-symbol">:=</span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">to</span><span class="pas1-space"> MaxInt </span><span class="pas1-reservedword">div</span><span class="pas1-space"> </span><span class="pas1-space"> CpuSpeed </span><span class="pas1-reservedword">do <br /></span><span class="pas1-space"> t </span><span class="pas1-symbol">:=</span><span class="pas1-space"> i </span><span class="pas1-symbol">*</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-number">1</span><span class="pas1-symbol">/</span><span class="pas1-number">100</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> QueryPerformanceCounter</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Stop</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> Writeln</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Format</span><span class="pas1-symbol">(</span><span class="pas1-string">'First Pass Result: %f'</span><span class="pas1-symbol">,[</span><span class="pas1-identifier">t</span><span class="pas1-symbol">])); <br /></span><span class="pas1-space"> </span><span class="pas1-comment">{ This is needed because the compiler would optimize, <br /> and would notice the result of the loop isn't used at all, <br /> so therefor the result is useless.. so depending on the compiler, it will <br /> choose what to do with it, this disables that optimization } <br /></span><span class="pas1-space"> QueryPerformanceCounter</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Start2</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">for</span><span class="pas1-space"> i</span><span class="pas1-symbol">:=</span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">to</span><span class="pas1-space"> MaxInt </span><span class="pas1-reservedword">div</span><span class="pas1-space"> CpuSpeed </span><span class="pas1-reservedword">do <br /></span><span class="pas1-space"> t </span><span class="pas1-symbol">:=</span><span class="pas1-space"> i </span><span class="pas1-symbol">*</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-number">1</span><span class="pas1-symbol">/</span><span class="pas1-number">100</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> QueryPerformanceCounter</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Stop2</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> Writeln</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Format</span><span class="pas1-symbol">(</span><span class="pas1-string">'Second Pass Result: %15.6f'</span><span class="pas1-symbol">,[</span><span class="pas1-identifier">t</span><span class="pas1-symbol">])); <br /></span><span class="pas1-space"> </span><span class="pas1-comment">{ This is needed because the compiler would optimize, <br /> and would notice the result of the loop isn't used at all, <br /> so therefor the result is useless.. so depending on the compiler, it will <br /> choose what to do with it, this disables that optimization } <br /></span><span class="pas1-space"> Writeln</span><span class="pas1-symbol">(</span><span class="pas1-string">'Done, Results:'</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> Writeln</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Format</span><span class="pas1-symbol">(</span><span class="pas1-string">'/ 100 Time: %6.4f seconds'</span><span class="pas1-
symbol">+</span><span class="pas1-character">#13#10</span><span class="pas1-symbol">+ <br /></span><span class="pas1-space"> </span><span class="pas1-string">'/ 100 Clock: %d ticks'</span><span class="pas1-symbol">+</span><span class="pas1-character">#13#10</span><span class="pas1-symbol">+ <br /></span><span class="pas1-space"> </span><span class="pas1-string">'* 0.01 Time: %6.4f seconds'</span><span class="pas1-symbol">+</span><span class="pas1-character">#13#10</span><span class="pas1-symbol">+ <br /></span><span class="pas1-space"> </span><span class="pas1-string">'* 0.01 Clock: %d ticks'</span><span class="pas1-symbol">,[(</span><span class="pas1-identifier">Stop</span><span class="pas1-symbol">-</span><span class="pas1-identifier">Start</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-symbol">/</span><span class="pas1-space"> freq</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">Stop2</span><span class="pas1-symbol">-</span><span class="pas1-identifier">Start2</span><span class="pas1-symbol">)])); <br /></span><span class="pas1-space"> Writeln</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> Writeln</span><span class="pas1-symbol">(</span><span class="pas1-string">'Odd Number division:'</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> QueryPerformanceCounter</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Start</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">for</span><span class="pas1-space"> i</span><span class="pas1-symbol">:=</span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">to</span><span class="pas1-space"> high</span><span class="pas1-symbol">(</span><span class="pas1-identifier">i</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">div</span><span class="pas1-space"> CpuSpeed </span><span class="pas1-reservedword">do <br /></span><span class="pas1-space"> t </span><span class="pas1-symbol">:=</span><span class="pas1-space"> i </span><span class="pas1-symbol">/</span><span class="pas1-space"> </span><span class="pas1-number">556</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> QueryPerformanceCounter</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Stop</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> Writeln</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Format</span><span class="pas1-symbol">(</span><span class="pas1-string">'First Pass Result: %15.6f'</span><span class="pas1-symbol">,[</span><span class="pas1-identifier">t</span><span class="pas1-symbol">])); <br /></span><span class="pas1-space"> </span><span class="pas1-comment">{ This is needed because the compiler would optimize, <br /> and would notice the result of the loop isn't used at all, <br /> so therefor the result is useless.. so depending on the compiler, it will <br /> choose what to do with it, this disables that optimization } <br /></span><span class="pas1-space"> QueryPerformanceCounter</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Start2</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">for</span><span class="pas1-space"> i</span><span class="pas1-symbol">:=</span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">to</span><span class="pas1-space"> high</span><span class="pas1-symbol">(</span><span class="pas1-identifier">i</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">div</span><span class="pas1-space"> CpuSpeed </span><span class="pas1-reservedword">do <br /></span><span class="pas1-space"> t </span><span class="pas1-symbol">:=</span><span class="pas1-space"> i </span><span class="pas1-symbol">*</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-number">1</span><span class="pas1-symbol">/</span><span class="pas1-number">556</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> QueryPerformanceCounter</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Stop2</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> Writeln</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Format</span><span class="pas1-symbol">(</span><span class="pas1-string">'Second Pass Result: %15.6f'</span><span class="pas1-symbol">,[</span><span class="pas1-identifier">t</span><span class="pas1-symbol">])); <br /></span><span class="pas1-space"> </span>
<span class="pas1-space"> Writeln</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Format</span><span class="pas1-symbol">(</span><span class="pas1-string">'/ 556 Time: %6.4f seconds'</span><span class="pas1-symbol">+</span><span class="pas1-character">#13#10</span><span class="pas1-symbol">+ <br /></span><span class="pas1-space"> </span><span class="pas1-string">'/ 556 Clock: %d ticks'</span><span class="pas1-symbol">+</span><span class="pas1-character">#13#10</span><span class="pas1-symbol">+ <br /></span><span class="pas1-space"> </span><span class="pas1-string">'* (1/556) Time: %6.4f seconds'</span><span class="pas1-symbol">+</span><span class="pas1-character">#13#10</span><span class="pas1-symbol">+ <br /></span><span class="pas1-space"> </span><span class="pas1-string">'* (1/556) Clock: %d ticks'</span><span class="pas1-symbol">,[(</span><span class="pas1-identifier">Stop</span><span class="pas1-symbol">-</span><span class="pas1-identifier">Start</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-symbol">/</span><span class="pas1-space"> freq</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">Stop</span><span class="pas1-symbol">-</span><span class="pas1-identifier">Start</span><span class="pas1-symbol">),</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">Stop2</span><span class="pas1-symbol">-</span><span class="pas1-identifier">Start2</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-symbol">/</span><span class="pas1-space"> freq</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">Stop2</span><span class="pas1-symbol">-</span><span class="pas1-identifier">Start2</span><span class="pas1-symbol">)])); <br /></span><span class="pas1-space"> Writeln</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Format</span><span class="pas1-symbol">(</span><span class="pas1-string">' (1/556) = %15.14f (approximate)'</span><span class="pas1-symbol">,[</span><span class="pas1-number">1</span><span class="pas1-symbol">/</span><span class="pas1-number">556</span><span class="pas1-symbol">])); <br /></span><span class="pas1-comment">// Readln; <br /> <br /></span><span class="pas1-reservedword">end</span><span class="pas1-symbol">. <br /></span></span> <br /></div></pre><p>On an old P3 900Mhz:</p><blockquote><div><span style="FONT-FAMILY: courier new">Simple Number division:<br />Calculating<br />First Pass Result: 2147483,64<br />Second Pass Result: 2147483,64<br />Done, Results:<br />/ 100 Time: 10,3319 seconds<br />/ 100 Clock: 36983482 ticks<br />* 0.01 Time: 2,0378 seconds<br />* 0.01 Clock: 7294251 ticks<br /><br />Odd Number division:<br />First Pass Result: 386238,0647482014610000<br />Second Pass Result: 386238,0647482014610000<br />Done, Results:<br />/ 556 Time: 10,0735 seconds<br />/ 556 Clock: 36058581 ticks<br />* (1/556) Time: 2,0446 seconds<br />* (1/556) Clock: 7318775 ticks<br />(1/556) = 0,0017985611510791 (approximate)</span></div></blockquote><p>On a new P4 2.3 Ghz:</p><blockquote><div><span style="FONT-FAMILY: courier new">Simple Number division:<br />Calculating<br />First Pass Result: 2147483.64<br />Second Pass Result: 2147483.64<br />Done, Results:<br />/ 100 Time: 4.6227 seconds<br />/ 100 Clock: 16547055 ticks<br />* 0.01 Time: 1.0782 seconds<br />* 0.01 Clock: 3859508 ticks<br /><br />Odd Number division:<br />First Pass Result: 386238.064748<br />Second Pass Result: 386238.064748<br />Done, Results:<br />/ 556 Time: 4.5820 seconds<br />/ 556 Clock: 16401425 ticks<br />* (1/556) Time: 12.1746 seconds<br />* (1/556) Clock: 43579366 ticks<br />(1/556) = 0.00179856115108 (approximate)</span></div></blockquote><p>The results are variating, on simple numbers like 0.01 the speedup is allways working, but somehow the very complex numbers tend to be slower sometimes.</p><p>I use this tip allot when working with percentage.Davy Landmanhttp://www.blogger.com/profile/06890346525536829946noreply@blogger.comtag:blogger.com,1999:blog-15443912.post-1124319727375622942005-08-18T01:02:00.001+02:002008-07-21T23:14:29.015+02:00Automatic Cropping of a Bitmap<span class="Notice">I've moved my blog and it's post to my new blog, please go to <a href="http://landman-code.blogspot.com/2005/08/automatic-cropping-of-bitmap.html">Automatic Cropping of a Bitmap on Landman Code</a>.</span>
I have created a lot of program’s which needed to do some operations on Bitmaps, most of them are pretty simple, but recently I needed some auto cropping due to the fact I could not calculate the width and height without allot of calculation, but the maximum could easily be calculated/estimated, therefor I needed an algorithm for cropping these bitmap automatically.</p><p>Everyone who uses Delphi and Bitmaps should have at least heard about scanlines, and in particularly <a href="http://homepages.borland.com/efg2lab/">efg</a>’s pages on the <a href="http://homepages.borland.com/efg2lab/ImageProcessing/Scanline.htm">topic</a>. In short: </p><blockquote cite="http://homepages.borland.com/efg2lab/ImageProcessing/Scanline.htm"><p>The ScanLine property, new in Delphi 3, allows quick access to individual pixels, but you must know what PixelFormat you're working with before you can access the pixels correctly.</p></blockquote><p>Because I almost always work with 24bit bitmaps, I didn’t adapt the code for other pixel formats, but it should really just be editing the “<span style="font-family:Courier New;">procedure AutoCropBitmap(InputBitmap, OutputBitmap: TBitmap; iBleeding : Integer; BackColor: TColor);</span>” overload to start the right sub functions for each pixel format.</p><p>The current function will always translate it to an 24bit bitmap, which can be a processor and memory heavy job, the advise is therefor directly after creating the bitmap set the PixelFormat to pf24bit. </p><p>You might notice the overloads, well thats just one part of me being lazy again, sometimes I haven’t got the time to create an extra variable and assign the property’s etc. The overloads allow the choice of which input and output you’ll like.</p><pre style="BORDER-RIGHT: 1px inset; PADDING-RIGHT: 6px; BORDER-TOP: 1px inset; PADDING-LEFT: 6px; PADDING-BOTTOM: 6px; MARGIN: 0px; OVERFLOW: auto; BORDER-LEFT: 1px inset; WIDTH: 440px; PADDING-TOP: 6px; BORDER-BOTTOM: 1px inset; HEIGHT: 600px"><code><span style="font: 10pt Courier New;"><span class="pas1-reservedword">unit</span><span class="pas1-space"> unBitmapCropping</span><span class="pas1-symbol">;</span><span class="pas1-space"> <br /> <br /></span><span class="pas1-reservedword">interface</span><span class="pas1-space"> <br /> <br /></span><span class="pas1-reservedword">uses <br /></span><span class="pas1-space"> Windows</span><span class="pas1-symbol">,</span><span class="pas1-space"> Graphics</span><span class="pas1-symbol">,</span><span class="pas1-space"> Dialogs</span><span class="pas1-symbol">,</span><span class="pas1-space"> SysUtils</span><span class="pas1-symbol">,</span><span class="pas1-space"> Math</span><span class="pas1-symbol">,</span><span class="pas1-space"> Classes</span><span class="pas1-symbol">;</span><span class="pas1-space"> <br /> <br /></span><span class="pas1-reservedword">const <br /></span><span class="pas1-space"> PixelCountMax </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-number">32768</span><span class="pas1-symbol">;</span><span class="pas1-space"> <br /> <br /></span><span class="pas1-reservedword">type <br /></span><span class="pas1-space"> pRGBArray </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-symbol">^</span><span class="pas1-identifier">TRGBArray</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> TRGBArray </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-reservedword">array</span><span class="pas1-symbol">[</span><span class="pas1-number">0</span><span class="pas1-symbol">..</span><span class="pas1-identifier">PixelCountMax</span><span class="pas1-symbol">-</span><span class="pas1-number">1</span><span class="pas1-symbol">]</span><span class="pas1-space"> </span><span class="pas1-reservedword">of</span><span class="pas1-space"> TRGBTriple</span><span class="pas1-symbol">;</span><span class="pas1-space"> <br /> <br /> </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> AutoCropBitmap</span><span class="pas1-symbol">(</span><span class="pas1-identifier">InputBitmap</span><span class="pas1-symbol">,</span><span class="pas1-space"> OutputBitmap</span><span class="pas1-symbol">:</span><span class="pas1-space"> TBitmap</span><span class="pas1-symbol">;</span><span class="pas1-space"> iBleeding </span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-reservedword">overload</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> AutoCropBitmap</span><span class="pas1-symbol">(</span><span class="pas1-identifier">InputBitmap</span><span class="pas1-symbol">,</span><span class="pas1-space"> OutputBitmap</span><span class="pas1-symbol">:</span><span class="pas1-space"> TBitmap</span><span class="pas1-symbol">;</span><span class="pas1-space"> iBleeding </span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">;</span><span class="pas1-space"> BackColor</span><span class="pas1-symbol">:</span><span class="pas1-space"> TColor</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-reservedword">overload</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> AutoCropBitmap</span><span class="pas1-symbol">(</span><span class="pas1-identifier">BitMapToCrop</span><span class="pas1-symbol">:</span><span class="pas1-space"> TBitmap</span><span class="pas1-symbol">;</span><span class="pas1-space"> iBleeding </span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-reservedword">overload</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> AutoCropBitmap</span><span class="pas1-symbol">(</span><span class="pas1-identifier">BitMapToCrop</span><span class="pas1-symbol">:</span><span class="pas1-space"> TBitmap</span><span class="pas1-symbol">;</span><span class="pas1-space"> iBleeding </span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">;</span><span class="pas1-space"> BackColor</span><span class="pas1-symbol">:</span><span class="pas1-space"> TColor</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-reservedword">overload</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> AutoCropBmp</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> sFileName </span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-symbol">;</span><span class="pas1-space"> iBleeding </span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-reservedword">overload</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> AutoCropBmp</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> sFileName </span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-symbol">;</span><span class="pas1-space"> iBleeding </span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">;</span><span class="pas1-space"> BackColor</span><span class="pas1-symbol">:</span><span class="pas1-space"> TColor</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-reservedword">overload</span><span class="pas1-symbol">;</span><span class="pas1-space"> <br /> <br /></span><span class="pas1-reservedword">implementation</span><span class="pas1-space"> <br /> <br /></span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> AutoCropBitmap</span><span class="pas1-symbol">(</span><span class="pas1-identifier">BitMapToCrop</span><span class="pas1-symbol">:</span><span class="pas1-space"> TBitmap</span><span class="pas1-symbol">;</span><span class="pas1-space"> iBleeding </span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">); <br /></span><span class="pas1-reservedword">var</span><span class="pas1-space"> bmpTmp </span><span class="pas1-symbol">:</span><span class="pas1-space"> TBitmap</span><span class="pas1-symbol">; <br /></span><span class="pas1-reservedword">begin <br /></span><span class="pas1-space"> bmpTmp </span><span class="pas1-symbol">:=</span><span class="pas1-space"> TBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">try <br /></span><span class="pas1-space"> AutoCropBitmap</span><span class="pas1-symbol">(</span><span class="pas1-identifier">BitMapToCrop</span><span class="pas1-symbol">,</span><span class="pas1-identifier">bmpTmp</span><span class="pas1-symbol">,</span><span class="pas1-identifier">iBleeding</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> BitMapToCrop</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Assign</span><span class="pas1-symbol">(</span><span class="pas1-identifier">bmpTmp</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">finally <br /></span><span class="pas1-space"> bmpTmp</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Free</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">; <br /></span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;</span><span class="pas1-space"> <br /> <br /></span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> AutoCropBitmap</span><span class="pas1-symbol">(</span><span class="pas1-identifier">BitMapToCrop</span><span class="pas1-symbol">:</span><span class="pas1-space"> TBitmap</span><span class="pas1-symbol">;</span><span class="pas1-space"> iBleeding </span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">;</span><span class="pas1-space"> BackColor</span><span class="pas1-symbol">:</span><span class="pas1-space"> TColor</span><span class="pas1-symbol">); <br /></span><span class="pas1-reservedword">var</span><span class="pas1-space"> bmpTmp </span><span class="pas1-symbol">:</span><span class="pas1-space"> TBitmap</span><span class="pas1-symbol">; <br /></span><span class="pas1-reservedword">begin <br /></span><span class="pas1-space"> bmpTmp </span><span class="pas1-symbol">:=</span><span class="pas1-space"> TBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">try <br /></span><span class="pas1-space"> AutoCropBitmap</span><span class="pas1-symbol">(</span><span class="pas1-identifier">BitMapToCrop</span><span class="pas1-symbol">,</span><span class="pas1-identifier">bmpTmp</span><span class="pas1-symbol">,</span><span class="pas1-identifier">iBleeding</span><span class="pas1-symbol">,</span><span class="pas1-space"> BackColor</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> BitMapToCrop</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Assign</span><span class="pas1-symbol">(</span><span class="pas1-identifier">bmpTmp</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">finally <br /></span><span class="pas1-space"> bmpTmp</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Free</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">; <br /></span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;</span><span class="pas1-space"> <br /> <br /></span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> AutoCropBitmap</span><span class="pas1-symbol">(</span><span class="pas1-identifier">InputBitmap</span><span class="pas1-symbol">,</span><span class="pas1-space"> OutputBitmap</span><span class="pas1-symbol">:</span><span class="pas1-space"> TBitmap</span><span class="pas1-symbol">;</span><span class="pas1-space"> iBleeding </span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">); <br /></span><span class="pas1-reservedword">begin <br /></span><span class="pas1-space"> AutoCropBitmap</span><span class="pas1-symbol">(</span><span class="pas1-identifier">InputBitmap</span><span class="pas1-symbol">,</span><span class="pas1-identifier">OutputBitmap</span><span class="pas1-symbol">,</span><span class="pas1-space"> iBleeding</span><span class="pas1-symbol">,</span><span class="pas1-space"> InputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Canvas</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Pixels</span><span class="pas1-symbol">[</span><span class="pas1-number">0</span><span class="pas1-symbol">,</span><span class="pas1-number">0</span><span class="pas1-symbol">]); <br /></span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;</span><span class="pas1-space"> <br /> <br /></span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> AutoCropBitmap</span><span class="pas1-symbol">(</span><span class="pas1-identifier">InputBitmap</span><span class="pas1-symbol">,</span><span class="pas1-space"> OutputBitmap</span><span class="pas1-symbol">:</span><span class="pas1-space"> TBitmap</span><span class="pas1-symbol">;</span><span class="pas1-space"> iBleeding </span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">;</span><span class="pas1-space"> BackColor</span><span class="pas1-symbol">:</span><span class="pas1-space"> TColor</span><span class="pas1-symbol">); <br /></span><span class="pas1-reservedword">var</span><span class="pas1-space"> Row </span><span class="pas1-symbol">:</span><span class="pas1-space"> pRGBArray</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> MyTop</span><span class="pas1-symbol">,</span><span class="pas1-space"> MyBottom</span><span class="pas1-symbol">,</span><span class="pas1-space"> MyLeft</span><span class="pas1-symbol">, <br /></span><span class="pas1-space"> i</span><span class="pas1-symbol">,</span><span class="pas1-space"> j</span><span class="pas1-symbol">,</span><span class="pas1-space"> MyRight </span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">; <br /></span><span class="pas1-reservedword">begin <br /></span><span class="pas1-space"> MyTop </span><span class="pas1-symbol">:=</span><span class="pas1-space"> InputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Height</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> MyLeft </span><span class="pas1-symbol">:=</span><span class="pas1-space"> InputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Width</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> MyBottom </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> MyRight </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> InputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">PixelFormat </span><span class="pas1-symbol">:=</span><span class="pas1-space"> pf24bit</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> OutputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">PixelFormat </span><span class="pas1-symbol">:=</span><span class="pas1-space"> pf24Bit</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> </span><span class="pas1-comment">{ Find Top } <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">for</span><span class="pas1-space"> j </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">to</span><span class="pas1-space"> InputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Height</span><span class="pas1-symbol">-</span><span class="pas1-number">1</span><span class="pas1-space"> </span><span class="pas1-reservedword">do <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">begin <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> j </span><span class="pas1-symbol">></span><span class="pas1-space"> MyTop </span><span class="pas1-reservedword">then <br /></span><span class="pas1-space"> Break</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> Row </span><span class="pas1-symbol">:=</span><span class="pas1-space"> pRGBArray</span><span class="pas1-symbol">(</span><span class="pas1-identifier">InputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Scanline</span><span class="pas1-symbol">[</span><span class="pas1-identifier">j</span><span class="pas1-symbol">]); <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">for</span><span class="pas1-space"> i</span><span class="pas1-symbol">:=</span><span class="pas1-space"> InputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Width </span><span class="pas1-symbol">-</span><span class="pas1-space"> </span><span class="pas1-number">1</span><span class="pas1-space"> </span><span class="pas1-reservedword">downto</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">do <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> </span><span class="pas1-symbol">((</span><span class="pas1-identifier">Row</span><span class="pas1-symbol">[</span><span class="pas1-identifier">i</span><span class="pas1-symbol">].</span><span class="pas1-identifier">rgbtRed </span><span class="pas1-symbol"><></span><span class="pas1-space"> GetRvalue</span><span class="pas1-symbol">(</span><span class="pas1-identifier">BackColor</span><span class="pas1-symbol">))</span><span class="pas1-space"> </span><span class="pas1-reservedword">or <br /></span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">Row</span><span class="pas1-symbol">[</span><span class="pas1-identifier">i</span><span class="pas1-symbol">].</span><span class="pas1-identifier">rgbtGreen </span><span class="pas1-symbol"><></span><span class="pas1-space"> GetGvalue</span><span class="pas1-symbol">(</span><span class="pas1-identifier">BackColor</span><span class="pas1-symbol">))</span><span class="pas1-space"> </span><span class="pas1-reservedword">or <br /></span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">Row</span><span class="pas1-symbol">[</span><span class="pas1-identifier">i</span><span class="pas1-symbol">].</span><span class="pas1-identifier">rgbtBlue </span><span class="pas1-symbol"><></span><span class="pas1-space"> GetBvalue</span><span class="pas1-symbol">(</span><span class="pas1-identifier">BackColor</span><span class="pas1-symbol">)))</span><span class="pas1-space"> </span><span class="pas1-reservedword">then <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">begin <br /></span><span class="pas1-space"> MyTop </span><span class="pas1-symbol">:=</span><span class="pas1-space"> j</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> Break</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> MyTop </span><span class="pas1-symbol">=</span><span class="pas1-space"> InputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Height </span><span class="pas1-reservedword">then <br /></span><span class="pas1-space"> </span><span class="pas1-comment">{ Empty Bitmap } <br /></span><span class="pas1-space"> MyTop </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-symbol">;</span><span class="pas1-space"> <br /> <br /> </span><span class="pas1-comment">{ Find Bottom } <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">for</span><span class="pas1-space"> j </span><span class="pas1-symbol">:=</span><span class="pas1-space"> InputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Height</span><span class="pas1-symbol">-</span><span class="pas1-number">1</span><span class="pas1-space"> </span><span class="pas1-reservedword">Downto</span><span class="pas1-space"> MyTop </span><span class="pas1-reservedword">do <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">begin <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">j </span><span class="pas1-symbol">+</span><span class="pas1-space"> </span><span class="pas1-number">1</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-symbol"><</span><span class="pas1-space"> MyBottom </span><span class="pas1-reservedword">then <br /></span><span class="pas1-space"> Break</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> Row </span><span class="pas1-symbol">:=</span><span class="pas1-space"> pRGBArray</span><span class="pas1-symbol">(</span><span class="pas1-identifier">InputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Scanline</span><span class="pas1-symbol">[</span><span class="pas1-identifier">j</span><span class="pas1-symbol">]); <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">for</span><span class="pas1-space"> i</span><span class="pas1-symbol">:=</span><span class="pas1-space"> InputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Width </span><span class="pas1-symbol">-</span><span class="pas1-space"> </span><span class="pas1-number">1</span><span class="pas1-space"> </span><span class="pas1-reservedword">downto</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">do <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> </span><span class="pas1-symbol">((</span><span class="pas1-identifier">Row</span><span class="pas1-symbol">[</span><span class="pas1-identifier">i</span><span class="pas1-symbol">].</span><span class="pas1-identifier">rgbtRed </span><span class="pas1-symbol"><></span><span class="pas1-space"> GetRvalue</span><span class="pas1-symbol">(</span><span class="pas1-identifier">BackColor</span><span class="pas1-symbol">))</span><span class="pas1-space"> </span><span class="pas1-reservedword">or <br /></span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">Row</span><span class="pas1-symbol">[</span><span class="pas1-identifier">i</span><span class="pas1-symbol">].</span><span class="pas1-identifier">rgbtGreen </span><span class="pas1-symbol"><></span><span class="pas1-space"> GetGvalue</span><span class="pas1-symbol">(</span><span class="pas1-identifier">BackColor</span><span class="pas1-symbol">))</span><span class="pas1-space"> </span><span class="pas1-reservedword">or <br /></span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">Row</span><span class="pas1-symbol">[</span><span class="pas1-identifier">i</span><span class="pas1-symbol">].</span><span class="pas1-identifier">rgbtBlue </span><span class="pas1-symbol"><></span><span class="pas1-space"> GetBvalue</span><span class="pas1-symbol">(</span><span class="pas1-identifier">BackColor</span><span class="pas1-symbol">)))</span><span class="pas1-space"> </span><span class="pas1-reservedword">then <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">begin <br /></span><span class="pas1-space"> MyBottom </span><span class="pas1-symbol">:=</span><span class="pas1-space"> j</span><span class="pas1-symbol">+</span><span class="pas1-number">1</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> Break</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;</span><span class="pas1-space"> <br /> <br /> </span><span class="pas1-comment">{ Find Left } <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">for</span><span class="pas1-space"> j </span><span class="pas1-symbol">:=</span><span class="pas1-space"> MyTop </span><span class="pas1-reservedword">to</span><span class="pas1-space"> MyBottom</span><span class="pas1-symbol">-</span><span class="pas1-number">1</span><span class="pas1-space"> </span><span class="pas1-reservedword">do <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">begin <br /></span><span class="pas1-space"> Row </span><span class="pas1-symbol">:=</span><span class="pas1-space"> pRGBArray</span><span class="pas1-symbol">(</span><span class="pas1-identifier">InputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Scanline</span><span class="pas1-symbol">[</span><span class="pas1-identifier">j</span><span class="pas1-symbol">]); <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">for</span><span class="pas1-space"> i</span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">to</span><span class="pas1-space"> MyLeft</span><span class="pas1-symbol">-</span><span class="pas1-number">1</span><span class="pas1-space"> </span><span class="pas1-reservedword">do <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> </span><span class="pas1-symbol">((</span><span class="pas1-identifier">Row</span><span class="pas1-symbol">[</span><span class="pas1-identifier">i</span><span class="pas1-symbol">].</span><span class="pas1-identifier">rgbtRed </span><span class="pas1-symbol"><></span><span class="pas1-space"> GetRvalue</span><span class="pas1-symbol">(</span><span class="pas1-identifier">BackColor</span><span class="pas1-symbol">))</span><span class="pas1-space"> </span><span class="pas1-reservedword">or <br /></span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">Row</span><span class="pas1-symbol">[</span><span class="pas1-identifier">i</span><span class="pas1-symbol">].</span><span class="pas1-identifier">rgbtGreen </span><span class="pas1-symbol"><></span><span class="pas1-space"> GetGvalue</span><span class="pas1-symbol">(</span><span class="pas1-identifier">BackColor</span><span class="pas1-symbol">))</span><span class="pas1-space"> </span><span class="pas1-reservedword">or <br /></span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">Row</span><span class="pas1-symbol">[</span><span class="pas1-identifier">i</span><span class="pas1-symbol">].</span><span class="pas1-identifier">rgbtBlue </span><span class="pas1-symbol"><></span><span class="pas1-space"> GetBvalue</span><span class="pas1-symbol">(</span><span class="pas1-identifier">BackColor</span><span class="pas1-symbol">)))</span><span class="pas1-space"> </span><span class="pas1-reservedword">then <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">begin <br /></span><span class="pas1-space"> MyLeft </span><span class="pas1-symbol">:=</span><span class="pas1-space"> i</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> Break</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> MyLeft </span><span class="pas1-symbol">=</span><span class="pas1-space"> InputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Width </span><span class="pas1-reservedword">then <br /></span><span class="pas1-space"> </span><span class="pas1-comment">{ Empty Bitmap } <br /></span><span class="pas1-space"> MyLeft </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-symbol">;</span><span class="pas1-space"> <br /> <br /> </span><span class="pas1-comment">{ Find Right } <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">for</span><span class="pas1-space"> j </span><span class="pas1-symbol">:=</span><span class="pas1-space"> MyTop </span><span class="pas1-reservedword">to</span><span class="pas1-space"> MyBottom </span><span class="pas1-symbol">-</span><span class="pas1-number">1</span><span class="pas1-space"> </span><span class="pas1-reservedword">do <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">begin <br /></span><span class="pas1-space"> Row </span><span class="pas1-symbol">:=</span><span class="pas1-space"> pRGBArray</span><span class="pas1-symbol">(</span><span class="pas1-identifier">InputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Scanline</span><span class="pas1-symbol">[</span><span class="pas1-identifier">j</span><span class="pas1-symbol">]); <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">for</span><span class="pas1-space"> i</span><span class="pas1-symbol">:=</span><span class="pas1-space"> InputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Width</span><span class="pas1-symbol">-</span><span class="pas1-number">1</span><span class="pas1-space"> </span><span class="pas1-reservedword">downto</span><span class="pas1-space"> MyRight </span><span class="pas1-reservedword">do <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> </span><span class="pas1-symbol">((</span><span class="pas1-identifier">Row</span><span class="pas1-symbol">[</span><span class="pas1-identifier">i</span><span class="pas1-symbol">].</span><span class="pas1-identifier">rgbtRed </span><span class="pas1-symbol"><></span><span class="pas1-space"> GetRvalue</span><span class="pas1-symbol">(</span><span class="pas1-identifier">BackColor</span><span class="pas1-symbol">))</span><span class="pas1-space"> </span><span class="pas1-reservedword">or <br /></span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">Row</span><span class="pas1-symbol">[</span><span class="pas1-identifier">i</span><span class="pas1-symbol">].</span><span class="pas1-identifier">rgbtGreen </span><span class="pas1-symbol"><></span><span class="pas1-space"> GetGvalue</span><span class="pas1-symbol">(</span><span class="pas1-identifier">BackColor</span><span class="pas1-symbol">))</span><span class="pas1-space"> </span><span class="pas1-reservedword">or <br /></span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">Row</span><span class="pas1-symbol">[</span><span class="pas1-identifier">i</span><span class="pas1-symbol">].</span><span class="pas1-identifier">rgbtBlue </span><span class="pas1-symbol"><></span><span class="pas1-space"> GetBvalue</span><span class="pas1-symbol">(</span><span class="pas1-identifier">BackColor</span><span class="pas1-symbol">)))</span><span class="pas1-space"> </span><span class="pas1-reservedword">then <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">begin <br /></span><span class="pas1-space"> MyRight </span><span class="pas1-symbol">:=</span><span class="pas1-space"> i</span><span class="pas1-symbol">+</span><span class="pas1-number">1</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> Break</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">MyRight </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">or</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">MyBottom </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">then <br /></span><span class="pas1-space"> </span><span class="pas1-comment">{ Empty Bitmap } <br /></span><span class="pas1-space"> iBleeding </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-symbol">; <br /> <br /></span><span class="pas1-space"> OutputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Width </span><span class="pas1-symbol">:=</span><span class="pas1-space"> MyRight </span><span class="pas1-symbol">-</span><span class="pas1-space"> MyLeft </span><span class="pas1-symbol">+</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">iBleeding </span><span class="pas1-symbol">*</span><span class="pas1-space"> </span><span class="pas1-number">2</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> OutputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Height </span><span class="pas1-symbol">:=</span><span class="pas1-space"> MyBottom </span><span class="pas1-symbol">-</span><span class="pas1-space"> MyTop </span><span class="pas1-symbol">+</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">iBleeding </span><span class="pas1-symbol">*</span><span class="pas1-space"> </span><span class="pas1-number">2</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> OutputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Canvas</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Brush</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Color </span><span class="pas1-symbol">:=</span><span class="pas1-space"> BackColor</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> OutputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Canvas</span><span class="pas1-symbol">.</span><span class="pas1-identifier">FillRect</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Rect</span><span class="pas1-symbol">(</span><span class="pas1-number">0</span><span class="pas1-symbol">,</span><span class="pas1-number">0</span><span class="pas1-symbol">,</span><span class="pas1-identifier">OutputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Width</span><span class="pas1-symbol">,</span><span class="pas1-identifier">OutputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Height</span><span class="pas1-symbol">));</span><span class="pas1-space"> <br /> <br /> BitBlt</span><span class="pas1-symbol">(</span><span class="pas1-identifier">OutputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">canvas</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Handle</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-symbol">-</span><span class="pas1-identifier">MyLeft </span><span class="pas1-symbol">+</span><span class="pas1-space"> iBleeding</span><span class="pas1-symbol">, <br /></span><span class="pas1-space"> </span><span class="pas1-symbol">-</span><span class="pas1-identifier">MyTop </span><span class="pas1-symbol">+</span><span class="pas1-space"> iBleeding</span><span class="pas1-symbol">,</span><span class="pas1-identifier">MyLeft </span><span class="pas1-symbol">+</span><span class="pas1-space"> MyRight</span><span class="pas1-symbol">,</span><span class="pas1-identifier">MyTop </span><span class="pas1-symbol">+</span><span class="pas1-space"> MyBottom</span><span class="pas1-symbol">, <br /></span><span class="pas1-space"> InputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Canvas</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Handle</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-symbol">,</span><span class="pas1-space"> SRCCOPY</span><span class="pas1-symbol">); <br /></span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;</span><span class="pas1-space"> <br /> <br /></span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> AutoCropBmp</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> sFileName </span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-symbol">;</span><span class="pas1-space"> iBleeding </span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">); <br /></span><span class="pas1-reservedword">var</span><span class="pas1-space"> InputBitmap</span><span class="pas1-symbol">,</span><span class="pas1-space"> OutputBitmap </span><span class="pas1-symbol">:</span><span class="pas1-space"> TBitmap</span><span class="pas1-symbol">; <br /></span><span class="pas1-reservedword">begin <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> </span><span class="pas1-reservedword">not</span><span class="pas1-space"> FileExists</span><span class="pas1-symbol">(</span><span class="pas1-identifier">sFileName</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">then <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">raise</span><span class="pas1-space"> Exception</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">(</span><span class="pas1-string">'File doesn''s exists.'</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> InputBitmap </span><span class="pas1-symbol">:=</span><span class="pas1-space"> TBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> OutputBitmap </span><span class="pas1-symbol">:=</span><span class="pas1-space"> TBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">try <br /></span><span class="pas1-space"> InputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">LoadFromFile</span><span class="pas1-symbol">(</span><span class="pas1-identifier">sFileName</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> OutputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">PixelFormat </span><span class="pas1-symbol">:=</span><span class="pas1-space"> InputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">PixelFormat</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> AutoCropBitmap</span><span class="pas1-symbol">(</span><span class="pas1-identifier">InputBitmap</span><span class="pas1-symbol">,</span><span class="pas1-space"> OutputBitmap</span><span class="pas1-symbol">,</span><span class="pas1-identifier">iBleeding</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> OutputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">SaveToFile</span><span class="pas1-symbol">(</span><span class="pas1-identifier">sFileName</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">finally <br /></span><span class="pas1-space"> OutputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Free</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> InputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Free</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">; <br /></span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;</span><span class="pas1-space"> <br /> <br /></span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> AutoCropBmp</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> sFileName </span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-symbol">;</span><span class="pas1-space"> iBleeding </span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">;</span><span class="pas1-space"> BackColor</span><span class="pas1-symbol">:</span><span class="pas1-space"> TColor</span><span class="pas1-symbol">); <br /></span><span class="pas1-reservedword">var</span><span class="pas1-space"> InputBitmap</span><span class="pas1-symbol">,</span><span class="pas1-space"> OutputBitmap </span><span class="pas1-symbol">:</span><span class="pas1-space"> TBitmap</span><span class="pas1-symbol">; <br /></span><span class="pas1-reservedword">begin <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> </span><span class="pas1-reservedword">not</span><span class="pas1-space"> FileExists</span><span class="pas1-symbol">(</span><span class="pas1-identifier">sFileName</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">then <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">raise</span><span class="pas1-space"> Exception</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">(</span><span class="pas1-string">'File doesn''s exists.'</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> InputBitmap </span><span class="pas1-symbol">:=</span><span class="pas1-space"> TBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> OutputBitmap </span><span class="pas1-symbol">:=</span><span class="pas1-space"> TBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">try <br /></span><span class="pas1-space"> InputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">LoadFromFile</span><span class="pas1-symbol">(</span><span class="pas1-identifier">sFileName</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> OutputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">PixelFormat </span><span class="pas1-symbol">:=</span><span class="pas1-space"> InputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">PixelFormat</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> AutoCropBitmap</span><span class="pas1-symbol">(</span><span class="pas1-identifier">InputBitmap</span><span class="pas1-symbol">,</span><span class="pas1-space"> OutputBitmap</span><span class="pas1-symbol">,</span><span class="pas1-identifier">iBleeding</span><span class="pas1-symbol">,</span><span class="pas1-space"> BackColor</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> OutputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">SaveToFile</span><span class="pas1-symbol">(</span><span class="pas1-identifier">sFileName</span><span class="pas1-symbol">); <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">finally <br /></span><span class="pas1-space"> OutputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Free</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> InputBitmap</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Free</span><span class="pas1-symbol">; <br /></span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">; <br /></span><span class="pas1-reservedword">end</span><span class="pas1-symbol">; <br /> <br /></span><span class="pas1-reservedword">end</span><span class="pas1-symbol">.</span><span class="pas1-space"> <br /> <br /></span></span> <br /></code></pre><p>I started off with an <a href="http://www.efg2.com/Lab/Library/UseNet/2000/0307.txt">example</a> found on efg’s site, and started optimizing it’s algorithm:</p><ul><li>Dismissed the Temp variables and the counter variable.</li><li>Making the loops<span style="font-family:courier ne;"> downto 0</span> as many as possible (this will make the loop slightly faster).</li><li>Making sure no extra round on the loop is used (adding breaks).</li><li>Decreasing the number of core operations (removing if’s)</li></ul><p>With this I created a >400% speed gain.</p><p>Writing this article, I got the following ideas for a little more speedup:</p><ul><li>Storing the <span style="font-family:Courier New;">GetXvalue</span> results, as to decrease the recalculation in each for loop.</li><li>Maybe running loops for 0 till the end will make it faster because of better page alignment</li></ul><p>But I will try that out an other time.Davy Landmanhttp://www.blogger.com/profile/06890346525536829946noreply@blogger.comtag:blogger.com,1999:blog-15443912.post-1124179276923772122005-08-16T10:01:00.001+02:002008-07-21T23:15:52.963+02:00CPU and Form Friendly (Long) Sleep<span class="Notice">I've moved my blog and it's post to my new blog, please go to <a href="http://landman-code.blogspot.com/2005/08/cpu-and-form-friendly-long-sleep.html">CPU and Form Friendly (Long) Sleep on Landman Code</a>,</span> Because a <span style="FONT-FAMILY: Courier New">Sleep(1000)</span> will seriously freeze your form for a second, the you’ll see that the solution will often be using a <span style="FONT-FAMILY: Courier New">Application.ProcessMessages </span>loop until the second has passed, but the problem with that loop is, it will create 100% cpu usage. </p><p>Let’s say your waiting for a response from a printer your controlling, than the 100% usage might slow down the complete process, not to mention that on a laptop you’ll be seriously eating the battery.</p><p>The following source offers a nice solution to this problem.</p><pre><code><span style="FONT: 10pt Courier New"><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TForm</span><span class="pas1-symbol">.</span><span class="pas1-identifier">LongDelay</span><span class="pas1-symbol">(</span><span class="pas1-identifier">DelayMs </span><span class="pas1-symbol">:</span><span class="pas1-space"> Cardinal</span><span class="pas1-symbol">);</span><br /><span class="pas1-reservedword">var</span><span class="pas1-space"> StopTime </span><span class="pas1-symbol">:</span><span class="pas1-space"> Cardinal</span><span class="pas1-symbol">;</span><br /><span class="pas1-reservedword">begin</span><br /><span class="pas1-space"> StopTime </span><span class="pas1-symbol">:=</span><span class="pas1-space"> GetTickCount </span><span class="pas1-symbol">+</span><span class="pas1-space"> DelayMs</span><span class="pas1-symbol">;</span><br /><span class="pas1-space"> </span><span class="pas1-reservedword">while</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">GetTickCount </span><span class="pas1-symbol"><</span><span class="pas1-space"> StopTime</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">do</span><br /><span class="pas1-space"> </span><span class="pas1-reservedword">begin</span><br /><span class="pas1-space"> Application</span><span class="pas1-symbol">.</span><span class="pas1-identifier">ProcessMessages</span><span class="pas1-symbol">;</span><br /><span class="pas1-space"> Sleep</span><span class="pas1-symbol">(</span><span class="pas1-number">1</span><span class="pas1-symbol">);</span><br /><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;</span><br /><span class="pas1-reservedword">end</span><span class="pas1-symbol">;</span><br /></span></code></pre><p>It’s pretty straight forward, offcourse when using a basic windows function, you should check out <a href="http://msdn.microsoft.com/library/en-us/dllproc/base/sleep.asp">MSDN</a> for the arguments and remarks. There was one thing that was interresting.</p><blockquote cite="http://msdn.microsoft.com/library/en-us/dllproc/base/sleep.asp"><p>A value of zero causes the thread to relinquish the remainder of its time slice to any other thread of equal priority that is ready to run. If there are no other threads of equal priority ready to run, the function returns immediately, and the thread continues execution.</p></blockquote><p>This fixes one problem, you will only use the cpu when it’s idle. But that still makes this a battery eater on laptops.</p><p>I hope you liked this first post, this was just a minor subject.. But I got to start somewhere.Davy Landmanhttp://www.blogger.com/profile/06890346525536829946noreply@blogger.comtag:blogger.com,1999:blog-15443912.post-1124116191352111682005-08-15T16:27:00.001+02:002008-07-25T10:40:03.212+02:00Welcome<span class='Notice'>I've moved my blog and it's post to my new blog, please go to <a href='http://landman-code.blogspot.com/'>my new blog called Landman Code</a>.</span> Welcome to my Blog, </p>
<p>you’ll probably think.. wow, yet another useless blog.
You’re probably right.</p>
<p>But I will try to explain why I still created this blog. As a student, I travel a lot, therefore I bought a laptop <span style="font-size:78%;">(IBM Think Pad T22)</span>. I think many programmers will recognize that once you’re programming, you will always miss just that one piece of code you know you have on the other computer.
Seeing the fact that a <a href="http://www.everything2.com/index.pl?node_id=965707">good programmer is a lazy programmer</a>, you will too not like to rewrite that piece of code (also known as a snippet).</p>
<p>I find myself having two solutions to that problem. </p><ul><li>Logging in to the other computer trough VNC</li><li>Post it on the Internet</li></ul><p>Always running the laptop and the other computer is not a nice option, therefore I choose the Internet. At first I used an simple html page, but I figured, a blog has a few extras which allow the discussion of my frequently used snippets.</p>
<p>The focus of this weblog will be on the following subjects:</p><ul><li>Optimizing</li><li>String operations</li><li>Image Manipulation</li><li>Windows API</li><li>Extended Dialogs</li><li>File In/Output</li><li>Database</li><li>Office Automation</li></ul><p>The programming language will be Delphi, and all thought I’m Dutch, I will (try to) keep this blog in English.Davy Landmanhttp://www.blogger.com/profile/06890346525536829946noreply@blogger.com