From 6d8ff8cc05db7ae0436b6d51331a0a9849520c08 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 28 Mar 2013 14:36:21 -0700 Subject: [PATCH] use a thread to distribute voxels to clients on a clock --- voxel/src/main.cpp | 157 +++++++++++++++++++++++++++------------------ 1 file changed, 95 insertions(+), 62 deletions(-) diff --git a/voxel/src/main.cpp b/voxel/src/main.cpp index dc64e34eaf..330aa51df7 100644 --- a/voxel/src/main.cpp +++ b/voxel/src/main.cpp @@ -39,32 +39,34 @@ const int MIN_BRIGHTNESS = 64; const float DEATH_STAR_RADIUS = 4.0; const float MAX_CUBE = 0.05f; -const int MAX_VOXEL_TREE_DEPTH_LEVELS = 10; +const int VOXEL_SEND_INTERVAL_USECS = 30 * 1000; +const int PACKETS_PER_CLIENT_PER_INTERVAL = 3; + +const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4; AgentList agentList('V', VOXEL_LISTEN_PORT); +VoxelTree randomTree; -int randomlyFillVoxelTree(int levelsToGo, VoxelNode *currentRootNode) { +void randomlyFillVoxelTree(int levelsToGo, VoxelNode *currentRootNode) { // randomly generate children for this node // the first level of the tree (where levelsToGo = MAX_VOXEL_TREE_DEPTH_LEVELS) has all 8 if (levelsToGo > 0) { - - int grandChildrenFromNode = 0; + bool createdChildren = false; int colorArray[4] = {}; createdChildren = false; for (int i = 0; i < 8; i++) { - if (((i == 0 || i == 1 | i == 4 | i == 5) && (randomBoolean() || levelsToGo != 1)) ) { + if (true) { // create a new VoxelNode to put here currentRootNode->children[i] = new VoxelNode(); // give this child it's octal code currentRootNode->children[i]->octalCode = childOctalCode(currentRootNode->octalCode, i); - // fill out the lower levels of the tree using that node as the root node - grandChildrenFromNode = randomlyFillVoxelTree(levelsToGo - 1, currentRootNode->children[i]); - + randomlyFillVoxelTree(levelsToGo - 1, currentRootNode->children[i]); + if (currentRootNode->children[i]->color[3] == 1) { for (int c = 0; c < 3; c++) { colorArray[c] += currentRootNode->children[i]->color[c]; @@ -73,10 +75,6 @@ int randomlyFillVoxelTree(int levelsToGo, VoxelNode *currentRootNode) { colorArray[3]++; } - if (grandChildrenFromNode > 0) { - currentRootNode->childMask += (1 << (7 - i)); - } - createdChildren = true; } } @@ -89,16 +87,88 @@ int randomlyFillVoxelTree(int levelsToGo, VoxelNode *currentRootNode) { // set the color value for this node currentRootNode->setColorFromAverageOfChildren(colorArray); } - - return createdChildren; } else { // this is a leaf node, just give it a color currentRootNode->setRandomColor(MIN_BRIGHTNESS); - - return 0; } } +void *distributeVoxelsToListeners(void *args) { + + timeval lastSendTime; + + unsigned char *stopOctal; + int packetCount; + + int totalBytesSent; + + unsigned char *voxelPacket = new unsigned char[MAX_VOXEL_PACKET_SIZE]; + unsigned char *voxelPacketEnd; + + float treeRoot[3] = {-40, 0, -40}; + + while (true) { + gettimeofday(&lastSendTime, NULL); + + // enumerate the agents to send 3 packets to each + for (int i = 0; i < agentList.getAgents().size(); i++) { + + Agent *thisAgent = (Agent *)&agentList.getAgents()[i]; + VoxelAgentData *agentData = (VoxelAgentData *)(thisAgent->getLinkedData()); + + // lock this agent's delete mutex so that the delete thread doesn't + // kill the agent while we are working with it + pthread_mutex_lock(&thisAgent->deleteMutex); + + stopOctal = NULL; + packetCount = 0; + totalBytesSent = 0; + randomTree.leavesWrittenToBitstream = 0; + + for (int j = 0; j < PACKETS_PER_CLIENT_PER_INTERVAL; j++) { + voxelPacketEnd = voxelPacket; + stopOctal = randomTree.loadBitstreamBuffer(voxelPacketEnd, + randomTree.rootNode, + agentData->rootMarkerNode, + agentData->position, + treeRoot, + stopOctal); + + agentList.getAgentSocket().send(thisAgent->getActiveSocket(), voxelPacket, voxelPacketEnd - voxelPacket); + + packetCount++; + totalBytesSent += voxelPacketEnd - voxelPacket; + + if (agentData->rootMarkerNode->childrenVisitedMask == 255) { + break; + } + } + + // for any agent that has a root marker node with 8 visited children + // recursively delete its marker nodes so we can revisit + if (agentData->rootMarkerNode->childrenVisitedMask == 255) { + delete agentData->rootMarkerNode; + agentData->rootMarkerNode = new MarkerNode(); + } + + // unlock the delete mutex so the other thread can + // kill the agent if it has dissapeared + pthread_mutex_unlock(&thisAgent->deleteMutex); + } + + // dynamically sleep until we need to fire off the next set of voxels + double usecToSleep = VOXEL_SEND_INTERVAL_USECS - (usecTimestampNow() - usecTimestamp(&lastSendTime)); + + if (usecToSleep > 0) { + usleep(usecToSleep); + } else { + std::cout << "Last send took too much time, not sleeping!\n"; + } + } + + pthread_exit(0); +} + void attachVoxelAgentDataToAgent(Agent *newAgent) { if (newAgent->getLinkedData() == NULL) { newAgent->setLinkedData(new VoxelAgentData()); @@ -116,20 +186,13 @@ int main(int argc, const char * argv[]) srand((unsigned)time(0)); - // use our method to create a random voxel tree - VoxelTree randomTree; - // create an octal code buffer and load it with 0 so that the recursive tree fill can give // octal codes to the tree nodes that it is creating randomlyFillVoxelTree(MAX_VOXEL_TREE_DEPTH_LEVELS, randomTree.rootNode); + + pthread_t sendVoxelThread; + pthread_create(&sendVoxelThread, NULL, distributeVoxelsToListeners, NULL); - unsigned char *voxelPacket = new unsigned char[MAX_VOXEL_PACKET_SIZE]; - unsigned char *voxelPacketEnd; - - unsigned char *stopOctal; - int packetCount; - int totalBytesSent; - sockaddr agentPublicAddress; char *packetData = new char[MAX_PACKET_SIZE]; @@ -139,49 +202,19 @@ int main(int argc, const char * argv[]) while (true) { if (agentList.getAgentSocket().receive(&agentPublicAddress, packetData, &receivedBytes)) { if (packetData[0] == 'H') { - - if (agentList.addOrUpdateAgent(&agentPublicAddress, &agentPublicAddress, packetData[0], agentList.getLastAgentId())) { + if (agentList.addOrUpdateAgent(&agentPublicAddress, + &agentPublicAddress, + packetData[0], + agentList.getLastAgentId())) { agentList.increaseAgentId(); } agentList.updateAgentWithData(&agentPublicAddress, (void *)packetData, receivedBytes); - - VoxelAgentData *agentData = (VoxelAgentData *) agentList.getAgents()[agentList.indexOfMatchingAgent(&agentPublicAddress)].getLinkedData(); - int newLevel = 10; - if (newLevel > agentData->lastSentLevel) { - // the agent has already received a deeper level than this from us - // do nothing - - stopOctal = randomTree.rootNode->octalCode; - packetCount = 0; - totalBytesSent = 0; - randomTree.leavesWrittenToBitstream = 0; - - while (stopOctal != NULL) { - voxelPacketEnd = voxelPacket; - stopOctal = randomTree.loadBitstreamBuffer(voxelPacketEnd, - stopOctal, - randomTree.rootNode, - newLevel); - - agentList.getAgentSocket().send((sockaddr *)&agentPublicAddress, - voxelPacket, - voxelPacketEnd - voxelPacket); - - packetCount++; - totalBytesSent += voxelPacketEnd - voxelPacket; - } - - printf("%d packets sent to client totalling %d bytes\n", packetCount, totalBytesSent); - printf("%d leaves were sent - %f bpv\n", - randomTree.leavesWrittenToBitstream, - (float)totalBytesSent / randomTree.leavesWrittenToBitstream); - - agentData->lastSentLevel = newLevel; - } } } } + + pthread_join(sendVoxelThread, NULL); return 0; } \ No newline at end of file