sync with private branch

pull/2/head
weidai 2003-06-19 17:09:07 +00:00
parent 5b25f4b45f
commit 376fe5b4ae
11 changed files with 195 additions and 71 deletions

View File

@ -188,10 +188,6 @@ SOURCE=.\diamond.dat
# End Source File
# Begin Source File
SOURCE=.\digest.dat
# End Source File
# Begin Source File
SOURCE=.\dsa1024.dat
# End Source File
# Begin Source File

View File

@ -21,9 +21,10 @@ NAMESPACE_BEGIN(CryptoPP)
word64 Timer::GetCurrentTimerValue()
{
#if defined(CRYPTOPP_WIN32_AVAILABLE)
FILETIME now;
GetSystemTimeAsFileTime(&now);
return now.dwLowDateTime + ((word64)now.dwHighDateTime << 32);
LARGE_INTEGER now;
if (!QueryPerformanceCounter(&now))
throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceCounter failed with error " + IntToString(GetLastError()));
return now.QuadPart;
#elif defined(CRYPTOPP_UNIX_AVAILABLE)
timeval now;
gettimeofday(&now, NULL);
@ -35,20 +36,33 @@ word64 Timer::GetCurrentTimerValue()
#endif
}
unsigned long Timer::ConvertTo(word64 t, Unit unit)
word64 Timer::TicksPerSecond()
{
switch (unit)
#if defined(CRYPTOPP_WIN32_AVAILABLE)
static LARGE_INTEGER freq;
if (freq.QuadPart == 0)
{
case SECONDS:
return (unsigned long)(t / (TicksPerMillisecond() * 1000));
case MILLISECONDS:
return (unsigned long)(t / TicksPerMillisecond());
case MICROSECONDS:
assert(TicksPerMillisecond() % 1000 == 0);
return (unsigned long)(t / (TicksPerMillisecond() / 1000));
if (!QueryPerformanceFrequency(&freq))
throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceFrequency failed with error " + IntToString(GetLastError()));
}
assert(false);
return 0;
return freq.QuadPart;
#elif defined(CRYPTOPP_UNIX_AVAILABLE) || defined(macintosh)
return 1000000;
#endif
}
word64 Timer::ConvertTo(word64 t, Unit unit)
{
static unsigned long unitsPerSecondTable[] = {1, 1000, 1000*1000, 1000*1000*1000};
assert(unit < sizeof(unitsPerSecondTable) / sizeof(unitsPerSecondTable[0]));
unsigned long unitsPerSecond = unitsPerSecondTable[unit];
const word64 freq = TicksPerSecond();
if (freq % unitsPerSecond == 0)
return t / (freq / unitsPerSecond);
else
return word64((double)t * unitsPerSecond / freq);
}
void Timer::StartTimer()
@ -57,7 +71,7 @@ void Timer::StartTimer()
m_started = true;
}
unsigned long Timer::ElapsedTime()
word64 Timer::ElapsedTimeInWord64()
{
if (m_stuckAtZero)
return 0;
@ -70,6 +84,13 @@ unsigned long Timer::ElapsedTime()
}
}
unsigned long Timer::ElapsedTime()
{
word64 elapsed = ElapsedTimeInWord64();
assert(elapsed <= ULONG_MAX);
return (unsigned long)elapsed;
}
NAMESPACE_END
#endif

View File

@ -11,23 +11,16 @@ NAMESPACE_BEGIN(CryptoPP)
class Timer
{
public:
enum Unit {SECONDS, MILLISECONDS, MICROSECONDS};
enum Unit {SECONDS = 0, MILLISECONDS, MICROSECONDS, NANOSECONDS};
Timer(Unit unit, bool stuckAtZero = false) : m_timerUnit(unit), m_stuckAtZero(stuckAtZero), m_started(false) {}
static word64 GetCurrentTimerValue(); // GetCurrentTime is a macro in MSVC 6.0
static unsigned long ConvertTo(word64 t, Unit unit);
// this is not the resolution, just a conversion factor into milliseconds
static inline unsigned int TicksPerMillisecond()
{
#if defined(CRYPTOPP_WIN32_AVAILABLE)
return 10000;
#elif defined(CRYPTOPP_UNIX_AVAILABLE) || defined(macintosh)
return 1000;
#endif
}
static word64 ConvertTo(word64 t, Unit unit);
// this is not the resolution, just a conversion factor into seconds
static word64 TicksPerSecond();
void StartTimer();
word64 ElapsedTimeInWord64();
unsigned long ElapsedTime();
private:

View File

@ -4,6 +4,8 @@
#include "network.h"
#include "wait.h"
#define CRYPTOPP_TRACE_NETWORK 0
NAMESPACE_BEGIN(CryptoPP)
unsigned int NonblockingSource::PumpMessages2(unsigned int &messageCount, bool blocking)
@ -78,6 +80,9 @@ unsigned int NetworkSource::GeneralPump2(unsigned long &byteCount, bool blocking
break;
unsigned int recvResult = receiver.GetReceiveResult();
#if CRYPTOPP_TRACE_NETWORK
OutputDebugString((IntToString((unsigned int)this) + ": Received " + IntToString(recvResult) + " bytes\n").c_str());
#endif
m_dataEnd += recvResult;
m_waitingForResult = false;
@ -102,11 +107,17 @@ ReceiveNoWait:
m_waitingForResult = true;
// call Receive repeatedly as long as data is immediately available,
// because some receivers tend to return data in small pieces
#if CRYPTOPP_TRACE_NETWORK
OutputDebugString((IntToString((unsigned int)this) + ": Receiving " + IntToString(m_buf.size()-m_dataEnd) + " bytes\n").c_str());
#endif
while (receiver.Receive(m_buf+m_dataEnd, m_buf.size()-m_dataEnd))
{
unsigned int recvResult = receiver.GetReceiveResult();
#if CRYPTOPP_TRACE_NETWORK
OutputDebugString((IntToString((unsigned int)this) + ": Received " + IntToString(recvResult) + " bytes\n").c_str());
#endif
m_dataEnd += recvResult;
if (receiver.EofReceived() || m_dataEnd == m_buf.size())
if (receiver.EofReceived() || m_dataEnd > m_buf.size() /2)
{
m_waitingForResult = false;
break;
@ -154,33 +165,56 @@ DoOutput:
// *************************************************************
NetworkSink::NetworkSink(unsigned int maxBufferSize, bool autoFlush)
: m_maxBufferSize(maxBufferSize), m_autoFlush(autoFlush)
, m_needSendResult(false), m_buffer(STDMIN(16U*1024U, maxBufferSize)), m_blockedBytes(0)
NetworkSink::NetworkSink(unsigned int maxBufferSize, unsigned int autoFlushBound)
: m_maxBufferSize(maxBufferSize), m_autoFlushBound(autoFlushBound)
, m_needSendResult(false), m_wasBlocked(false)
, m_buffer(STDMIN(16U*1024U+256, maxBufferSize)), m_skipBytes(0)
, m_speedTimer(Timer::MILLISECONDS), m_byteCountSinceLastTimerReset(0)
, m_currentSpeed(0), m_maxObservedSpeed(0)
{
}
float NetworkSink::ComputeCurrentSpeed()
{
if (m_speedTimer.ElapsedTime() > 1000)
{
m_currentSpeed = m_byteCountSinceLastTimerReset * 1000 / m_speedTimer.ElapsedTime();
m_maxObservedSpeed = STDMAX(m_currentSpeed, m_maxObservedSpeed * 0.98f);
m_byteCountSinceLastTimerReset = 0;
m_speedTimer.StartTimer();
// OutputDebugString(("max speed: " + IntToString((int)m_maxObservedSpeed) + " current speed: " + IntToString((int)m_currentSpeed) + "\n").c_str());
}
return m_currentSpeed;
}
unsigned int NetworkSink::Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking)
{
if (m_blockedBytes)
if (m_skipBytes)
{
assert(length >= m_blockedBytes);
inString += length - m_blockedBytes;
length = m_blockedBytes;
assert(length >= m_skipBytes);
inString += m_skipBytes;
length -= m_skipBytes;
}
LazyPutter lp(m_buffer, inString, length);
if (!blocking || m_buffer.CurrentSize() > m_autoFlushBound)
TimedFlush(0, 0);
unsigned int targetSize = messageEnd ? 0 : m_maxBufferSize;
TimedFlush(blocking ? INFINITE_TIME : 0, m_autoFlush ? 0 : targetSize);
if (blocking)
TimedFlush(INFINITE_TIME, targetSize);
if (m_buffer.CurrentSize() > targetSize)
{
assert(!blocking);
m_blockedBytes = STDMIN(m_buffer.CurrentSize() - targetSize, (unsigned long)length);
m_buffer.UndoLazyPut(m_blockedBytes);
return STDMAX(m_blockedBytes, 1U);
unsigned int blockedBytes = STDMIN(m_buffer.CurrentSize() - targetSize, (unsigned long)length);
m_buffer.UndoLazyPut(blockedBytes);
m_wasBlocked = true;
m_skipBytes += length - blockedBytes;
return STDMAX(blockedBytes, 1U);
}
m_blockedBytes = 0;
m_wasBlocked = false;
m_skipBytes = 0;
if (messageEnd)
AccessSender().SendEof();
@ -206,6 +240,9 @@ unsigned int NetworkSink::TimedFlush(unsigned long maxTime, unsigned int targetS
break;
unsigned int sendResult = sender.GetSendResult();
#if CRYPTOPP_TRACE_NETWORK
OutputDebugString((IntToString((unsigned int)this) + ": Sent " + IntToString(sendResult) + " bytes\n").c_str());
#endif
m_buffer.Skip(sendResult);
totalFlushSize += sendResult;
m_needSendResult = false;
@ -221,6 +258,9 @@ unsigned int NetworkSink::TimedFlush(unsigned long maxTime, unsigned int targetS
unsigned int contiguousSize = 0;
const byte *block = m_buffer.Spy(contiguousSize);
#if CRYPTOPP_TRACE_NETWORK
OutputDebugString((IntToString((unsigned int)this) + ": Sending " + IntToString(contiguousSize) + " bytes\n").c_str());
#endif
sender.Send(block, contiguousSize);
m_needSendResult = true;
@ -228,6 +268,9 @@ unsigned int NetworkSink::TimedFlush(unsigned long maxTime, unsigned int targetS
break; // once time limit is reached, return even if there is more data waiting
}
m_byteCountSinceLastTimerReset += totalFlushSize;
ComputeCurrentSpeed();
return totalFlushSize;
}

View File

@ -51,8 +51,20 @@ public:
virtual bool EofReceived() const =0;
};
class CRYPTOPP_NO_VTABLE NonblockingSinkInfo
{
public:
virtual ~NonblockingSinkInfo() {}
virtual unsigned int GetMaxBufferSize() const =0;
virtual unsigned int GetCurrentBufferSize() const =0;
//! compute the current speed of this sink in bytes per second
virtual float ComputeCurrentSpeed() =0;
//! get the maximum observed speed of this sink in bytes per second
virtual float GetMaxObservedSpeed() const =0;
};
//! a Sink class that queues input and can flush to a device for a specified amount of time.
class CRYPTOPP_NO_VTABLE NonblockingSink : public Sink
class CRYPTOPP_NO_VTABLE NonblockingSink : public Sink, public NonblockingSinkInfo
{
public:
bool IsolatedFlush(bool hardFlush, bool blocking);
@ -70,10 +82,8 @@ public:
virtual unsigned int TimedFlush(unsigned long maxTime, unsigned int targetSize = 0) =0;
virtual void SetMaxBufferSize(unsigned int maxBufferSize) =0;
virtual void SetAutoFlush(bool autoFlush = true) =0;
virtual unsigned int GetMaxBufferSize() const =0;
virtual unsigned int GetCurrentBufferSize() const =0;
//! set a bound which will cause sink to flush if exceeded by GetCurrentBufferSize()
virtual void SetAutoFlushBound(unsigned int bound) =0;
};
//! Network Sender
@ -116,32 +126,39 @@ private:
class CRYPTOPP_NO_VTABLE NetworkSink : public NonblockingSink
{
public:
NetworkSink(unsigned int maxBufferSize, bool autoFlush);
NetworkSink(unsigned int maxBufferSize, unsigned int autoFlushBound);
unsigned int GetMaxWaitObjectCount() const
{return GetSender().GetMaxWaitObjectCount();}
void GetWaitObjects(WaitObjectContainer &container)
{if (m_blockedBytes || !m_buffer.IsEmpty()) AccessSender().GetWaitObjects(container);}
{if (m_wasBlocked || !m_buffer.IsEmpty()) AccessSender().GetWaitObjects(container);}
unsigned int Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking);
unsigned int TimedFlush(unsigned long maxTime, unsigned int targetSize = 0);
void SetMaxBufferSize(unsigned int maxBufferSize) {m_maxBufferSize = maxBufferSize;}
void SetAutoFlush(bool autoFlush = true) {m_autoFlush = autoFlush;}
void SetAutoFlushBound(unsigned int bound) {m_autoFlushBound = bound;}
unsigned int GetMaxBufferSize() const {return m_maxBufferSize;}
unsigned int GetCurrentBufferSize() const {return m_buffer.CurrentSize();}
//! compute the current speed of this sink in bytes per second
float ComputeCurrentSpeed();
//! get the maximum observed speed of this sink in bytes per second
float GetMaxObservedSpeed() const {return m_maxObservedSpeed;}
protected:
virtual NetworkSender & AccessSender() =0;
const NetworkSender & GetSender() const {return const_cast<NetworkSink *>(this)->AccessSender();}
private:
unsigned int m_maxBufferSize;
bool m_autoFlush, m_needSendResult;
unsigned int m_maxBufferSize, m_autoFlushBound;
bool m_needSendResult, m_wasBlocked;
ByteQueue m_buffer;
unsigned int m_blockedBytes;
unsigned int m_skipBytes;
Timer m_speedTimer;
float m_byteCountSinceLastTimerReset, m_currentSpeed, m_maxObservedSpeed;
};
#endif // #ifdef HIGHRES_TIMER_AVAILABLE

View File

@ -234,9 +234,15 @@ void ByteQueue::LazyPut(const byte *inString, unsigned int size)
{
if (m_lazyLength > 0)
FinalizeLazyPut();
m_lazyString = const_cast<byte *>(inString);
m_lazyLength = size;
m_lazyStringModifiable = false;
if (inString == m_tail->buf+m_tail->m_tail)
Put(inString, size);
else
{
m_lazyString = const_cast<byte *>(inString);
m_lazyLength = size;
m_lazyStringModifiable = false;
}
}
void ByteQueue::LazyPutModifiable(byte *inString, unsigned int size)

View File

@ -68,7 +68,7 @@ public:
Unflushable() {}
Unflushable(BufferedTransformation *q) : T(q) {}
bool Flush(bool completeFlush, int propagation=-1, bool blocking=true)
{return ChannelFlush(NULL_CHANNEL, completeFlush, propagation);}
{return ChannelFlush(NULL_CHANNEL, completeFlush, propagation, blocking);}
bool IsolatedFlush(bool hardFlush, bool blocking)
{assert(false); return false;}
bool ChannelFlush(const std::string &channel, bool hardFlush, int propagation=-1, bool blocking=true)

View File

@ -200,8 +200,8 @@ private:
class SocketSink : public NetworkSink, public Socket
{
public:
SocketSink(socket_t s = INVALID_SOCKET, unsigned int maxBufferSize=0, bool autoFlush=false)
: NetworkSink(maxBufferSize, autoFlush), Socket(s), m_sender(*this) {}
SocketSink(socket_t s=INVALID_SOCKET, unsigned int maxBufferSize=0, unsigned int autoFlushBound=16*1024)
: NetworkSink(maxBufferSize, autoFlushBound), Socket(s), m_sender(*this) {}
void SendEof() {ShutDown(SD_SEND);}

View File

@ -13,6 +13,12 @@
#include <unistd.h>
#endif
#define TRACE_WAIT 0
#if TRACE_WAIT
#include "hrtimer.h"
#endif
NAMESPACE_BEGIN(CryptoPP)
unsigned int WaitObjectContainer::MaxWaitObjects()
@ -25,9 +31,8 @@ unsigned int WaitObjectContainer::MaxWaitObjects()
}
WaitObjectContainer::WaitObjectContainer()
#ifndef NDEBUG
: m_sameResultCount(0)
, m_timer(Timer::MILLISECONDS)
#if CRYPTOPP_DETECT_NO_WAIT
: m_sameResultCount(0), m_timer(Timer::MILLISECONDS)
#endif
{
Clear();
@ -45,6 +50,19 @@ void WaitObjectContainer::Clear()
m_noWait = false;
}
void WaitObjectContainer::SetNoWait()
{
#if CRYPTOPP_DETECT_NO_WAIT
if (-1 == m_lastResult && m_timer.ElapsedTime() > 1000)
{
if (m_sameResultCount > m_timer.ElapsedTime())
try {throw 0;} catch (...) {} // possible no-wait loop, break in debugger
m_timer.StartTimer();
}
#endif
m_noWait = true;
}
#ifdef USE_WINDOWS_STYLE_SOCKETS
struct WaitingThreadData
@ -90,7 +108,7 @@ WaitObjectContainer::~WaitObjectContainer()
void WaitObjectContainer::AddHandle(HANDLE handle)
{
#ifndef NDEBUG
#if CRYPTOPP_DETECT_NO_WAIT
if (m_handles.size() == m_lastResult && m_timer.ElapsedTime() > 1000)
{
if (m_sameResultCount > m_timer.ElapsedTime())
@ -165,7 +183,18 @@ void WaitObjectContainer::CreateThreads(unsigned int count)
bool WaitObjectContainer::Wait(unsigned long milliseconds)
{
if (m_noWait || m_handles.empty())
{
#if CRYPTOPP_DETECT_NO_WAIT
if (-1 == m_lastResult)
m_sameResultCount++;
else
{
m_lastResult = -1;
m_sameResultCount = 0;
}
#endif
return true;
}
if (m_handles.size() > MAXIMUM_WAIT_OBJECTS)
{
@ -211,10 +240,23 @@ bool WaitObjectContainer::Wait(unsigned long milliseconds)
}
else
{
#if TRACE_WAIT
static Timer t(Timer::MICROSECONDS);
static unsigned long lastTime = 0;
unsigned long timeBeforeWait = t.ElapsedTime();
#endif
DWORD result = ::WaitForMultipleObjects(m_handles.size(), &m_handles[0], FALSE, milliseconds);
#if TRACE_WAIT
if (milliseconds > 0)
{
unsigned long timeAfterWait = t.ElapsedTime();
OutputDebugString(("Handles " + IntToString(m_handles.size()) + ", Woke up by " + IntToString(result-WAIT_OBJECT_0) + ", Busied for " + IntToString(timeBeforeWait-lastTime) + " us, Waited for " + IntToString(timeAfterWait-timeBeforeWait) + " us, max " + IntToString(milliseconds) + "ms\n").c_str());
lastTime = timeAfterWait;
}
#endif
if (result >= WAIT_OBJECT_0 && result < WAIT_OBJECT_0 + m_handles.size())
{
#ifndef NDEBUG
#if CRYPTOPP_DETECT_NO_WAIT
if (result == m_lastResult)
m_sameResultCount++;
else

12
wait.h
View File

@ -14,7 +14,13 @@
#include <sys/types.h>
#endif
#ifndef NDEBUG
#ifdef NDEBUG
#define CRYPTOPP_DETECT_NO_WAIT 0
#else
#define CRYPTOPP_DETECT_NO_WAIT 1
#endif
#if CRYPTOPP_DETECT_NO_WAIT
#include "hrtimer.h"
#endif
@ -38,7 +44,7 @@ public:
WaitObjectContainer();
void Clear();
void SetNoWait() {m_noWait = true;}
void SetNoWait();
bool Wait(unsigned long milliseconds);
#ifdef USE_WINDOWS_STYLE_SOCKETS
@ -62,7 +68,7 @@ private:
#endif
bool m_noWait;
#ifndef NDEBUG
#if CRYPTOPP_DETECT_NO_WAIT
#ifdef USE_WINDOWS_STYLE_SOCKETS
DWORD m_lastResult;
#else

View File

@ -123,8 +123,8 @@ private:
class WindowsPipeSink : public WindowsHandle, public NetworkSink, public WindowsPipeSender
{
public:
WindowsPipeSink(HANDLE h=INVALID_HANDLE_VALUE, unsigned int maxBufferSize=0, bool autoFlush=false)
: WindowsHandle(h), NetworkSink(maxBufferSize, autoFlush) {}
WindowsPipeSink(HANDLE h=INVALID_HANDLE_VALUE, unsigned int maxBufferSize=0, unsigned int autoFlushBound=16*1024)
: WindowsHandle(h), NetworkSink(maxBufferSize, autoFlushBound) {}
NetworkSink::GetMaxWaitObjectCount;
NetworkSink::GetWaitObjects;