From b9fdba27113b59a97ae7b45486a991f170655575 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 26 Apr 2013 11:08:41 -0700 Subject: [PATCH] Rather than creating a thread to read datagrams, just set the socket to nonblocking mode and check it before simulating. This addresses one aspect of the lack of synchronization on AgentList, but there are other issues... --- interface/src/main.cpp | 68 ++++++++++++------------------ libraries/shared/src/UDPSocket.cpp | 14 +++++- libraries/shared/src/UDPSocket.h | 3 ++ 3 files changed, 43 insertions(+), 42 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index f1abfb36aa..582a03ed00 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -39,8 +39,6 @@ #include #endif -#include - #include #include #include @@ -88,10 +86,7 @@ using namespace std; void reshape(int width, int height); // will be defined below void loadViewFrustum(ViewFrustum& viewFrustum); // will be defined below - -pthread_t networkReceiveThread; -bool stopNetworkReceiveThread = false; - +unsigned char incomingPacket[MAX_PACKET_SIZE]; int packetCount = 0; int packetsPerSecond = 0; int bytesPerSecond = 0; @@ -429,8 +424,6 @@ void terminate () { #ifndef _WIN32 audio.terminate(); #endif - stopNetworkReceiveThread = true; - pthread_join(networkReceiveThread, NULL); exit(EXIT_SUCCESS); } @@ -1492,41 +1485,34 @@ void key(unsigned char k, int x, int y) } // Receive packets from other agents/servers and decide what to do with them! -void *networkReceive(void *args) +void networkReceive() { sockaddr senderAddress; ssize_t bytesReceived; - unsigned char *incomingPacket = new unsigned char[MAX_PACKET_SIZE]; - while (!stopNetworkReceiveThread) { - if (AgentList::getInstance()->getAgentSocket().receive(&senderAddress, incomingPacket, &bytesReceived)) { - packetCount++; - bytesCount += bytesReceived; - - switch (incomingPacket[0]) { - case PACKET_HEADER_TRANSMITTER_DATA: - myAvatar.processTransmitterData(incomingPacket, bytesReceived); - break; - case PACKET_HEADER_VOXEL_DATA: - case PACKET_HEADER_Z_COMMAND: - case PACKET_HEADER_ERASE_VOXEL: - voxels.parseData(incomingPacket, bytesReceived); - break; - case PACKET_HEADER_BULK_AVATAR_DATA: - AgentList::getInstance()->processBulkAgentData(&senderAddress, - incomingPacket, - bytesReceived); - break; - default: - AgentList::getInstance()->processAgentData(&senderAddress, incomingPacket, bytesReceived); - break; - } + while (AgentList::getInstance()->getAgentSocket().receive(&senderAddress, incomingPacket, &bytesReceived)) { + packetCount++; + bytesCount += bytesReceived; + + switch (incomingPacket[0]) { + case PACKET_HEADER_TRANSMITTER_DATA: + myAvatar.processTransmitterData(incomingPacket, bytesReceived); + break; + case PACKET_HEADER_VOXEL_DATA: + case PACKET_HEADER_Z_COMMAND: + case PACKET_HEADER_ERASE_VOXEL: + voxels.parseData(incomingPacket, bytesReceived); + break; + case PACKET_HEADER_BULK_AVATAR_DATA: + AgentList::getInstance()->processBulkAgentData(&senderAddress, + incomingPacket, + bytesReceived); + break; + default: + AgentList::getInstance()->processAgentData(&senderAddress, incomingPacket, bytesReceived); + break; } } - - delete[] incomingPacket; - pthread_exit(0); - return NULL; } void idle(void) { @@ -1560,6 +1546,9 @@ void idle(void) { // updateAvatar(deltaTime); + // read incoming packets from network + networkReceive(); + //loop through all the other avatars and simulate them... AgentList* agentList = AgentList::getInstance(); for(AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { @@ -1703,6 +1692,7 @@ int main(int argc, const char * argv[]) listenPort = atoi(portStr); } AgentList::createInstance(AGENT_TYPE_AVATAR, listenPort); + AgentList::getInstance()->getAgentSocket().setBlocking(false); gettimeofday(&applicationStartupTime, NULL); const char* domainIP = getCmdOption(argc, argv, "--domain"); @@ -1785,10 +1775,6 @@ int main(int argc, const char * argv[]) printLog("Local Voxel File loaded.\n"); } - // create thread for receipt of data via UDP - pthread_create(&networkReceiveThread, NULL, networkReceive, NULL); - printLog("Network receive thread created.\n"); - glutTimerFunc(1000, Timer, 0); glutMainLoop(); diff --git a/libraries/shared/src/UDPSocket.cpp b/libraries/shared/src/UDPSocket.cpp index 0fa5ce08a4..31040946e0 100644 --- a/libraries/shared/src/UDPSocket.cpp +++ b/libraries/shared/src/UDPSocket.cpp @@ -119,7 +119,7 @@ unsigned short loadBufferWithSocketInfo(char *addressBuffer, sockaddr *socket) { } } -UDPSocket::UDPSocket(int listeningPort) { +UDPSocket::UDPSocket(int listeningPort) : blocking(true) { init(); // create the socket handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); @@ -191,6 +191,18 @@ bool UDPSocket::init() { return true; } +void UDPSocket::setBlocking(bool blocking) { + this->blocking = blocking; + +#ifdef _WIN32 + u_long mode = blocking ? 0 : 1; + ioctlsocket(handle, FIONBIO, &mode); +#else + int flags = fcntl(handle, F_GETFL, 0); + fcntl(handle, F_SETFL, blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK)); +#endif +} + // Receive data on this socket with retrieving address of sender bool UDPSocket::receive(void *receivedData, ssize_t *receivedBytes) { diff --git a/libraries/shared/src/UDPSocket.h b/libraries/shared/src/UDPSocket.h index 2bc5638b5e..80c093d6f4 100644 --- a/libraries/shared/src/UDPSocket.h +++ b/libraries/shared/src/UDPSocket.h @@ -23,12 +23,15 @@ class UDPSocket { UDPSocket(int listening_port); ~UDPSocket(); bool init(); + void setBlocking(bool blocking); + bool isBlocking() { return blocking; } int send(sockaddr *destAddress, const void *data, size_t byteLength); int send(char *destAddress, int destPort, const void *data, size_t byteLength); bool receive(void *receivedData, ssize_t *receivedBytes); bool receive(sockaddr *recvAddress, void *receivedData, ssize_t *receivedBytes); private: int handle; + bool blocking; }; bool socketMatch(sockaddr *first, sockaddr *second);