CRITICAL_SECTION (MSDN) in Windows can be used for thread synchronization. Essentially you can create a variable and limit it’s ownership to one thread at a time. Something like this
CRITICAL_SECTION cs; volatile long counter = 0; int main(){ InitializeCriticalSection(&cs); //Create threads and run thread_func //..... //..... } void thread_func (){ //Get ownership of counter EnterCriticalSection(&cs); //Increment counter counter++; printf("No. of threads run: %d\n", counter); //Leave ownership of counter //so that other threads can have it LeaveCriticalSection(&cs); }
Threads block while waiting for ownership of counter . So only one thread will have access to counter at a time.
Earlier we have created a TCP server using winsock (https://jijnasu.in/c-tcp-server-in-windows-thread-per-connection/). Let’s make use of CRITICAL_SECTION to count the number of requests served by our server.
#include <winsock.h> #include <stdio.h> #include <string.h> #include <sys/types.h> #define PORT 50001 //Function that threads run static DWORD __stdcall func(int s); //Function to set no. of req served static void __stdcall inc(); //CRITICAL_SECTION variable CRITICAL_SECTION cs; /* (long counter) to count the number of requests served. Volatile so that the value is read from memory and not cache (I think so) */ volatile long counter = 0; int main() { //Dont ask just put it in there WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) { fprintf(stderr, "WSAStartup failed.\n"); exit(1); } //Socket initiation int sock; if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { printf("Socket initiation failed!"); return 0; } //Socket settings struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(PORT); addr.sin_addr.s_addr = inet_addr("127.0.0.1"); memset(addr.sin_zero, '\0', sizeof addr.sin_zero); //Bind the socket int b; if ((b = bind(sock, &addr, sizeof(addr))) == SOCKET_ERROR) { printf("Socket initiation failed!"); return 0; } //Listen on socket int l = listen(sock, 25); //Initialize CRITICAL_SECTION InitializeCriticalSection(&cs); printf("TCP server listening on port %d\n", PORT); //If (con) pass it to a new thread while (1) { struct sockaddr_in client_addr; unsigned int c_len = sizeof client_addr; int s1 = accept(sock, &client_addr, &c_len); unsigned int cur_tid; _beginthreadex(NULL, 0, func, s1, 0, &cur_tid); } //Cleanup closesocket(sock); WSACleanup(); return 0; } static DWORD __stdcall func(int s) { puts("Connection accepted"); //Read data from client char buff[1024]; unsigned int tot_bytes = recv(s, buff, sizeof(buff), MSG_PEEK); char * client_data = (char *)malloc(tot_bytes + 1); for (int i = 0; i < (tot_bytes); i++) { client_data[i] = buff[i]; } client_data[tot_bytes] = '\0'; printf("Msg from client: %s\n", client_data); //Pretend you are processing info puts("Processing req"); Sleep(5000); puts("Processing complete"); //Prepare message for the client char * message; if (strcmp(client_data, "COMMAND1") == 0) { char lmsg[] = "COMMAND1 recieved"; message = (char *)malloc(strlen(lmsg)); message = lmsg; } else if (strcmp(client_data, "COMMAND2") == 0) { char lmsg[] = "COMMAND2 recieved"; message = (char *)malloc(strlen(lmsg)); message = lmsg; } else { char lmsg[] = "NO COMMAND recieved"; message = (char *)malloc(strlen(lmsg)); message = lmsg; } free(client_data); //Send data to client send(s, message, strlen(message), 0); inc(); return 0; } static void __stdcall inc() { EnterCriticalSection(&cs); counter++; printf("No. of reqs served: %d\n", counter); LeaveCriticalSection(&cs); }