CThreadPool class in the Win32 tools library. The bug is present in all versions of the class.
void CThreadPool::ThreadStopped(WorkerThread *pThread)
{
::InterlockedDecrement(&m_activeThreads);
::InterlockedDecrement(&m_initialisedThreads);
RemoveThreadFromList(pThread);
OnThreadStopped();
}
Should actually be
void CThreadPool::ThreadStopped(WorkerThread *pThread)
{
::InterlockedDecrement(&m_activeThreads);
::InterlockedDecrement(&m_initialisedThreads);
OnThreadStopped();
RemoveThreadFromList(pThread);
}
This function is called when worker threads shut down. When RemoveThreadFromList() is called for the last active thread an event is set and this causes the main thread to complete its wait for the thread pool to shut down cleanly and continue. This usually results in the thread pool object being destroyed. There's a race condition between the destruction of the object and the completion of the final call to the virtual function OnThreadStopped().
TcpListener to throw together a simple server but I want something built in an efficient, async, "IIS-beating", style.
So, if anyone knows where I could find such a beast; or if someone would like to rise to the challenge and write something, please get in touch...
read() and wont come back to you until the call times out (and the operation that you're trying to test fails) or the read completes...
AcceptEx earlier in the week I found some time today to test out my ideas.
The implementation went pretty smoothly. It was helped by the fact that I had a previous attempt at using AcceptEx floating around. It was helped more by the refactoring that I'd done recently and the fact that it was easy to take the tests I had for the listen/accept version of the socket server code and adjust them to work with the new AcceptEx version.
AcceptEx for ages, and even written an article about how to use it but I always thought that it just wasn't something I needed to use in our servers. I'd latched on to the officially advertised reasons for using it and ignored the more subtle advantages...
CAsyncSocketConnectionManager is pretty easy to test, it only has one public function; Connect().
So, what exactly do these tests look like?
bool CAsyncSocket::Read(bool throwOnFailure = false);
If C++ allowed us to overload a function call based on return type then we wouldn't need the horrible throwOnFailure wart and the compiler could pick the right version depending on if we try to use the return value or not... So a call like this: bool ok = pSocket->Read(); would return errors and a call like this: pSocket->Read(); would throw exceptions...
I know why C++ doesn't support overloads on return type and I accept that the above could be confusing but...
I suppose the way around it is to call the functions different things;
void CAsyncSocket::Read();
bool CAsyncSocket::TryRead();
Hmm... Undecided...