This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

| 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.

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.