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...
This commit is contained in:
Andrzej Kapolka 2013-04-26 11:08:41 -07:00
parent 46041b2ed9
commit b9fdba2711
3 changed files with 43 additions and 42 deletions

View file

@ -39,8 +39,6 @@
#include <ifaddrs.h>
#endif
#include <pthread.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
@ -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();

View file

@ -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) {

View file

@ -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);