  | 
   Win32 Thread Primitives & Utils 
   Submitted by  |   
  
  
Here are some C++ classes the wrap Win32 thread primatives/sync utils and parts of the Winsock API. I hope you can use them.
Any comments on the code, give me a buzz
Have a good one 
Dave
 | 
 
 
 
Currently browsing [threadsyncsockets.zip] (7,491 bytes) - [Mutex.cpp] - (383 bytes)
 
 /* Dave Pallot */
/* pallot@iinet.net.au */
/* Copyright 2000 */
  #include "Mutex.h"
  Mutex::Mutex()
{
	m_mutex = ::CreateMutex((SECURITY_ATTRIBUTES*) 0,	// use default security attributes
							false,									// no initial owner
							static_cast<char*>(0));				// anonymous mutex
}
  Mutex::~Mutex()
{
	if (m_mutex != NULL)
	{
		::CloseHandle(m_mutex);
	}
}
     |  
  
 | 
 
  
Currently browsing [threadsyncsockets.zip] (7,491 bytes) - [Mutex.h] - (425 bytes)
 
 /* Dave Pallot */
/* pallot@iinet.net.au */
/* Copyright 2000 */
  #ifndef MUTEX_H
#define MUTEX_H
  #include <windows.h>
  class Mutex 
{
public:    
    Mutex();
    virtual ~Mutex();
  public:
    inline void get() { if (m_mutex != NULL) ::WaitForSingleObject(m_mutex, INFINITE); }
    inline void release() { if (m_mutex != NULL) ::ReleaseMutex(m_mutex); }
  private:
	HANDLE m_mutex;
};
#endif //MUTEX_H   |  
  
 | 
 
  
Currently browsing [threadsyncsockets.zip] (7,491 bytes) - [Semaphore.cpp] - (654 bytes)
 
 /* Dave Pallot */
/* pallot@iinet.net.au */
/* Copyright 2000 */
  #include "Semaphore.h"
  Semaphore::Semaphore()
{
	m_handle = ::CreateSemaphore((SECURITY_ATTRIBUTES*)0, 0, 1024, 0);
}
  Semaphore::~Semaphore()
{
	if (m_handle != NULL)
	{
		::CloseHandle(m_handle);
	}
}
  unsigned int Semaphore::wait(unsigned int nSec)
{	
	DWORD waitRetCode = WAIT_FAILED;
  	if (m_handle)
	{
		waitRetCode = ::WaitForSingleObject(m_handle, nSec);
	}
  	return waitRetCode;
}
  void Semaphore::signal()
{
	if (m_handle)
	{
		::ReleaseSemaphore(m_handle, 1, NULL);
	}
}
  unsigned int Semaphore::wait()
{
	return wait(INFINITE);
}
     |  
  
 | 
 
  
Currently browsing [threadsyncsockets.zip] (7,491 bytes) - [Semaphore.h] - (378 bytes)
 
 /* Dave Pallot */
/* pallot@iinet.net.au */
/* Copyright 2000 */
  #ifndef SEMAPHORE_H
#define SEMAPHORE_H
  #include <windows.h>
  class Semaphore
{
public:    
    Semaphore();
    virtual ~Semaphore();
  public:
    unsigned int wait();
    unsigned int wait(unsigned int nSec);
    void signal();
  private:    
    HANDLE m_handle;
};
#endif //SEMAPHORE_H   |  
  
 | 
 
  
Currently browsing [threadsyncsockets.zip] (7,491 bytes) - [Socket.cpp] - (6,291 bytes)
 
 /* Dave Pallot */
/* pallot@iinet.net.au */
/* Copyright 2000 */
  #include "Socket.h"
  bool Socket::m_init = false;
unsigned int Socket::m_instance = 0;
  Socket::Socket() :
	m_socket(INVALID_SOCKET),
	m_state(Closed)
{
	if (m_init == false)
	{
		WSADATA socketData;
  		int retCode = ::WSAStartup(0x0101, &socketData);
  		if (retCode == 0)
		{
			m_init = true;
		}
	}
  	m_instance++;
}
  
Socket::~Socket()
{
	close();
	
	if (m_init == true)
	{
		m_instance--;
  		if (m_instance == 0)
		{
			::WSACleanup();
		}
	}
}
  
int Socket::initSocket()
{
	if (m_socket == INVALID_SOCKET)
	{
		m_socket = ::socket(AF_INET, SOCK_STREAM, 0);
  		if (m_socket != INVALID_SOCKET)
		{
			m_state = Init;
			
			// Add debug info
			#ifdef _DEBUG
				int opt = SO_DEBUG;
				::setsockopt(m_socket, SOL_SOCKET, 0, (char *)opt, sizeof(opt));
			#endif	
			
		}
	}
  	return m_socket;
}
  
void Socket::close()
{
	if (m_socket != INVALID_SOCKET)
	{
		if (::closesocket(m_socket) != SOCKET_ERROR)
		{
			m_state = Closed;
			m_socket = INVALID_SOCKET;
		}
	}
}
  
int Socket::connect(const char* hostname, unsigned short port)
{
	int retCode = SOCKET_ERROR;
	
	if (m_socket != INVALID_SOCKET && m_state == Init)
	{
		// Arrives in network host order
		struct hostent* host = ::gethostbyname(hostname);
  		if (host != NULL)
		{
			unsigned long ipAddress = 0;
  			::memcpy( (char*) &(ipAddress), host->h_addr, host->h_length );
  			m_inetAddr.m_address.sin_family = AF_INET;				   // Socket Type
			m_inetAddr.m_address.sin_addr.S_un.S_addr = ipAddress;   // IP Address	
			m_inetAddr.m_address.sin_port = ::htons(port);			   // Port
			retCode = ::connect(m_socket, (struct sockaddr*)&m_inetAddr.m_address, sizeof(struct sockaddr));
		
			if (retCode == 0)
			{
				m_state = Connected;
			}
		}
	}
  	return retCode;
}
  
int Socket::listen(unsigned short port, int backlog)
{
	int retCode = SOCKET_ERROR;
  	if (m_socket != INVALID_SOCKET && m_state == Init)
	{
		m_inetAddr.m_address.sin_family = AF_INET;
		m_inetAddr.m_address.sin_addr.S_un.S_addr = ::htonl(INADDR_ANY); // Listen on Any Address
		m_inetAddr.m_address.sin_port = ::htons(port);
  		retCode = ::bind(m_socket, (struct sockaddr*)&m_inetAddr.m_address, sizeof(m_inetAddr.m_address));
		
		if (retCode == 0)
		{
			retCode = ::listen(m_socket, backlog);
  			if (retCode == 0)
			{	
				m_state = Listening;
			}
		}
	}
  	return retCode;
}
 
 
  
int Socket::accept(Socket& socket)
{
	// Close accepting socket
	socket.close();
	
	// We must be listening before we can accept
	if (m_state == Listening)
	{
		int length = sizeof(struct sockaddr);
  		socket.m_socket = ::accept(m_socket, (struct sockaddr*)&socket.m_inetAddr.m_address, &length);
		
		if (socket.m_socket != INVALID_SOCKET)
		{
			socket.m_state = Connected;
		}
		else
		{
			// Didn't accept client so close it down
			socket.close();
		}
	}
  	return socket.m_socket;
}
  
unsigned int Socket::sendBuffer(const char* buffer, unsigned int size)
{
	int bytesSent = 0;
  	if (m_state == Connected)
	{
		bytesSent = ::send(m_socket, buffer, size, 0);
  		if (bytesSent == 0 || bytesSent == SOCKET_ERROR)
		{
			close();
		}
	}
  	return bytesSent;
}
  
unsigned int Socket::readBuffer(char* buffer, unsigned int size)
{
	int bytesReadTotal = 0;
	char* ptr = buffer;
  	if (m_state == Connected)
	{
		int bytesRead = 0;
		// Always good to make sure we have the whole packet
		while (size > 0)
		{
			bytesRead = ::recv(m_socket, ptr, size, 0);
			
			if (bytesRead == 0 || bytesRead == SOCKET_ERROR)
			{
				close();
				break;
			}
			
			size -= bytesRead;
			ptr += bytesRead;
			bytesReadTotal += bytesRead;
		}
	}
  	return bytesReadTotal;
}
  
Socket& Socket::operator >> (bool& data)
{
	if (m_state == Connected)
	{
		int read = ::recv(m_socket, (char*)&data, sizeof(bool), 0);
  		if (read == 0 || read == SOCKET_ERROR)
		{
			close();
		}
	}
  	return *this;
}
  
Socket& Socket::operator >> (char& data)
{	
	if (m_state == Connected)
	{
		int read = ::recv(m_socket, &data, sizeof(char), 0);
  		if (read == 0 || read == SOCKET_ERROR)
		{
			close();
		}
	}
  	return *this;
}
  Socket& Socket::operator >> (int& data)
{
	if (m_state == Connected)
	{
		int size = sizeof(int);
		int value = 0;
  		int bytesRead = 0;
  		while (size > 0)
		{
			bytesRead = ::recv(m_socket, (char*)&(value)+bytesRead, size, 0);
  			if (bytesRead == 0 || bytesRead == SOCKET_ERROR)
			{
				close();
				break;
			}
			
			size -= bytesRead;
		}
  		if (bytesRead > 0)
		{	
			data = ::ntohl(value);
		}
  	}
  	return *this;
}
  
Socket& Socket::operator >> (unsigned int& data)
{
	if (m_state == Connected)
	{
		int size = sizeof(unsigned int);
		unsigned int value = 0;
  		int bytesRead = 0;
  		while (size > 0)
		{
			bytesRead = ::recv(m_socket, (char*)&(value)+bytesRead, size, 0);
  			if (bytesRead == 0 || bytesRead == SOCKET_ERROR)
			{
				close();
				break;
			}
			
			size -= bytesRead;
		}
  		if (bytesRead > 0)
		{
			data = ::ntohl(value);
		}
  	}
  	return *this;
}
  Socket& Socket::operator << (bool data)
{
	if (m_state == Connected)
	{
		int sent = ::send(m_socket, (char*)&data, sizeof(bool), 0);
  		if (sent == 0 || sent == SOCKET_ERROR)
		{
			close();
		}
	}
  	return *this;
}
  
Socket& Socket::operator << (char data)
{
	if (m_state == Connected)
	{
		int sent = ::send(m_socket, (char*)&data, sizeof(char), 0);
  		if (sent == 0 || sent == SOCKET_ERROR)
		{
			close();
		}
	}
  	return *this;
}
  Socket& Socket::operator << (int data)
{
	if (m_state == Connected)
	{
		int tmpData = ::htonl(data);
  		int sent = ::send(m_socket, (char*)&tmpData, sizeof(int), 0);
  		if (sent == 0 || sent == SOCKET_ERROR)
		{
			close();
		}
	}
  	return *this;
}
  
Socket& Socket::operator << (unsigned int data)
{
	if (m_state == Connected)
	{
		int tmpData = ::htonl(data);
  		int sent = ::send(m_socket, (char*)&tmpData, sizeof(unsigned int), 0);
  		if (sent == 0 || sent == SOCKET_ERROR)
		{
			close();
		}
	}
  	return *this;
}
     |  
  
 | 
 
  
Currently browsing [threadsyncsockets.zip] (7,491 bytes) - [Socket.h] - (1,634 bytes)
 
 /* Dave Pallot */
/* pallot@iinet.net.au */
/* Copyright 2000 */
  #ifndef SOCKET_H
#define SOCKET_H
  #include <windows.h>
#include <winsock.h>
  #include "InetAddress.h"
  class Socket
{
public:
	enum SocketState
	{
		Init,
		Closed,
		Connected,
		Listening
	};
  public:
    Socket();
    virtual ~Socket();
  public:
	int initSocket();
	void close();
	int connect(const char* hostname, unsigned short port);
	int listen(unsigned short port, int backlog = SOMAXCONN);
	int accept(Socket& socket);
	unsigned int sendBuffer(const char* buffer, unsigned int size);
	unsigned int readBuffer(char* buffer, unsigned int size);
  	Socket& operator >> (bool& data);
	Socket& operator >> (char& data);
	Socket& operator >> (int& data);
	Socket& operator >> (unsigned int& data);
  	Socket& operator << (bool data);
	Socket& operator << (char data);
	Socket& operator << (int data);
	Socket& operator << (unsigned int data);
  	static bool m_init;
	static unsigned int m_instance;
  
public:
	SocketState getSocketState() { return m_state; }
	const InetAddress* getInetAddr() const { return &m_inetAddr; }
  
public:
	inline void clearSet(fd_set& set)
	{
		FD_ZERO(&set);	
	}
  	inline void addSet(fd_set& set)
	{
		FD_SET(m_socket, &set);
	}
  	inline int isSet(fd_set& set)
	{
		return FD_ISSET(m_socket, &set);
	}
  	inline void removeSet(fd_set& set)
	{
		FD_CLR(m_socket, &set);
	}
  	inline int readSelect(fd_set& set)
	{
		return ::select(0, &set, 0, 0, 0);
	}
  private:
	SocketState m_state;
  	SOCKET m_socket;
  	InetAddress m_inetAddr;
};
  #endif //SOCKET_H   |  
  
 | 
 
  
Currently browsing [threadsyncsockets.zip] (7,491 bytes) - [Thread.cpp] - (1,400 bytes)
 
 /* Dave Pallot */
/* pallot@iinet.net.au */
/* Copyright 2000 */
  #include "Thread.h"
  Thread::Thread(Runnable* runnable) :
	m_running(false),
	m_run(runnable),
	m_threadHandle(0),
	m_waiting(false)
{
}
  Thread::~Thread()
{
	stop();
}
  
bool Thread::start()
{
	if (m_threadHandle == 0)
	{
		unsigned long threadId = 0;
		
		m_threadHandle = ::CreateThread( (SECURITY_ATTRIBUTES*) 0,		   // use default security attributes
										0,								   // use default stack size
										(LPTHREAD_START_ROUTINE)ThreadProc,	// thread start routine
										(void*) m_run,								// parameter to start routine
										0,											// creation flags - run immediately
										&threadId);									// returned thread identifier
		if (m_threadHandle != 0)
		{
			m_running = true;
		}
	}
  	return m_running;
}
  
void Thread::stop()
{
	if (m_threadHandle != 0)
	{
		if (::CloseHandle(m_threadHandle) == TRUE)
		{
			m_running = false;
			m_threadHandle = 0;
			
			if (m_waiting == true)
			{
				m_semaphore.signal();
				m_waiting = false;
			}
		}
	}
}
  
void Thread::join()
{
	if (m_running == true)
	{
		m_waiting = true;
		m_semaphore.wait();
	}
}
  
DWORD WINAPI ThreadProc(LPVOID param)
{
   Runnable* runnable = reinterpret_cast<Runnable*>(param);
     runnable->runThis();
     runnable->stop();
     return 0;
}
 
 
     |  
  
 | 
 
  
Currently browsing [threadsyncsockets.zip] (7,491 bytes) - [Thread.h] - (761 bytes)
 
 /* Dave Pallot */
/* pallot@iinet.net.au */
/* Copyright 2000 */
  #ifndef THREAD_H
#define THREAD_H
  #pragma warning(disable : 4355)
  #include <windows.h>
#include "Semaphore.h"
  
class Runnable;
  class Thread
{
public:
	Thread(Runnable* runnable);
	virtual ~Thread();    
  public:
	bool start();
	void join();
  	inline bool isRunning() { return m_running; }
  private:
	void stop();
  private:
	HANDLE m_threadHandle;
	bool m_running;
	bool m_waiting;
  	Runnable* m_run;
	Semaphore m_semaphore;
	
	friend DWORD WINAPI ThreadProc(LPVOID param);
};
  
class Runnable : public Thread
{
protected:
	Runnable() : Thread(this)
	{}
  	virtual ~Runnable() {}
  public:
	virtual void runThis() = 0;
};
  #endif //THREAD_H   |  
  
 | 
 
  
Currently browsing [threadsyncsockets.zip] (7,491 bytes) - [InetAddress.h] - (697 bytes)
 
 /* Dave Pallot */
/* pallot@iinet.net.au */
/* Copyright 2000 */
  #ifndef INETADDRESS_H
#define INETADDRESS_H
  #include <string>
#include <winsock.h>
  class InetAddress
{
public:
    InetAddress() {}
    virtual ~InetAddress() {}
  public:
	/* Returns in Host Byte Order */
	unsigned long getULongIP() const
	{
		return ::ntohl(m_address.sin_addr.S_un.S_addr);
	}
  	/* Returns in Host Byte Order */
	unsigned short getPort() const 
	{
		return ::ntohs(m_address.sin_port);
	}
  	std::string getStrIP() const
	{
		return std::string(::inet_ntoa(m_address.sin_addr));
	}
  private:
	struct sockaddr_in m_address;
  	friend class Socket;
};
  #endif //INETADDRESS_H   |  
  
 | 
 
 
 
The zip file viewer built into the Developer Toolbox made use
of the zlib library, as well as the zlibdll source additions.
 
 
 |