Sophie

Sophie

distrib > Mandriva > 10.2 > i586 > media > contrib > by-pkgid > 7457b841ac8136d3a1a9d3d960c5252e > files > 1743

libcryptopp-doc-5.2.1-2mdk.i586.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>Crypto++: wait.cpp Source File</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.7 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="namespaces.html">Namespace List</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Class&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="namespacemembers.html">Namespace&nbsp;Members</a> | <a class="qindex" href="functions.html">Class&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>wait.cpp</h1><pre class="fragment"><div>00001 <span class="comment">// wait.cpp - written and placed in the public domain by Wei Dai</span>
00002 
00003 <span class="preprocessor">#include "pch.h"</span>
00004 <span class="preprocessor">#include "wait.h"</span>
00005 <span class="preprocessor">#include "misc.h"</span>
00006 
00007 <span class="preprocessor">#ifdef SOCKETS_AVAILABLE</span>
00008 <span class="preprocessor"></span>
00009 <span class="preprocessor">#ifdef USE_BERKELEY_STYLE_SOCKETS</span>
00010 <span class="preprocessor"></span><span class="preprocessor">#include &lt;errno.h&gt;</span>
00011 <span class="preprocessor">#include &lt;sys/types.h&gt;</span>
00012 <span class="preprocessor">#include &lt;sys/time.h&gt;</span>
00013 <span class="preprocessor">#include &lt;unistd.h&gt;</span>
00014 <span class="preprocessor">#endif</span>
00015 <span class="preprocessor"></span>
00016 <span class="preprocessor">#define TRACE_WAIT 0</span>
00017 <span class="preprocessor"></span>
00018 <span class="preprocessor">#if TRACE_WAIT</span>
00019 <span class="preprocessor"></span><span class="preprocessor">#include "hrtimer.h"</span>
00020 <span class="preprocessor">#endif</span>
00021 <span class="preprocessor"></span>
00022 NAMESPACE_BEGIN(CryptoPP)
00023 
00024 unsigned <span class="keywordtype">int</span> <a class="code" href="class_wait_object_container.html">WaitObjectContainer</a>::MaxWaitObjects()
00025 {
00026 <span class="preprocessor">#ifdef USE_WINDOWS_STYLE_SOCKETS</span>
00027 <span class="preprocessor"></span>        <span class="keywordflow">return</span> MAXIMUM_WAIT_OBJECTS * (MAXIMUM_WAIT_OBJECTS-1);
00028 <span class="preprocessor">#else</span>
00029 <span class="preprocessor"></span>        <span class="keywordflow">return</span> FD_SETSIZE;
00030 <span class="preprocessor">#endif</span>
00031 <span class="preprocessor"></span>}
00032 
00033 WaitObjectContainer::WaitObjectContainer()
00034 #<span class="keywordflow">if</span> CRYPTOPP_DETECT_NO_WAIT
00035         : m_sameResultCount(0), m_timer(Timer::MILLISECONDS)
00036 #endif
00037 {
00038         Clear();
00039 }
00040 
00041 <span class="keywordtype">void</span> WaitObjectContainer::Clear()
00042 {
00043 <span class="preprocessor">#ifdef USE_WINDOWS_STYLE_SOCKETS</span>
00044 <span class="preprocessor"></span>        m_handles.clear();
00045 <span class="preprocessor">#else</span>
00046 <span class="preprocessor"></span>        m_maxFd = 0;
00047         FD_ZERO(&amp;m_readfds);
00048         FD_ZERO(&amp;m_writefds);
00049 <span class="preprocessor">#endif</span>
00050 <span class="preprocessor"></span>        m_noWait = <span class="keyword">false</span>;
00051 }
00052 
00053 <span class="keywordtype">void</span> WaitObjectContainer::SetNoWait()
00054 {
00055 <span class="preprocessor">#if CRYPTOPP_DETECT_NO_WAIT</span>
00056 <span class="preprocessor"></span>        <span class="keywordflow">if</span> (-1 == m_lastResult &amp;&amp; m_timer.<a class="code" href="class_timer_base.html#_timer_basea5">ElapsedTime</a>() &gt; 1000)
00057         {
00058                 <span class="keywordflow">if</span> (m_sameResultCount &gt; m_timer.<a class="code" href="class_timer_base.html#_timer_basea5">ElapsedTime</a>())
00059                         <span class="keywordflow">try</span> {<span class="keywordflow">throw</span> 0;} <span class="keywordflow">catch</span> (...) {}   <span class="comment">// possible no-wait loop, break in debugger</span>
00060                 m_timer.<a class="code" href="class_timer_base.html#_timer_basea3">StartTimer</a>();
00061         }
00062 <span class="preprocessor">#endif</span>
00063 <span class="preprocessor"></span>        m_noWait = <span class="keyword">true</span>;
00064 }
00065 
00066 <span class="preprocessor">#ifdef USE_WINDOWS_STYLE_SOCKETS</span>
00067 <span class="preprocessor"></span>
00068 <span class="keyword">struct </span>WaitingThreadData
00069 {
00070         <span class="keywordtype">bool</span> waitingToWait, terminate;
00071         HANDLE startWaiting, stopWaiting;
00072         <span class="keyword">const</span> HANDLE *waitHandles;
00073         <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> count;
00074         HANDLE threadHandle;
00075         DWORD threadId;
00076         DWORD* error;
00077 };
00078 
00079 WaitObjectContainer::~WaitObjectContainer()
00080 {
00081         <span class="keywordflow">try</span>             <span class="comment">// don't let exceptions escape destructor</span>
00082         {
00083                 <span class="keywordflow">if</span> (!m_threads.empty())
00084                 {
00085                         HANDLE threadHandles[MAXIMUM_WAIT_OBJECTS];
00086                         <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> i;
00087                         <span class="keywordflow">for</span> (i=0; i&lt;m_threads.size(); i++)
00088                         {
00089                                 WaitingThreadData &amp;thread = *m_threads[i];
00090                                 <span class="keywordflow">while</span> (!thread.waitingToWait)   <span class="comment">// spin until thread is in the initial "waiting to wait" state</span>
00091                                         Sleep(0);
00092                                 thread.terminate = <span class="keyword">true</span>;
00093                                 threadHandles[i] = thread.threadHandle;
00094                         }
00095                         PulseEvent(m_startWaiting);
00096                         ::WaitForMultipleObjects(m_threads.size(), threadHandles, TRUE, INFINITE);
00097                         <span class="keywordflow">for</span> (i=0; i&lt;m_threads.size(); i++)
00098                                 CloseHandle(threadHandles[i]);
00099                         CloseHandle(m_startWaiting);
00100                         CloseHandle(m_stopWaiting);
00101                 }
00102         }
00103         <span class="keywordflow">catch</span> (...)
00104         {
00105         }
00106 }
00107 
00108 
00109 <span class="keywordtype">void</span> WaitObjectContainer::AddHandle(HANDLE handle)
00110 {
00111 <span class="preprocessor">#if CRYPTOPP_DETECT_NO_WAIT</span>
00112 <span class="preprocessor"></span>        <span class="keywordflow">if</span> (m_handles.size() == m_lastResult &amp;&amp; m_timer.<a class="code" href="class_timer_base.html#_timer_basea5">ElapsedTime</a>() &gt; 1000)
00113         {
00114                 <span class="keywordflow">if</span> (m_sameResultCount &gt; m_timer.<a class="code" href="class_timer_base.html#_timer_basea5">ElapsedTime</a>())
00115                         <span class="keywordflow">try</span> {<span class="keywordflow">throw</span> 0;} <span class="keywordflow">catch</span> (...) {}   <span class="comment">// possible no-wait loop, break in debugger</span>
00116                 m_timer.<a class="code" href="class_timer_base.html#_timer_basea3">StartTimer</a>();
00117         }
00118 <span class="preprocessor">#endif</span>
00119 <span class="preprocessor"></span>        m_handles.push_back(handle);
00120 }
00121 
00122 DWORD WINAPI WaitingThread(LPVOID lParam)
00123 {
00124         std::auto_ptr&lt;WaitingThreadData&gt; pThread((WaitingThreadData *)lParam);
00125         WaitingThreadData &amp;thread = *pThread;
00126         std::vector&lt;HANDLE&gt; handles;
00127 
00128         <span class="keywordflow">while</span> (<span class="keyword">true</span>)
00129         {
00130                 thread.waitingToWait = <span class="keyword">true</span>;
00131                 ::WaitForSingleObject(thread.startWaiting, INFINITE);
00132                 thread.waitingToWait = <span class="keyword">false</span>;
00133 
00134                 <span class="keywordflow">if</span> (thread.terminate)
00135                         <span class="keywordflow">break</span>;
00136                 <span class="keywordflow">if</span> (!thread.count)
00137                         <span class="keywordflow">continue</span>;
00138 
00139                 handles.resize(thread.count + 1);
00140                 handles[0] = thread.stopWaiting;
00141                 std::copy(thread.waitHandles, thread.waitHandles+thread.count, handles.begin()+1);
00142 
00143                 DWORD result = ::WaitForMultipleObjects(handles.size(), &amp;handles[0], FALSE, INFINITE);
00144 
00145                 <span class="keywordflow">if</span> (result == WAIT_OBJECT_0)
00146                         <span class="keywordflow">continue</span>;       <span class="comment">// another thread finished waiting first, so do nothing</span>
00147                 SetEvent(thread.stopWaiting);
00148                 <span class="keywordflow">if</span> (!(result &gt; WAIT_OBJECT_0 &amp;&amp; result &lt; WAIT_OBJECT_0 + handles.size()))
00149                 {
00150                         assert(!<span class="stringliteral">"error in WaitingThread"</span>);      <span class="comment">// break here so we can see which thread has an error</span>
00151                         *thread.error = ::GetLastError();
00152                 }
00153         }
00154 
00155         <span class="keywordflow">return</span> S_OK;    <span class="comment">// return a value here to avoid compiler warning</span>
00156 }
00157 
00158 <span class="keywordtype">void</span> WaitObjectContainer::CreateThreads(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> count)
00159 {
00160         <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> currentCount = m_threads.size();
00161         <span class="keywordflow">if</span> (currentCount == 0)
00162         {
00163                 m_startWaiting = ::CreateEvent(NULL, TRUE, FALSE, NULL);
00164                 m_stopWaiting = ::CreateEvent(NULL, TRUE, FALSE, NULL);
00165         }
00166 
00167         <span class="keywordflow">if</span> (currentCount &lt; count)
00168         {
00169                 m_threads.resize(count);
00170                 <span class="keywordflow">for</span> (<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> i=currentCount; i&lt;count; i++)
00171                 {
00172                         m_threads[i] = <span class="keyword">new</span> WaitingThreadData;
00173                         WaitingThreadData &amp;thread = *m_threads[i];
00174                         thread.terminate = <span class="keyword">false</span>;
00175                         thread.startWaiting = m_startWaiting;
00176                         thread.stopWaiting = m_stopWaiting;
00177                         thread.waitingToWait = <span class="keyword">false</span>;
00178                         thread.threadHandle = CreateThread(NULL, 0, &amp;WaitingThread, &amp;thread, 0, &amp;thread.threadId);
00179                 }
00180         }
00181 }
00182 
00183 <span class="keywordtype">bool</span> WaitObjectContainer::Wait(<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> milliseconds)
00184 {
00185         <span class="keywordflow">if</span> (m_noWait || m_handles.empty())
00186         {
00187 <span class="preprocessor">#if CRYPTOPP_DETECT_NO_WAIT</span>
00188 <span class="preprocessor"></span>                <span class="keywordflow">if</span> (-1 == m_lastResult)
00189                         m_sameResultCount++;
00190                 <span class="keywordflow">else</span>
00191                 {
00192                         m_lastResult = -1;
00193                         m_sameResultCount = 0;
00194                 }
00195 <span class="preprocessor">#endif</span>
00196 <span class="preprocessor"></span>                <span class="keywordflow">return</span> <span class="keyword">true</span>;
00197         }
00198 
00199         <span class="keywordflow">if</span> (m_handles.size() &gt; MAXIMUM_WAIT_OBJECTS)
00200         {
00201                 <span class="comment">// too many wait objects for a single WaitForMultipleObjects call, so use multiple threads</span>
00202                 <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> WAIT_OBJECTS_PER_THREAD = MAXIMUM_WAIT_OBJECTS-1;
00203                 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> nThreads = (m_handles.size() + WAIT_OBJECTS_PER_THREAD - 1) / WAIT_OBJECTS_PER_THREAD;
00204                 <span class="keywordflow">if</span> (nThreads &gt; MAXIMUM_WAIT_OBJECTS)    <span class="comment">// still too many wait objects, maybe implement recursive threading later?</span>
00205                         <span class="keywordflow">throw</span> Err(<span class="stringliteral">"WaitObjectContainer: number of wait objects exceeds limit"</span>);
00206                 CreateThreads(nThreads);
00207                 DWORD error = S_OK;
00208                 
00209                 <span class="keywordflow">for</span> (<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> i=0; i&lt;m_threads.size(); i++)
00210                 {
00211                         WaitingThreadData &amp;thread = *m_threads[i];
00212                         <span class="keywordflow">while</span> (!thread.waitingToWait)   <span class="comment">// spin until thread is in the initial "waiting to wait" state</span>
00213                                 Sleep(0);
00214                         <span class="keywordflow">if</span> (i&lt;nThreads)
00215                         {
00216                                 thread.waitHandles = &amp;m_handles[i*WAIT_OBJECTS_PER_THREAD];
00217                                 thread.count = STDMIN(WAIT_OBJECTS_PER_THREAD, m_handles.size() - i*WAIT_OBJECTS_PER_THREAD);
00218                                 thread.error = &amp;error;
00219                         }
00220                         <span class="keywordflow">else</span>
00221                                 thread.count = 0;
00222                 }
00223 
00224                 ResetEvent(m_stopWaiting);
00225                 PulseEvent(m_startWaiting);
00226 
00227                 DWORD result = ::WaitForSingleObject(m_stopWaiting, milliseconds);
00228                 <span class="keywordflow">if</span> (result == WAIT_OBJECT_0)
00229                 {
00230                         <span class="keywordflow">if</span> (error == S_OK)
00231                                 <span class="keywordflow">return</span> <span class="keyword">true</span>;
00232                         <span class="keywordflow">else</span>
00233                                 <span class="keywordflow">throw</span> Err(<span class="stringliteral">"WaitObjectContainer: WaitForMultipleObjects failed with error "</span> + IntToString(error));
00234                 }
00235                 SetEvent(m_stopWaiting);
00236                 <span class="keywordflow">if</span> (result == WAIT_TIMEOUT)
00237                         <span class="keywordflow">return</span> <span class="keyword">false</span>;
00238                 <span class="keywordflow">else</span>
00239                         <span class="keywordflow">throw</span> Err(<span class="stringliteral">"WaitObjectContainer: WaitForSingleObject failed with error "</span> + IntToString(::GetLastError()));
00240         }
00241         <span class="keywordflow">else</span>
00242         {
00243 <span class="preprocessor">#if TRACE_WAIT</span>
00244 <span class="preprocessor"></span>                <span class="keyword">static</span> <a class="code" href="class_timer.html">Timer</a> t(Timer::MICROSECONDS);
00245                 <span class="keyword">static</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> lastTime = 0;
00246                 <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> timeBeforeWait = t.ElapsedTime();
00247 <span class="preprocessor">#endif</span>
00248 <span class="preprocessor"></span>                DWORD result = ::WaitForMultipleObjects(m_handles.size(), &amp;m_handles[0], FALSE, milliseconds);
00249 <span class="preprocessor">#if TRACE_WAIT</span>
00250 <span class="preprocessor"></span>                <span class="keywordflow">if</span> (milliseconds &gt; 0)
00251                 {
00252                         <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> timeAfterWait = t.ElapsedTime();
00253                         OutputDebugString((<span class="stringliteral">"Handles "</span> + IntToString(m_handles.size()) + <span class="stringliteral">", Woke up by "</span> + IntToString(result-WAIT_OBJECT_0) + <span class="stringliteral">", Busied for "</span> + IntToString(timeBeforeWait-lastTime) + <span class="stringliteral">" us, Waited for "</span> + IntToString(timeAfterWait-timeBeforeWait) + <span class="stringliteral">" us, max "</span> + IntToString(milliseconds) + <span class="stringliteral">"ms\n"</span>).c_str());
00254                         lastTime = timeAfterWait;
00255                 }
00256 <span class="preprocessor">#endif</span>
00257 <span class="preprocessor"></span>                <span class="keywordflow">if</span> (result &gt;= WAIT_OBJECT_0 &amp;&amp; result &lt; WAIT_OBJECT_0 + m_handles.size())
00258                 {
00259 <span class="preprocessor">#if CRYPTOPP_DETECT_NO_WAIT</span>
00260 <span class="preprocessor"></span>                        <span class="keywordflow">if</span> (result == m_lastResult)
00261                                 m_sameResultCount++;
00262                         <span class="keywordflow">else</span>
00263                         {
00264                                 m_lastResult = result;
00265                                 m_sameResultCount = 0;
00266                         }
00267 <span class="preprocessor">#endif</span>
00268 <span class="preprocessor"></span>                        <span class="keywordflow">return</span> <span class="keyword">true</span>;
00269                 }
00270                 <span class="keywordflow">else</span> <span class="keywordflow">if</span> (result == WAIT_TIMEOUT)
00271                         <span class="keywordflow">return</span> <span class="keyword">false</span>;
00272                 <span class="keywordflow">else</span>
00273                         <span class="keywordflow">throw</span> Err(<span class="stringliteral">"WaitObjectContainer: WaitForMultipleObjects failed with error "</span> + IntToString(::GetLastError()));
00274         }
00275 }
00276 
00277 <span class="preprocessor">#else</span>
00278 <span class="preprocessor"></span>
00279 <span class="keywordtype">void</span> WaitObjectContainer::AddReadFd(<span class="keywordtype">int</span> fd)
00280 {
00281         FD_SET(fd, &amp;m_readfds);
00282         m_maxFd = STDMAX(m_maxFd, fd);
00283 }
00284 
00285 <span class="keywordtype">void</span> WaitObjectContainer::AddWriteFd(<span class="keywordtype">int</span> fd)
00286 {
00287         FD_SET(fd, &amp;m_writefds);
00288         m_maxFd = STDMAX(m_maxFd, fd);
00289 }
00290 
00291 <span class="keywordtype">bool</span> WaitObjectContainer::Wait(<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> milliseconds)
00292 {
00293         <span class="keywordflow">if</span> (m_noWait || m_maxFd == 0)
00294                 <span class="keywordflow">return</span> <span class="keyword">true</span>;
00295 
00296         timeval tv, *timeout;
00297 
00298         <span class="keywordflow">if</span> (milliseconds == <a class="code" href="cryptlib_8h.html#a0">INFINITE_TIME</a>)
00299                 timeout = NULL;
00300         <span class="keywordflow">else</span>
00301         {
00302                 tv.tv_sec = milliseconds / 1000;
00303                 tv.tv_usec = (milliseconds % 1000) * 1000;
00304                 timeout = &amp;tv;
00305         }
00306 
00307         <span class="keywordtype">int</span> result = select(m_maxFd+1, &amp;m_readfds, &amp;m_writefds, NULL, timeout);
00308 
00309         <span class="keywordflow">if</span> (result &gt; 0)
00310                 <span class="keywordflow">return</span> <span class="keyword">true</span>;
00311         <span class="keywordflow">else</span> <span class="keywordflow">if</span> (result == 0)
00312                 <span class="keywordflow">return</span> <span class="keyword">false</span>;
00313         <span class="keywordflow">else</span>
00314                 <span class="keywordflow">throw</span> Err(<span class="stringliteral">"WaitObjectContainer: select failed with error "</span> + errno);
00315 }
00316 
00317 <span class="preprocessor">#endif</span>
00318 <span class="preprocessor"></span>
00319 <span class="comment">// ********************************************************</span>
00320 
<a name="l00321"></a><a class="code" href="class_waitable.html#_zlib_decompressora19">00321</a> <span class="keywordtype">bool</span> <a class="code" href="class_waitable.html#_zlib_decompressora19">Waitable::Wait</a>(<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> milliseconds)
00322 {
00323         <a class="code" href="class_wait_object_container.html">WaitObjectContainer</a> container;
00324         <a class="code" href="class_waitable.html#_waitablea1">GetWaitObjects</a>(container);
00325         <span class="keywordflow">return</span> container.<a class="code" href="class_wait_object_container.html#_wait_object_containera3">Wait</a>(milliseconds);
00326 }
00327 
00328 NAMESPACE_END
00329 
00330 <span class="preprocessor">#endif</span>
</div></pre><hr size="1"><address style="align: right;"><small>Generated on Sun Nov 7 08:23:59 2004 for Crypto++ by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 ></a> 1.3.7 </small></address>
</body>
</html>