<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6243160301039941892</id><updated>2012-02-16T23:53:47.468-05:00</updated><category term='mobile'/><category term='C++'/><category term='C#'/><category term='Python'/><category term='Signal Control'/><category term='Diary'/><category term='Assembly'/><category term='Dynamic Traffic Assignment'/><category term='Matlab'/><category term='.NEt'/><category term='C/C++'/><category term='Delphi'/><category term='Aimsun API'/><category term='Qt'/><category term='Debugging'/><category term='Aimsun'/><category term='multithreading'/><category term='VISSIM'/><category term='Reverse Engineering'/><category term='COM'/><category term='FORTRAN'/><category term='Script Programming'/><category term='database'/><title type='text'>TrafficDigger's Blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>37</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-3399714905023319925</id><published>2012-01-07T22:54:00.002-05:00</published><updated>2012-01-08T00:53:09.116-05:00</updated><title type='text'>Brain controlled Traffic Simulation?</title><content type='html'>Here is a brave wave&amp;nbsp; detection device that can read your brain's EEG wave, &amp;nbsp; at an amazing price less than $200. &lt;br /&gt;&lt;br /&gt;http://neurosky.com/Products/MindSet.aspx &lt;br /&gt;There is even a SDK for this device. &lt;br /&gt;http://store.neurosky.com/collections/coming-soon&lt;br /&gt;&lt;br /&gt;Wow- the demo shows this little gadget can even typing characters,&amp;nbsp; controlled by your brain wave.&amp;nbsp; Seems someday we can develop some brain-controlled traffic simulation.&amp;nbsp; I can just be lying in bed with my eyes closed and by "concentrating" and my brain would directly control the simulation task.&amp;nbsp; Brain-Driven Traffic Simulation.........&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-3399714905023319925?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/3399714905023319925/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2012/01/brain-controlled-traffic-simulation.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/3399714905023319925'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/3399714905023319925'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2012/01/brain-controlled-traffic-simulation.html' title='Brain controlled Traffic Simulation?'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-3116950078182464382</id><published>2012-01-01T18:24:00.002-05:00</published><updated>2012-01-02T00:10:15.410-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mobile'/><title type='text'>Nokia N8 刷机</title><content type='html'>Nokia N8用了一年多了， 保修期刚过。&amp;nbsp; 这是一部北美版的英文机 - 无法看中文网页和中文短信。&amp;nbsp; 因为下个月回国， 今天决定 把它的固件刷成全中文的。&lt;br /&gt;&lt;br /&gt;1. 下载&lt;a href="http://friska-flasher.blogspot.com/2011/10/navifirm-plus-15.html"&gt;NaviFirm Plus&lt;/a&gt;&lt;br /&gt;2. 再下载Nokia 刷机软件Phoenix from &lt;a href="http://q.yesky.com/viewthread.php?tid=59443018&amp;amp;extra=page%3D2%26amp%3Bfilter%3Dtype%26amp%3Btypeid%3D25%20"&gt;here&amp;nbsp; &lt;/a&gt;&lt;br /&gt;3. 用 第二步下载的特殊版本的firmware 11.5降级。&lt;br /&gt;4. 降级后， 再用第二步下载的Phoenix 软件升级firmware 至25.07 (这是目前有中文持的固件的最高版本， 用NaviFirm-Plus下载）。&lt;br /&gt;5. 刷机后， Nokia Ovi Suite 会提示新版本25.08 - 注意！ 不要升级到25.08， 因为这不是一个支持中文的版本。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;成功！ :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-3116950078182464382?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/3116950078182464382/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2012/01/nokia-n8.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/3116950078182464382'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/3116950078182464382'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2012/01/nokia-n8.html' title='Nokia N8 刷机'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-7073839774619616143</id><published>2011-10-20T10:56:00.003-04:00</published><updated>2011-10-20T11:05:31.758-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Delphi'/><category scheme='http://www.blogger.com/atom/ns#' term='FORTRAN'/><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><category scheme='http://www.blogger.com/atom/ns#' term='database'/><title type='text'>Delphi exception, Fortran mystery</title><content type='html'>Yesterday I had experienced a most mysterious exception which&amp;nbsp; turned out to be caused by a simple mistake.&lt;br /&gt;&lt;br /&gt;As I said,&amp;nbsp; I have an enterprise SQL database server that provides geodata to ArcGIS.&amp;nbsp; The geodata are generated by a sophisticated and powerful macroscopic traffic simulator we developed.&amp;nbsp; The simulator, called &lt;b&gt;&lt;i&gt;DYNEV&lt;/i&gt;&lt;/b&gt; is super fast that for&amp;nbsp; super large transportation networks, that for thousands of links and wide area simulation,&amp;nbsp; it will take less than a minute for 10 hour simulation time with dynamic traffic assignment.&amp;nbsp;&amp;nbsp; There are many gems about this simulator, its modeling,&amp;nbsp; and the system but probably I'll talk about it later.&lt;br /&gt;&lt;br /&gt;The DYNEV simulator is written/rewritten in tens of thousands lines of FORTRAN 2003/2008 with FORTRAN's latest nice and sexy features,&amp;nbsp; while retaining the performance of original FORTRAN assembly-like power.&amp;nbsp; The data exporter to various databases,&amp;nbsp; however is written in Delphi (objecct pascal) in the format of a DLLs , because the Delphi's super power to interface with&lt;b&gt;&lt;i&gt; d&lt;/i&gt;&lt;i&gt;ifferent, virtually near all kinds&lt;/i&gt;&lt;/b&gt; of databases.&lt;br /&gt;&lt;br /&gt;Yesterday when we run DYNEV,&amp;nbsp; we had a fatal exception happened, thrown from DYNEV program, towards the end of the simulation run when trying to export the data to SQL server.&lt;br /&gt;The mysterious thing is, the exception only happens on &lt;i&gt;&lt;b&gt;deployment &lt;/b&gt;&lt;/i&gt;machine; if running from my &lt;b&gt;&lt;i&gt;development&lt;/i&gt;&lt;/b&gt; machine,&amp;nbsp; everything is running beautifully.&lt;br /&gt;&lt;br /&gt;It cost me quite a while to figure it out -&lt;br /&gt;On the &lt;b&gt;&lt;i&gt;development&lt;/i&gt;&lt;/b&gt; machine,&amp;nbsp; I have SQL Server Express 2008 R2,&amp;nbsp; which is a capacity limited, local SQL server,&amp;nbsp; installed for debugging and testing purpose.&amp;nbsp; When developing,&amp;nbsp; I use that local server as the default database connection, but the system has an ini file that specifies the real database server to connect.&lt;br /&gt;&lt;br /&gt;The mistake I made is,&amp;nbsp; the SQL server connection instance, when created and initialized,&amp;nbsp; uses the default connection set up, which will try to create a connection in the first place to the local SQL server on my development machine. Something like this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;i&gt;lvSQLConn := TMSSQLConnection.Create;&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;i&gt;try&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;i&gt;&amp;nbsp;&amp;nbsp; try&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;i&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;i&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lvSQLConn.ServerAddress := (server address specified from the ini file)&lt;the address="" file="" from="" ini="" set=""&gt; &lt;/the&gt;&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;i&gt;&amp;nbsp;&amp;nbsp; except&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;i&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;i&gt;&amp;nbsp;&amp;nbsp; end;&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;i&gt;finally&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;i&gt;&amp;nbsp;&amp;nbsp; lvSQLConn.Free; &lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;i&gt;end;&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So the default connection happens during the &lt;b&gt;&lt;i&gt;construction.&lt;/i&gt;&lt;/b&gt;&amp;nbsp; Of course,&amp;nbsp; when running on my development machine,&amp;nbsp; there will be absolutely no problem,&amp;nbsp; because that local SQL server will always be available to access as Named Pipe.&amp;nbsp;&amp;nbsp; However, on deployment machine,&amp;nbsp; that local SQL server becomes inaccessible (because network remote connection is disabled), hence an exception (something like "&lt;b&gt;&lt;i&gt;Server doesn't support requested protocol&lt;/i&gt;&lt;/b&gt;") is thrown right in the middle of construction, which, as you see from the code, is not caught by the try-except-finally, but caught by its host, i.e., DYNEV, which is in FORTRAN and has no idea about the type of exception.&lt;br /&gt;&lt;br /&gt;The fix is very simple and straightforward,&amp;nbsp; once the cause is pin-pointed:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Move the class construction line into the try-except-finally&lt;/li&gt;&lt;li&gt;Turned off the default connection (i.e., set the Active := False for the data access component during design time).&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-7073839774619616143?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/7073839774619616143/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2011/10/delphi-exception-fortran-mystery.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/7073839774619616143'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/7073839774619616143'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2011/10/delphi-exception-fortran-mystery.html' title='Delphi exception, Fortran mystery'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-535792142995423860</id><published>2011-10-18T21:32:00.006-04:00</published><updated>2011-11-28T18:15:39.500-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Script Programming'/><title type='text'>VPN connect and disconnect script</title><content type='html'>Assume a business model uses two database servers,&amp;nbsp; one is master, behind a corporate firewall; the other is a replication behind another firewall.&amp;nbsp; At midnight,&amp;nbsp; a one-way replication will be performed to sync the master database server with the replication one.&amp;nbsp; Before the synchronization is performed, a VPN connection needs to be established, and the VPN connection will be released after the synchronization is done.&lt;br /&gt;&lt;br /&gt;Autoit,&amp;nbsp; &lt;a href="http://www.autoitscript.com/site/autoit/"&gt;http://www.autoitscript.com/site/autoit/&lt;/a&gt; provides a very neat solution to automate this -&amp;nbsp; that is,&amp;nbsp; first create an Autoit script, then compile the script as an&lt;i&gt;&lt;b&gt; executable&lt;/b&gt;&lt;/i&gt;,&amp;nbsp; and schedule the &lt;b&gt;&lt;i&gt;executable&lt;/i&gt;&lt;/b&gt;&amp;nbsp; as a Windows task.&lt;br /&gt;&lt;br /&gt;The tricky part is,&amp;nbsp; in order to make this work,&amp;nbsp; the scheduled task MUST be set as "Run only when user is logged on".&amp;nbsp; This is because if not,&amp;nbsp; Windows OS will run the program &lt;b&gt;&lt;i&gt;in the background&lt;/i&gt;&lt;/b&gt; and Autoit cannot grab the window's handle therefore any key strokes emulation will not work.&lt;br /&gt;&lt;br /&gt;In summary,&amp;nbsp; &lt;br /&gt;&lt;ul&gt;&lt;li&gt; Download AutoIt&lt;/li&gt;&lt;li&gt;Create a script like this: &lt;/li&gt;&lt;/ul&gt;R&lt;i&gt;&lt;span style="font-size: x-small;"&gt;un("C:\Program Files (x86)\Cisco Systems\VPN Client\vpnclient.exe connect &lt;vpn profile=""&gt; user &lt;username&gt;wuppy pwd puppypwd &lt;password&gt;") &lt;br /&gt;Sleep(5000)&lt;br /&gt;ControlSend("[CLASS:WinConsoleClass", "","","y")&lt;br /&gt;Sleep(1000)&lt;br /&gt;RunWait("dbsync.exe&lt;path of="" program="" synchronization="" the=""&gt;")&lt;br /&gt;Run("C:\Program Files (x86)\Cisco Systems\VPN Client\vpnclient.exe disconnect") &lt;/path&gt;&lt;/password&gt;&lt;/username&gt;&lt;/vpn&gt;&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Use AutoIt compile the above script.&lt;/li&gt;&lt;li&gt;Set a scheduled task with Windows task scheduler, with "&lt;b&gt;&lt;i&gt;Run only when user is logged on&lt;/i&gt;&lt;/b&gt;" option selected.&lt;/li&gt;&lt;li&gt;&lt;u&gt;&lt;b&gt;Locked&lt;/b&gt;&lt;/u&gt; the user account for which the above task is scheduled.&amp;nbsp; This is&lt;b&gt;&lt;i&gt; important&lt;/i&gt;&lt;/b&gt;.&amp;nbsp; You must NOT log off because then the task will not be run (even you set it as "&lt;b&gt;&lt;i&gt;Run whether user is logged on or not&lt;/i&gt;&lt;/b&gt;").&amp;nbsp; The reason is the CISCO VPN client connection if running in the background (i.e., "&lt;b&gt;&lt;i&gt;Run whether user is logged on or not&lt;/i&gt;&lt;/b&gt;" is selected),&amp;nbsp; it can NOT receive emulated key strokes to accept the connection, hence the scheduled task will be launched but it will be hanging there forever.&lt;/li&gt;&lt;/ul&gt;In the above script,&amp;nbsp;&amp;nbsp; &lt;b&gt;&lt;i&gt;RunWait&lt;/i&gt;&lt;/b&gt; command is used to launch &lt;span style="color: #cccccc;"&gt;&lt;span style="color: black;"&gt;the database synchronization program&lt;/span&gt; &lt;/span&gt;&lt;i&gt;dbsync.exe&lt;/i&gt;.&amp;nbsp; Then the script execution &lt;b&gt;&lt;i&gt;waits&lt;/i&gt;&lt;/b&gt; till &lt;span style="background-color: #eeeeee;"&gt;dbsync.exe&lt;/span&gt; finishes, before &lt;b&gt;&lt;i&gt;disconnecting&lt;/i&gt;&lt;/b&gt; the VPN connection.&lt;br /&gt;&lt;ul&gt;&lt;/ul&gt;Also noted that "&lt;b&gt;&lt;i&gt;ControlSend&lt;/i&gt;&lt;/b&gt;" is used instead of "&lt;i&gt;&lt;b&gt;Send&lt;/b&gt;&lt;/i&gt;" to send the emulated "y" key stroke,&amp;nbsp; as in the following script line:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;i style="background-color: #eeeeee;"&gt;&lt;span style="font-size: x-small;"&gt;ControlSend("[CLASS:WinConsoleClass", "","","&lt;/span&gt;&lt;b&gt;&lt;span style="font-size: x-small;"&gt;y&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;i style="background-color: #eeeeee;"&gt;&lt;span style="font-size: x-small;"&gt;")&lt;/span&gt;&lt;/i&gt;&lt;span style="background-color: #eeeeee;"&gt; &lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;Without the emulated "y",&amp;nbsp; the CISCO VPN client will simply hang there forever,&amp;nbsp; waiting for the user's confirmation. &lt;br /&gt;&lt;br /&gt;The difference between "&lt;i&gt;&lt;b&gt;ControlSend&lt;/b&gt;&lt;/i&gt;" and "&lt;i&gt;&lt;b&gt;Send&lt;/b&gt;&lt;/i&gt;" is Send is going to send an emulated key stroke to &lt;b&gt;&lt;i&gt;the active window&lt;/i&gt;&lt;/b&gt;,&amp;nbsp; while ControlSend&amp;nbsp; to &lt;b&gt;&lt;i&gt;any window specified with its class title.&lt;/i&gt;&lt;/b&gt;&amp;nbsp; Send will not work with the logged user locked, since in that case there is no "active" window as seen by Autoit.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-535792142995423860?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/535792142995423860/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2011/10/vpn-connect-and-disconnect-script.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/535792142995423860'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/535792142995423860'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2011/10/vpn-connect-and-disconnect-script.html' title='VPN connect and disconnect script'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-7392393736199725198</id><published>2011-10-09T11:10:00.002-04:00</published><updated>2011-10-23T12:05:18.496-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Delphi'/><category scheme='http://www.blogger.com/atom/ns#' term='multithreading'/><title type='text'>Note on OmniThreadLibrary (OTL): Communication Channel</title><content type='html'>To facilitate communication between two thread task workers,&amp;nbsp; OmniThreadLibrary provides a very handy mechanism, i.e., communication channel.&amp;nbsp;&amp;nbsp; Two different task works, each can register the one end point of the channel, and communicate through that channel like this:&lt;br /&gt;&lt;br /&gt;Taken from demo 8 RegisterComm,&lt;br /&gt;&lt;br /&gt;&lt;b&gt;In the main thread, create the communication channel, the task controls, and associate the two end points of the channel with each of the task worker: &lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;b&gt;procedure&lt;/b&gt; TfrmTestRegisterComm.FormCreate(Sender: TObject);&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: x-small;"&gt;begin&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&amp;nbsp; FCommChannel := CreateTwoWayChannel(1024);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&amp;nbsp; FClient1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; := CreateTask(TCommTester.Create(FCommChannel.Endpoint1))&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .MonitorWith(OmniTED)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; .Run;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&amp;nbsp; FClient2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; := CreateTask(TCommTester.Create(FCommChannel.Endpoint2))&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; .MonitorWith(OmniTED)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Run;&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: x-small;"&gt;end;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;In the task worker's constructor, keep a local reference to the end point:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;b&gt;constructor&lt;/b&gt; TCommTester.Create(commEndpoint: IOmniCommunicationEndpoint);&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: x-small;"&gt;begin&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&amp;nbsp;&lt;b&gt; inherited&lt;/b&gt; Create;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&amp;nbsp; ctComm := commEndpoint;&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: x-small;"&gt;end;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;In the task worker's initializer, &lt;/b&gt;&lt;b&gt;register the end point with its task&lt;/b&gt;&lt;b&gt;: &lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;b&gt;function &lt;/b&gt;TCommTester.Initialize: boolean;&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: x-small;"&gt;begin&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&amp;nbsp; Task.RegisterComm(ctComm);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&amp;nbsp; Result := true;&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: x-small;"&gt;end; &lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;From the above, you can see, the steps are:&lt;br /&gt;&lt;ol&gt;&lt;li&gt; Create the two way channel using "CreateTwoWayChannel",&amp;nbsp; the number 1024 indicates the length of the message queue;&lt;/li&gt;&lt;li&gt;Associate the two end points of the channel with two task workers;&lt;/li&gt;&lt;li&gt;Inside the task worker's Initialize( ),&amp;nbsp; register the communication end point with the worker's IOmniTask.&lt;/li&gt;&lt;/ol&gt;After all these are done, and wen a task worker wants to talk to the other task worker, simply do something like below, then the other task worker's MSG_FORWARDING message handler will be invoked.&amp;nbsp; Isn't that nice?&lt;br /&gt;&lt;br /&gt;Therefore, if a task worker wants to talk to its task control,&amp;nbsp; it can keep using&amp;nbsp;&lt;span style="font-size: x-small;"&gt;Task.Comm.Send&lt;/span&gt;, or if it wants to talk to another task worker, use&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;ctComm.Send(MSG_FORWARDING,&amp;nbsp; msg.MsgData); &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;In case you want a task worker to send messages to ITSELF,&amp;nbsp;&amp;nbsp; &lt;/b&gt;you can register the same communication channel "twice" with the same task worker like the following:&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;b&gt;function&lt;/b&gt; TCommTester.Initialize: boolean;&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: x-small;"&gt;begin&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&amp;nbsp; Task.RegisterComm(ctComm);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&amp;nbsp; Task.RegisterComm(ctComm.&lt;b&gt;OtherEndpoint&lt;/b&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&amp;nbsp; Result := true;&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: x-small;"&gt;end;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Cool!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-7392393736199725198?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/7392393736199725198/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2011/10/note-on-omnithreadlibrary-otl.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/7392393736199725198'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/7392393736199725198'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2011/10/note-on-omnithreadlibrary-otl.html' title='Note on OmniThreadLibrary (OTL): Communication Channel'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-5255812863413600275</id><published>2011-10-05T18:29:00.003-04:00</published><updated>2011-10-05T22:13:24.273-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Delphi'/><category scheme='http://www.blogger.com/atom/ns#' term='Qt'/><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><title type='text'>Using Delphi DLL with C++</title><content type='html'>Delphi has very good support for developing database applications.&amp;nbsp; Recently I am working on an database exporter of a scientific application developed in C++/Qt.&amp;nbsp; Because of Delphi's superb capability and easiness handling database,&amp;nbsp; I decide to use Delphi and DevArt's DAC components.&amp;nbsp; To inter-op with the C++ host,&amp;nbsp; the database part is developed as a DLL.&lt;br /&gt;&lt;br /&gt;The tricky part is, the DLLs generated by Delphi won't have import lib files, which are required by the C++ host.&amp;nbsp; To overcome that, you have a few options:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Generate proper import lib&amp;nbsp; by defining your own def file, &lt;a href="http://www.esanu.name/delphi/DLL/Calling%20delphi%20DLL%20from%20MS%20Visual%20C.html%20"&gt;see this post&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Convert Delphi DLL to static lib using&lt;a href="http://www.codeguru.com/cpp/w-p/dll/importexportissues/print.php/c3647"&gt; this tool &lt;/a&gt;&lt;/li&gt;&lt;li&gt;Or dynamically loading the DLL at run time.&lt;/li&gt;&lt;/ol&gt;To dynamically load the DLL at run time,&amp;nbsp; you have to do the following &lt;a href="http://msdn.microsoft.com/en-us/library/ms810279.aspx"&gt;tedious steps&lt;/a&gt; (excerpted from MSDN):&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Define the function prototypes.   &lt;div class="codeSnippetContainer"&gt;&lt;div class="codeSnippetContainerTabs"&gt;&lt;/div&gt;&lt;div class="codeSnippetContainerCodeContainer"&gt;&lt;div class="codeSnippetToolBar"&gt;&lt;div class="codeSnippetToolBarText"&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="codeSnippetContainerCode" dir="ltr" id="CodeSnippetContainerCode_1359d77b-dbc2-4d2b-a5f6-b85bd43b5630"&gt;&lt;div style="color: black;"&gt;&lt;pre&gt;typedef short (CALLBACK* FindArtistType)(LPCTSTR);&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;Load the DLL using the &lt;b&gt;LoadLibrary&lt;/b&gt; function.&lt;/li&gt;&lt;li&gt;Keep the handle to the DLL instance.   &lt;div class="codeSnippetContainer"&gt;&lt;div class="codeSnippetContainerTabs"&gt;&lt;/div&gt;&lt;div class="codeSnippetContainerCodeContainer"&gt;&lt;div class="codeSnippetToolBar"&gt;&lt;div class="codeSnippetToolBarText"&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="codeSnippetContainerCode" dir="ltr" id="CodeSnippetContainerCode_27cd30a2-8e6b-4403-9743-323dda3167a7"&gt;&lt;div style="color: black;"&gt;&lt;pre&gt;dllHandle = LoadLibrary("art.dll");&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;Get a pointer to each function using the &lt;b&gt;GetProcAddress&lt;/b&gt; function.&lt;/li&gt;&lt;li&gt;Cast function pointers to the types defined in Step 1.   &lt;div class="codeSnippetContainer"&gt;&lt;div class="codeSnippetContainerTabs"&gt;&lt;/div&gt;&lt;div class="codeSnippetContainerCodeContainer"&gt;&lt;div class="codeSnippetToolBar"&gt;&lt;div class="codeSnippetToolBarText"&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="codeSnippetContainerCode" dir="ltr" id="CodeSnippetContainerCode_0c618084-5f2f-4d21-8885-8018f0b60e15"&gt;&lt;div style="color: black;"&gt;&lt;pre&gt;FindArtistPtr = (FindArtistType)GetProcAddress(dllHandle,&lt;br /&gt;         "FindArtist");&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;Verify function pointers.   &lt;div class="codeSnippetContainer"&gt;&lt;div class="codeSnippetContainerTabs"&gt;&lt;/div&gt;&lt;div class="codeSnippetContainerCodeContainer"&gt;&lt;div class="codeSnippetToolBar"&gt;&lt;div class="codeSnippetToolBarText"&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="codeSnippetContainerCode" dir="ltr" id="CodeSnippetContainerCode_51198bae-9045-43fc-ac83-8f116bd5c94b"&gt;&lt;div style="color: black;"&gt;&lt;pre&gt;if (runTimeLinkSuccess = (NULL != FindArtistPtr))&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;Use functions.   &lt;div class="codeSnippetContainer"&gt;&lt;div class="codeSnippetContainerTabs"&gt;&lt;/div&gt;&lt;div class="codeSnippetContainerCodeContainer"&gt;&lt;div class="codeSnippetToolBar"&gt;&lt;div class="codeSnippetToolBarText"&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="codeSnippetContainerCode" dir="ltr" id="CodeSnippetContainerCode_21df1a5e-d6ee-412e-9cf6-aa389d1e9206"&gt;&lt;div style="color: black;"&gt;&lt;pre&gt;short retVal = FindArtistPtr(myArtist);&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;Unload the DLL.   &lt;div class="codeSnippetContainer"&gt;&lt;div class="codeSnippetContainerTabs"&gt;&lt;/div&gt;&lt;div class="codeSnippetContainerCodeContainer"&gt;&lt;div class="codeSnippetToolBar"&gt;&lt;div class="codeSnippetToolBarText"&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="codeSnippetContainerCode" dir="ltr" id="CodeSnippetContainerCode_9afc0db0-6502-4fcb-a691-6af4ac8dcd46"&gt;&lt;div style="color: black;"&gt;&lt;pre&gt;freeResult = FreeLibrary(dllHandle);&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;div style="text-align: left;"&gt;Qt provides a very nice class, QLibrary to streamline the above procedures, and the nice thing is, the instance is ref counted so if a DLL won't be unloaded unless all QLibrary instances go out of scope.&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;div style="color: black; text-align: left;"&gt;&lt;/div&gt;&lt;div style="color: black; text-align: left;"&gt;&lt;/div&gt;&lt;div style="color: black; text-align: left;"&gt;&lt;br /&gt;The following is the sample code that loads the dll&amp;nbsp; developed in Delphi. Isn't that nice?&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-qYvFLbzIQ04/TozZy48P2SI/AAAAAAAAAD0/h9KnlKzpdV4/s1600/10-5-2011+6-27-02+PM.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="193" src="http://3.bp.blogspot.com/-qYvFLbzIQ04/TozZy48P2SI/AAAAAAAAAD0/h9KnlKzpdV4/s400/10-5-2011+6-27-02+PM.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-5255812863413600275?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/5255812863413600275/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2011/10/using-delphi-dll-with-c.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/5255812863413600275'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/5255812863413600275'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2011/10/using-delphi-dll-with-c.html' title='Using Delphi DLL with C++'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-qYvFLbzIQ04/TozZy48P2SI/AAAAAAAAAD0/h9KnlKzpdV4/s72-c/10-5-2011+6-27-02+PM.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-3075999711590410695</id><published>2011-09-11T13:39:00.004-04:00</published><updated>2011-09-11T20:56:29.255-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Aimsun API'/><category scheme='http://www.blogger.com/atom/ns#' term='Aimsun'/><title type='text'>Blog Statistics</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-qGC5HY6Dtz0/TmzybgFs4lI/AAAAAAAAADg/gIM3F6_iKdY/s1600/9-11-2011%2B1-39-15%2BPM.jpg"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 412px; height: 241px;" src="http://1.bp.blogspot.com/-qGC5HY6Dtz0/TmzybgFs4lI/AAAAAAAAADg/gIM3F6_iKdY/s200/9-11-2011%2B1-39-15%2BPM.jpg" alt="" id="BLOGGER_PHOTO_ID_5651158186727367250" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;I am really perplexed by the statistics of this blog. It indicates that the post "&lt;span style="font-size:85%;"&gt;&lt;span style="font-style: italic;"&gt;Interfacing AIMSUN API with Delphi&lt;/span&gt;&lt;/span&gt;" has the highest number of views.&lt;br /&gt;&lt;br /&gt;I am wondering how many Aimsun users are using Delphi instead of C++ for developing externa apps?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-3075999711590410695?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/3075999711590410695/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2011/09/blog-statistics.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/3075999711590410695'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/3075999711590410695'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2011/09/blog-statistics.html' title='Blog Statistics'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-qGC5HY6Dtz0/TmzybgFs4lI/AAAAAAAAADg/gIM3F6_iKdY/s72-c/9-11-2011%2B1-39-15%2BPM.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-3054161842320453306</id><published>2011-09-11T11:12:00.008-04:00</published><updated>2011-09-11T21:01:27.984-04:00</updated><title type='text'>VISSIM copy protection and others</title><content type='html'>&lt;h1&gt;&lt;span style="font-weight: normal;font-size:100%;" &gt;&lt;/span&gt;&lt;/h1&gt;It is very interesting that this blog has some traffic directed by key words such as "vissim hack", "vissim patch" etc.&lt;br /&gt;&lt;br /&gt;Of course, this is not a hacker's blog, while,   I believe ever since VISSIM employs WiBu CodeMeter as its DRM,  it is IMPOSSIBLE, or near IMPOSSIBLE to hack VISSIM  or what so ever.&lt;br /&gt;&lt;br /&gt;Honestly,  I don't see the point of hacking VISSIM since it is a profession software; its end users are traffic and transportation consulting business,  public sectors or academics.  It is beyond my imagination that they would use a hacked VISSIM to do their projects.  Granted that VISSIM licenses are not cheap but comparing to projects with hundreds of thousands of dollars budget,  licensing fees are fairly trivia and in some cases are even paid off by the clients .  Besides VISSIM also offers affordable academic licenses.&lt;br /&gt;&lt;br /&gt;Oh yeah yeah yeah yeah, you are a dedicated,  stubborn, enthusiastic,  hard-core hacker with tons of free time and no worries for making a living, and sure you want to prove yourself - well, then see below&lt;br /&gt;&lt;br /&gt;--------------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;WiBu each year has a hacker's contest and so far nobody is able to claim its $15000 prize yet.&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;Chinese Hackers Fail to Crack CodeMeter’s Strong Security&lt;/span&gt;     &lt;p&gt; &lt;span style="font-size:85%;"&gt;&lt;em&gt;No takers for $15,000 prize; Wibu-Systems survives yet another hacker’s contest&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;     &lt;p&gt;&lt;span style="font-size:85%;"&gt;SEATTLE, WA – (Dec 12, 2010) – Among the 138 Chinese software  developers, students, professors, and other high-tech gurus who applied  to crack Wibu-Systems’ CodeMeter software protection system, no one was  able to collect the $15,000 prize.&lt;/span&gt;&lt;/p&gt;     &lt;p&gt;&lt;span style="font-size:85%;"&gt;Registered applicants were given a protected software  application, a CodeMeter hardware CmStick, and four weeks to crack the  application. Just as in previous contests, no one was able to crack the  CodeMeter-protected application. The task was to create a version of the  application that would run without the CmStick being present in the  computer. At stake was a prize of 100,000 RMB or about $15,000.&lt;/span&gt;&lt;/p&gt;     &lt;p&gt;&lt;span style="font-size:85%;"&gt;Zou Haiyan, National Sales Director of Wibu-Systems (Shanghai),  explains: “It is a big success having proven the high security level of  CodeMeter in our Hacker’s Contest in China this year. Of course it is  impossible to have 100% security. But with CodeMeter our customers will  get a very high level of security. We constantly improve our security  issue so that our customers can always rely on a strong protection  solution.”&lt;/span&gt;&lt;/p&gt;     &lt;p&gt;&lt;span style="font-size:85%;"&gt;CodeMeter by Wibu-Systems AG, headquartered in Karlsruhe,  Germany, is a proven and established hardware and activation-based  solution protecting and licensing software used by software vendors  worldwide. Continual improvements in encryption/decryption technology  provides CodeMeter with strong mechanisms against cracking, for example  record/playback attacks. Inside the CodeMeter smart card chip different  security algorithms are used: 128-Bit AES, 224 Bit elliptical curve, and  1024 Bit RSA. Software vendors can decrypt only the part of the  software that is running so that never the complete software is  available unprotected on the computer. In addition, all communications  between the CodeMeter stick and the software application are encrypted  to prevent so-called “man in the middle” attacks.&lt;/span&gt;&lt;/p&gt;      &lt;h2&gt;&lt;br /&gt;&lt;/h2&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-3054161842320453306?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/3054161842320453306/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2011/09/vissim-copy-protection-and-others.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/3054161842320453306'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/3054161842320453306'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2011/09/vissim-copy-protection-and-others.html' title='VISSIM copy protection and others'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-81664515891707241</id><published>2011-09-10T22:22:00.005-04:00</published><updated>2011-09-11T11:01:06.702-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><title type='text'>Build log4cxx with Visual Studio 2010</title><content type='html'>Steps for building log4cxx with VS2005 and VS2008 can be found from here&lt;br /&gt;&lt;a href="http://www.dreamcubes.com/b2/software-development/28/log4cxx-for-win32-with-vs2005/"&gt;http://www.dreamcubes.com/b2/software-development/28/log4cxx-for-win32-with-vs2005/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And to build log4cxx with Visual Studio 2010, some steps are advised here&lt;br /&gt;&lt;a href="http://permalink.gmane.org/gmane.comp.apache.logging.log4cxx.user/2842"&gt;http://permalink.gmane.org/gmane.comp.apache.logging.log4cxx.user/2842&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;These steps are simply copied below in italics fonts for convenience:&lt;span style="font-family:monospace;"&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-style: italic;"&gt;1. Move all those LOG4CXX_LIST_DEF macros to before the class definition.  in telnetappender.h you will also need to move the typedef that precedes this  macro.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;2. If the compiler complains about KeySet not being member of LoggingEvent,  just remove the scope (since we moved the type to outside the class in the  previous step, these types no longer are inside the class) ex:  change: LoggingEvent::KeySet set; to: KeySet set;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt; 3. If the compiler complains about insert_iterator not being in the namespace  std, add #include &lt;iterator&gt;&lt;/iterator&gt;&lt;/span&gt;&lt;/span&gt;&lt;iterator&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-style: italic;"&gt; to the include section of the source file &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;4. For some reason the VS2010 converter 'forgot' to reference the lib files  from apr,apr-util and xml, so i had to add them manually.  &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I followed these steps and have the following observations:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Step 4 didn't happen to me.&lt;/li&gt;&lt;li&gt;Step 1 is a little complex depending on what compiler you use.    If you use Visual Studio 2010's default &lt;span style="font-weight: bold;"&gt;VC++ compiler&lt;/span&gt; 10,  then you'll get &lt;span style="font-size:85%;"&gt;&lt;span style="font-style: italic;"&gt;error C2252 : an explicit instantiation of a template can only occur at namespace scope&lt;/span&gt;&lt;/span&gt;;  however,   &lt;span&gt;if you use &lt;/span&gt;&lt;span style="font-weight: bold;"&gt;Intel C++ compiler 2011 SP1, you'll just get a warning. &lt;/span&gt;  After moving the LOG4CXX_LIST_DEF macros to before the class definition,  &lt;span style="font-weight: bold;"&gt;Intel C++ compiler 2011 SP1 &lt;/span&gt;will drop the warning but pop out a new warning about &lt;span style="font-size:85%;"&gt;&lt;span style="font-style: italic;"&gt;explicit instantiation more than once&lt;/span&gt;&lt;/span&gt;.   &lt;span style="font-weight: bold;"&gt; &lt;/span&gt;&lt;span style="color: rgb(51, 51, 0); font-weight: bold;"&gt;In other words, with Intel Compiler,  Step 1 is optional (as I've tested, you can just simply ignore these cute warnings).&lt;/span&gt;&lt;/li&gt;&lt;li&gt;Step 2 is necessary for both VC++ and Intel C++ compilers&lt;/li&gt;&lt;li&gt;Step 3 is necessary for both VC++ and Intel C++ compilers&lt;/li&gt;&lt;/ul&gt;Interestingly,  log4cxx built with Intel C++ compiler with some Intel specific optimization switches on shows some what performance improvement by 5% ~10% (this is a rough estimate based on the before-and-after comparison of some program I wrote, you mileage may vary depending on the context,  use case and what particular switches). &lt;br /&gt;&lt;br /&gt;Also Intel C++ tends to generate larger binary files.&lt;br /&gt;&lt;br /&gt;After the play with myself on this,  I organized the log4cxx Visual Studio 2010 solution files (with additional settings for Intel compilers).  It can be &lt;span style="font-weight: bold;"&gt;downloaded from&lt;/span&gt; &lt;a href="http://www.wupingxin.net/downloads/log4cxx-vs2010.7z"&gt;here&lt;/a&gt; , so you don't have to go through the troubles yourself. &lt;br /&gt;&lt;br /&gt;If you download it and find it helpful,  please let me know and say "Thank you!" :-)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/iterator&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-81664515891707241?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/81664515891707241/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2011/09/build-log4cxx-with-visual-studio-2010.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/81664515891707241'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/81664515891707241'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2011/09/build-log4cxx-with-visual-studio-2010.html' title='Build log4cxx with Visual Studio 2010'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-4660292364500792786</id><published>2011-08-19T13:07:00.003-04:00</published><updated>2011-08-19T13:19:34.612-04:00</updated><title type='text'>Note on OmniThreadLibrary (OTL): ChainTo/MsgWait</title><content type='html'>&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;ChainTo &lt;/span&gt;is a very handy decorator of IOmniTaskControl interface - the use case is &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;[we have a list of tasks, and we want to assign these tasks to a list working threads, one task a thread,  and have these threads executing one after another, sequentially]&lt;br /&gt;&lt;br /&gt;For example (Sample 16),&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;span style="font-weight: bold;"&gt;procedure&lt;/span&gt; TfrmTestChainTo.btnStartTasksClick(Sender: TObject);&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;var&lt;/span&gt;&lt;br /&gt; task1: IOmniTaskControl;&lt;br /&gt; task2: IOmniTaskControl;&lt;br /&gt; task3: IOmniTaskControl;&lt;br /&gt; taskA: IOmniTaskControl;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;begin&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; task3 := CreateTask(BgTask, '3').MonitorWith(OmniTED);&lt;br /&gt; task2 := CreateTask(BgTask, '2').MonitorWith(OmniTED).&lt;span style="font-weight: bold;"&gt;ChainTo&lt;/span&gt;(task3);&lt;br /&gt; task1 := CreateTask(BgTask, '1').MonitorWith(OmniTED).&lt;span style="font-weight: bold;"&gt;ChainTo&lt;/span&gt;(task2);&lt;br /&gt;&lt;br /&gt; task1.Run;&lt;br /&gt;&lt;br /&gt; taskA := CreateTask(BgTask, 'A').MonitorWith(OmniTED).&lt;span style="font-weight: bold;"&gt;ChainTo&lt;/span&gt;(&lt;br /&gt;          CreateTask(BgTask, 'B').MonitorWith(OmniTED).&lt;span style="font-weight: bold;"&gt;ChainTo&lt;/span&gt;(&lt;br /&gt;          CreateTask(BgTask, 'C').MonitorWith(OmniTED)));&lt;br /&gt;&lt;br /&gt; taskA.Run;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;end;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When task1.Run called, task1 runs first, after it finishes, task2 starts then task  3.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;MsgWait&lt;/li&gt;&lt;/ul&gt;MsgWait is needed if the worker thread calls something that involves windows message loop. For example, a timer .&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;  FHelloWorld := CreateTask(THelloWorld.Create(), 'Hello, World!')&lt;br /&gt;                .MonitorWith(oeMonitor)&lt;br /&gt;                .SetTimer(500, MSG_INTERNAL_TIMER)&lt;br /&gt;                //.MsgWait&lt;br /&gt;                .Run;&lt;br /&gt;&lt;span style="font-family:times new roman;font-size:100%;"&gt;&lt;br /&gt;MsgWait is not needed for SetTimer, but needed for the following:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;span style="font-weight: bold;"&gt;function&lt;/span&gt; THelloWorld.Initialize: boolean;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;begin&lt;/span&gt;&lt;br /&gt; FTimer := TDSiTimer.Create(true, 1000, DoTimer);&lt;br /&gt; Result := true;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;end;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-family: times new roman;"&gt;The following is exercpted from The Delphi Geek Blog:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;[&lt;a href="http://www.thedelphigeek.com/2008/09/processing-windows-messages-in.html"&gt;http://www.thedelphigeek.com/2008/09/processing-windows-messages-in.html&lt;/a&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;h2&gt;MsgWait&lt;/h2&gt;&lt;p align="justify"&gt;In case you want to learn more about OTL internals, read ahead …&lt;/p&gt;&lt;p align="justify"&gt;Let’s take a short look at the &lt;em&gt;.MsgWait&lt;/em&gt;  implementation. The function itself just sets two internal fields and  returns the object itself so that we can chain another method to it.&lt;/p&gt;&lt;pre class="pas-source"&gt;&lt;span class="pas-kwd"&gt;function&lt;/span&gt; TOmniTaskControl.MsgWait(wakeMask: DWORD): IOmniTaskControl;&lt;br /&gt;&lt;span class="pas-kwd"&gt;begin&lt;/span&gt;&lt;br /&gt; Options := Options + [tcoMessageWait];&lt;br /&gt; otcExecutor.WakeMask := wakeMask;&lt;br /&gt; Result := Self;&lt;br /&gt;&lt;span class="pas-kwd"&gt;end&lt;/span&gt;; &lt;span class="pas-comment"&gt;{ TOmniTaskControl.MsgWait }&lt;/span&gt;&lt;/pre&gt;&lt;p align="justify"&gt;The hard work is done in &lt;em&gt;TOmniTaskExecutor.Asy_DispatchMessages&lt;/em&gt;. If the &lt;em&gt;tcoMessageWait&lt;/em&gt;  option is set, the MsgWaitForMultipleObjectsEx will also wait for  Windows messages (in addition to everything else it does) because it  will receive non-null &lt;em&gt;waitWakeMask. &lt;/em&gt;When a message is detected, the code will call &lt;em&gt;ProcessThreadMessages &lt;/em&gt;method  which simply peeks and dispatches all Windows messages (and Delphi’s  internal message dispatch mechanism takes care of all the rest).&lt;/p&gt;&lt;pre class="pas-source"&gt;&lt;span class="pas-kwd"&gt;if&lt;/span&gt; tcoMessageWait &lt;span class="pas-kwd"&gt;in&lt;/span&gt; Options &lt;span class="pas-kwd"&gt;then&lt;/span&gt;&lt;br /&gt; waitWakeMask := WakeMask&lt;br /&gt;&lt;span class="pas-kwd"&gt;else&lt;/span&gt;&lt;br /&gt; waitWakeMask := &lt;span class="pas-num"&gt;0&lt;/span&gt;;&lt;br /&gt;&lt;span class="pas-comment"&gt;//...&lt;/span&gt;&lt;br /&gt;awaited := MsgWaitForMultipleObjectsEx(numWaitHandles, waitHandles,&lt;br /&gt; cardinal(timeout_ms), waitWakeMask, flags);&lt;br /&gt;&lt;span class="pas-comment"&gt;//...&lt;/span&gt;&lt;br /&gt;&lt;span class="pas-kwd"&gt;else&lt;/span&gt; &lt;span class="pas-kwd"&gt;if&lt;/span&gt; awaited = (WAIT_OBJECT_0 + numWaitHandles) &lt;span class="pas-kwd"&gt;then&lt;/span&gt; &lt;span class="pas-comment"&gt;//message&lt;/span&gt;&lt;br /&gt; ProcessThreadMessages&lt;br /&gt;&lt;br /&gt;&lt;span class="pas-kwd"&gt;procedure&lt;/span&gt; TOmniTaskExecutor.ProcessThreadMessages;&lt;br /&gt;&lt;span class="pas-kwd"&gt;var&lt;/span&gt;&lt;br /&gt; msg: TMsg;&lt;br /&gt;&lt;span class="pas-kwd"&gt;begin&lt;/span&gt;&lt;br /&gt; &lt;span class="pas-kwd"&gt;while&lt;/span&gt; PeekMessage(Msg, &lt;span class="pas-num"&gt;0&lt;/span&gt;, &lt;span class="pas-num"&gt;0&lt;/span&gt;, &lt;span class="pas-num"&gt;0&lt;/span&gt;, PM_REMOVE) &lt;span class="pas-kwd"&gt;and&lt;/span&gt; (Msg.&lt;span class="pas-kwd"&gt;Message&lt;/span&gt; &amp;lt;&amp;gt; WM_QUIT) &lt;span class="pas-kwd"&gt;do&lt;/span&gt; &lt;span class="pas-kwd"&gt;begin&lt;/span&gt;&lt;br /&gt;   TranslateMessage(Msg);&lt;br /&gt;   DispatchMessage(Msg);&lt;br /&gt; &lt;span class="pas-kwd"&gt;end&lt;/span&gt;;&lt;br /&gt;&lt;span class="pas-kwd"&gt;end&lt;/span&gt;; &lt;span class="pas-comment"&gt;{ TOmniTaskControl.ProcessThreadMessages }&lt;/span&gt;&lt;/pre&gt;&lt;p align="justify"&gt;The &lt;em&gt;Asy_DispatchMessages &lt;/em&gt;is  probably the most complicated part of the OTL (once you understand the  lock-free structures inside the OtlContainers ;) Once you understand how  it works you’ll be fully prepared to write custom thread loops in  highly specialized threaded code. But don’t worry, you can use OTL even  if you don’t understand the magic hidden inside.&lt;/p&gt;&lt;p align="justify"&gt;&lt;span style="font-size:78%;"&gt;Note: The above is from the Delphi Geek Blog by &lt;span class="smalltext"&gt;&lt;/span&gt;&lt;a href="http://otl.17slon.com/forum/index.php?action=profile;u=1"&gt;Primoz Gabrijelcic&lt;/a&gt;,  the Delphi Guru and developer of the great OmniThreadLibrary.&lt;/span&gt;&lt;/p&gt;&lt;p align="justify"&gt;]&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-4660292364500792786?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/4660292364500792786/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2011/08/note-on-omnithreadlibrary-otl_19.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/4660292364500792786'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/4660292364500792786'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2011/08/note-on-omnithreadlibrary-otl_19.html' title='Note on OmniThreadLibrary (OTL): ChainTo/MsgWait'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-922131437159995227</id><published>2011-08-18T14:27:00.003-04:00</published><updated>2011-08-18T14:39:08.647-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Delphi'/><category scheme='http://www.blogger.com/atom/ns#' term='multithreading'/><title type='text'>Note on OmniThreadLibrary (OTL): Task Group</title><content type='html'>As we have noted in a previous &lt;a href="http://wupingxin.blogspot.com/2011/08/note-on-omnithreadlibrary-otl-thread.html"&gt;post &lt;/a&gt;  that a task group can be used to "group" control a group of thread tasks.&lt;br /&gt;&lt;br /&gt;The interface is declared as follows:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;  IOmniTaskGroup = &lt;span style="font-weight: bold;"&gt;interface&lt;/span&gt; &lt;span style="color: rgb(51, 51, 255);"&gt;['{B36C08B4-0F71-422C-8613-63C4D04676B7}']&lt;/span&gt;&lt;br /&gt;   &lt;span style="font-weight: bold;"&gt;function&lt;/span&gt;  GetTasks: IOmniTaskControlList;&lt;br /&gt;   &lt;span style="font-weight: bold;"&gt;function&lt;/span&gt;  Add(&lt;span style="font-weight: bold;"&gt;const&lt;/span&gt; taskControl: IOmniTaskControl): IOmniTaskGroup;&lt;br /&gt;   &lt;span style="font-weight: bold;"&gt;function&lt;/span&gt;  GetEnumerator: IOmniTaskControlListEnumerator;&lt;br /&gt;   &lt;span style="font-weight: bold;"&gt;function&lt;/span&gt;  RegisterAllCommWith(&lt;span style="font-weight: bold;"&gt;const&lt;/span&gt; task: IOmniTask): IOmniTaskGroup;&lt;br /&gt;   &lt;span style="font-weight: bold;"&gt;function&lt;/span&gt;  Remove(const taskControl: IOmniTaskControl): IOmniTaskGroup;&lt;br /&gt;   &lt;span style="font-weight: bold;"&gt;function&lt;/span&gt;  RunAll: IOmniTaskGroup;&lt;br /&gt;   &lt;span style="font-weight: bold;"&gt;procedure&lt;/span&gt; SendToAll(&lt;span style="font-weight: bold;"&gt;const&lt;/span&gt; msg: TOmniMessage);&lt;br /&gt;   &lt;span style="font-weight: bold;"&gt;function&lt;/span&gt;  TerminateAll(maxWait_ms: &lt;span style="font-weight: bold;"&gt;cardinal&lt;/span&gt; = INFINITE): &lt;span style="font-weight: bold;"&gt;boolean&lt;/span&gt;;&lt;br /&gt;   &lt;span style="font-weight: bold;"&gt;function&lt;/span&gt;  UnregisterAllCommFrom(&lt;span style="font-weight: bold;"&gt;const &lt;/span&gt;task: IOmniTask): IOmniTaskGroup;&lt;br /&gt;   &lt;span style="font-weight: bold;"&gt;function&lt;/span&gt;  WaitForAll(maxWait_ms: &lt;span style="font-weight: bold;"&gt;cardinal&lt;/span&gt; = INFINITE): boolean;&lt;br /&gt;   &lt;span style="font-weight: bold;"&gt;property&lt;/span&gt;  Tasks: IOmniTaskControlList &lt;span style="font-weight: bold;"&gt;read&lt;/span&gt; GetTasks;&lt;br /&gt; end; { IOmniTaskGroup }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The most interesting interesting interface functions are listed below -&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;    &lt;span style="font-weight: bold;"&gt;function&lt;/span&gt;  RunAll: IOmniTaskGroup;&lt;br /&gt;   &lt;span style="font-weight: bold;"&gt;procedure&lt;/span&gt; SendToAll(&lt;span style="font-weight: bold;"&gt;const&lt;/span&gt; msg: TOmniMessage);&lt;br /&gt;   &lt;span style="font-weight: bold;"&gt;function&lt;/span&gt;  TerminateAll(maxWait_ms: &lt;span style="font-weight: bold;"&gt;cardinal&lt;/span&gt; = INFINITE): &lt;span style="font-weight: bold;"&gt;boolean&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For example (sample 15)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: bold;"&gt;procedure &lt;/span&gt;TfrmTestTaskGroup.btnStartTasksClick(Sender: TObject);&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;var&lt;/span&gt;&lt;br /&gt; i: integer;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;begin&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(0, 51, 0);"&gt;  FTaskGroup := CreateTaskGroup;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;  for&lt;/span&gt; i := 1&lt;span style="font-weight: bold;"&gt; to&lt;/span&gt; 10 &lt;span style="font-weight: bold;"&gt;do &lt;/span&gt;&lt;br /&gt;   CreateTask(TMyWorker.Create()).MonitorWith(OmniTED)&lt;span style="font-weight: bold; color: rgb(0, 51, 0);"&gt;.Join(FTaskGroup);&lt;/span&gt;&lt;br /&gt; Log('Starting all tasks');&lt;br /&gt;&lt;span style="color: rgb(0, 51, 0); font-weight: bold;"&gt;  FTaskGroup.RunAll;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;end;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;and&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-weight: bold;"&gt;procedure&lt;/span&gt; TfrmTestTaskGroup.btnStopTasksClick(Sender: TObject);&lt;/span&gt;&lt;br /&gt;&lt;span style=" font-weight: bold;font-family:courier new;" &gt;begin&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-weight: bold;"&gt;  if &lt;/span&gt;assigned(FTaskGroup) &lt;span style="font-weight: bold;"&gt;then begin&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt; &lt;span style="font-weight: bold; color: rgb(0, 51, 0);"&gt;   FTaskGroup.TerminateAll;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    FTaskGroup := nil;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    Log('All stopped');&lt;/span&gt;&lt;br /&gt;&lt;span style=" font-weight: bold;font-family:courier new;" &gt;  end&lt;/span&gt;&lt;br /&gt;&lt;span style=" font-weight: bold;font-family:courier new;" &gt;  else&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    Log('Nothing to stop');&lt;/span&gt;&lt;br /&gt;&lt;span style=" font-weight: bold;font-family:courier new;" &gt;end;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-922131437159995227?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/922131437159995227/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2011/08/note-on-omnithreadlibrary-otl-task.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/922131437159995227'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/922131437159995227'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2011/08/note-on-omnithreadlibrary-otl-task.html' title='Note on OmniThreadLibrary (OTL): Task Group'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-4784366405278814573</id><published>2011-08-18T13:26:00.005-04:00</published><updated>2011-09-25T10:38:12.136-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Delphi'/><category scheme='http://www.blogger.com/atom/ns#' term='multithreading'/><title type='text'>Note on OmniThreadLibrary (OTL): TerminateWhen</title><content type='html'>Once a worker thread has been launched,  there are a few ways to &lt;span style="font-weight: bold;"&gt;terminate&lt;/span&gt; it: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;IOmniTaskControl.Terminate&lt;/li&gt;&lt;/ul&gt;This will set the termination signal, and if it is parameter-less, then the worker will wait indefinitely till the thread finishes normally.   If a wait-out time is specified,  the work will wait until the wait-out time, then kill the thread forcefully, if it has not finished. &lt;br /&gt;&lt;br /&gt;If a thread is killed forcefully,  there might be resource leak (Cleanup and destructor may not get invoked). &lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;   IOmniTaskControl.TerminateWhen&lt;/li&gt;&lt;/ul&gt;Use an event, or an IOmniCancellationToken, for example (sample 14), &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 85%;"&gt;&lt;span style="font-family: courier new;"&gt;&lt;span style="font-weight: bold;"&gt;procedure&lt;/span&gt; TfrmTestTerminateWhen.btnStartTasksClick(Sender: TObject);&lt;/span&gt; &lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;var&lt;/span&gt; &lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  i: integer;&lt;/span&gt; &lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;begin&lt;/span&gt; &lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  if assigned(FCounter) and (FCounter.Value &amp;gt; 0) then&lt;/span&gt; &lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    btnStopTasksClick(Sender);&lt;/span&gt; &lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  FCounter := CreateCounter(10);&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #006600; font-family: courier new; font-weight: bold;"&gt;  FTerminate := CreateOmniCancellationToken;&lt;/span&gt; &lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  for i := 1 to FCounter.Value do begin&lt;/span&gt; &lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    Log(Format('Task started: %d',&lt;/span&gt; &lt;br /&gt;&lt;span style="font-family: courier new;"&gt;      [CreateTask(TMyWorker.Create()).&lt;span style="color: #006600; font-weight: bold;"&gt;TerminateWhen(FTerminate&lt;/span&gt;).WithCounter(FCounter).&lt;/span&gt; &lt;br /&gt;&lt;span style="font-family: courier new;"&gt;         MonitorWith(OmniTED).Run.UniqueID]));&lt;/span&gt; &lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  end;&lt;/span&gt;&lt;/span&gt; &lt;br /&gt;&lt;span style="font-size: 85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;end&lt;/span&gt;&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;Then,  somewhere in the code,  call &lt;br /&gt;&lt;br /&gt;&lt;span style="color: #006600; font-size: 85%; font-weight: bold;"&gt;FTerminate.Signal&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;This is equivalent to calling IOmniTaskControl.Terminate, i.e., it will set the termination signal and wait indefinitely till the thread finishes.&amp;nbsp; When the termination signal is set, IOmniTask.Terminated will be &lt;span style="font-style: italic; font-weight: bold;"&gt;True&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;If the thread is currently inside an intense looping,  we can use the following methods to jump out of the looping immediately &lt;br /&gt;&lt;br /&gt;[method1] &lt;br /&gt;&lt;span style="font-size: 85%;"&gt;&lt;span style="font-weight: bold;"&gt;while&lt;/span&gt; True &lt;span style="font-weight: bold;"&gt;do&lt;/span&gt; &lt;br /&gt;&lt;span style="font-weight: bold;"&gt;begin&lt;/span&gt; &lt;br /&gt;... &lt;br /&gt;&lt;span style="font-weight: bold;"&gt;    if &lt;span style="color: #006600;"&gt;WaitForSingleObject(task.TerminateEvent, 0) = WAIT_OBJECT_0&lt;/span&gt;&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;then&lt;/span&gt; &lt;br /&gt;Break; &lt;br /&gt;... &lt;br /&gt;&lt;span style="font-weight: bold;"&gt;end&lt;/span&gt;&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;or &lt;br /&gt;[method2]&lt;br /&gt;&lt;span style="font-size: 85%;"&gt;&lt;span style="font-weight: bold;"&gt;while&lt;/span&gt; True &lt;span style="font-weight: bold;"&gt;do&lt;/span&gt; &lt;br /&gt;&lt;span style="font-weight: bold;"&gt;begin&lt;/span&gt; &lt;br /&gt;... &lt;br /&gt;&lt;span style="font-weight: bold;"&gt;    if &lt;span style="color: #006600;"&gt;task.Terminated&lt;/span&gt;&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;then&lt;/span&gt; &lt;br /&gt;Break; &lt;br /&gt;... &lt;br /&gt;&lt;span style="font-weight: bold;"&gt;end&lt;/span&gt;&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;or&lt;br /&gt;&lt;br /&gt;[method3] &lt;br /&gt;&lt;span style="font-size: 85%;"&gt;&lt;span style="font-weight: bold;"&gt;while&lt;/span&gt; True &lt;span style="font-weight: bold;"&gt;do&lt;/span&gt; &lt;br /&gt;&lt;span style="font-weight: bold;"&gt;begin&lt;/span&gt; &lt;br /&gt;... &lt;br /&gt;&lt;span style="font-weight: bold;"&gt;    if &lt;span style="color: #006600;"&gt;task.CancellationToken.IsSignalled&lt;/span&gt;&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;then&lt;/span&gt; &lt;br /&gt;Break; &lt;br /&gt;... &lt;br /&gt;&lt;span style="font-weight: bold;"&gt;end&lt;/span&gt;&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;To use the last one,  we need to associated a cancellation token as follows: &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 85%;"&gt;&lt;span style="font-family: courier new;"&gt;CreateTask(TMyWorker.Create()) &lt;br /&gt;&lt;span style="color: black;"&gt;.&lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;TerminateWhen(FTerminate&lt;/span&gt;&lt;span style="color: black;"&gt;)&lt;/span&gt; &lt;br /&gt;.&lt;span style="color: #006600; font-weight: bold;"&gt;CancelWith(FTerminate)&lt;/span&gt; &lt;br /&gt;.WithCounter(FCounter) &lt;br /&gt;.M&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;onitorWith(OmniTED) &lt;br /&gt;.Run&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-4784366405278814573?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/4784366405278814573/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2011/08/note-on-omnithreadlibrary-otl.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/4784366405278814573'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/4784366405278814573'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2011/08/note-on-omnithreadlibrary-otl.html' title='Note on OmniThreadLibrary (OTL): TerminateWhen'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-6116666319757639323</id><published>2011-08-16T12:54:00.011-04:00</published><updated>2011-08-16T16:14:52.280-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Delphi'/><category scheme='http://www.blogger.com/atom/ns#' term='multithreading'/><title type='text'>Note on OmniThreadLibrary (OTL): Exception</title><content type='html'>When an exception happens from a working thread,  OTL allows to pass the exception information to the calling thread (i.e., the one where the relevant IOmniTaskControl is created). (See OTL sample 13)&lt;br /&gt;&lt;br /&gt;The information is saved in IOmniTaskControl.FatalException, it is a normal Exception sub class, therefore if it is not nil, then from its class name and message, one can get the exception information. For example,&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;span style="font-weight: bold;"&gt;if&lt;/span&gt; Assigned(aTaskControl.FatalException) &lt;span style="font-weight: bold;"&gt;then&lt;/span&gt;&lt;br /&gt;lvExInfo := aTaskControl.FatalException.ClassName + ': ' + aTaskControl.FatalException.Message;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In sample 13,  the decorator Enforced(True) is used, i.e.,&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;CreateTask(TExceptionTest.Create(Sender = btnInitException)).Enforced(True)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;According to the author -&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-size:85%;" &gt;"...In short – OTL always tries to execute your task. If you call taskControl.Terminate &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;strong style="font-style: italic;"&gt;before&lt;/strong&gt;&lt;/span&gt;&lt;span style="font-style: italic;font-size:85%;" &gt; the task has even started, OTL will set the &lt;span style="color: rgb(51, 51, 255); font-weight: bold;"&gt;termination signal &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;strong style="font-style: italic;"&gt;and start executing task&lt;/strong&gt;&lt;/span&gt;&lt;span style="font-style: italic;font-size:85%;" &gt;.  This is not a good idea if the task was waiting in the thread pool  queue and threadPool.CancelAll or threadPool.Terminate was executed. To  bypass this auto-execute behaviour, you can call &lt;/span&gt;.&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: bold;"&gt;Enforced(f&lt;/span&gt;&lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: bold;"&gt;alse)&lt;/span&gt;.&lt;/span&gt;"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Given the above statement,  &lt;span style="font-style: italic; font-family:courier new;" &gt;Enforced(True)&lt;/span&gt; is not required,  since by default it is already set to &lt;span style="font-weight: bold; font-style: italic; color: rgb(51, 204, 0);"&gt;true&lt;/span&gt;. Therefore,  sample 13 runs the same if we remove &lt;span style="font-style: italic; font-family:courier new;" &gt;Enforced(True)&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Some special remarks for exceptions that happen with TOmniWorker instances -&lt;br /&gt;&lt;ul&gt;&lt;li&gt;When an exception occurs,   be it from inside a worker object's &lt;span style="font-size:85%;"&gt;&lt;span style="font-style: italic; font-family:courier new;" &gt;Initialize( )&lt;/span&gt;&lt;/span&gt;, &lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;span style="font-style: italic;"&gt; Cleanup( )&lt;/span&gt;&lt;/span&gt;, or an &lt;span style="font-style: italic; font-weight: bold;"&gt;event handler&lt;/span&gt; for an internal timer,  the worker thread will be immediately terminated (by its task control); it is &lt;span style="font-weight: bold; font-style: italic;"&gt;after&lt;/span&gt; the termination, the exception information is assigned to its task control's &lt;span style="font-style: italic; font-family:courier new;" &gt;FatalException&lt;/span&gt; property, and available from there.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;In all, I am not quite sure about the rationale of this behavior,  but I guess the author's intention is to pass the exception information to the task control in the first place,  though,  before that,  some necessary handling must have been performed (at the user's responsibility) in the worker thread where the exception is raised before passing that information. Otherwise,  I would expect high possibility of resource leak since after the exception the work thread will be terminated unconditionally and depending on where the exception happens,  &lt;span style="font-style: italic; font-family:courier new;" &gt;Cleanup( )&lt;/span&gt;,  and/or the worker object's &lt;span style="font-style: italic; font-family:courier new;" &gt;destructor&lt;/span&gt; may not even get invoked.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-6116666319757639323?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/6116666319757639323/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2011/08/note-on-omnithreadlibrary-otl-exception.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/6116666319757639323'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/6116666319757639323'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2011/08/note-on-omnithreadlibrary-otl-exception.html' title='Note on OmniThreadLibrary (OTL): Exception'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-8296472225173626300</id><published>2011-08-16T12:33:00.008-04:00</published><updated>2011-08-16T23:14:57.962-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Delphi'/><category scheme='http://www.blogger.com/atom/ns#' term='multithreading'/><title type='text'>Note on OmniThreadLibrary (OTL): Lock</title><content type='html'>&lt;span style="font-size:100%;"&gt;These series posts on OmniThreadLibrary (OTL) only serve as my personal  mnemonics notes on the usage of OTL.  OTL's internal workings are quite sophisticated, as documented in several scattering posts by the original author &lt;a href="http://otl.17slon.com/tutorials.htm"&gt;http://otl.17slon.com/tutorials.htm &lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For thread synchronization, OTL implements S&lt;span style="font-weight: bold;"&gt;pin Lock&lt;/span&gt;,  and T&lt;span style="font-weight: bold;"&gt;icket Spin Lock&lt;/span&gt;.  More information on Spin Lock from &lt;a href="http://en.wikipedia.org/wiki/Spinlock"&gt;here&lt;/a&gt;,  and Ticket Spin Lock from &lt;a href="http://en.wikipedia.org/wiki/Ticket_lock"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Under OTL framework,  a lock can be associated with a IOmniTaskControl by&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;span style="font-weight: bold;"&gt;function&lt;/span&gt; WithLock(&lt;span style="font-weight: bold;"&gt;const&lt;/span&gt; lock: TSynchroObject; autoDestroyLock: &lt;span style="font-weight: bold;"&gt;boolean&lt;/span&gt; = true): IOmniTaskControl; &lt;span style="font-weight: bold;"&gt;overload&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;function&lt;/span&gt; WithLock(&lt;span style="font-weight: bold;"&gt;const&lt;/span&gt; lock: IOmniCriticalSection): IOmniTaskControl; &lt;span style="font-weight: bold;"&gt;overload;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For example (excerpted from OTL sample 11)&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;span style="font-weight: bold;"&gt;procedure&lt;/span&gt; TfrmTestLock.btnTestLockClick(Sender: TObject);&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;var&lt;/span&gt;&lt;br /&gt; task   : IOmniTaskControl;&lt;br /&gt; iRepeat: integer;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;begin&lt;/span&gt;&lt;br /&gt;task := CreateTask(TestArray);&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;if&lt;/span&gt; sender = btnTestLock &lt;span style="font-weight: bold;"&gt;then&lt;/span&gt;&lt;br /&gt;   &lt;span style="font-weight: bold;"&gt;task.WithLock(TTicketSpinLock.Create);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;task.Run;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;for&lt;/span&gt; iRepeat := 1 to CTestRepetitions &lt;span style="font-weight: bold;"&gt;do&lt;/span&gt;&lt;br /&gt;   &lt;span style="font-weight: bold;"&gt;if not&lt;/span&gt; OneTest(task.Lock) &lt;span style="font-weight: bold;"&gt;then&lt;/span&gt;&lt;br /&gt;   &lt;span style="font-weight: bold;"&gt;begin&lt;/span&gt;&lt;br /&gt;       Log(Format('Test failed at repetition %d', [iRepeat]));&lt;br /&gt;       task.Terminate;&lt;br /&gt;       &lt;span style="font-weight: bold;"&gt;break;&lt;/span&gt; //for iRepeat&lt;br /&gt;   &lt;span style="font-weight: bold;"&gt;end;&lt;/span&gt;&lt;br /&gt; task.WaitFor(INFINITE);&lt;br /&gt; Log('Completed');&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;end;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;The &lt;span style="font-weight: bold;"&gt;autoDestroyLock&lt;/span&gt; by default is&lt;span style="font-weight: bold;"&gt; true&lt;/span&gt;, meaning the reference count will be decremented when the omni task control goes out of scope.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-8296472225173626300?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/8296472225173626300/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2011/08/note-on-omnithreadlibrary-otl-lock.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/8296472225173626300'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/8296472225173626300'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2011/08/note-on-omnithreadlibrary-otl-lock.html' title='Note on OmniThreadLibrary (OTL): Lock'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-131971951478244385</id><published>2011-08-15T17:13:00.010-04:00</published><updated>2011-08-19T12:37:05.068-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Delphi'/><category scheme='http://www.blogger.com/atom/ns#' term='multithreading'/><title type='text'>Note on OmniThreadLibrary (OTL): Thread Pool</title><content type='html'>OmniThreadLibarry (OTL) is a Delphi-based threading library developed by Delphi guru Primoz Gabrijelcic.  It is a great gift that Primoz contributes to the Delphi community (free with source code http://otl.17slon.com/index.htm).   The library is very handy except currently somewhat missing systematic documentation/tutorial, therefore a user would have to go through the supplied samples.&lt;br /&gt;&lt;br /&gt;Here is a little mnemonics on OTL's thread pool interface, &lt;span style="font-weight: bold;"&gt;IOmniThreadPool&lt;/span&gt;, based on Primoz's &lt;span style="font-weight: bold;"&gt;sample 11.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51); font-weight: bold;"&gt;1. To create a thread pool, use the utility function&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;      &lt;span style="font-weight: bold;"&gt; &lt;span style="font-size:85%;"&gt;function&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt; CreateThreadPool(const threadPoolName: string): IOmniThreadPool;&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold; font-family: courier new;font-family:courier new;font-size:85%;"  &gt;&lt;span style="font-family:courier new;"&gt;V&lt;/span&gt;ar &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;   FThreadPool : IOmniThreadPool;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;...&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;FThreadPool := CreateThreadPool('SignalOptimizationThreadPool');&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;A meaningful name can be set for the thread pool via the argument.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 51);"&gt;2.  After creating an interface,  some properties need to be configured (if not, default values  will be automatically used).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;MaxExecuting&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt; Maximum number of working threads that are allowed to be executing concurrently.  It can be any number up to 60.  If it is set to &lt;span style="color: rgb(51, 255, 51);font-size:130%;" &gt;0&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;,  &lt;span style="font-weight: bold;"&gt;NO&lt;/span&gt; tasks will be executed.&lt;/span&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;MaxQueued&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;Maximum number of queuing threads that are allowed to be waiting.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;IdleWorkerThreadTimeout_sec&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;The "time out" for idling threads, i.e.,  the &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;idling &lt;/span&gt;time before the thread in question is removed from the thread pool.&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;UniqueID&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Unique ID of the thread pool. For example,&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;Log(Format('Thread %d destroyed in thread pool %d', [threadID, pool.UniqueID]));&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;WaitOnTerminate_sec&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;The waiting time after a termiated is true.  If the thread cannot finish its task then after this time the thread will be killed forcefully.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 51);"&gt;3.  To associate a thread pool with tasks,  use &lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 51);"&gt;IOmniTaskControl.schedule&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;CreateTask(THelloWorker.Create(Handle,delay_ms)).MonitorWith(OmniTED).Schedule(FThreadPool);&lt;/span&gt;&lt;br /&gt;or&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;CreateTask(THelloWorker.Create(Handle,delay_ms)).MonitorWith(OmniTED).Schedule;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The second case, having no thread pool explicitly specified,  will use a default &lt;span style="font-weight: bold;"&gt;GlobalOmniThreadPool&lt;/span&gt; automatically.&lt;br /&gt;&lt;br /&gt;For &lt;span style="font-weight: bold;"&gt;unobserved&lt;/span&gt; tasks (i.e., the task controls are not assigned to explicit variables, nor a task monitor is associated),    we can use&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;FObservableTask := CreateTask(THelloWorker.Create(Handle), 'observed task')&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;.OnTerminated(ReleaseObservableTask)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;.&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;Schedule(FThreadPool);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;where,  &lt;span style="font-weight: bold;"&gt;ReleaseObservableTask&lt;/span&gt; is defined as:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;span style="font-weight: bold;"&gt;procedure&lt;/span&gt; TfrmTestOtlThreadPool.ReleaseObservableTask(&lt;span style="font-weight: bold;"&gt;const&lt;/span&gt; task: IOmniTaskControl);&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-family:courier new;font-size:85%;"  &gt;begin&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt; FObservableTask := nil;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-family:courier new;font-size:85%;"  &gt;end;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;To learn more about Unobserved, see &lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;" class="smalltext"&gt;&lt;/span&gt;&lt;a style="color: rgb(0, 0, 0); font-weight: bold;" href="http://otl.17slon.com/forum/index.php?action=profile;u=1"&gt;Primoz Gabrijelcic&lt;/a&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;'s original post:&lt;/span&gt;&lt;br /&gt;&lt;a style="color: rgb(51, 51, 255);" href="http://www.thedelphigeek.com/2009/11/omnithreadlibrary-patterns-task.html"&gt;http://www.thedelphigeek.com/2009/11/omnithreadlibrary-patterns-task.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(0, 0, 0);"&gt;4. To &lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(0, 0, 0);"&gt;terminate&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(0, 0, 0);"&gt; an individual  task&lt;/span&gt;,  we can  either call &lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;IOmniTaskControl.Terminate&lt;/span&gt;&lt;/span&gt;, or &lt;span style="font-size:85%;"&gt;IOmniThreadPool.Cancel(taskID).&lt;/span&gt;  The latter will wait for a &lt;span style="font-weight: bold;"&gt;WaitOnTerminate_sec&lt;/span&gt; time; after that,  the thread will be forcefully killed if it has not been finished normally.  The former,  similarly, you can either specify a (non-zero) customized wait time, leave it parameter-less (meaning wait indefinitely),  or terminate immediately (by specifying 0 wait time).&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;5.  &lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(0, 0, 0);"&gt;IOmniThreadPoo.CancelAll &lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;can be used to&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(0, 0, 0);"&gt; cancel/terminate all tasks &lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;with the thread pool.  For example,&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;GlobalOmniThreadPool.CancelAll,&lt;br /&gt;or&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;GlobalOmniThreadPool.CancelAll(1000).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In the latter example a wait out time is specified.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(0, 0, 0);"&gt;6. Sometimes we wish to wait for all tasks to finish before moving on to next action&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;, in this case, we can associate the thread pool with a &lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(0, 0, 0);"&gt;task group&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;for example,&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: courier new;font-family:courier new;font-size:85%;"  &gt;waitGroup := &lt;span style="color: rgb(0, 51, 51); font-weight: bold;"&gt;CreateTaskGroup&lt;/span&gt;;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: courier new;font-family:courier new;font-size:85%;"  &gt;&lt;span style="font-weight: bold;"&gt; for&lt;/span&gt; iTask := 1 &lt;span style="font-weight: bold;"&gt;to&lt;/span&gt; 6 &lt;span style="font-weight: bold;"&gt;do&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: courier new;font-family:courier new;font-size:85%;"  &gt;   CreateTask(THelloWorker.Create(Handle, 1000)).&lt;span style="font-weight: bold;"&gt;Unobserved.&lt;/span&gt;Join(waitGroup).Schedule;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: courier new;font-family:courier new;font-size:85%;"  &gt; &lt;span style="font-weight: bold;"&gt;while not&lt;/span&gt; waitGroup.WaitForAll(50) &lt;span style="font-weight: bold;"&gt;do&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: courier new;font-family:courier new;font-size:85%;"  &gt; &lt;span style="font-weight: bold;"&gt;begin&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: courier new;font-family:courier new;font-size:85%;"  &gt;   Application.ProcessMessages;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: courier new;font-family:courier new;font-size:85%;"  &gt; &lt;span style="font-weight: bold;"&gt;end;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(0, 0, 0);"&gt;7.  Events&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The following events can be associated with a&lt;span style="font-weight: bold;"&gt; IOmniEventMonitor&lt;/span&gt;.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;OnPoolThreadCreated&lt;/li&gt;&lt;li&gt;OnPoolThreadDestroying&lt;/li&gt;&lt;li&gt;OnPoolThreadKilled&lt;/li&gt;&lt;li&gt;OnPoolWOrkItemCompleted&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;For example, if we have the following worker,&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  &lt;span style="font-family:courier new;font-size:85%;"&gt;THelloWorker = &lt;span style="font-weight: bold;"&gt;class&lt;/span&gt;(TOmniWorker)&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: courier new;font-family:courier new;font-size:85%;"  &gt;  &lt;span style="font-weight: bold;"&gt;strict private&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: courier new;font-family:courier new;font-size:85%;"  &gt;    FDelayTIme  : Integer;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: courier new;font-family:courier new;font-size:85%;"  &gt;    FFormHandle : THandle;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: courier new;font-family:courier new;font-size:85%;"  &gt;    FTaskID     : Int64;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: courier new;font-family:courier new;font-size:85%;"  &gt;  &lt;span style="font-weight: bold;"&gt;public&lt;/span&gt;&lt;/span&gt;&lt;span style=" font-weight: bold;font-family:courier new;font-size:85%;"  &gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: courier new;font-family:courier new;font-size:85%;"  &gt;&lt;span style="font-weight: bold;"&gt;    constructor&lt;/span&gt; Create(aFormHandle:THandle;aDelay_ms:Integer = 1000);&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: courier new;font-family:courier new;font-size:85%;"  &gt;    &lt;span style="font-weight: bold;"&gt;destructor&lt;/span&gt;  Destroy; override;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: courier new;font-family:courier new;font-size:85%;"  &gt;    &lt;span style="font-weight: bold;"&gt;function &lt;/span&gt; Initialize: Boolean; override;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: courier new;font-family:courier new;font-size:85%;"  &gt;    &lt;span style="font-weight: bold;"&gt;procedure &lt;/span&gt;SleepTask(var aMsg: TMessage); message MSG_SLEEP;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: courier new;font-family:courier new;font-size:85%;"  &gt;    &lt;span style="font-weight: bold;"&gt;procedure&lt;/span&gt; Cleanup; override;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: courier new;font-family:courier new;font-size:85%;"  &gt;  &lt;span style="font-weight: bold;"&gt;end;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If we start the task by&lt;br /&gt;&lt;span style="font-family: courier new;font-family:courier new;font-size:85%;"  &gt;CreateTask(THelloWorker.Create(Handle,delay_ms)).MonitorWith(OmniTED).Schedule;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Then the global &lt;span style="font-weight: bold;"&gt;GlobalOmniTHreadPool&lt;/span&gt; is associated with the task.  Through the life cycle of the THelloWorker,   the sequence of events is as follows&lt;br /&gt;&lt;br /&gt;THelloWoker.Create -&amp;gt; OnPoolThreadCreated -&amp;gt; THelloWorker.Initialize-&amp;gt; ... (if Terminate is called with a generous wait out time ) -&amp;gt; THelloWorker.Cleanup-&amp;gt; THelloWorker.Destroy-&amp;gt; OnTaskTerminated-&amp;gt;OnPoolWorkItemCompleted-&amp;gt; after &lt;span style="font-weight: bold;"&gt;IdleWorkerThreadTimeout_sec, &lt;/span&gt;&lt;span&gt;OnPoolThreadDestroying&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;If a terminate (or cancel) is called with less then sufficient wait out time, then the thread is killed forcefully. In this case,  the flow is as follows&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;THelloWoker.Create -&amp;gt; OnPoolThreadCreated -&amp;gt;  THelloWorker.Initialize-&amp;gt; ... (if Terminate is called with a stingy  wait out time ) -&amp;gt; OnPoolWorkItemCompleted-&amp;gt; &lt;span style="font-weight: bold;"&gt;OnPoolThreadKilled&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-131971951478244385?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/131971951478244385/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2011/08/note-on-omnithreadlibrary-otl-thread.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/131971951478244385'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/131971951478244385'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2011/08/note-on-omnithreadlibrary-otl-thread.html' title='Note on OmniThreadLibrary (OTL): Thread Pool'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-7285158244358530629</id><published>2011-05-27T10:48:00.003-04:00</published><updated>2011-05-27T10:59:20.556-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Delphi'/><title type='text'>integer overflow trick</title><content type='html'>Delphi has a compiler switch {$Q},  if turned off the compiler will ignore integer overflow.  The following is a little trick to take advantage of this switch.&lt;br /&gt;&lt;br /&gt;Assuming you have a heavy loop that you need to obsessionally check some status, say, verify the current time clock, if certain conditions meet, break out of the loop.&lt;br /&gt;&lt;br /&gt;You have a integer variable numLoops,   the following is taken from OmniThreadLibrary by Delphi Guru &lt;a class="profile-name-link" href="profile/06903558857617342477" rel="author"&gt;Primoz Gabrijelcic &lt;/a&gt;&lt;br /&gt;&lt;br /&gt; repeat&lt;br /&gt;    {$Q-}Inc(numLoops);{$Q+}&lt;br /&gt;&lt;br /&gt;    if numLoops = 0 then&lt;br /&gt;    begin&lt;br /&gt;      time := DSiTimeGetTime64;&lt;br /&gt;&lt;br /&gt;      if time &amp;gt; endTime then&lt;br /&gt;        break; //repeat&lt;br /&gt;    end;&lt;br /&gt;&lt;br /&gt;    Inc(counter);&lt;br /&gt;&lt;br /&gt;    if BaseStack.Push(counter) then&lt;br /&gt;      Inc(numPushed)&lt;br /&gt;    else&lt;br /&gt;    begin&lt;br /&gt;      Inc(numSkipped);&lt;br /&gt;      DSiYield;&lt;br /&gt;    end;&lt;br /&gt;&lt;br /&gt;  until false;&lt;br /&gt;&lt;br /&gt;By using the trick, as you see in the above, the following code is saved:&lt;br /&gt;&lt;br /&gt;if numLoops = High(Word) then&lt;br /&gt;  numLoops = 0;&lt;br /&gt;&lt;br /&gt;Hence a couple of CPU cycles saved (this code is for benching marking a stack data structure so CPU cycles counts!)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-7285158244358530629?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/7285158244358530629/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2011/05/integer-overflow-trick.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/7285158244358530629'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/7285158244358530629'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2011/05/integer-overflow-trick.html' title='integer overflow trick'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-1850995206090788882</id><published>2011-05-25T12:28:00.005-04:00</published><updated>2011-05-27T10:47:45.997-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='FORTRAN'/><category scheme='http://www.blogger.com/atom/ns#' term='Dynamic Traffic Assignment'/><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><title type='text'>Lessons on floating point</title><content type='html'>I have been working on some work implementing Dynamic Traffic Assignment (DTA) and really encountered some issues related to floating point computations - and here is a summary of the lessons or experience -&lt;br /&gt;&lt;br /&gt;Some of the code is in FORTRAN 2003,  some of the code is in C++.  Both are latest Intel compilers.&lt;br /&gt;&lt;br /&gt;1. Intel compilers tend to generate binary code with larger size (with the same optimization switch) than Microsoft C++ compiler;&lt;br /&gt;&lt;br /&gt;2. FORTRAN 2003 is a whole new language and shouldn't be treated the same as FORTRAN77;&lt;br /&gt;&lt;br /&gt;3. In order for DEBUG build and RELEASE build to have identical floating point outputs,    &lt;br /&gt;&lt;br /&gt;       - FORTRAN compiler-&amp;gt;Floating Point Model must be "Strict"&lt;br /&gt;       - Floating Point Speculation  must be "Off",&lt;br /&gt;&lt;br /&gt;otherwise the two built versions may generate slightly different floating point numbers and if accumulated iteratively may cause non-trivial difference.&lt;br /&gt;&lt;br /&gt;4.  FOTRAN-&amp;gt;Run-time-&amp;gt;"Check Array and String Bounds" and "Check Uninitialized Variables" are very useful flags especially the code has to deal with legacy FORTRAN 77 code.&lt;br /&gt;&lt;br /&gt;5. FORTRAN-&amp;gt;Floating Point-&amp;gt;Floating Point Exception Handling,   enable "Underflow gives 0.0; Abort on other IEEE exceptions", so that floating point exceptions can be thrown timely.  But I don't find a comparable switch from Intel C++ compiler.&lt;br /&gt;&lt;br /&gt;Another lesson that calls for attention is floating point overflow - of course there are a whole bunch IEEE definitions on these,  but practically speaking,  this type of exception is pretty tricky to catch as I found they don't get thrown immediately when it happens (with the Intel compiler), if you have a multi-threaded program it is even harder to trace when and where a floating point overflow is triggered.&lt;br /&gt;&lt;br /&gt;In the Dynamic Traffic Assignment work,  the testing network is a tremendously huge network and the path cost itself is a big number, this big number when got exponential-ed, easily blows off the upper limits of a double precision.&lt;br /&gt;&lt;br /&gt;1. Be careful in using the exp( ) function and protection code should be in position to check floating point overflow;&lt;br /&gt;&lt;br /&gt;2. Using number scaling or other fast numerical techniques to approximate exp, if needed.&lt;br /&gt;&lt;br /&gt;3. Some C++ library can check overflow, including std::, boost::, leda:: but the problem is,  the overflow can be detected only BEFORE the value is assigned to a non-temporary variable. So the check point has to be executed with each iteration and that really drags down the performance.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-1850995206090788882?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/1850995206090788882/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2011/05/lessons-on-floating-point.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/1850995206090788882'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/1850995206090788882'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2011/05/lessons-on-floating-point.html' title='Lessons on floating point'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-3352987458710584062</id><published>2011-02-25T17:24:00.003-05:00</published><updated>2011-02-25T17:37:40.990-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='FORTRAN'/><category scheme='http://www.blogger.com/atom/ns#' term='C/C++'/><title type='text'>FORTRAN Interop with C/C++ (2)</title><content type='html'>Assuming we have the following function type defined in C, i.e.,&lt;br /&gt;typedef int (_stdcall * SetRelTurnFlowCbFunc)(DTAEnvironment *dtaEnv, TASession *taSesn, int iterID,  int arrSize, EdgeDynaAttrRec **edgeDynaAttrArr);&lt;br /&gt;&lt;br /&gt;This type is defined to facilitate call-back using function pointers.  The actual implementation of this function is defined using FORTRAN as&lt;br /&gt;&lt;br /&gt;FUNCTION SetRelTurnFlowCbFunc(dtaEnv, taSesn, iterID, arrSize, edgeDynaAttr_C_Arr) RESULT(f_result)&lt;br /&gt;!DEC$ ATTRIBUTES STDCALL :: SetRelTurnFlowCbFunc&lt;br /&gt;&lt;br /&gt;TYPE(C_PTR),    VALUE, INTENT(IN)  :: dtaEnv &lt;br /&gt;TYPE(C_PTR),    VALUE, INTENT(IN)  :: taSesn  &lt;br /&gt;INTEGER(C_INT), VALUE, INTENT(IN)  :: iterID&lt;br /&gt;INTEGER(C_INT), VALUE, INTENT(IN)  :: arrSize       &lt;br /&gt;TYPE(C_PTR),    VALUE, INTENT(IN)  :: edgeDynaAttr_C_Arr     &lt;br /&gt;&lt;br /&gt;....&lt;br /&gt;  &lt;br /&gt;CALL C_F_POINTER(edgeDynaAttr_C_Arr, edgeDynaAttr_F_Arr, [arrSize])&lt;br /&gt; &lt;br /&gt;DO n = 1, arrSize&lt;br /&gt;        CALL C_F_POINTER(edgeDynaAttr_F_Arr(n), aEdgeDynaAttrRec)          &lt;br /&gt;END DO&lt;br /&gt;RETURN&lt;br /&gt;END FUNCTION SetRelTurnFlowCbFunc  &lt;br /&gt;&lt;br /&gt;There are several subtleties here -&lt;br /&gt;1.  Use compiler directive to tell the FORTRAN compiler the calling convention.  You can leave this to the default setting of the IDE you use but I always do this explicitly.&lt;br /&gt;&lt;br /&gt;2. When converting from a C pointer to Fortran pointer,  using C_F_POINTER,  a explicit array size must be specified, so that the block of memory can be correctly addressed and interpreted by the FORTRAN compiler.&lt;br /&gt;&lt;br /&gt;3. For C pointer of pointer,  an inner loop is needed. In the above example, aEdgeDynaArrRec is declared as a Fortran pointer to some data structure. In the inner loop,  each C pointer is individually converted to the F-pointer.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-3352987458710584062?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/3352987458710584062/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2011/02/fortran-interop-with-cc-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/3352987458710584062'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/3352987458710584062'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2011/02/fortran-interop-with-cc-2.html' title='FORTRAN Interop with C/C++ (2)'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-8856711266205236862</id><published>2011-02-23T11:31:00.003-05:00</published><updated>2011-02-24T01:14:53.196-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='FORTRAN'/><category scheme='http://www.blogger.com/atom/ns#' term='C/C++'/><title type='text'>FORTRAN Interop with C/C++ (1)</title><content type='html'>FORTRAN.... oops  am I talking about some stone-age monster?  I hope not.   And the fact is that I have been recently involved in a project that requires interfacing with a FORTRAN numerical engine.  Hence the need to interface a FORTRAN host exe with a C++ DLL, while,  to make it more complicated, the FOTRAN host exe calls back to the C++ DLL through function  pointers.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;That is for sure a very interesting experience,  apart from that I am getting a little nostalgia being  reminded of my good old college days using FOR77 as my first programming language.    That is almost about 17 years ago.&lt;br /&gt;&lt;br /&gt;wow!  I think am really getting old now, and that makes me sad.&lt;br /&gt;&lt;br /&gt;Oh boy! 17 years after I touched FORTRAN, now I have to use it extensively, again.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-8856711266205236862?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/8856711266205236862/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2011/02/fortran-interop-with-cc-1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/8856711266205236862'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/8856711266205236862'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2011/02/fortran-interop-with-cc-1.html' title='FORTRAN Interop with C/C++ (1)'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-5371524920400918719</id><published>2010-12-02T10:03:00.005-05:00</published><updated>2011-02-23T11:31:35.778-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Diary'/><title type='text'>TeeChart 2010 Pro and DataAbstract Installation</title><content type='html'>To upgrade TeeChart 2010 std to pro,  particulary, remember to remove:&lt;br /&gt;1. Chart.dcu, DbChart.dcu, GDIPAPI.dcu, DGDIPOBJ.dcu, TeCanvas.dcu&lt;br /&gt;2. All other Tee*.dcu&lt;br /&gt;&lt;br /&gt;For Delphi XE pro,  remove DataAbstract_DBXDriver_Enterprise_D15, otherwise, going to have error like unable to found DBXSybaseASEDriver.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-5371524920400918719?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/5371524920400918719/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2010/12/teechart-2010-pro-and-dataabstract.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/5371524920400918719'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/5371524920400918719'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2010/12/teechart-2010-pro-and-dataabstract.html' title='TeeChart 2010 Pro and DataAbstract Installation'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-251981400615110925</id><published>2010-07-31T20:41:00.002-04:00</published><updated>2010-07-31T20:46:05.054-04:00</updated><title type='text'>VISSIM Installer flushes PATH!</title><content type='html'>Obviously there is some overlooking from PTV developer(s), or whoever prepared the VISSIM installer-  I notice that after installing VISSIM (5.20 SP11),  the contents of PATH environmental variable are completely erased and refilled with VISSIM-related only crap!&lt;br /&gt;&lt;br /&gt;This is annoying - really annoying...  @@$@%Q#%35  as a developer you would know the PATH would contain important paths and now I have to recollect and re-enter them manually!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-251981400615110925?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/251981400615110925/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2010/07/vissim-installer-flushes-path.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/251981400615110925'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/251981400615110925'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2010/07/vissim-installer-flushes-path.html' title='VISSIM Installer flushes PATH!'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-2384314874895892946</id><published>2010-01-27T11:19:00.002-05:00</published><updated>2010-01-27T11:25:27.191-05:00</updated><title type='text'>VISSIM Patch 103: Code Sign</title><content type='html'>The hacks to VISSIM COM instance model seem working - yet now I have a practical problem.  It uses code injection techniques and some anti-virus software would treat the hook DLL as malware.&lt;br /&gt;&lt;br /&gt;In order to distribute I have to sign it with some trusted certificate.  Though,  I can sign it using the certificate issued to my company (I have certificate issued by GlobalSign), I really feel reluctant to do so. &lt;br /&gt;&lt;br /&gt;So if somebody is interested in this little stuff,  I can give it to you for free but, you have to code sign it with your own certificate.   You can obtain a code sign certificate from VeriSign or GlobalSign.&lt;br /&gt;&lt;br /&gt;This completes the story.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-2384314874895892946?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/2384314874895892946/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2010/01/vissim-patch-103-code-sign.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/2384314874895892946'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/2384314874895892946'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2010/01/vissim-patch-103-code-sign.html' title='VISSIM Patch 103: Code Sign'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-1397899049523766101</id><published>2010-01-18T10:35:00.004-05:00</published><updated>2010-01-18T20:04:48.554-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='COM'/><category scheme='http://www.blogger.com/atom/ns#' term='VISSIM'/><category scheme='http://www.blogger.com/atom/ns#' term='Reverse Engineering'/><title type='text'>VISSIM Patch 102: Modify VISSM COM Instance Model</title><content type='html'>Ha! It was a crazy weekend after TRB... and I am intrigued to come out with a neater solution for the VISSIM COM instance issue.&lt;br /&gt;&lt;br /&gt;In the previous post I proposed to patch VISSIM.exe binary code, which turned out to be a really dirty solution.&lt;br /&gt;&lt;br /&gt;Why?&lt;br /&gt;&lt;br /&gt;VISSIM.exe's UI uses a .NET library while it is a mixed potpourri of native code and .NET IL code. It is never a pleasure to look at such a thing of a mixed nature - sometimes I found myself a neat freak.&lt;br /&gt;&lt;br /&gt;Besides, this kind of patch would immediately become useless if VISSIM has any new versions.&lt;br /&gt;&lt;br /&gt;A more general, neater solution would be to use a system level API hook technique to intercept VISSIM's call to ole32.dll API CoRegisterClassObject - the theory is simple, whatever VISSIM does internally, it has to call CoRegisterClassObject ultimately.&lt;br /&gt;&lt;br /&gt;All we need to do is to hook this API to override REGCLS flag.&lt;br /&gt;&lt;br /&gt;API hook is a technique used by most anti-virus software, of course,  it is also a common technique by malware programmers.&lt;br /&gt;&lt;br /&gt;I am done with this CoRegisterClassObject API hook and now I am in the middle of testing.&lt;br /&gt;&lt;br /&gt;This little hook dll will be released soon so one can use VISSIM in the following creative scenarios previously not possible:&lt;br /&gt;&lt;br /&gt;1. Invoke multiple VISSIM instances through COM;&lt;br /&gt;2. Multi-threading COM applications using VISSIM, each VISSIM instance is dispatched in its own threading context.&lt;br /&gt;&lt;br /&gt;Stay tuned.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-1397899049523766101?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/1397899049523766101/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2010/01/vissim-hacks-102-modify-vissm-com.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/1397899049523766101'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/1397899049523766101'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2010/01/vissim-hacks-102-modify-vissm-com.html' title='VISSIM Patch 102: Modify VISSM COM Instance Model'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-2369737035791861445</id><published>2010-01-14T09:56:00.028-05:00</published><updated>2010-01-18T20:06:11.701-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='COM'/><category scheme='http://www.blogger.com/atom/ns#' term='VISSIM'/><category scheme='http://www.blogger.com/atom/ns#' term='Reverse Engineering'/><title type='text'>VISSIM Patch  101:  Modify VISSM COM Instance Model</title><content type='html'>VISSIM has a licensed feature "VISSIM COM" that a user can use to do automation-style programming. It provides convenient and easy interfaces to access VISSIM functionality programmingly.&lt;br /&gt;&lt;br /&gt;However, VISSIM COM Server by design can only be invoked in "single instance" mode. That is,  if you have a COM client that tries to establish a connection with VISSIM COM server, the connection will be established ONLY to the FIRST VISSIM instance that has already been created.&lt;br /&gt;&lt;br /&gt;In other words, a new VISSIM instance is created if and only if there is currently no active VISSIM instance running. While on the other hand, if there are multiple VISSIM instances, your COM client would only connect to the first VISSIM COM instance.&lt;br /&gt;&lt;br /&gt;I believe there must be a good reason for this kind of design. Just like what I did with the &lt;span style="font-style: italic; color: rgb(51, 51, 51);"&gt;ACDSS adaptive control system&lt;/span&gt; currently being implemented in New York City.  ACDSS system implements a &lt;span style="font-style: italic; font-weight: bold;"&gt;Just-In-Time simulation framework&lt;/span&gt; to allow a so-called real-time operator-in-the-loop mode.  This JIT simulation is based on a new COM interface I developed on top of Aimsun.  This Aimsun COM server allows multiple instances to be started and in-sync so the operator can use Side-By-Side (a.k.a) SxS simulations to compare.&lt;br /&gt;&lt;br /&gt;If you are interested in the new adaptive control system, you can download this paper&lt;br /&gt;&lt;a href="http://www.wupingxin.net/papers/TRB2010_ACDSS.pdf"&gt;"Integrated Adaptive Control with Realtime Decision Support"&lt;/a&gt;, presented at this year's TRB just finished today.&lt;br /&gt;&lt;br /&gt;Yesterday at TRB,  a Minnesota friend asked me if it is possible to create multiple VISSIM COM server connections....&lt;br /&gt;&lt;br /&gt;En.... that is an interesting question, and the answer lies in a &lt;span style="font-style: italic;"&gt;clear understanding of what is under the hood of Microsoft's COM technology&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Let me do a little lecture for those non-programmers or who not familiar with the inner workings of COM.&lt;br /&gt;&lt;br /&gt;In this particular case,  VISSIM is a registered &lt;span style="font-style: italic; font-weight: bold;"&gt;out-of-process&lt;/span&gt; COM local server.  So I'll focus the explanation on out-of-process COM only, because&lt;span style="font-style: italic; font-weight: bold;"&gt; in-process&lt;/span&gt; COM has somewhat different mechanism, so in order not to confuse I'll rather leave it to some post later.&lt;br /&gt;&lt;br /&gt;For out-of-process COM exe server, such as VISSIM, a client program (&lt;span style="font-style: italic;"&gt;a client program can be written in any COM compliant languages such as VB, VC++, .NET blah blah blah you name it&lt;/span&gt;) starts a connection by calling Windows Operating System's COM API in the following sequence:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;1. CoCreateInstance&lt;/span&gt;&lt;br /&gt;Nothing need to mention about this COM API.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2. CoGetClassObject&lt;/span&gt;&lt;br /&gt;For In-Process COM object, CoGetClassObject will get the pointer to the class factory; but for out-of-process COM exe like VISSIM, CoGetClassObject will get the VISSIM path from the ProgID in the system registry.&lt;br /&gt;&lt;br /&gt;Note, different versions of VISSIM has different ProgID. Also remember VISSIM is registered a a LocalServer, so no DCOM crap is involved all I am taking is within the same local machine.&lt;br /&gt;&lt;br /&gt;3. Once the system locates VISSIM.exe,  &lt;span style="font-weight: bold;"&gt;CoRegisterClassObject&lt;/span&gt; (this is the ultimate ole32 API to be invoked, even VISSIM uses some .NET wrappers) will be invoked in the start-up code before calling the WinMain entry function of VISSIM.exe;&lt;br /&gt;&lt;br /&gt;Here is the signature of CoRegisterClassObject(CLSID, pUnk, dwClsContext, flags, &amp;amp;dwRegister)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The key point is the fourth parameter "flags"&lt;/span&gt;.  It determines during runtime whether VISSIM COM exe can be started as single instance or multiple instances.&lt;br /&gt;&lt;br /&gt;Check MSDN for more information about this COM API:&lt;br /&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms693407%28VS.85%29.aspx"&gt;http://msdn.microsoft.com/en-us/library/ms693407%28VS.85%29.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;OK, so the fourth parameter is a&lt;span style="font-weight: bold;"&gt; REGCLS&lt;/span&gt; enumeration variable defined as:&lt;br /&gt;&lt;br /&gt;typedef enum tagREGCLS&lt;br /&gt;{&lt;br /&gt;REGCLS_SINGLEUSE        = 0,&lt;br /&gt;REGCLS_MULTIPLEUSE      = 1,&lt;br /&gt;REGCLS_MULTI_SEPARATE   = 2,&lt;br /&gt;REGCLS_SUSPENDED        = 4,&lt;br /&gt;REGCLS_SURROGATE        = 8&lt;br /&gt;} REGCLS;&lt;br /&gt;&lt;br /&gt;All we need to do is to pass in &lt;span style="color: rgb(255, 0, 0);"&gt;REGCLS_SINGLEUSE&lt;/span&gt;, then VISSIM COM exe can be invoked in a "multinstance" manner.&lt;br /&gt;&lt;br /&gt;Why? Here is the description of the REGCLS flag:&lt;br /&gt;&lt;dl&gt;&lt;dt&gt;REGCLS_SINGLEUSE&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;After an application is connected to a class object with &lt;a id="ctl00_MTCS_main_ctl02" href="http://msdn.microsoft.com/en-us/library/ms684007%28VS.85%29.aspx" onclick="javascript:Track('ctl00_MTCS_main_ctl00|ctl00_MTCS_main_ctl02',this);"&gt;&lt;strong&gt;CoGetClassObject&lt;/strong&gt;&lt;/a&gt;, the c&lt;span style="color: rgb(255, 0, 0);"&gt;lass object&lt;/span&gt; is &lt;span style="color: rgb(255, 0, 0);"&gt;removed from public view&lt;/span&gt; so that no other applications can connect to it. This value is commonly used for single document interface (SDI) applications. Specifying this value does not affect the responsibility of the object application to call &lt;a id="ctl00_MTCS_main_ctl03" href="http://msdn.microsoft.com/en-us/library/ms688650%28VS.85%29.aspx" onclick="javascript:Track('ctl00_MTCS_main_ctl00|ctl00_MTCS_main_ctl03',this);"&gt;&lt;strong&gt;CoRevokeClassObject&lt;/strong&gt;&lt;/a&gt;; it must always call &lt;strong&gt;CoRevokeClassObject&lt;/strong&gt; when it is finished with an object class.&lt;/p&gt; &lt;/dd&gt;&lt;dt&gt;REGCLS_MULTIPLEUSE&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;Multiple applications can connect to the class object &lt;/span&gt;through calls to &lt;strong&gt;CoGetClassObject&lt;/strong&gt;. If both the REGCLS_MULTIPLEUSE and CLSCTX_LOCAL_SERVER are set in a call to &lt;a id="ctl00_MTCS_main_ctl04" href="http://msdn.microsoft.com/en-us/library/ms693407%28VS.85%29.aspx" onclick="javascript:Track('ctl00_MTCS_main_ctl00|ctl00_MTCS_main_ctl04',this);"&gt;&lt;strong&gt;CoRegisterClassObject&lt;/strong&gt;&lt;/a&gt;, the class object is also automatically registered as an in-process server, whether or not CLSCTX_INPROC_SERVER is explicitly set.&lt;/p&gt; &lt;/dd&gt;&lt;/dl&gt;&lt;br /&gt;Here is a little twisty - essentially it says,  if REGCLS_SINGLEUSE is set, then any client connection request would result in creation of a new class object - in our case, the class object is VISSIM object represente by IVissim interface. Creating a new class object means starting a new VISSIM.exe process, because VISSIM.exe is the host of the class object. Period.&lt;br /&gt;&lt;br /&gt;4. A little interesting additional information on what happens after CoRegisterClassObject - Internally, a&lt;span style="font-style: italic;"&gt; I/O completion port&lt;/span&gt; (a.k.a IOCP)  is created.  You know, I/O completion port is a low level IPC mechanism. By low level, I mean, File handle, Winsock2, name pipes etc all these higher level IPC mechanism would be built on top of I/O Completion port.  So IOCP is pretty ugly if you ever bother to delve into that level to satisfy your peeking eyes and curiosity.&lt;br /&gt;&lt;br /&gt;By the way, IPC = Inter Process Communication&lt;br /&gt;&lt;br /&gt;The created  I/O completion port receives &lt;span style="font-style: italic;"&gt;I/O completion packets&lt;/span&gt; then dispatches the package via Windows messaging then to the WndProc registered by ole32.dll. That WndProc then &lt;span style="font-weight: bold;"&gt;unarshall&lt;/span&gt; the out-of-process COM method invocation and restores the original function's &lt;span style="font-weight: bold; font-style: italic;"&gt;stack frame&lt;/span&gt;,  hence finishes the entire invocation COM function.&lt;br /&gt;&lt;br /&gt;This creation of&lt;span style="font-weight: bold; font-style: italic;"&gt; stack frame&lt;/span&gt; on the fly is similar to how web services are implemented. All are based on &lt;span style="font-weight: bold; font-style: italic;"&gt;stack frames &lt;/span&gt;created during run time.  Oh ... wait... what... you don't know what is stack frame?  Stack frame is just a memory footprint to prepare a function invocation, say, you need to allocate sufficient memories from the stack, then save all the current states registers and push the parameters.  Of course, in COM, the convention is always &lt;span style="font-weight: bold; font-style: italic;"&gt;stdcall&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Depending on the threading model the subject COM objects implements (single apartment, multiple apartment or whatever), there are some nuisances but I am not going to touch it here. It is pretty complex to explain.&lt;br /&gt;&lt;br /&gt;OK.   Enough background information about the inner workings of VISSIM COM. I hope I made myself understood.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0); font-weight: bold; font-style: italic;"&gt;The next critical question is how to utilize this information to change VISSIM COM Server' default behavior? &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The problem is, &lt;span style="font-weight: bold;"&gt;CoRegisterClassObject&lt;/span&gt; is called &lt;span style="font-style: italic;"&gt;inside&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/span&gt; VISSIM.exe.  Without VISSIM source code, how can we specify the REGCLS flag?&lt;br /&gt;&lt;br /&gt;That is not a problem.   As long as we know the track point is the API function CoRegisterClassObject, things are just getting straightforward.&lt;br /&gt;&lt;br /&gt;On quick and dirty solution is to use some little reverse engineering techniques to patch VISSIM's binary code. Of course, the purpose for doing that, must be legitimately justified. In the case of my Minnesota friend, he needs this to facilitate the interoperability and integration of his system with VISSIM, the nature of which is academic research by an educational institution.   Therefore according to DMCA Digital Millennium Copyright Act signed into law by President Bill Clinton in 1998, that is a legitimate cause of action generally. But don't believe what I said here coz I am not a lawyer!&lt;br /&gt;&lt;br /&gt;Bottom line, remember,  if you do so, chances are it might be interpreted as breaking license agreement hence losing technical support for real projects (Seriously,  I don't really believe that is going to happen but be warned!)&lt;br /&gt;&lt;br /&gt;You might ask, why not request a new feature from PTV? Of course one can do that and actually I would encourage anybody to do  that coz that is the right channel - but sometimes I found my PTV friends are pretty busy with their own priority list so I'd prefer to do a little DIY and have some fun myself, temporarily.&lt;br /&gt;&lt;br /&gt;Oh Geez! I am writing this on the train back to New York.   With so many brain numbing sessions it is moving shakingly forward, really making me feel dizzy as if my eyeballs are falling off my face so I'll have to leave the next post tonight or tomorrow.&lt;br /&gt;&lt;br /&gt;Stay tuned. Audience (I really hope I had some readers, but somehow I guess I myself is the only reader of my blog.... so most of the time I am just being  a stupid lonely programmer mumbling to himself....whatever.... it is just something to kill time on an empty dirty train)....&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-2369737035791861445?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/2369737035791861445/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2010/01/vissim-hacks-modify-vissm-com-instance.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/2369737035791861445'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/2369737035791861445'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2010/01/vissim-hacks-modify-vissm-com-instance.html' title='VISSIM Patch  101:  Modify VISSM COM Instance Model'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-3599241354515769592</id><published>2010-01-02T10:43:00.000-05:00</published><updated>2010-01-02T10:45:16.326-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Debugging'/><title type='text'>Disable 8.3 Filename</title><content type='html'>What is 8.3 file name?  See wikipedia at &lt;br /&gt;http://en.wikipedia.org/wiki/8.3_filename&lt;br /&gt;&lt;br /&gt;How to disable it?&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Windows Server 2003 and Windows XP&lt;br /&gt;To disable the 8.3 name creation on all NTFS partitions, type fsutil.exe behavior set disable8dot3 1 at a command prompt, and then press ENTER.&lt;br /&gt;&lt;br /&gt;Windows 2000 and Windows NT&lt;br /&gt;&lt;br /&gt;To disable the 8.3 name creation on all NTFS partitions, use the following steps: Important This section, method, or task contains steps that tell you how to modify the registry. However, serious problems might occur if you modify the registry incorrectly. Therefore, make sure that you follow these steps carefully. For added protection, back up the registry before you modify it. Then, you can restore the registry if a problem occurs. For more information about how to back up and restore the registry, click the following article number to view the article in the Microsoft Knowledge Base:&lt;br /&gt;322756  (http://support.microsoft.com/kb/322756/ ) How to back up and restore the registry in Windows&lt;br /&gt;&lt;br /&gt;   1. Start Regedt32.exe and locate the following registry key:&lt;br /&gt;      HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem&lt;br /&gt;   2. Select the NtfsDisable8dot3NameCreation entry.&lt;br /&gt;&lt;br /&gt;      NOTE: By default, the value for this entry is set to 0.&lt;br /&gt;   3. On the Edit menu, click DWORD. Type a value of 1 in the Data field.&lt;br /&gt;   4. Click OK and then quit Regedt32.&lt;br /&gt;   5. Quit Windows NT and turn off your computer.&lt;br /&gt;   6. Restart your computer and Windows NT.&lt;br /&gt;&lt;br /&gt;NOTE: The change to the NtfsDisable8dot3NameCreation registry entry affects only files, folders, and profiles that are created after the change. Files that already exist are not affected.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-3599241354515769592?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/3599241354515769592/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2010/01/disable-83-filename.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/3599241354515769592'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/3599241354515769592'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2010/01/disable-83-filename.html' title='Disable 8.3 Filename'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-4293540648312538247</id><published>2009-12-28T12:50:00.000-05:00</published><updated>2009-12-28T12:51:07.555-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Delphi'/><title type='text'>bpl, bpi, dcp</title><content type='html'>For both Delphi and C++ Builder&lt;br /&gt; - bpl = dll&lt;br /&gt;&lt;br /&gt;For Delphi&lt;br /&gt; -dcp = lib header  (for linking bpl)  + static lib&lt;br /&gt;&lt;br /&gt;For C++ builder&lt;br /&gt;- bpi = lib header (for linking bpl)&lt;br /&gt;&lt;br /&gt;When making a package,&lt;br /&gt;&lt;br /&gt;Delphi generates bpl + dcp&lt;br /&gt;C++ Builder generates bpl + bpi + lib (static lib)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-4293540648312538247?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/4293540648312538247/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2009/12/bpl-bpi-dcp.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/4293540648312538247'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/4293540648312538247'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2009/12/bpl-bpi-dcp.html' title='bpl, bpi, dcp'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-4561554618534310352</id><published>2009-11-29T14:33:00.009-05:00</published><updated>2009-12-06T11:42:52.021-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Debugging'/><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><title type='text'>DLL conflicting with Legion</title><content type='html'>I used some "tricks" to exploit the virtual tables of Aimsun C++ objects but with the latest Aimsun 6.1 (which by default would install a Legion for Aimsun module),  a previously working code segment always throws access violation exception....&lt;br /&gt;&lt;br /&gt;It turns out that some DLL from the Legion for Aimsun module is the "bad guy".... , and the issue can be temporarily resolved by uninstalling Legion for Aimsun module.&lt;br /&gt;&lt;br /&gt;- Following up:  The cause of the crash is nailed down to the C Runtime library msvcr80.dll that Legion for Aimsun is dependent on, yet the PE loader load the msvcr80.dll of version 8.0.50727.42 which is NOT what legion expects (it expects a newer version) but I have to make it visible on system path for some reason.&lt;br /&gt;&lt;br /&gt;- Following up again: This issue is getting more interesting because it only happens on Vista machine.&lt;br /&gt;&lt;br /&gt;- PS, I might be wrong but Legion seems only runs on Windows platform ( didn't find that there is Linux or MacOS versions of Legion yet); this doesn't seem to be consistent with Aimsun's cross-platform implementation? (Aimsun has Max OS and Linux versions since it is developed in Qt).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-4561554618534310352?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/4561554618534310352/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2009/11/legion-for-aimsun-not-blessing.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/4561554618534310352'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/4561554618534310352'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2009/11/legion-for-aimsun-not-blessing.html' title='DLL conflicting with Legion'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-6566831585735175519</id><published>2009-11-02T11:14:00.008-05:00</published><updated>2009-11-02T11:41:16.332-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VISSIM'/><category scheme='http://www.blogger.com/atom/ns#' term='Signal Control'/><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><title type='text'>VISSIM Signal Control DLL SignalGUI Flow Chart</title><content type='html'>VISSIM provides quite a few interfaces for integrating external signal control logic. A user can use VAP, or, more directly, using the so-called signal control API DLL to incorporate whatever "advanced" control logic he believes.&lt;br /&gt;&lt;br /&gt;Oh yeah, believe me, the VAP DLL actually is the same as a normal signal control external DLL, all the 3 exported functions are the same. My guess is that PTV just put an additional VAP script parser for VAP but all the underlying stuff is the same.&lt;br /&gt;&lt;br /&gt;Also VISSIM has a RGB editor that is pretty nice but to my great surprise it was developed using .NET without any obfuscation. The Transyt 7F guys are much more wary in that they at least did a little homework obfuscating their IL code.  Though obfuscation won't stop any persistent reverser with perseverance, but still it is better than nothing!&lt;br /&gt;&lt;br /&gt;PTV guys! Honk honk! Warning! .......&lt;br /&gt;&lt;br /&gt;I have a &lt;a href="http://wupingxin.blogspot.com/2009/07/vissim-signal-control-api-some-hints.html"&gt;previous article&lt;/a&gt; about the inner workings of VISSIM signal control DLL. So up till now you still don't know what I am talking about, I whole-heartedly suggest you read that article first.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Togother with Signal Control DLL API, PTV also provide another GUI interface ( in a DLL) for configuring any parameters relevant to the signal control DLL. That is the so-called signalGUI dll.&lt;br /&gt;&lt;br /&gt;The signal GUI DLL has pretty confusing control flow if you simply read its code. So I put a little more chart here to help those perplexed.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;If you found it useful, for example save your life, save your marriage, or help finish your work quickly and make your boss happy, or get a raise, whatever, don't forget to drop me an email!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_k2DBn0WY4XM/Su8HzYAbh_I/AAAAAAAAACQ/By9hafmRUuU/s1600-h/SignalGUI.jpg"&gt;&lt;img style="MARGIN: 0pt 10px 10px 0pt; WIDTH: 133px; FLOAT: left; HEIGHT: 200px; CURSOR: pointer" id="BLOGGER_PHOTO_ID_5399543057439492082" border="0" alt="" src="http://2.bp.blogspot.com/_k2DBn0WY4XM/Su8HzYAbh_I/AAAAAAAAACQ/By9hafmRUuU/s200/SignalGUI.jpg" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-6566831585735175519?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/6566831585735175519/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2009/11/vissim-signal-control-dll-signalgui.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/6566831585735175519'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/6566831585735175519'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2009/11/vissim-signal-control-dll-signalgui.html' title='VISSIM Signal Control DLL SignalGUI Flow Chart'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_k2DBn0WY4XM/Su8HzYAbh_I/AAAAAAAAACQ/By9hafmRUuU/s72-c/SignalGUI.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-2424231013778161085</id><published>2009-10-31T16:27:00.004-04:00</published><updated>2009-10-31T21:31:52.519-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='COM'/><category scheme='http://www.blogger.com/atom/ns#' term='Aimsun'/><category scheme='http://www.blogger.com/atom/ns#' term='Matlab'/><title type='text'>Aimsun COM Interface (3) - Matlab example</title><content type='html'>Matlab is a very powerful computational platform that runs on multi-platforms, including Windows, Mac-OS, Linux... you name it.&lt;br /&gt;&lt;br /&gt;On Microsoft Windows, Matlab provides pretty good support for COM automation. So today, let me illustrates a little Aimsun COM sample using Matlab.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;When using Aimsun COM under Matlab environment, all the automation objects are accessed by the relevant IDispatch interface.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Here is the first line that creates a reference to the Aimsun Application object. 'angcomsvr.AimsunServer' is the progID, also in Matlab the string is single quoted, just like Pascal.&lt;br /&gt;&lt;br /&gt;&lt;span style="FONT-STYLE: italic; COLOR: rgb(51,51,255)"&gt;aimsunApp = actxserver('angcomsvr.AimsunServer');&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;After creating the reference, we need to initialize the object by:.&lt;br /&gt;&lt;br /&gt;&lt;span style="FONT-STYLE: italic; COLOR: rgb(51,51,255)"&gt;aimsunApp.InitAimsunApp(&lt;span style="COLOR: rgb(255,0,0)"&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The integer parameter 0 will be marshalled as a boolean false, indicating that Aimsun is going to be started as "non-console", i.e., GUI model.&lt;br /&gt;&lt;br /&gt;Now that we have successfully initialized Aimsun App, we can now to whateve we like, e.g., open an network, generate new demand or run the simulation. All of these through line by line Matlab code, just like what you can usually do with Aimsun's default Python scripting.&lt;br /&gt;&lt;br /&gt;&lt;span style="FONT-STYLE: italic; COLOR: rgb(51,102,255)"&gt;aimsunApp.OpenNetwork(&lt;span style="COLOR: rgb(51,204,0)"&gt;'D:\Network\whatever.ang'&lt;/span&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Or you can have a little fun by maximizing, minimizing, reposition the main Aimsun window:&lt;br /&gt;&lt;br /&gt;&lt;span style="FONT-STYLE: italic; COLOR: rgb(51,51,255)"&gt;aimsunApp.ShowMaximized;&lt;/span&gt;&lt;br /&gt;&lt;span style="FONT-STYLE: italic; COLOR: rgb(51,51,255)"&gt;aimsunApp.ShowMinimized;&lt;/span&gt;&lt;br /&gt;&lt;span style="FONT-STYLE: italic; COLOR: rgb(51,51,255)"&gt;aimsunApp.SetWindowPosition(0, 0, 150, 150);&lt;/span&gt;&lt;br /&gt;&lt;span style="FONT-STYLE: italic; COLOR: rgb(51,51,255)"&gt;aimsunApp.Run;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In order to close the Aimsun Application, use&lt;br /&gt;&lt;br /&gt;&lt;span style="FONT-STYLE: italic; COLOR: rgb(51,51,255)"&gt;aimsunApp.release&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This will decrement the&lt;span style="FONT-STYLE: italic; FONT-WEIGHT: bold"&gt; reference count&lt;/span&gt; and since the Aimsun COM is implemented as &lt;span style="FONT-STYLE: italic; FONT-WEIGHT: bold"&gt;multi-instance&lt;/span&gt; COM server, decrementing the reference count by 1 will immediately drop it to 0, hence deleting the object from memory.&lt;br /&gt;&lt;br /&gt;That is it. Next I will illustrate an &lt;span style="FONT-STYLE: italic; FONT-WEIGHT: bold"&gt;Excel &lt;/span&gt;sample. Then I'll show more complicated simulation scenario using Pascal.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-2424231013778161085?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/2424231013778161085/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2009/10/aimsun-com-interface-3-matlab-example.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/2424231013778161085'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/2424231013778161085'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2009/10/aimsun-com-interface-3-matlab-example.html' title='Aimsun COM Interface (3) - Matlab example'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-8988479948686372265</id><published>2009-10-18T13:33:00.009-04:00</published><updated>2011-08-27T12:50:27.012-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Reverse Engineering'/><category scheme='http://www.blogger.com/atom/ns#' term='Debugging'/><title type='text'>OpenMP Runtime Version Conflicts</title><content type='html'>I was working on a software project that I have been working on in the past two years...&lt;br /&gt;&lt;br /&gt;The strangest thing happened when I tried to launch the main GUI of the system - I double clicked it, it flashed in the screen then disappeared immediately.&lt;br /&gt;&lt;br /&gt;This doesn't make sense at all - it was working just a few days ago and I didn't recall I did anything...&lt;br /&gt;&lt;br /&gt;I launched  the debugger from the IDE, but the same thing happened while none of the source code break points get hit!&lt;br /&gt;&lt;br /&gt;My first reaction is,  something must go wrong in the compiler generated start-up code....&lt;br /&gt;&lt;br /&gt;So, Plan B.&lt;br /&gt;&lt;br /&gt;This time I launched the OllyDBG debuggger from which I started my executable.&lt;br /&gt;&lt;br /&gt;..... oh..... modules loaded one by one.... then...... boop!&lt;br /&gt;&lt;br /&gt;I got this error message from a console window, and the main program just halted:&lt;br /&gt;&lt;br /&gt;"&lt;span style="font-style: italic;"&gt; &lt;/span&gt;&lt;b style="color: black; background-color: rgb(255, 255, 102); font-style: italic;"&gt;&lt;/b&gt;&lt;span style="font-style: italic;" class="postbody"&gt;OMP abort: Initializing lidguide40.dll, but found libiomp5md.dll already initialized.&lt;br /&gt;This may cause preformance KMP_DUPLICATE_LIB _OK=TRUE to ignore this problem and force  the program to continue anyway.  Please note that the use of KMP_DUPLICAT_LIB_OK is Unsupported and using it may cause   undefined behavioer.  For more infomation,please contact Intel(R) Premier Support. &lt;/span&gt;"&lt;br /&gt;&lt;br /&gt;So what is going on?&lt;br /&gt;&lt;br /&gt;Here is an explanation from Intel website:&lt;br /&gt;&lt;br /&gt;"&lt;span style="font-style: italic;"&gt;Both libiomp5md.dll and libguide40.dll are Intel OpenMP Runtime library. The libiomp5md.dll is new Intel OpenMP* Compatibility library while the libguide40.dll is legacy OpenMP library.  The Intel® IPP 6.x and Intel® Compiler 11.x threading libraries are switching from the legacy OpenMP* run-time library (libguide*) to the compatibility library (libiomp*).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;The dynamic library, libguide40.dll, is still included in the current releases for backwards compatibility and will be removed in a future release. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;The error is caused by multiple OpenMP libraries were linked in same application. For example, if a application link the libiomp5md.dll from IPP 6.x,  at the same time, it also link other software, e.g third-party library, which link libguide40.dll, then the error arises because of the duplicate initialization of OpenMP Runtime library&lt;/span&gt;"&lt;br /&gt;&lt;br /&gt;So it turns out that two third party libraries I was using are dependent on TWO different versions of OpenMP libraries.&lt;br /&gt;&lt;br /&gt;In all,  it wasn't a challenging problem that requires  RE technique to find the cause, however it is an elusive problem as the Console warning window never show up, or it did but in a very very short time to prevent naked human eyes to notice.&lt;br /&gt;&lt;br /&gt;Solution?  For the time being I just add the environmental variable as suggested but later  I am thinking of removing one of the third party libraries.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-8988479948686372265?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/8988479948686372265/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2009/10/hack-me-hack-my-code.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/8988479948686372265'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/8988479948686372265'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2009/10/hack-me-hack-my-code.html' title='OpenMP Runtime Version Conflicts'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-9068323793234504521</id><published>2009-07-19T12:27:00.019-04:00</published><updated>2009-10-31T21:32:17.832-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='COM'/><category scheme='http://www.blogger.com/atom/ns#' term='Aimsun'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='.NEt'/><title type='text'>Aimsun COM Interface (2) - C# Sample</title><content type='html'>As I said, I am going to post a few samples illustrating the application of the new Aimsun COM interface. And now I am showing how to use it with .NET/C#.&lt;br /&gt;&lt;br /&gt;C# is employed for the demo, because it is the preferred .NET language. However, the procedures are pretty much the same with VB.NET, Delphi.NET, Delphi Prism, and C++/CLI.NET.&lt;br /&gt;&lt;br /&gt;So I'll just cut long story short using C# for the illustration.&lt;br /&gt;&lt;br /&gt;First in first, this COM server needs to be registered with Windows Operating System. This can be achieved by quite different ways. I listed some below:&lt;br /&gt;&lt;br /&gt;&lt;ul style="TEXT-ALIGN: left"&gt;&lt;li&gt;Using command line parameters:&lt;/li&gt;&lt;/ul&gt;&lt;div style="TEXT-ALIGN: left"&gt;&lt;span style="FONT-STYLE: italic; FONT-WEIGHT: bold"&gt;Register &lt;/span&gt;angcomsvr.exe /regserver&lt;br /&gt;&lt;span style="FONT-STYLE: italic; FONT-WEIGHT: bold"&gt;Unregister&lt;/span&gt; angcomsvr.exe /unregister&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;ul style="TEXT-ALIGN: left"&gt;&lt;li&gt;Using Win32 API &lt;span style="FONT-STYLE: italic; FONT-WEIGHT: bold"&gt;CreateProcess&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div style="TEXT-ALIGN: left"&gt;You can double click the link to see how to register using Win32 API. I simply copied it from &lt;a href="http://www.geocities.com/izenkov/howto-regcomexe.htm"&gt;another site&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now that the Aimsun COM server is registered, the next step is to &lt;span style="FONT-STYLE: italic; FONT-WEIGHT: bold"&gt;add reference &lt;/span&gt;to the COM server. It is pretty straightforward from Visual Studio IDE, so I'll pass it.&lt;br /&gt;&lt;br /&gt;The following code (Click to enlarge) is the &lt;span style="FONT-STYLE: italic"&gt;actual&lt;/span&gt; C# code that embodies the following actions:&lt;br /&gt;&lt;span style="FONT-STYLE: italic"&gt;1. Start Aimsun&lt;/span&gt;&lt;br /&gt;&lt;span style="FONT-STYLE: italic"&gt;2. Open an Aimsun network&lt;/span&gt;&lt;br /&gt;&lt;span style="FONT-STYLE: italic"&gt;3. Pick a replication and run - on a single step by step basis&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_k2DBn0WY4XM/SmNO73xEiBI/AAAAAAAAABg/KgGhUVY7GOs/s1600-h/C%23.jpg"&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 380px; DISPLAY: block; HEIGHT: 315px; CURSOR: pointer" id="BLOGGER_PHOTO_ID_5360214771990038546" border="0" alt="" src="http://1.bp.blogspot.com/_k2DBn0WY4XM/SmNO73xEiBI/AAAAAAAAABg/KgGhUVY7GOs/s320/C%23.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;Since this sample is only for demo purpose, I didn't put anything other than basic elements. As a matter of fact, it can be put in much more sophisticated scenarios e.g., threading, .NET remoting, or web applications using ASP.NET. &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-9068323793234504521?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/9068323793234504521/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2009/07/aimsun-com-interface-2-c-sample.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/9068323793234504521'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/9068323793234504521'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2009/07/aimsun-com-interface-2-c-sample.html' title='Aimsun COM Interface (2) - C# Sample'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_k2DBn0WY4XM/SmNO73xEiBI/AAAAAAAAABg/KgGhUVY7GOs/s72-c/C%23.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-5162777668529067526</id><published>2009-07-19T09:57:00.028-04:00</published><updated>2009-07-20T18:53:44.400-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='COM'/><category scheme='http://www.blogger.com/atom/ns#' term='Aimsun'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='Matlab'/><category scheme='http://www.blogger.com/atom/ns#' term='.NEt'/><title type='text'>Aimsun COM Interface (1)</title><content type='html'>As I have pointed out in a &lt;a href="http://wupingxin.blogspot.com/2009/07/aimsun-scripting-different-perspective.html"&gt;previous article&lt;/a&gt;, Aimsun is a cross-platform application that runs on Linux, MacOS and Windows. COM is a Windows platform-specific technology, so naturally Aimsun itself does not have &lt;a href="http://www.microsoft.com/com/default.mspx"&gt;COM/Automation&lt;/a&gt; support. Nor I think TSS ever wants to put that in their list of buzz words.&lt;br /&gt;&lt;br /&gt;But sometimes, we do find COM/Automation convenient, especially when we have the need to interface Aimsun with other programming languages such as VB/VBScript, Excel, MATLAB, Delphi, FORTRAN, C#/.NET etc.&lt;br /&gt;&lt;br /&gt;Hence the start of the development to implement a COM interface for Aimsun.&lt;br /&gt;&lt;br /&gt;It is not a simple wrap-up of Aimsun SDK functions.&lt;br /&gt;&lt;br /&gt;The challenge is I don't have access to Aimsun source code, neither does Aimsun's native development language, i.e., Qt/C++ seem to have a stable support for COM/Active X development, at least with ActiveQt current release.&lt;br /&gt;&lt;br /&gt;So finally I chose to resort to Windows Operating System API and COM SDK directly. Therefore, this Aimsun COM interface is purely Window specific, and based on the following packages:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Aimsun SDK (needs special license from TSS) &lt;/li&gt;&lt;li&gt;Windows Operating System APIs (WIN32 API)&lt;/li&gt;&lt;li&gt;Windows COM SDK&lt;/li&gt;&lt;li&gt;A little tweak of the compiler generated C++ code and manipulation of the v-table of some C++ classes.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Currently this Aimsun COM interface has the following specifics:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Dual Interface supporting both &lt;span style="FONT-STYLE: italic"&gt;IUnknown&lt;/span&gt; and &lt;span style="FONT-STYLE: italic"&gt;IDispatch&lt;/span&gt;, with the latter allowing using popular scripting language VBScript, JavaScript, MatLab etc.&lt;/li&gt;&lt;li&gt;Earlier binding so strong typed languages such C++, Delphi, FORTRAN languages can interface Aimsun kernel without runtime performance loss.&lt;/li&gt;&lt;li&gt;Interop with .NET by COM-Interop/P-Invoke&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;This Aimsun-COM implements the following custom Interfaces, and I plan to add more if I have time:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;IAimsunInstance&lt;/li&gt;&lt;li&gt;IAimsunDemand&lt;/li&gt;&lt;li&gt;IAimsunExperiment&lt;/li&gt;&lt;li&gt;IAimsunMicroSimulator&lt;/li&gt;&lt;li&gt;IAimsunMOE&lt;/li&gt;&lt;li&gt;IAimsunNetwork&lt;/li&gt;&lt;li&gt;IAimsunScenario&lt;/li&gt;&lt;li&gt;IAimsunSignalControl&lt;/li&gt;&lt;/ul&gt;Anyone with some experienced with VISSIM COM might find the above a little familiar.&lt;br /&gt;&lt;br /&gt;That is right. The idea is the same, i.e., to hide un-necessary class information and publish everything as interfaces and properties, while allowing the user to access the functionality using his favorite language, be it VB, Delphi, Java, .NET or whatever language that is COM-compliant.&lt;br /&gt;&lt;br /&gt;Another good manifestation of this idea is &lt;a href="http://edndoc.esri.com/arcobjects/8.3/"&gt;ArcGIS's ArcObjects&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;But be reminded that .NET(/C#) interop with Aimsun-COM is via COM-interop/P-Invoke, the internal mechanism is a little different from native COM language such as C++ or Delphi.&lt;br /&gt;&lt;br /&gt;After registration of new Aimsun COM server, the system Registry has the following added entry (Double click the figure to see):&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_k2DBn0WY4XM/SmMqTIppJOI/AAAAAAAAABA/ePehR8g3zAA/s1600-h/aimsunCOM.png"&gt;&lt;img style="MARGIN: 0pt 10px 10px 0pt; WIDTH: 421px; FLOAT: left; HEIGHT: 145px; CURSOR: pointer" id="BLOGGER_PHOTO_ID_5360174489729049826" border="0" alt="" src="http://3.bp.blogspot.com/_k2DBn0WY4XM/SmMqTIppJOI/AAAAAAAAABA/ePehR8g3zAA/s320/aimsunCOM.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;As you can see, this Aimsun COM server has a ProgID "angcomsvr.AimsunServer", and a GUID is {04B0631C-0A6A-49E6-AB17-845A31F79B74}. The default interface is IAimsunInstance.&lt;br /&gt;&lt;br /&gt;Keep this information in mind, because we are going to use it later with various examples.&lt;br /&gt;&lt;br /&gt;In the following days I will demo this Aimsun COM interface with Delphi, C# and MATLAB samples. And if I have time, I am also going to show the interaction of Aimsun COM with &lt;span style="FONT-STYLE: italic"&gt;Internet Explorer&lt;/span&gt;, and demonstrate some interesting (toy) web applications with it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-5162777668529067526?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/5162777668529067526/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2009/07/aimsun-com-interface-1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/5162777668529067526'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/5162777668529067526'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2009/07/aimsun-com-interface-1.html' title='Aimsun COM Interface (1)'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_k2DBn0WY4XM/SmMqTIppJOI/AAAAAAAAABA/ePehR8g3zAA/s72-c/aimsunCOM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-8972557078388846203</id><published>2009-07-18T12:56:00.005-04:00</published><updated>2009-07-19T18:16:04.572-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VISSIM'/><category scheme='http://www.blogger.com/atom/ns#' term='Script Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Signal Control'/><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><title type='text'>VISSIM Signal Control API:  Let's Talk about it</title><content type='html'>&lt;p&gt;&lt;span class="postbody"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-style: italic;"&gt;- This is a re-posted article from my previous one published at Blogline, with minor modifications.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span class="postbody"&gt;&lt;span style="font-size:85%;"&gt;Besides &lt;span style="color: rgb(255, 0, 0);"&gt;VAP&lt;/span&gt;, PTV provides &lt;span style="color: rgb(51, 102, 255);"&gt;&lt;em&gt;&lt;strong&gt;Signal Control APIs &lt;/strong&gt;&lt;/em&gt; &lt;/span&gt;for customized external signal control. To be sure, the Signal Control APIs provided by PTV include several header files and  C++ source files. These files contains a plethora of  information for any interested user to get some hint about the coding style and design patterns implemented in VISSIM simulator.&lt;br /&gt;&lt;br /&gt;After studying the source codes for a few days, I am having great fun to read through the APIs and really get a grasp of the intended ideas of PTV developer(s).  &lt;/span&gt;&lt;/span&gt;&lt;span class="postbody"&gt;&lt;span style="font-size:85%;"&gt;And,  I am willing to share some hints here. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;  &lt;/p&gt;&lt;hr /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 102, 255);"&gt;1. THE ORGNIZATION OF THE SIGNAL CONTROL API&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The Signal Control APIs includes the following C++ source file&lt;br /&gt;&lt;br /&gt;a. lsa_fehl.h/lsa_fehl.cpp: Utility functions showing various error messages are defined in these files; The messages information can be found from the string resource lsa_ra_e.rc&lt;br /&gt;b. lsa_puff.h/lsa_puff.cp : Core data structures, such as &lt;span style="color: rgb(255, 0, 0);"&gt;&lt;em&gt;&lt;strong&gt;T_DET, T_LSA_PUFFER&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;are defined here.&lt;br /&gt;c. lsa_rahm.h/lsa_rahm.cpp: These two files define some wrapper functions for sc_dll_functions. Mostly in German.&lt;br /&gt;d. lsapuffr.h : Defines various Macros to facilitate the interfacing of VISSIM and the external controller. e. sc_dll_functions.h/sc_dll_functions.cpp : Various functions are defined here to provide read-write access to detector, signal controller, routing information.&lt;br /&gt;f. sc_dll_main.h/sc_dll_main.cpp : the user mostly modifies the call back functions defined here to implement his control logic. This might involve calling the access functions defined in sc_dll_functions.h g. SC_Interface.h/SC_Interface.cpp : the interface functions that connect VISSIM and the controller are defined here.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 102, 255);"&gt;2. MAJOR DATA STRUCTURES &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The most important data structure is the sturct &lt;strong&gt;&lt;em&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;T_LSA_Puffer&lt;/span&gt;&lt;/em&gt;&lt;/strong&gt;. This encapsulate Signal Controller Number, and pointers to detectors list. This struct is the building block of a LINKED LIST that contains a list of T_LSA_Puffer.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 102, 255);"&gt;3. CONTROL FLOW &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;At the start of simulation, a LINKED LIST of T_LSA_Puffer will be constructed. The element of the linked list is individual T_LSA_Puffer, which corresponds to each individual signal controller, get initialized.&lt;br /&gt;&lt;br /&gt;During the simulation, at each controller updating step, through ControllerSetValue function, VISSIM transfers a LARGE NUMBER of data, identified by the MACROS, to the signal control dll. These data is stored two places, one place the those global variables defined in lsa_puff.cpp, the other place is the LINKED LIST of T_LSA_Puffer.&lt;br /&gt;&lt;br /&gt;It is important to NOTE, all the utility functions, and the functions defined in sc_dll_functions.h, are actually WRAPPER functions simply to facilitate the read-write of the LINKED LIST! THIS IS THE BEAUTY of the entire API package. I hope somebody can appreciate this like me.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Following this, VISSIM sequentially executes a few more call-back commands to get back the signal timing, specifically, with ControllerGetValue.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 102, 255);"&gt;4. BIG PICTURE &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The kernel of the Signal Control APIs is actually only two files , i.e., SC_interface.cpp/SC_interface.h. All the other files are wrappers that aim to organize and facilitate the signal timing calculation, read and write of various global variables.&lt;br /&gt;&lt;br /&gt;From these Signal Control APIs and the wrapper files, we can get a grasp of the coding style of VISSIM in general and also some hints of the underlying design patters.&lt;br /&gt;&lt;br /&gt;Overall, from the External Driver Module APIs as well as from this Signal Control APIs, it can be seen that, the philosophy of VISSM APIs is to use call back functions to expose data while the user have NO access to the internal of the program. This means, VISSIM doesn't EXPORT any functions that the user can call. All the user can to is to process the data and send back the data to VISSIM via callback again. This allows flexibility on the user side, as he can freely develop wrapper class on top of the data. But the entire process is totally transparent to VISSIM.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-8972557078388846203?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/8972557078388846203/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2009/07/vissim-signal-control-api-some-hints.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/8972557078388846203'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/8972557078388846203'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2009/07/vissim-signal-control-api-some-hints.html' title='VISSIM Signal Control API:  Let&apos;s Talk about it'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-4795524216716278910</id><published>2009-07-18T12:43:00.008-04:00</published><updated>2009-07-18T12:53:33.521-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Delphi'/><category scheme='http://www.blogger.com/atom/ns#' term='Aimsun API'/><title type='text'>Interfacing Aimsun API with Delphi</title><content type='html'>&lt;p&gt;Note this is a re-post of my previous article published in Blogline, with minor modifications.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;AIMSUN provides several interfacing mechnisms for advanced applications. Among these, AIMSUN APIs, formerly known as AIMSUN GETRAM Extensions, are widely used.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;In the AIMSUN APIs manual, these APIs functions are given in terms of C/C++, while illustrative examples are also in C/C++.&lt;/p&gt;  &lt;p&gt;I would like to mention that it is also possible to interfacing AIMSUN using Delphi (Object Pascal). &lt;/p&gt;  &lt;p&gt;And, most importantly, by using Delphi, you can not only happily enjoy the syntactically beautiful Pascal language, but also the powerful VCL framework, and the vast selections of Delphi components from Delphi community.&lt;br /&gt;For example, the great Indy component for Socket programming.&lt;/p&gt;  &lt;p&gt;&lt;br /&gt;The following shows a simple AIMSUN API example written in Delphi ---- this sample can be downloaded from my web:  &lt;a href="http://www.wupingxin.net/Downloads/AIMSUN_API_DELPHI.zip" target="_blank"&gt;http://www.wupingxin.net/Downloads/AIMSUN_API_DELPHI.zip&lt;/a&gt; , from which you can load the Delphi-generated Dll into your AIMSUN application.&lt;/p&gt;  &lt;p&gt;The key points are to be keep in mind:&lt;br /&gt;&lt;/p&gt;  &lt;p&gt;1. Use CDECL calling convention&lt;/p&gt;&lt;p&gt;2. Referencing a2kernelxxx.dll, where "xxx" is the version number.&lt;/p&gt;&lt;p&gt;3. Unlike C++, Delphi doesn't not do name mangling&lt;br /&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;library AAPI_DE;&lt;br /&gt;uses&lt;br /&gt;AKIProxie in 'AKIProxie.pas';&lt;br /&gt;{$R *.res}&lt;br /&gt;function AAPILoad:Integer; cdecl;&lt;br /&gt;begin&lt;br /&gt;AKIPrintString('LOAD AIMSUN EXTENSTION DLL FROM DELPHI!');&lt;br /&gt;Result := 0;&lt;br /&gt;end;&lt;/p&gt;  &lt;p&gt;function AAPIInit:Integer; cdecl;&lt;br /&gt;begin&lt;br /&gt;AKIPrintString('\tInit');&lt;br /&gt;Result := 0;&lt;br /&gt;end;&lt;/p&gt;  &lt;p&gt;function AAPIManage(time:Single; timeSta:Single; timTrans:Single; acicle:Single):Integer;cdecl;&lt;br /&gt;begin&lt;br /&gt;AKIPrintString('\tManage');&lt;br /&gt;Result := 0;&lt;br /&gt;end;&lt;/p&gt;  &lt;p&gt;function AAPIPostManage(time:Single; timeSta:Single; timTrans:Single; acicle:Single) :Integer;cdecl;&lt;br /&gt;begin&lt;br /&gt;AKIPrintString('\tPostManage');&lt;br /&gt;Result := 0;&lt;br /&gt;end;&lt;/p&gt;  &lt;p&gt;function AAPIFinish:Integer;cdecl;&lt;br /&gt;begin&lt;br /&gt;AKIPrintString('\tFinish');&lt;br /&gt;Result := 0;&lt;br /&gt;end;&lt;/p&gt;  &lt;p&gt;function AAPIUnLoad:Integer;cdecl;&lt;br /&gt;begin&lt;br /&gt;AKIPrintString('\tUnload');&lt;br /&gt;Result := 0;&lt;br /&gt;end;&lt;/p&gt;  &lt;p&gt;exports&lt;br /&gt;AAPILoad,&lt;br /&gt;AAPIInit,&lt;br /&gt;AAPIManage,&lt;br /&gt;AAPIPostManage,&lt;br /&gt;AAPIFinish,&lt;br /&gt;AAPIUnLoad;&lt;br /&gt;&lt;br /&gt;begin&lt;br /&gt;end.&lt;/p&gt;  &lt;p&gt;// Pascal unit of APKProxie.h in C/C++&lt;br /&gt;unit AKIProxie;&lt;br /&gt;interface&lt;br /&gt;function AKIPrintString(Str:PChar):Integer;cdecl;&lt;/p&gt;  implementation&lt;br /&gt;const&lt;br /&gt;AIMSUN_KERNEL_DLL = 'C:\Program Files\TSS-Transport Simulation Systems\AIMSUN NG v7.0\a2kernel7.dll';&lt;br /&gt;function AKIPrintString(Str:PChar):Integer;cdecl; external AIMSUN_KERNEL_DLL;&lt;br /&gt;end.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-4795524216716278910?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/4795524216716278910/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2009/07/interfacing-aimsun-api-with-delphi.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/4795524216716278910'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/4795524216716278910'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2009/07/interfacing-aimsun-api-with-delphi.html' title='Interfacing Aimsun API with Delphi'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-1855691162698447645</id><published>2009-07-18T11:58:00.004-04:00</published><updated>2009-07-18T12:54:02.498-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Script Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Aimsun'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Aimsun scripting: A different perspective</title><content type='html'>&lt;p&gt;Aimsun is an Object-Oriented  Framework and Unified Platform for Traffic Modeling.  There are three fundamental key words here, Number 1 -  &lt;span style="font-weight: bold; font-style: italic;"&gt;Object-Oriented&lt;/span&gt;, Number 2 &lt;span style="font-style: italic; font-weight: bold;"&gt;Framework&lt;/span&gt;, and Number 3 &lt;span style="font-weight: bold; font-style: italic;"&gt;Platform&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;I don't know if people really understand the meaning and significance of these three words, because sometimes I really feel saddened, or, humored that people tend to identify Aimsun with other ordinary traffic simulators.   Add to it that more often than not,  I am scared to discover so many publications from TRB with self-claimed success in establishing whatsoever "framework".&lt;br /&gt;&lt;/p&gt;&lt;p&gt;For sure these days "Platform", "Framework" such words are squandered and are more and more becoming hype terms.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;But believe me,  they do bear a true meaning with Aimsun.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;It is not the intention of this post to elaborate  on these which are going to be the various subjects of my future narrative.  &lt;/p&gt;&lt;p&gt;Today I would like to re-post an article of mine some time ago. It is about a different, maybe innovative perspective of using Aimsun scripting.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Aimsun has provide a plethora of programming interfaces for its users: Aimsun Simulator API, Aimsun SDK, Aimsun scripting, MicroSDK, Logistics SDK, you name it. These SDKs, together with Aimsun software and internal modeling,  constitute a very well designed and architected framework.  &lt;/p&gt;  &lt;p&gt;All these APIs, albeit having different focuses, have ONE in common, i.e., they MUST be invoked within Aimsun ( i.e., Aimsun SDK and Scripting), or called-back during run time (i.e.,  simulator API and MicroSDK). This means Aimsun cannot be used as a COM sever, and may not be invoked by external applications while accessing its kernel functionality.  &lt;/p&gt;&lt;p&gt;Well, it is only partially true.  First, Aimsun is cross-platform, it runs on Linux, MacOS, and Windows.  COM is a very much Windows specific technology, so it doesn't seem to make sense to dedicate Aimsun to a platform specific feature.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Second some the COM-like functionality can be achieved by using ANGApp class fully accessible by Python scripting. As a matter of fact, TSS makes Scripting a subset of Aimsun SDK, in terms of available functionalities.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Here,  in this post, I would like to point out the feasibility of using Python C API to access the Aimsun SDK functionalties through embedded scripting. Interested readers can immediately get the hints and develop creative solutions based on this idea.&lt;br /&gt;&lt;br /&gt;The following shows aa Python wrapper class that encapsulate some COM-like interfaces:&lt;br /&gt;&lt;br /&gt;from PyANGBasic import *&lt;br /&gt;from PyANGApp import *&lt;br /&gt;from PyANGAimsun import *&lt;br /&gt;from PyANGKernel import *&lt;br /&gt;from PyANGConsole import *&lt;br /&gt;&lt;br /&gt;__author__        = "Wuping Xin"&lt;br /&gt;__company__    = "Traffic Digger Innovative Inc."&lt;br /&gt;__copyright__   = "Copyright (c) No Rights Reserved"&lt;br /&gt;__license__        = "python"&lt;br /&gt;__version__       = "$1.0.0 $"&lt;br /&gt;__date__            = "$Date: 2009/07/15 11:57 $"&lt;br /&gt;&lt;br /&gt;class AimsunApp:&lt;br /&gt;  "Wrapper class of Aimsun ANGApp class for C++ application with Python C API"&lt;br /&gt;  def __init__(self, isCon = False):&lt;br /&gt;      self.angInstance  = None&lt;br /&gt;      self.simulator      = None&lt;br /&gt;      self.model            = None&lt;br /&gt;      self.angGui          = None&lt;br /&gt;      self.isConsole      = isCon&lt;br /&gt;  def initInstance(self):     &lt;br /&gt;     pass   &lt;/p&gt;  &lt;p&gt;   def freeInstance(self):&lt;br /&gt;      pass&lt;br /&gt; def openNetwork(self,filename):&lt;br /&gt;      pass &lt;br /&gt; def runInteractive(self):&lt;br /&gt;      self.angInstance.run()&lt;br /&gt; def __setModel(self):&lt;br /&gt;      self.model = self.angInstance.getModel()&lt;br /&gt;&lt;br /&gt; def initSimulator(self,repID,simMode = 0):&lt;br /&gt;      .......&lt;br /&gt; def runSingleStep(self):&lt;/p&gt;&lt;p&gt;        self. angInstance.processEvents()&lt;br /&gt;      self.simulator.simulationStep()&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;/strong&gt; &lt;br /&gt;Now, with this class ready, the following C++ code can call the class method from an external C++ application:&lt;br /&gt;&lt;br /&gt;  Py_Initialize();&lt;br /&gt;   ..........&lt;br /&gt;  pName       = PyString_FromString("aimsunpy_interface");&lt;br /&gt;  pModule = PyImport_Import(pName);&lt;br /&gt;  pDict             = PyModule_GetDict(pModule);&lt;br /&gt;&lt;br /&gt;  // Build the name of a callable class&lt;br /&gt;  pClass = PyDict_GetItemString(pDict, "AimsunApp");&lt;br /&gt;&lt;br /&gt;  // Create an instance of the class&lt;br /&gt;  if (PyCallable_Check(pClass))&lt;br /&gt;  {&lt;br /&gt;      pInstance = PyObject_CallObject(pClass, NULL);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  PyObject_CallMethod(pInstance, "initInstance", NULL);&lt;br /&gt;  PyObject_CallMethod(pInstance, "openNetwork","s","C:\\Test\\test.ang");&lt;br /&gt;  PyObject_CallMethod(pInstance, "initSimulator","i",346);&lt;br /&gt;  ..........&lt;/p&gt;  &lt;p&gt;&lt;br /&gt;&lt;/p&gt;  &lt;p&gt;&lt;u&gt;Now, an interesting and expensive (cost me a few hours to find out) lesson learned is that, when trying to load a C-Extension module, i.e., *.pyd file,  if the host program that embeds Python interpreter links with pythonxx_d.dll, then PyImport_Import will import the xxxx_d.pyd, even if the module's name is specified without "_d"!&lt;/u&gt;  &lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;A warning is in order.  This approach is dependent on Aimsun's Python embedded interpreter hence runtime performance is unavoidable.   But if that is not an issue, this approach would make it possible to integrate Aimsun with external applications, for example, MATLAB platform.&lt;br /&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-1855691162698447645?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/1855691162698447645/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2009/07/aimsun-scripting-different-perspective.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/1855691162698447645'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/1855691162698447645'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2009/07/aimsun-scripting-different-perspective.html' title='Aimsun scripting: A different perspective'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-4796629055728850124</id><published>2009-07-17T21:58:00.011-04:00</published><updated>2009-07-19T18:41:23.379-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Assembly'/><category scheme='http://www.blogger.com/atom/ns#' term='Aimsun'/><category scheme='http://www.blogger.com/atom/ns#' term='Debugging'/><title type='text'>Inside Aimsun ANGApp.close</title><content type='html'>Aimsun &lt;span style="font-style: italic; font-weight: bold;"&gt;ANGApp&lt;/span&gt; is a class available to python scripting. It is a very interesting class that TSS provides to its general users, and can be very powerful if the user really appreciates how it works.&lt;br /&gt;&lt;br /&gt;In the past a few days, I have been cleaning up my previous codes, while working on a project proposal that may require Aimsun micro + meso. And for some reason, one code snippet that has worked previously crashes on ANGApp.close ... ...&lt;br /&gt;&lt;br /&gt;This time I am pretty hesitant to write to TSS for help - though I am sure they are going to help, as always TSS is very kind and prompt in supporting their users - sometimes a little delay if they are busy. And for these couple of days, I know they are being working their tails off on the new release of Aimsun 6.1.0 - couldn't be more busier.&lt;br /&gt;&lt;br /&gt;So I decided not to bother them and find out myself.&lt;br /&gt;&lt;br /&gt;All rightee ......the question is, what is really going on inside ANGAPP.close()? And why there is a crash? Let's take a &lt;em&gt;partial&lt;/em&gt; look at the code segment:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt;OK, save the current state of ESI by pushing it to stack&lt;/span&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt;. This is a no brainer&lt;/span&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt;.&lt;/span&gt;&lt;br /&gt;.text:00B620E0 &lt;span style="color: rgb(51, 102, 255);"&gt;&lt;span style="font-weight: bold;"&gt;push&lt;/span&gt; esi&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt;Note, ECX always holds the "this" pointer for C++ class. So, after &lt;span style="color: rgb(255, 153, 0);"&gt;mov ESI, ECX&lt;/span&gt;, ESI stores the starting address of the current ANGApp instance&lt;/span&gt;&lt;br /&gt;.text:00B620E1 &lt;span style="color: rgb(51, 102, 255); font-weight: bold;"&gt;mov&lt;/span&gt; &lt;span style="color: rgb(51, 102, 255);"&gt;esi, ecx&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt;Now, since &lt;/span&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt;ESI+0&lt;/span&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt; is the starting address of the subject ANGApp instance, &lt;/span&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt;ESI + 8&lt;/span&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt; must be the address for some private member-variable, and by looking &lt;/span&gt;&lt;/span&gt;at the instruction at 00B620EA &lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt;, we can immediately get the hint that it must be&lt;/span&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt; the address for &lt;/span&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt;a GGui* pointer&lt;/span&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt; . Now, what about ESI + 4? Note the fact that ANGApp inherits from QObject, thus ESI+4 actually is the address for a protected pointer of type QObjectData. &lt;span style="font-weight: bold;"&gt;What about ESI+0xC? Hey, are you as curious as I am? That is a good question! That is actually the address for a pointer of type GKModel *.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt;Doh~!&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;.text:00B620E3 &lt;span style="color: rgb(102, 51, 255);"&gt;&lt;span style="font-weight: bold;"&gt;mov&lt;/span&gt; ecx, [esi+8]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt;IS the GGui* NULL?&lt;/span&gt;&lt;br /&gt;.text:00B620E6 &lt;span style="color: rgb(51, 102, 255);"&gt;&lt;span style="font-weight: bold;"&gt;test&lt;/span&gt; ecx, ecx&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;.text:00B620E8&lt;span style="color: rgb(102, 51, 255); font-weight: bold;"&gt; jz short &lt;/span&gt;&lt;span style="color: rgb(102, 51, 255);"&gt;loc_B620FC&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt;If the GGui* is not NULL then call GGui.getActiveModel&lt;/span&gt;&lt;br /&gt;.text:00B620EA &lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 102, 255);"&gt;&lt;span style="font-weight: bold;"&gt;call &lt;/span&gt;ds:__imp_?getActiveModel@GGui@@QBEPAVGKModel@@XZ ;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;.text:00B620F0 &lt;span style="color: rgb(51, 102, 255);"&gt;&lt;span style="font-weight: bold;"&gt;mov&lt;/span&gt; ecx, [esi+8]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt;Now after invoking GGui.getActiveModel, EAX holds the returned pointer for GKModel&lt;/span&gt;&lt;br /&gt;.text:00B620F3 &lt;span style="color: rgb(51, 102, 255);"&gt;&lt;span style="font-weight: bold;"&gt;push&lt;/span&gt; eax&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt;Then GGui.closeDocument is called with the returned GKModel pointer from above instruction&lt;/span&gt;&lt;br /&gt;.text:00B620F4 &lt;span style="color: rgb(51, 102, 255);"&gt;&lt;span style="font-weight: bold;"&gt;call&lt;/span&gt; ds:__imp_?closeDocument@GGui@@QAE_NPAVGKModel@@@Z&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt;Okaydokay. So far so good! Now restore ESI&lt;/span&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt;.&lt;/span&gt;&lt;br /&gt;.text:00B620FA &lt;span style="color: rgb(102, 51, 255);"&gt;&lt;span style="font-weight: bold;"&gt;pop&lt;/span&gt; esi&lt;/span&gt;&lt;br /&gt;.text:00B620FB &lt;span style="color: rgb(51, 51, 255); font-weight: bold;"&gt;retn&lt;/span&gt;&lt;br /&gt;.text:00B620FC ; ---------------------------------------------------------------------------&lt;br /&gt;.text:00B620FC&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.text:00B620FC loc_B620FC:&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt;[ESI + 0xC] is the address that holds the pointer of type GKModel* &lt;/span&gt;&lt;br /&gt;.text:00B620FC &lt;span style="color: rgb(102, 51, 255); font-weight: bold;"&gt;mov &lt;/span&gt;&lt;span style="color: rgb(102, 51, 255);"&gt;ecx, [esi+0Ch]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt;Now ECX holds the pointer to GKModel&lt;/span&gt;&lt;br /&gt;.text:00B620FF &lt;span style="color: rgb(102, 51, 255); font-weight: bold;"&gt;test &lt;/span&gt;&lt;span style="color: rgb(102, 51, 255);"&gt;ecx, ecx&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.text:00B62101&lt;span style="color: rgb(102, 51, 255); font-weight: bold;"&gt; jz short&lt;/span&gt;&lt;span style="color: rgb(102, 51, 255);"&gt; loc_B62112&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt;Here is the tricky part. [ECX +0] is the address of the v-table of GKModel class&lt;/span&gt;&lt;br /&gt;.text:00B62103 &lt;span style="color: rgb(51, 51, 255); font-weight: bold;"&gt;mov eax, [ecx]&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt;Now EDX stores the address of the v-table of GKModel class&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;.text:00B62105 &lt;span style="color: rgb(51, 51, 255); font-weight: bold;"&gt;mov edx, [eax]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt;Index 1 means the first virtual function in the v-table. Note, GKModel inherits from GKObject. Therefore, the first virtual function in the v-table is the destructor ~GKObject()&lt;/span&gt;&lt;br /&gt;.text:00B62107&lt;span style="font-weight: bold;"&gt; &lt;/span&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;"&gt;push 1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt;Now call the destructor&lt;/span&gt;&lt;br /&gt;.text:00B62109 &lt;span style="color: rgb(51, 102, 255); font-weight: bold;"&gt;call edx&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 153, 153);"&gt;Reset the GKModel* pointer to zero.&lt;/span&gt;&lt;br /&gt;.text:00B6210B&lt;span style="color: rgb(51, 102, 255); font-weight: bold;"&gt; mov dword ptr [esi+0Ch], 0&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This is perfect code logically showing no problem at all! And it turns out that the crash was caused by a corrupted memoy I artificially manipulated which screw up ANGApp's initernal data!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-4796629055728850124?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/4796629055728850124/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2009/07/inside-aimsun-angappclose.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/4796629055728850124'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/4796629055728850124'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2009/07/inside-aimsun-angappclose.html' title='Inside Aimsun ANGApp.close'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6243160301039941892.post-181941580616927276</id><published>2009-07-11T14:35:00.003-04:00</published><updated>2009-07-18T11:58:22.122-04:00</updated><title type='text'>Moving from Blogline</title><content type='html'>I decided to move  my blog from Blogline to Blogspot ... ...&lt;br /&gt;&lt;br /&gt;This blog will mostly document anything interesting and fun, while I am doing my work, research or daydreaming -- the subjects include but not limited to:  traffic simulation modeling,  programming, and reverse engineering ... ...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6243160301039941892-181941580616927276?l=wupingxin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wupingxin.blogspot.com/feeds/181941580616927276/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wupingxin.blogspot.com/2009/07/moving-from-blogline.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/181941580616927276'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6243160301039941892/posts/default/181941580616927276'/><link rel='alternate' type='text/html' href='http://wupingxin.blogspot.com/2009/07/moving-from-blogline.html' title='Moving from Blogline'/><author><name>W. XIN</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
