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.