﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-致开</title><link>http://www.cppblog.com/xiaxili/</link><description /><language>zh-cn</language><lastBuildDate>Wed, 08 Apr 2026 04:29:23 GMT</lastBuildDate><pubDate>Wed, 08 Apr 2026 04:29:23 GMT</pubDate><ttl>60</ttl><item><title>C++ Common knowledge base</title><link>http://www.cppblog.com/xiaxili/archive/2009/01/04/71140.html</link><dc:creator>Xiaxi</dc:creator><author>Xiaxi</author><pubDate>Sun, 04 Jan 2009 08:42:00 GMT</pubDate><guid>http://www.cppblog.com/xiaxili/archive/2009/01/04/71140.html</guid><wfw:comment>http://www.cppblog.com/xiaxili/comments/71140.html</wfw:comment><comments>http://www.cppblog.com/xiaxili/archive/2009/01/04/71140.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/xiaxili/comments/commentRss/71140.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xiaxili/services/trackbacks/71140.html</trackback:ping><description><![CDATA[1. Derived classes use the function name to hide the function with the same names in Parent class. This is declared by C++ Language Specification. Actually this is not a good design, so we should try to prevent this happen in our design.<br><br>2. Override your "new" operator for your class if necessary. And keep in mind that the overrided "new" operation applies for whole inheritance tree.<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;X<br>{<br></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br>&nbsp;&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">operator</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">(size_t&nbsp;sz);&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">allocate&nbsp;sz&nbsp;bytes</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;&nbsp;</span><span style="color: #0000ff;">operator</span><span style="color: #000000;">&nbsp;delete(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;p)&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">free&nbsp;p;</span><span style="color: #008000;"><br></span><span style="color: #000000;">};</span></div>
<br>3. Inheritance talk. <br>As we know, you can call the child method through your base class or reference. But you could not call the child method through your base object even this method is overridden in your child class.<br>Say we have such a piece of code:<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Base<br>{<br></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">virtual</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;Display(){<br>&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">"</span><span style="color: #000000;">base</span><span style="color: #000000;">"</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">endl;}<br>};<br><br></span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Derived&nbsp;:&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;Base<br>{<br></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">virtual</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;Display(){<br>&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">"</span><span style="color: #000000;">derived</span><span style="color: #000000;">"</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">endl;};<br>};<br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;_tmain(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;argc,&nbsp;_TCHAR</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;argv[])<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;Base&nbsp;ba;<br>&nbsp;&nbsp;&nbsp;&nbsp;Derived&nbsp;de;<br>&nbsp;&nbsp;&nbsp;&nbsp;ba&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;de;<br>&nbsp;&nbsp;&nbsp;&nbsp;ba.Display();<br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;Base&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;pba&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">de;<br>&nbsp;&nbsp;&nbsp;&nbsp;pba</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">Display();<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br>}</span></div>
Many persons wonder this phenomenon and has a lot of questions. But if you take a look at the assembly code, you can get it clear.<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008000;">//</span><span style="color: #008000;">Base::Display&nbsp;actually&nbsp;is&nbsp;a&nbsp;global&nbsp;function.&nbsp;<br></span><span style="color: #008000;">//</span><span style="color: #008000;">In&nbsp;Compiling&nbsp;phase,&nbsp;this&nbsp;piece&nbsp;of&nbsp;calling&nbsp;will&nbsp;be&nbsp;regarded&nbsp;as&nbsp;calling&nbsp;the&nbsp;global&nbsp;function.</span><span style="color: #008000;"><br></span><span style="color: #000000;">ba.Display();<br>0041155A&nbsp;&nbsp;lea&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ecx,[ba]&nbsp;<br>0041155D&nbsp;&nbsp;call&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Base::Display&nbsp;(411140h)&nbsp;<br><br></span><span style="color: #008000;">//</span><span style="color: #008000;">As&nbsp;we&nbsp;know,&nbsp;the&nbsp;virtual&nbsp;methods&nbsp;in&nbsp;C++&nbsp;are&nbsp;implemented&nbsp;by&nbsp;virtual&nbsp;table.&nbsp;<br></span><span style="color: #008000;">//</span><span style="color: #008000;">So&nbsp;this&nbsp;calling&nbsp;will&nbsp;be&nbsp;happen&nbsp;in&nbsp;execution&nbsp;time,&nbsp;which&nbsp;finds&nbsp;the&nbsp;correct&nbsp;method.</span><span style="color: #008000;"><br></span><span style="color: #000000;">pba</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">Display();<br></span><span style="color: #000000;">00411568</span><span style="color: #000000;">&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eax,dword&nbsp;ptr&nbsp;[pba]&nbsp;<br>0041156B&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;edx,dword&nbsp;ptr&nbsp;[eax]&nbsp;<br>0041156D&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;esi,esp&nbsp;<br>0041156F&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ecx,dword&nbsp;ptr&nbsp;[pba]&nbsp;<br></span><span style="color: #000000;">00411572</span><span style="color: #000000;">&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eax,dword&nbsp;ptr&nbsp;[edx]&nbsp;<br></span><span style="color: #000000;">00411574</span><span style="color: #000000;">&nbsp;&nbsp;call&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eax&nbsp;&nbsp;<br></span><span style="color: #000000;">00411576</span><span style="color: #000000;">&nbsp;&nbsp;cmp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;esi,esp&nbsp;<br></span><span style="color: #000000;">00411578</span><span style="color: #000000;">&nbsp;&nbsp;call&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@ILT</span><span style="color: #000000;">+</span><span style="color: #000000;">455</span><span style="color: #000000;">(__RTC_CheckEsp)&nbsp;(4111CCh)&nbsp;</span></div>
<br><br><img src ="http://www.cppblog.com/xiaxili/aggbug/71140.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xiaxili/" target="_blank">Xiaxi</a> 2009-01-04 16:42 <a href="http://www.cppblog.com/xiaxili/archive/2009/01/04/71140.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Concurrency Programming - Write your own ReaderLock and WriterLock</title><link>http://www.cppblog.com/xiaxili/archive/2008/12/30/70801.html</link><dc:creator>Xiaxi</dc:creator><author>Xiaxi</author><pubDate>Tue, 30 Dec 2008 13:34:00 GMT</pubDate><guid>http://www.cppblog.com/xiaxili/archive/2008/12/30/70801.html</guid><wfw:comment>http://www.cppblog.com/xiaxili/comments/70801.html</wfw:comment><comments>http://www.cppblog.com/xiaxili/archive/2008/12/30/70801.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/xiaxili/comments/commentRss/70801.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xiaxili/services/trackbacks/70801.html</trackback:ping><description><![CDATA[This article is based on the previous articles, since we'll use the mutex and semaphore in our class. This artical will mainly be consisted by the C++ code, not too many words. <br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">windows.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br><br></span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Lock<br>{<br></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br>&nbsp;&nbsp;&nbsp;&nbsp;Lock()<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hMutex&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;CreateMutex(NULL,&nbsp;</span><span style="color: #0000ff;">false</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">OWNLOCK</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hSemaphore&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;CreateSemaphore(NULL,&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">OWNSEMAPHORE</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iReaderCount&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;AcquireReadLock()<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WaitForSingleObject(hMutex,&nbsp;INFINITE);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(</span><span style="color: #000000;">++</span><span style="color: #000000;">iReaderCount&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WaitForSingleObject(hSemaphore,&nbsp;INFINITE);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ReleaseMutex(hMutex);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;ReleaseReadLock()<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WaitForSingleObject(hMutex,&nbsp;INFINITE);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(</span><span style="color: #000000;">--</span><span style="color: #000000;">iReaderCount&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ReleaseSemaphore(hSemaphore,&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">,&nbsp;NULL);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ReleaseMutex(hMutex);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;AcquireWriteLock()<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WaitForSingleObject(hSemaphore,&nbsp;INFINITE);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;ReleaseWriteLock()<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ReleaseSemaphore(hSemaphore,&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">,&nbsp;NULL);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="color: #0000ff;">private</span><span style="color: #000000;">:<br>&nbsp;&nbsp;&nbsp;&nbsp;HANDLE&nbsp;hMutex;<br>&nbsp;&nbsp;&nbsp;&nbsp;HANDLE&nbsp;hSemophore;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;iReaderCount;<br>};</span></div>
<br>Regarding when to use the lock, I'm saying that if the data is shared between threads, any access to this piece of data should be protected, locked. Also using the right type of lock is also necessary, otherwise it will be the bottleneck of your application.<br><br>Another issue is that at which granularity to add the lock. My suggestion is that don't add too many locks at one time, which will cause hard to locate the problems if it happens. You should at as few locks as possiable at one time.<br><br><img src ="http://www.cppblog.com/xiaxili/aggbug/70801.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xiaxili/" target="_blank">Xiaxi</a> 2008-12-30 21:34 <a href="http://www.cppblog.com/xiaxili/archive/2008/12/30/70801.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Win 32 Mulit-Thread Synchronous</title><link>http://www.cppblog.com/xiaxili/archive/2008/12/28/70590.html</link><dc:creator>Xiaxi</dc:creator><author>Xiaxi</author><pubDate>Sun, 28 Dec 2008 14:27:00 GMT</pubDate><guid>http://www.cppblog.com/xiaxili/archive/2008/12/28/70590.html</guid><wfw:comment>http://www.cppblog.com/xiaxili/comments/70590.html</wfw:comment><comments>http://www.cppblog.com/xiaxili/archive/2008/12/28/70590.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/xiaxili/comments/commentRss/70590.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xiaxili/services/trackbacks/70590.html</trackback:ping><description><![CDATA[At current few applications still use the Single-Thread model. Every application benefits a lot from the multi-threads model: quick UI response, concurrent workflow, etc. But there is a concern that if you could not master the multi-thread well, it would be your nightmare.<br><br>In this article, I'll give some introductions to the common sychronous skills that we used in Win32. <br><br><span style="font-weight: bold;">1. CRITICAL_SECTION</span><br>CRITICAL_SECTION is used to protect your resources. Here the resource includes the memory blocks, files, data structures, etc. <br>One mind is that CRITICAL_SECTION is not the kernel object. So the cost of using it is less that the mutex kernel object. I think at most cases we should prefer to this choice if you don't want to syschrous between the multiple processes.<br>So here is the steps that you can use it.
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008000;">//</span><span style="color: #008000;">1.&nbsp;declare&nbsp;a&nbsp;critical_section&nbsp;object</span><span style="color: #008000;"><br></span><span style="color: #000000;">CRITICAL_SECTION&nbsp;cs;<br><br></span><span style="color: #008000;">//</span><span style="color: #008000;">2.&nbsp;initialize&nbsp;it&nbsp;before&nbsp;use.</span><span style="color: #008000;"><br></span><span style="color: #000000;">InitializeCriticalSection(</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">cs);<br><br></span><span style="color: #008000;">//</span><span style="color: #008000;">3.&nbsp;try&nbsp;to&nbsp;enter&nbsp;into&nbsp;the&nbsp;critical&nbsp;section<br></span><span style="color: #008000;">//</span><span style="color: #008000;">if&nbsp;success,&nbsp;this&nbsp;function&nbsp;will&nbsp;return.&nbsp;Otherwise,&nbsp;the&nbsp;calling&nbsp;thread&nbsp;will&nbsp;be&nbsp;forced&nbsp;to&nbsp;sleep.</span><span style="color: #008000;"><br></span><span style="color: #000000;">EnterCriticalSection(</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">cs);<br><br></span><span style="color: #008000;">//</span><span style="color: #008000;">do&nbsp;some&nbsp;stuff<br><br></span><span style="color: #008000;">//</span><span style="color: #008000;">4.&nbsp;leave&nbsp;the&nbsp;critical_section</span><span style="color: #008000;"><br></span><span style="color: #000000;">LeaveCriticalSection(</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">cs);<br><br></span><span style="color: #008000;">//</span><span style="color: #008000;">5.&nbsp;if&nbsp;not&nbsp;used&nbsp;any&nbsp;more,&nbsp;delete&nbsp;it.</span><span style="color: #008000;"><br></span><span style="color: #000000;">DeleteCriticalSection(</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">cs);</span></div>
<br>One point is that the thread can enter into the critical_section several times after it already enter into it. The only thing that you should be aware of is that you should call the LeaveCriticalSection() same times as calling the EnterCriticalSection.<br><br>Here are some suggestions about how to use the critical_section.<br>&nbsp;&nbsp; - Do not lock one resource for long time. This may cause other threads waiting and may lead to UI hang.<br>&nbsp;&nbsp; - Do not call the Sleep() or Wait...()&nbsp; during the critical_section.<br><br><span style="font-weight: bold;">2. Mutex</span>&nbsp; - Mutual Exclusion<br>Mutex is a kernel object and need the user-mode and kernel-mode switch if using it, which means a lot of cost are necessary. But there is a good poing is that you can use the Mutex between sereval processes, which the CRITICAL_SECTION could not provide this funcnality.<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008000;">//</span><span style="color: #008000;">1.&nbsp;Create&nbsp;a&nbsp;mutex&nbsp;using&nbsp;the&nbsp;Win32&nbsp;API<br></span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;&nbsp;&nbsp;you&nbsp;can&nbsp;also&nbsp;call&nbsp;OpenMutex()&nbsp;to&nbsp;open&nbsp;an&nbsp;existing&nbsp;mutex.</span><span style="color: #008000;"><br></span><span style="color: #000000;">HANDLE&nbsp;hMutex&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;CreateMutex(NULL,&nbsp;</span><span style="color: #0000ff;">true</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">MSCAR</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br><br></span><span style="color: #008000;">//</span><span style="color: #008000;">2.&nbsp;Lock&nbsp;the&nbsp;mutex<br></span><span style="color: #008000;">//</span><span style="color: #008000;">you&nbsp;can&nbsp;call&nbsp;WaitForMultipleObjects()&nbsp;if&nbsp;you&nbsp;want&nbsp;to&nbsp;lock&nbsp;several&nbsp;mutex</span><span style="color: #008000;"><br></span><span style="color: #000000;">HRESULT&nbsp;hr&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;WaitForSingleObject(hMutex,&nbsp;INFINITE);<br><br></span><span style="color: #008000;">//</span><span style="color: #008000;">3.&nbsp;got&nbsp;the&nbsp;lock&nbsp;and&nbsp;do&nbsp;something</span><span style="color: #008000;"><br></span><span style="color: #0000ff;">if</span><span style="color: #000000;">(hr&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;WAIT_OBJECT_0)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;"><img src="http://www.cppblog.com/Images/dot.gif"><img src="http://www.cppblog.com/Images/dot.gif"></span><span style="color: #008000;"><br></span><span style="color: #000000;">}<br></span><span style="color: #008000;">//</span><span style="color: #008000;">4.&nbsp;release&nbsp;the&nbsp;mutex.&nbsp;this&nbsp;can&nbsp;lead&nbsp;to&nbsp;other&nbsp;threads&nbsp;getting&nbsp;the&nbsp;mutex</span><span style="color: #008000;"><br></span><span style="color: #000000;">ReleaseMutex(hMutex)<br><br></span><span style="color: #008000;">//</span><span style="color: #008000;">5.&nbsp;Close&nbsp;the&nbsp;handle.&nbsp;This&nbsp;should&nbsp;not&nbsp;be&nbsp;forgotten&nbsp;otherwise&nbsp;lead&nbsp;to&nbsp;handle&nbsp;leak.</span><span style="color: #008000;"><br></span><span style="color: #000000;">CloseHandle(hMutex);</span></div>
&nbsp;<br><br><span style="font-weight: bold;">3. Semaphores</span><br>A lot of articles introduces several scenarios about how to use the semaphore, such like a buffer. So here I don't want to take too much. Just show the steps.<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008000;">//</span><span style="color: #008000;">create&nbsp;a&nbsp;semaphore,&nbsp;with&nbsp;the&nbsp;max_count&nbsp;set.</span><span style="color: #008000;"><br></span><span style="color: #000000;">HANDLE&nbsp;hSemaphore&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;CreateSemaphore(NULL,&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">COUNT</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br><br></span><span style="color: #008000;">//</span><span style="color: #008000;">the&nbsp;following&nbsp;is&nbsp;two&nbsp;threads&nbsp;running.<br></span><span style="color: #008000;">//</span><span style="color: #008000;">thread&nbsp;1</span><span style="color: #008000;"><br></span><span style="color: #000000;">{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">add&nbsp;some&nbsp;resource</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">long</span><span style="color: #000000;">&nbsp;lCount;<br>&nbsp;&nbsp;&nbsp;&nbsp;ReleaseSemaphore(hSemaphore,&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">lCount);<br>}<br><br><br></span><span style="color: #008000;">//</span><span style="color: #008000;">thread&nbsp;2</span><span style="color: #008000;"><br></span><span style="color: #000000;">{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">wait&nbsp;for&nbsp;resources.&nbsp;If&nbsp;resource&nbsp;is&nbsp;more&nbsp;than&nbsp;1,&nbsp;this&nbsp;thread&nbsp;will&nbsp;be&nbsp;wake&nbsp;up.</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;WaitForSingleThread(hSemaphore,&nbsp;INFINITE);<br>&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">do&nbsp;some&nbsp;handling<img src="http://www.cppblog.com/Images/dot.gif"></span><span style="color: #008000;"><br></span><span style="color: #000000;">}</span></div>
You may notice from the demo code that the thread 1 doesn't get the ownership of the semaphore, but calls the ReleaseSemaphore(). This is the difference betwen the mutex and semaphore. For semaphore, threads doesn't need to get the ownership to call the ReleaseSemaphore().<br><br>4. Events<br>Event is the most flexiable to use. Its only purpose is to become the singled or unsignled. For mutex kernel objects, it will become singled after the thread calls the Wait...() function and shortly return back to unsigned status. But for evetns, these two status will be controled by application. Application can set its status perfectly as it hopes.<br>There are also two types of events: Auto and Munual. Auto event means that this event will become unsignled automatically after this event becomes signled, which always some thread wakes up from sleep. Munual event means that the application needs to call ResetEvent() to set the event in unsigled status. I'll list the API here.<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008000;">//</span><span style="color: #008000;">Create&nbsp;the&nbsp;event&nbsp;</span><span style="color: #008000;"><br></span><span style="color: #000000;">HANDLE&nbsp;CreateEvent();<br><br></span><span style="color: #008000;">//</span><span style="color: #008000;">Set&nbsp;the&nbsp;event&nbsp;in&nbsp;singled&nbsp;status</span><span style="color: #008000;"><br></span><span style="color: #000000;">BOOL&nbsp;SetEvent();<br><br></span><span style="color: #008000;">//</span><span style="color: #008000;">set&nbsp;the&nbsp;event&nbsp;in&nbsp;unsingled&nbsp;status</span><span style="color: #008000;"><br></span><span style="color: #000000;">BOOL&nbsp;ResetEvent();<br><br></span></div>
<br><br><br><br><br><img src ="http://www.cppblog.com/xiaxili/aggbug/70590.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xiaxili/" target="_blank">Xiaxi</a> 2008-12-28 22:27 <a href="http://www.cppblog.com/xiaxili/archive/2008/12/28/70590.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Apartments in COM</title><link>http://www.cppblog.com/xiaxili/archive/2008/12/16/69605.html</link><dc:creator>Xiaxi</dc:creator><author>Xiaxi</author><pubDate>Tue, 16 Dec 2008 13:55:00 GMT</pubDate><guid>http://www.cppblog.com/xiaxili/archive/2008/12/16/69605.html</guid><wfw:comment>http://www.cppblog.com/xiaxili/comments/69605.html</wfw:comment><comments>http://www.cppblog.com/xiaxili/archive/2008/12/16/69605.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/xiaxili/comments/commentRss/69605.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xiaxili/services/trackbacks/69605.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Will COM die? At least I don't think so. Its idea is still widely used in software. <br><br>This article is going to explain a bit about the confusing concept about the Apartment, mainly focusing at the MTA and Neutral. Hope you can learn some from it.&nbsp;&nbsp;<a href='http://www.cppblog.com/xiaxili/archive/2008/12/16/69605.html'>阅读全文</a><img src ="http://www.cppblog.com/xiaxili/aggbug/69605.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xiaxili/" target="_blank">Xiaxi</a> 2008-12-16 21:55 <a href="http://www.cppblog.com/xiaxili/archive/2008/12/16/69605.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>STA in COM</title><link>http://www.cppblog.com/xiaxili/archive/2008/12/16/69560.html</link><dc:creator>Xiaxi</dc:creator><author>Xiaxi</author><pubDate>Tue, 16 Dec 2008 03:57:00 GMT</pubDate><guid>http://www.cppblog.com/xiaxili/archive/2008/12/16/69560.html</guid><wfw:comment>http://www.cppblog.com/xiaxili/comments/69560.html</wfw:comment><comments>http://www.cppblog.com/xiaxili/archive/2008/12/16/69560.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/xiaxili/comments/commentRss/69560.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xiaxili/services/trackbacks/69560.html</trackback:ping><description><![CDATA[COM now has five types of Apartment:<br>1. Legacy<br>2. STA<br>3. Free<br>4. Both<br>5. Neutral<br><br>I'll discuss the Apartment in this article.<br><br>COM Objects living in Apartment will be protected by COM, any other calls for this object will be serialized by the COM. If there are concurrent threading in your application and you also don't want to the complicated multi-thread concurrency, you may get to love the Apartment model.<br><br>Here are some points of the Apartment modle:<br>1. Each Single Apartment only contains one thread.<br>2. Each thread should call ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
to join the STA.<br>3. If&nbsp; you want to call the STA COM object living in other STA, you need to marshal your pointer.<br>4. Each STA may contain more than one COM objects.<br>5. At one time a STA allows only one thread running.<br><br>The code for COM object is simple. Here is I just list the code snippet for the client.<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">iostream</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">using</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">namespace</span><span style="color: #000000;">&nbsp;std;<br><br>#import&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">CarDemo.dll</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;no_namespace<br><br><br><br></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;ThreadFunc(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">);<br></span><span style="color: #008000;">//</span><span style="color: #008000;">IFreeCar&nbsp;*&nbsp;pCar;<br></span><span style="color: #008000;">//</span><span style="color: #008000;">IFreeCar&nbsp;*&nbsp;pCar;</span><span style="color: #008000;"><br></span><span style="color: #000000;">ICar&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;pCar;<br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;_tmain(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;argc,&nbsp;_TCHAR</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;argv[])<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;::CoInitializeEx(NULL,&nbsp;COINIT_MULTITHREADED);<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ICar&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;pCar;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;::CoCreateInstance(__uuidof(Car)&nbsp;,&nbsp;NULL,&nbsp;CLSCTX_INPROC_SERVER&nbsp;&nbsp;,&nbsp;__uuidof(ICar)&nbsp;,&nbsp;(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">**</span><span style="color: #000000;">)</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">pCar);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IStream</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;interfaceStream1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IStream</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;interfaceStream2;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CoMarshalInterThreadInterfaceInStream(__uuidof(ICar),&nbsp;pCar,&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">interfaceStream1);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CoMarshalInterThreadInterfaceInStream(__uuidof(ICar),&nbsp;pCar,&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">interfaceStream2);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HANDLE&nbsp;hThread[</span><span style="color: #000000;">2</span><span style="color: #000000;">];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hThread[</span><span style="color: #000000;">0</span><span style="color: #000000;">]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(HANDLE)::_beginthread(ThreadFunc,&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">,&nbsp;(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">*</span><span style="color: #000000;">)interfaceStream1);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hThread[</span><span style="color: #000000;">1</span><span style="color: #000000;">]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(HANDLE)::_beginthread(ThreadFunc,&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">,&nbsp;(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">*</span><span style="color: #000000;">)interfaceStream2);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;::WaitForMultipleObjects(</span><span style="color: #000000;">2</span><span style="color: #000000;">,&nbsp;hThread,&nbsp;</span><span style="color: #0000ff;">true</span><span style="color: #000000;">,&nbsp;INFINITE);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pCar</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">Release();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;iVal;<br>&nbsp;&nbsp;&nbsp;&nbsp;cin</span><span style="color: #000000;">&gt;&gt;</span><span style="color: #000000;">iVal;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;::CoUninitialize();<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br>}<br><br></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;ThreadFunc(LPVOID&nbsp;lpParameter)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;::CoInitializeEx(NULL,&nbsp;COINIT_APARTMENTTHREADED);<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IStream</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;pStream&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;reinterpret_cast</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">IStream</span><span style="color: #000000;">*&gt;</span><span style="color: #000000;">(lpParameter);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ICar&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;pCar;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CoGetInterfaceAndReleaseStream(pStream,&nbsp;__uuidof(ICar),&nbsp;reinterpret_cast</span><span style="color: #000000;">&lt;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">**&gt;</span><span style="color: #000000;">(</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">pCar));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pCar</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">Drive(</span><span style="color: #000000;">3</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pCar</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">Release();<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;::CoUninitialize();<br>}</span></div>
<br>Here is some helpful links for you to understand the STA better:<br>http://support.microsoft.com/default.aspx?scid=kb;en-us;172314
<br>http://support.microsoft.com/kb/206076
<br><br><br><br> <img src ="http://www.cppblog.com/xiaxili/aggbug/69560.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xiaxili/" target="_blank">Xiaxi</a> 2008-12-16 11:57 <a href="http://www.cppblog.com/xiaxili/archive/2008/12/16/69560.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>COM Stub and Proxy</title><link>http://www.cppblog.com/xiaxili/archive/2008/12/15/69533.html</link><dc:creator>Xiaxi</dc:creator><author>Xiaxi</author><pubDate>Mon, 15 Dec 2008 14:28:00 GMT</pubDate><guid>http://www.cppblog.com/xiaxili/archive/2008/12/15/69533.html</guid><wfw:comment>http://www.cppblog.com/xiaxili/comments/69533.html</wfw:comment><comments>http://www.cppblog.com/xiaxili/archive/2008/12/15/69533.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/xiaxili/comments/commentRss/69533.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xiaxili/services/trackbacks/69533.html</trackback:ping><description><![CDATA[In the following cases leads to the usage of the Stub and Proxy:<br>1. Call COM Interfaces living in other Apartments.<br>2. Call COM Interfaces living in an EXE Server.<br><br>Definition for Stub and Proxy:<br>&nbsp;- Proxy : A COM object loaded into the client's process, which packages up client requests for any out-of-process ( or out of apartment ) method invocation.<br>&nbsp;- Stub : A COM object loaded into the server's process, which receives the client's requests, unpackages them, and handles them off to the "real COM object."<br><br>Under the hoold, a procedure named "Marshaling" works between process, which includes the process of packing, sending, receiving and unpacking data between clients and servers, via Stubs and Proxies.<br><br><img src ="http://www.cppblog.com/xiaxili/aggbug/69533.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xiaxili/" target="_blank">Xiaxi</a> 2008-12-15 22:28 <a href="http://www.cppblog.com/xiaxili/archive/2008/12/15/69533.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>A simple C++/CLI code snippet</title><link>http://www.cppblog.com/xiaxili/archive/2008/12/15/69501.html</link><dc:creator>Xiaxi</dc:creator><author>Xiaxi</author><pubDate>Mon, 15 Dec 2008 08:31:00 GMT</pubDate><guid>http://www.cppblog.com/xiaxili/archive/2008/12/15/69501.html</guid><wfw:comment>http://www.cppblog.com/xiaxili/comments/69501.html</wfw:comment><comments>http://www.cppblog.com/xiaxili/archive/2008/12/15/69501.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/xiaxili/comments/commentRss/69501.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xiaxili/services/trackbacks/69501.html</trackback:ping><description><![CDATA[In my current project, i need to search out the GUIDs from some certain strings. This is a difficult job if you want to written with the tradition C++. But with C++/CLI, we can benefit from the powerful .NET library. I have to admit that mixing the C++/CLI code with the C++ code is a bit confusing.<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">stdafx.h</span><span style="color: #000000;">"</span><span style="color: #000000;"><br><br>#</span><span style="color: #0000ff;">using</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">system.dll</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>#</span><span style="color: #0000ff;">using</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">system.data.dll</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">using</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">namespace</span><span style="color: #000000;">&nbsp;System;<br></span><span style="color: #0000ff;">using</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">namespace</span><span style="color: #000000;">&nbsp;System::Text::RegularExpressions;<br></span><span style="color: #0000ff;">using</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">namespace</span><span style="color: #000000;">&nbsp;System::Runtime::InteropServices;<br><br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;_tmain(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;argc,&nbsp;_TCHAR</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;argv[])<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;</span><span style="color: #000000;">^</span><span style="color: #000000;">&nbsp;sDelivDataXML&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">gp:GUID=\</span><span style="color: #000000;">"</span><span style="color: #000000;">7F57069D</span><span style="color: #000000;">-</span><span style="color: #000000;">DD5C</span><span style="color: #000000;">-</span><span style="color: #000000;">48E9</span><span style="color: #000000;">-</span><span style="color: #000000;">B746</span><span style="color: #000000;">-</span><span style="color: #000000;">6FAFF0271B9A\</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;gp:Included=\</span><span style="color: #000000;">"</span><span style="color: #0000ff;">true</span><span style="color: #000000;">\</span><span style="color: #000000;">"</span><span style="color: #000000;">gp:Component&nbsp;gp:GUID=\</span><span style="color: #000000;">"</span><span style="color: #000000;">02023E2A</span><span style="color: #000000;">-</span><span style="color: #000000;">A4ED</span><span style="color: #000000;">-</span><span style="color: #000000;">45B8</span><span style="color: #000000;">-</span><span style="color: #000000;">9900</span><span style="color: #000000;">-</span><span style="color: #000000;">D3A144F09C82\</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br>&nbsp;&nbsp;&nbsp;&nbsp;String</span><span style="color: #000000;">^</span><span style="color: #000000;">&nbsp;pat&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br>&nbsp;&nbsp;&nbsp;&nbsp;Regex</span><span style="color: #000000;">^</span><span style="color: #000000;">&nbsp;r&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;gcnew&nbsp;Regex(&nbsp;pat,RegexOptions::Compiled);<br>&nbsp;&nbsp;&nbsp;&nbsp;Match</span><span style="color: #000000;">^</span><span style="color: #000000;">&nbsp;m&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;r</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">Match(sDelivDataXML);<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;matchCount&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(&nbsp;m</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">Success&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console::WriteLine(&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">{0}</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;m</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">Value&nbsp;);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;m</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">NextMatch();<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br>}</span></div>
<br>I will not cover the grama or any other knowledge of C++/CLI or the regular expression in this article. If you have any questions about the String^ or how to write the regular expression, just google it. <br><br>The Output :<br><span style="font-weight: bold;">7F57069D-DD5C-48E9-B746-6FAFF0271B9A</span><br style="font-weight: bold;"><span style="font-weight: bold;">02023E2A-A4ED-45B8-9900-D3A144F09C82</span><br><br>ok, enjoy it!<br><br><br><img src ="http://www.cppblog.com/xiaxili/aggbug/69501.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xiaxili/" target="_blank">Xiaxi</a> 2008-12-15 16:31 <a href="http://www.cppblog.com/xiaxili/archive/2008/12/15/69501.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Add C++/CLI support in your legacy code</title><link>http://www.cppblog.com/xiaxili/archive/2008/12/15/69479.html</link><dc:creator>Xiaxi</dc:creator><author>Xiaxi</author><pubDate>Mon, 15 Dec 2008 03:50:00 GMT</pubDate><guid>http://www.cppblog.com/xiaxili/archive/2008/12/15/69479.html</guid><wfw:comment>http://www.cppblog.com/xiaxili/comments/69479.html</wfw:comment><comments>http://www.cppblog.com/xiaxili/archive/2008/12/15/69479.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/xiaxili/comments/commentRss/69479.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xiaxili/services/trackbacks/69479.html</trackback:ping><description><![CDATA[Just now I'm maintaining an old piece of code, written in C++. And now i&nbsp; just want to search out some special strings following special pattern, and it seems that there is no good way that the tradition c++ way. So since now the .net is growing almost 7 years old and the c++/cli is coming mature, i decide to take advantage of the .net powerful functionality.<br><br>Steps are simple, not very complicated.<br>Here is the steps.<br>1. Add the header file (.h). <br>2. Add the body file (.cpp). Include the header file in the body file.<br>3. Pop-up the Property page for the body file. Property-&gt;C/C++-&gt;General-&gt;<span style="font-weight: bold;">Compile with common language support : common language runtime support</span><br>4. If your project is vc++ and uses the precompiled header, go to Property-&gt;C/C++-&gt;<span style="font-weight: bold;">Precompiled Headers-&gt;Create/Use Precompiled Header : Not using precompiled header.</span><br>5. You also needs to set Property-&gt;C/C++-&gt;<span style="font-weight: bold;">Enable C++ Exception : Yes with SEH Exceptions(/EHa)</span><br><br>ok, now go to rebuild your project and it will works!<br><br>Enjoy the power of the .NET!<br><br><img src ="http://www.cppblog.com/xiaxili/aggbug/69479.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xiaxili/" target="_blank">Xiaxi</a> 2008-12-15 11:50 <a href="http://www.cppblog.com/xiaxili/archive/2008/12/15/69479.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>正确的使用CComSafeArray,CComVariant和CComBSTR</title><link>http://www.cppblog.com/xiaxili/archive/2008/07/17/56466.html</link><dc:creator>Xiaxi</dc:creator><author>Xiaxi</author><pubDate>Thu, 17 Jul 2008 13:10:00 GMT</pubDate><guid>http://www.cppblog.com/xiaxili/archive/2008/07/17/56466.html</guid><wfw:comment>http://www.cppblog.com/xiaxili/comments/56466.html</wfw:comment><comments>http://www.cppblog.com/xiaxili/archive/2008/07/17/56466.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/xiaxili/comments/commentRss/56466.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xiaxili/services/trackbacks/56466.html</trackback:ping><description><![CDATA[如果你用C++来编写COM，那么你将必不可少的使用这三个类型。使用这三种wrapper class毫无疑问会简化我们的编程，使得使用SAFEARRAY, VARIANT和BSTR简单。但是，使用这三个类型依然需要小心，因为使用不当的话，就会造成内存泄漏，或效率降低。<br><br>1. 如果拷贝两个BSTR<br>假如我们一个BSTR，这个时候我希望复制一份BSTR，并丢弃之前的BSTR。通常我们会这么写：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">CComBSTR&nbsp;StringToBSTR(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">&nbsp;sVal)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CComBSTR&nbsp;bstrValue&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;sVal.data();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;bstrValue;<br>}<br><br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CComBSTR&nbsp;vValue&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;StringToBSTR(</span><span style="color: #000000;">"</span><span style="color: #000000;">value</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br>}</span></div>
<br>当然，上面这个程序没有任何问题，不会有任何内存泄漏的可能。但是，你有没有上面代码里都发生了什么了？<br>答案很简单，在函数StringToBSTR里面，讲bstrValue返回的时候，会调用CComBSTR::Copy()，在Copy()里面将会调用<br>&nbsp;::SysAllocStringByteLen()<br>这个函数。而后在给vValue赋值的时候，又 会调用一次<br>::SysAllocString()<br>显而易见，开销很大。<br><br>那么，我们将怎么改进这段代码了？<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">BSTR&nbsp;StringToBSTR(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">&nbsp;sVal)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CComBSTR&nbsp;bstrValue&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;sVal.data();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;bstrValue.Detach();<br>}<br><br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CComBSTR&nbsp;vValue.Attach(StringToBSTR(</span><span style="color: #000000;">"</span><span style="color: #000000;">value</span><span style="color: #000000;">"</span><span style="color: #000000;">));<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br>}</span></div>
这样，通过CComBSTR::Detach()，我们将BSTR返回回来，通过CComBSTR::Attach()，我们将BSTR指针存储起来。这样，就减小了两次开销，大大提高了效率，也不会造成内存效率。<br><br>2. 如何使用CComSafeArray<br>使用CComSafeArray的一个最大的好处，就是它会自动释放元素是VARIANT和BSTR。也就是说，如果你的类型是VARIANT，它会自动调用::VariantClear()。如果你的类型是BSTR，他会自动调用::SysStringFree()方法。但是使用它的时候，同样要小心。<br>2.1 成对使用::SafeArrayAccessData()和::SafeArrayUnaccessData()<br>我们有时候会这样使用CComSafeArray的元素：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;DoSomething()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CComSafeArray</span><span style="color: #000000;">&lt;</span><span style="color: #0000ff;">double</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;pSafeArray(</span><span style="color: #000000;">3</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">double</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;pVal&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;NULL;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;::SafeArrayAccessData(pSafeArray</span><span style="color: #000000;">.</span><span style="color: #000000;">m_psa,&nbsp;(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">**</span><span style="color: #000000;">)</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">pVal);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">handle&nbsp;the&nbsp;elements&nbsp;through&nbsp;the&nbsp;pVal;</span><span style="color: #008000;"><br></span><span style="color: #000000;">}</span></div>
因为::SafeArrayAccessData
方法会在SFAEARRAY上给lock加1. 如果上面程序显示调用CComSafeArray::Destroy()函数，你检查它返回来的HRESULT的时候，应该是下面的值：<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; hr&nbsp;&nbsp; &nbsp;0x8002000d 内存已锁定。 &nbsp;&nbsp; &nbsp;HRESULT<br>如果你不仔细检查，那么将造成CComSafeArray没有释放。<br>2.2 从CComSafeArray转为成CComVariant<br>有时候我们使用CComVariant包装SAFEARRY。你会这样写代码：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;DoSomething()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CComSafeArray</span><span style="color: #000000;">&lt;</span><span style="color: #0000ff;">double</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;pSafeArray(</span><span style="color: #000000;">3</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">fill&nbsp;the&nbsp;safearray</span><span style="color: #008000;"><br></span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CComVariant&nbsp;v&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;pSafeArray.Detach();<br>}</span></div>
你可能会任务CComVariant会存储pSafeArray的指针。可惜，你错了。<br>CComVariant会调用::SafeArrayCopy
来完成赋值操作。而你的pSafeArray已经调用了Detach()操作，那么它里面的SAFEARRAY就变成了孤儿，没有人去释放它了。<br>那么你应该怎么写了？<br>你可以这么写：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;DoSomething()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CComSafeArray</span><span style="color: #000000;">&lt;</span><span style="color: #0000ff;">double</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;pSafeArray(</span><span style="color: #000000;">3</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">fill&nbsp;the&nbsp;safearray</span><span style="color: #008000;"><br></span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CComVariant&nbsp;v&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;pSafeArray.m_psa;<br>}</span></div>
这样，CComVariant会调用::SafeArrayCopy
来完成复制操作，而CComSafeArray也会保证在析构的时候释放里面的SAFEARRAY。<br><br>使用上面三个wrapper类，确实可以很方便我们编程，也能避免很多memory leak。但是，使用他们同样要小心，不然，同样会造成性能损失，或者，更糟糕的，内存泄漏。<br>
<br><br><img src ="http://www.cppblog.com/xiaxili/aggbug/56466.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xiaxili/" target="_blank">Xiaxi</a> 2008-07-17 21:10 <a href="http://www.cppblog.com/xiaxili/archive/2008/07/17/56466.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>