From 836d286b75dabf039a2e25e403cc09212708ca0c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 25 Apr 2013 13:11:13 -0700 Subject: [PATCH] initial transition from vector to multi-dimensional array in AgentList --- interface/src/Head.cpp | 13 +- interface/src/main.cpp | 25 ++- libraries/shared/src/Agent.cpp | 27 ++-- libraries/shared/src/Agent.h | 11 +- libraries/shared/src/AgentList.cpp | 235 ++++++++++++++++++----------- libraries/shared/src/AgentList.h | 44 +++++- voxel-server/src/main.cpp | 16 -- 7 files changed, 226 insertions(+), 145 deletions(-) diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index f6683b6a9a..ac44e3e530 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -301,20 +301,19 @@ void Head::simulate(float deltaTime) { // if the avatar being simulated is mine, then loop through // all the other avatars to get information about them... //------------------------------------------------------------- - if ( _isMine ) - { + if ( _isMine ) { _nearOtherAvatar = false; float closestDistance = 10000.0f; - AgentList * agentList = AgentList::getInstance(); + AgentList* agentList = AgentList::getInstance(); //_numOtherAvatars = 0; - for(std::vector::iterator agent = agentList->getAgents().begin(); - agent != agentList->getAgents().end(); + for(AgentListIterator agent = agentList->begin(); + agent != agentList->end(); agent++) { - if (( agent->getLinkedData() != NULL && ( agent->getType() == AGENT_TYPE_AVATAR ) )) { - Head *otherAvatar = (Head *)agent->getLinkedData(); + if ((*agent).getLinkedData() != NULL && (*agent).getType() == AGENT_TYPE_AVATAR) { + Head *otherAvatar = (Head *)(*agent).getLinkedData(); // if ( _numOtherAvatars < MAX_OTHER_AVATARS ) { diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 41ffdc1e92..0ede2ed23b 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -907,11 +907,11 @@ void display(void) // Render avatars of other agents AgentList *agentList = AgentList::getInstance(); - for(std::vector::iterator agent = agentList->getAgents().begin(); - agent != agentList->getAgents().end(); + for(AgentListIterator agent = agentList->begin(); + agent != agentList->end(); agent++) { - if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) { - Head *avatar = (Head *)agent->getLinkedData(); + if ((*agent).getLinkedData() != NULL && (*agent).getType() == AGENT_TYPE_AVATAR) { + Head *avatar = (Head *)(*agent).getLinkedData(); avatar->render(0); } } @@ -980,12 +980,13 @@ void display(void) glPointSize(1.0f); char agents[100]; - int totalAgents = AgentList::getInstance()->getAgents().size(); + AgentList *agentList = AgentList::getInstance(); int totalAvatars = 0, totalServers = 0; - for (int i = 0; i < totalAgents; i++) { - (AgentList::getInstance()->getAgents()[i].getType() == AGENT_TYPE_AVATAR) - ? totalAvatars++ : totalServers++; + + for (AgentListIterator agent = agentList->begin(); agent != agentList->end(); agent++) { + (*agent).getType() == AGENT_TYPE_AVATAR ? totalAvatars++ : totalServers++; } + sprintf(agents, "Servers: %d, Avatars: %d\n", totalServers, totalAvatars); drawtext(WIDTH-150,20, 0.10, 0, 1.0, 0, agents, 1, 0, 0); @@ -1489,11 +1490,9 @@ void idle(void) { //loop through all the other avatars and simulate them... AgentList * agentList = AgentList::getInstance(); - for(std::vector::iterator agent = agentList->getAgents().begin(); agent != agentList->getAgents().end(); agent++) - { - if (agent->getLinkedData() != NULL) - { - Head *avatar = (Head *)agent->getLinkedData(); + for(AgentListIterator agent = agentList->begin(); agent != agentList->end(); agent++) { + if ((*agent).getLinkedData() != NULL) { + Head *avatar = (Head *)(*agent).getLinkedData(); avatar->simulate(deltaTime); } } diff --git a/libraries/shared/src/Agent.cpp b/libraries/shared/src/Agent.cpp index 3a92e6c05e..cd694ccf78 100644 --- a/libraries/shared/src/Agent.cpp +++ b/libraries/shared/src/Agent.cpp @@ -22,7 +22,19 @@ using shared_lib::printLog; -Agent::Agent(sockaddr *agentPublicSocket, sockaddr *agentLocalSocket, char agentType, uint16_t thisAgentId) { +int unpackAgentId(unsigned char *packedData, uint16_t *agentId) { + memcpy(agentId, packedData, sizeof(uint16_t)); + return sizeof(uint16_t); +} + +int packAgentId(unsigned char *packStore, uint16_t agentId) { + memcpy(packStore, &agentId, sizeof(uint16_t)); + return sizeof(uint16_t); +} + +Agent::Agent(sockaddr *agentPublicSocket, sockaddr *agentLocalSocket, char agentType, uint16_t thisAgentId) : + _isAlive(true) +{ if (agentPublicSocket != NULL) { publicSocket = new sockaddr; memcpy(publicSocket, agentPublicSocket, sizeof(sockaddr)); @@ -46,12 +58,11 @@ Agent::Agent(sockaddr *agentPublicSocket, sockaddr *agentLocalSocket, char agent activeSocket = NULL; linkedData = NULL; _bytesReceivedMovingAverage = NULL; - - deleteMutex = new pthread_mutex_t; - pthread_mutex_init(deleteMutex, NULL); } Agent::Agent(const Agent &otherAgent) { + _isAlive = otherAgent._isAlive; + if (otherAgent.publicSocket != NULL) { publicSocket = new sockaddr; memcpy(publicSocket, otherAgent.publicSocket, sizeof(sockaddr)); @@ -92,9 +103,6 @@ Agent::Agent(const Agent &otherAgent) { } else { _bytesReceivedMovingAverage = NULL; } - - deleteMutex = new pthread_mutex_t; - pthread_mutex_init(deleteMutex, NULL); } Agent& Agent::operator=(Agent otherAgent) { @@ -105,6 +113,7 @@ Agent& Agent::operator=(Agent otherAgent) { void Agent::swap(Agent &first, Agent &second) { using std::swap; + swap(first._isAlive, second._isAlive); swap(first.publicSocket, second.publicSocket); swap(first.localSocket, second.localSocket); swap(first.activeSocket, second.activeSocket); @@ -114,13 +123,9 @@ void Agent::swap(Agent &first, Agent &second) { swap(first.firstRecvTimeUsecs, second.firstRecvTimeUsecs); swap(first.lastRecvTimeUsecs, second.lastRecvTimeUsecs); swap(first._bytesReceivedMovingAverage, second._bytesReceivedMovingAverage); - swap(first.deleteMutex, second.deleteMutex); } Agent::~Agent() { - // the deleteMutex isn't destroyed here - // that's handled by the agent list silent agent removal thread - delete publicSocket; delete localSocket; delete linkedData; diff --git a/libraries/shared/src/Agent.h b/libraries/shared/src/Agent.h index b1d2347c21..1b8fadfdd8 100644 --- a/libraries/shared/src/Agent.h +++ b/libraries/shared/src/Agent.h @@ -31,8 +31,6 @@ public: bool matches(sockaddr *otherPublicSocket, sockaddr *otherLocalSocket, char otherAgentType); - pthread_mutex_t *deleteMutex; - char getType() const; const char* getTypeName() const; void setType(char newType); @@ -58,6 +56,9 @@ public: AgentData* getLinkedData(); void setLinkedData(AgentData *newData); + bool isAlive() const { return _isAlive; }; + void setAlive(bool isAlive) { _isAlive = isAlive; }; + void recordBytesReceived(int bytesReceived); float getAverageKilobitsPerSecond(); float getAveragePacketsPerSecond(); @@ -73,9 +74,11 @@ private: double lastRecvTimeUsecs; SimpleMovingAverage* _bytesReceivedMovingAverage; AgentData* linkedData; - + bool _isAlive; }; -std::ostream& operator<<(std::ostream& os, const Agent* agent); + +int unpackAgentId(unsigned char *packedData, uint16_t *agentId); +int packAgentId(unsigned char *packStore, uint16_t agentId); #endif /* defined(__hifi__Agent__) */ diff --git a/libraries/shared/src/AgentList.cpp b/libraries/shared/src/AgentList.cpp index 15c4abdd85..809ee2af03 100644 --- a/libraries/shared/src/AgentList.cpp +++ b/libraries/shared/src/AgentList.cpp @@ -59,11 +59,15 @@ AgentList* AgentList::getInstance() { return _sharedInstance; } +AgentList::AgentList(char newOwnerType, unsigned int newSocketListenPort) : + _agentBuckets(), + _numAgents(0), + agentSocket(newSocketListenPort), + ownerType(newOwnerType), + socketListenPort(newSocketListenPort), + lastAgentId(0) +{ -AgentList::AgentList(char newOwnerType, unsigned int newSocketListenPort) : agentSocket(newSocketListenPort) { - ownerType = newOwnerType; - socketListenPort = newSocketListenPort; - lastAgentId = 0; } AgentList::~AgentList() { @@ -73,10 +77,6 @@ AgentList::~AgentList() { stopPingUnknownAgentsThread(); } -std::vector& AgentList::getAgents() { - return agents; -} - UDPSocket& AgentList::getAgentSocket() { return agentSocket; } @@ -108,10 +108,9 @@ void AgentList::processAgentData(sockaddr *senderAddress, unsigned char *packetD void AgentList::processBulkAgentData(sockaddr *senderAddress, unsigned char *packetData, int numTotalBytes) { // find the avatar mixer in our agent list and update the lastRecvTime from it - int bulkSendAgentIndex = indexOfMatchingAgent(senderAddress); + Agent* bulkSendAgent = agentWithAddress(senderAddress); - if (bulkSendAgentIndex >= 0) { - Agent *bulkSendAgent = &agents[bulkSendAgentIndex]; + if (bulkSendAgent) { bulkSendAgent->setLastRecvTimeUsecs(usecTimestampNow()); bulkSendAgent->recordBytesReceived(numTotalBytes); } @@ -128,17 +127,18 @@ void AgentList::processBulkAgentData(sockaddr *senderAddress, unsigned char *pac currentPosition += unpackAgentId(currentPosition, &agentID); memcpy(packetHolder + 1, currentPosition, numTotalBytes - (currentPosition - startPosition)); - int matchingAgentIndex = indexOfMatchingAgent(agentID); + Agent* matchingAgent = agentWithID(agentID); - if (matchingAgentIndex < 0) { + if (!matchingAgent) { // we're missing this agent, we need to add it to the list addOrUpdateAgent(NULL, NULL, AGENT_TYPE_AVATAR, agentID); - // theoretically if we can lock the vector we could assume this is size - 1 - matchingAgentIndex = indexOfMatchingAgent(agentID); + // TODO: this is a really stupid way to do this + // Add a reverse iterator and go from the end of the list + matchingAgent = agentWithID(agentID); } - currentPosition += updateAgentWithData(&agents[matchingAgentIndex], + currentPosition += updateAgentWithData(matchingAgent, packetHolder, numTotalBytes - (currentPosition - startPosition)); } @@ -146,10 +146,10 @@ void AgentList::processBulkAgentData(sockaddr *senderAddress, unsigned char *pac int AgentList::updateAgentWithData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes) { // find the agent by the sockaddr - int agentIndex = indexOfMatchingAgent(senderAddress); + Agent* matchingAgent = agentWithAddress(senderAddress); - if (agentIndex != -1) { - return updateAgentWithData(&agents[agentIndex], packetData, dataBytes); + if (matchingAgent) { + return updateAgentWithData(matchingAgent, packetData, dataBytes); } else { return 0; } @@ -171,24 +171,24 @@ int AgentList::updateAgentWithData(Agent *agent, unsigned char *packetData, int return agent->getLinkedData()->parseData(packetData, dataBytes); } -int AgentList::indexOfMatchingAgent(sockaddr *senderAddress) { - for(std::vector::iterator agent = agents.begin(); agent != agents.end(); agent++) { - if (agent->getActiveSocket() != NULL && socketMatch(agent->getActiveSocket(), senderAddress)) { - return agent - agents.begin(); +Agent* AgentList::agentWithAddress(sockaddr *senderAddress) { + for(AgentListIterator agent = begin(); agent != end(); agent++) { + if ((*agent).getActiveSocket() != NULL && socketMatch((*agent).getActiveSocket(), senderAddress)) { + return &*agent; } } - return -1; + return NULL; } -int AgentList::indexOfMatchingAgent(uint16_t agentID) { - for(std::vector::iterator agent = agents.begin(); agent != agents.end(); agent++) { - if (agent->getAgentId() == agentID) { - return agent - agents.begin(); +Agent* AgentList::agentWithID(uint16_t agentID) { + for(AgentListIterator agent = begin(); agent != end(); agent++) { + if ((*agent).getAgentId() == agentID) { + return &*agent; } } - return -1; + return NULL; } uint16_t AgentList::getLastAgentId() { @@ -227,53 +227,46 @@ int AgentList::updateList(unsigned char *packetData, size_t dataBytes) { } bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, char agentType, uint16_t agentId) { - std::vector::iterator agent; + AgentListIterator agent = end(); if (publicSocket != NULL) { - for (agent = agents.begin(); agent != agents.end(); agent++) { - if (agent->matches(publicSocket, localSocket, agentType)) { + for (agent = begin(); agent != end(); agent++) { + if ((*agent).matches(publicSocket, localSocket, agentType)) { // we already have this agent, stop checking break; } } - } else { - agent = agents.end(); - } + } - if (agent == agents.end()) { + if (agent == end()) { // we didn't have this agent, so add them - Agent newAgent = Agent(publicSocket, localSocket, agentType, agentId); + Agent *newAgent = new Agent(publicSocket, localSocket, agentType, agentId); if (socketMatch(publicSocket, localSocket)) { // likely debugging scenario with two agents on local network // set the agent active right away - newAgent.activatePublicSocket(); + newAgent->activatePublicSocket(); } - if (newAgent.getType() == AGENT_TYPE_AUDIO_MIXER && audioMixerSocketUpdate != NULL) { + if (newAgent->getType() == AGENT_TYPE_AUDIO_MIXER && audioMixerSocketUpdate != NULL) { // this is an audio mixer // for now that means we need to tell the audio class // to use the local socket information the domain server gave us sockaddr_in *publicSocketIn = (sockaddr_in *)publicSocket; audioMixerSocketUpdate(publicSocketIn->sin_addr.s_addr, publicSocketIn->sin_port); - } else if (newAgent.getType() == AGENT_TYPE_VOXEL) { - newAgent.activatePublicSocket(); + } else if (newAgent->getType() == AGENT_TYPE_VOXEL) { + newAgent->activatePublicSocket(); } - printLog("Added agent - "); - Agent::printLog(newAgent); - - pthread_mutex_lock(&vectorChangeMutex); - agents.push_back(newAgent); - pthread_mutex_unlock(&vectorChangeMutex); + addAgentToList(newAgent); return true; } else { - if (agent->getType() == AGENT_TYPE_AUDIO_MIXER || agent->getType() == AGENT_TYPE_VOXEL) { + if ((*agent).getType() == AGENT_TYPE_AUDIO_MIXER || (*agent).getType() == AGENT_TYPE_VOXEL) { // until the Audio class also uses our agentList, we need to update // the lastRecvTimeUsecs for the audio mixer so it doesn't get killed and re-added continously - agent->setLastRecvTimeUsecs(usecTimestampNow()); + (*agent).setLastRecvTimeUsecs(usecTimestampNow()); } // we had this agent already, do nothing for now @@ -281,25 +274,41 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, } } +void AgentList::addAgentToList(Agent* newAgent) { + // find the correct array to add this agent to + int bucketIndex = _numAgents / AGENTS_PER_BUCKET; + + if (!_agentBuckets[bucketIndex]) { + _agentBuckets[bucketIndex] = new Agent*[AGENTS_PER_BUCKET](); + } + + _agentBuckets[bucketIndex][_numAgents % AGENTS_PER_BUCKET] = newAgent; + + ++_numAgents; + + printLog("Added agent - "); + Agent::printLog(*newAgent); +} + void AgentList::broadcastToAgents(unsigned char *broadcastData, size_t dataBytes, const char* agentTypes, int numAgentTypes) { - for(std::vector::iterator agent = agents.begin(); agent != agents.end(); agent++) { + for(AgentListIterator agent = begin(); agent != end(); agent++) { // only send to the AgentTypes we are asked to send to. - if (agent->getActiveSocket() != NULL && memchr(agentTypes, agent->getType(), numAgentTypes)) { + if ((*agent).getActiveSocket() != NULL && memchr(agentTypes, (*agent).getType(), numAgentTypes)) { // we know which socket is good for this agent, send there - agentSocket.send(agent->getActiveSocket(), broadcastData, dataBytes); + agentSocket.send((*agent).getActiveSocket(), broadcastData, dataBytes); } } } void AgentList::handlePingReply(sockaddr *agentAddress) { - for(std::vector::iterator agent = agents.begin(); agent != agents.end(); agent++) { + for(AgentListIterator agent = begin(); agent != end(); agent++) { // check both the public and local addresses for each agent to see if we find a match // prioritize the private address so that we prune erroneous local matches - if (socketMatch(agent->getPublicSocket(), agentAddress)) { - agent->activatePublicSocket(); + if (socketMatch((*agent).getPublicSocket(), agentAddress)) { + (*agent).activatePublicSocket(); break; - } else if (socketMatch(agent->getLocalSocket(), agentAddress)) { - agent->activateLocalSocket(); + } else if (socketMatch((*agent).getLocalSocket(), agentAddress)) { + (*agent).activateLocalSocket(); break; } } @@ -307,8 +316,8 @@ void AgentList::handlePingReply(sockaddr *agentAddress) { Agent* AgentList::soloAgentOfType(char agentType) { if (memchr(SOLO_AGENT_TYPES, agentType, sizeof(SOLO_AGENT_TYPES)) != NULL) { - for(std::vector::iterator agent = agents.begin(); agent != agents.end(); agent++) { - if (agent->getType() == agentType) { + for(AgentListIterator agent = begin(); agent != end(); agent++) { + if ((*agent).getType() == agentType) { return &*agent; } } @@ -327,15 +336,15 @@ void *pingUnknownAgents(void *args) { while (!pingUnknownAgentThreadStopFlag) { gettimeofday(&lastSend, NULL); - for(std::vector::iterator agent = agentList->getAgents().begin(); - agent != agentList->getAgents().end(); + for(AgentListIterator agent = agentList->begin(); + agent != agentList->end(); agent++) { - if (agent->getActiveSocket() == NULL - && (agent->getPublicSocket() != NULL && agent->getLocalSocket() != NULL)) { + if ((*agent).getActiveSocket() == NULL + && ((*agent).getPublicSocket() != NULL && (*agent).getLocalSocket() != NULL)) { // ping both of the sockets for the agent so we can figure out // which socket we can use - agentList->getAgentSocket().send(agent->getPublicSocket(), &PACKET_HEADER_PING, 1); - agentList->getAgentSocket().send(agent->getLocalSocket(), &PACKET_HEADER_PING, 1); + agentList->getAgentSocket().send((*agent).getPublicSocket(), &PACKET_HEADER_PING, 1); + agentList->getAgentSocket().send((*agent).getLocalSocket(), &PACKET_HEADER_PING, 1); } } @@ -359,31 +368,21 @@ void AgentList::stopPingUnknownAgentsThread() { } void *removeSilentAgents(void *args) { - std::vector *agents = (std::vector *)args; + AgentList *agentList = (AgentList *)args; double checkTimeUSecs, sleepTime; while (!silentAgentThreadStopFlag) { checkTimeUSecs = usecTimestampNow(); - for(std::vector::iterator agent = agents->begin(); agent != agents->end();) { + for(AgentListIterator agent = agentList->begin(); agent != agentList->end(); agent++) { - pthread_mutex_t* agentDeleteMutex = agent->deleteMutex; - - if ((checkTimeUSecs - agent->getLastRecvTimeUsecs()) > AGENT_SILENCE_THRESHOLD_USECS - && agent->getType() != AGENT_TYPE_VOXEL - && pthread_mutex_trylock(agentDeleteMutex) == 0) { + if ((checkTimeUSecs - (*agent).getLastRecvTimeUsecs()) > AGENT_SILENCE_THRESHOLD_USECS + && (*agent).getType() != AGENT_TYPE_VOXEL) { printLog("Killing agent - "); Agent::printLog(*agent); - // make sure the vector isn't currently adding an agent - pthread_mutex_lock(&vectorChangeMutex); - agent = agents->erase(agent); - pthread_mutex_unlock(&vectorChangeMutex); - - // release the delete mutex and destroy it - pthread_mutex_unlock(agentDeleteMutex); - pthread_mutex_destroy(agentDeleteMutex); + (*agent).setAlive(false); } else { agent++; } @@ -402,7 +401,7 @@ void *removeSilentAgents(void *args) { } void AgentList::startSilentAgentRemovalThread() { - pthread_create(&removeSilentAgentsThread, NULL, removeSilentAgents, (void *)&agents); + pthread_create(&removeSilentAgentsThread, NULL, removeSilentAgents, (void *)this); } void AgentList::stopSilentAgentRemovalThread() { @@ -464,12 +463,74 @@ void AgentList::stopDomainServerCheckInThread() { pthread_join(checkInWithDomainServerThread, NULL); } -int unpackAgentId(unsigned char *packedData, uint16_t *agentId) { - memcpy(agentId, packedData, sizeof(uint16_t)); - return sizeof(uint16_t); +AgentListIterator AgentList::begin() const { + Agent** agentBucket = NULL; + + for (int i = 0; i < _numAgents; i++) { + if (i % AGENTS_PER_BUCKET == 0) { + agentBucket = _agentBuckets[i / AGENTS_PER_BUCKET]; + } + + if (agentBucket[i % AGENTS_PER_BUCKET]->isAlive()) { + return AgentListIterator(this, i); + } + } + + return AgentListIterator(this, 0); } -int packAgentId(unsigned char *packStore, uint16_t agentId) { - memcpy(packStore, &agentId, sizeof(uint16_t)); - return sizeof(uint16_t); +AgentListIterator AgentList::end() const { + Agent** agentBucket = _agentBuckets[(_numAgents - 1) / AGENTS_PER_BUCKET]; + + for (int i = _numAgents - 1; i >= 0; i--) { + if (i % AGENTS_PER_BUCKET == 0) { + agentBucket = _agentBuckets[i / AGENTS_PER_BUCKET]; + } + + if (agentBucket[i % AGENTS_PER_BUCKET]->isAlive()) { + return AgentListIterator(this, i + 1); + } + } + + return AgentListIterator(this, 0); +} + +AgentListIterator::AgentListIterator(const AgentList* agentList, int agentIndex) : +_agentIndex(agentIndex) { + _agentList = agentList; +} + +AgentListIterator& AgentListIterator::operator=(const AgentListIterator& otherValue) { + _agentList = otherValue._agentList; + _agentIndex = otherValue._agentIndex; + return (*this); +} + +bool AgentListIterator::operator==(const AgentListIterator &otherValue) { + return _agentIndex == otherValue._agentIndex; +} + +bool AgentListIterator::operator!=(const AgentListIterator &otherValue) { + return !(*this == otherValue); +} + +Agent& AgentListIterator::operator*() { + Agent** agentBucket = _agentList->_agentBuckets[_agentIndex / AGENTS_PER_BUCKET]; + return *agentBucket[_agentIndex % AGENTS_PER_BUCKET]; +} + +AgentListIterator& AgentListIterator::operator++() { + if (*this != _agentList->end()) { + ++_agentIndex; + } + + return (*this); +} + +AgentListIterator& AgentListIterator::operator++(int) { + if (*this != _agentList->end()) { + ++_agentIndex; + } + + return (*this); } diff --git a/libraries/shared/src/AgentList.h b/libraries/shared/src/AgentList.h index 76d6917168..8ac1e984c3 100644 --- a/libraries/shared/src/AgentList.h +++ b/libraries/shared/src/AgentList.h @@ -9,8 +9,8 @@ #ifndef __hifi__AgentList__ #define __hifi__AgentList__ -#include #include +#include #include "Agent.h" #include "UDPSocket.h" @@ -19,6 +19,9 @@ #include "pthread.h" #endif +const int MAX_NUM_AGENTS = 10000; +const int AGENTS_PER_BUCKET = 100; + const int MAX_PACKET_SIZE = 1500; const unsigned int AGENT_SOCKET_LISTEN_PORT = 40103; const int AGENT_SILENCE_THRESHOLD_USECS = 2 * 1000000; @@ -28,15 +31,21 @@ extern char DOMAIN_HOSTNAME[]; extern char DOMAIN_IP[100]; // IP Address will be re-set by lookup on startup extern const int DOMAINSERVER_PORT; +class AgentListIterator; + class AgentList { public: static AgentList* createInstance(char ownerType, unsigned int socketListenPort = AGENT_SOCKET_LISTEN_PORT); static AgentList* getInstance(); + + AgentListIterator begin() const; + AgentListIterator end() const; void(*linkedDataCreateCallback)(Agent *); void(*audioMixerSocketUpdate)(in_addr_t, in_port_t); - std::vector& getAgents(); + int size() { return _numAgents; } + UDPSocket& getAgentSocket(); uint16_t getLastAgentId(); @@ -44,8 +53,8 @@ public: int updateList(unsigned char *packetData, size_t dataBytes); - int indexOfMatchingAgent(sockaddr *senderAddress); - int indexOfMatchingAgent(uint16_t agentID); + Agent* agentWithAddress(sockaddr *senderAddress); + Agent* agentWithID(uint16_t agentID); bool addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, char agentType, uint16_t agentId); @@ -67,6 +76,8 @@ public: void stopDomainServerCheckInThread(); void startPingUnknownAgentsThread(); void stopPingUnknownAgentsThread(); + + friend AgentListIterator; private: static AgentList* _sharedInstance; @@ -75,10 +86,13 @@ private: AgentList(AgentList const&); // Don't implement, needed to avoid copies of singleton void operator=(AgentList const&); // Don't implement, needed to avoid copies of singleton + void addAgentToList(Agent* newAgent); + + Agent** _agentBuckets[MAX_NUM_AGENTS / AGENTS_PER_BUCKET]; + int _numAgents; UDPSocket agentSocket; char ownerType; unsigned int socketListenPort; - std::vector agents; uint16_t lastAgentId; pthread_t removeSilentAgentsThread; pthread_t checkInWithDomainServerThread; @@ -87,7 +101,23 @@ private: void handlePingReply(sockaddr *agentAddress); }; -int unpackAgentId(unsigned char *packedData, uint16_t *agentId); -int packAgentId(unsigned char *packStore, uint16_t agentId); +class AgentListIterator : public std::iterator { +public: + AgentListIterator(const AgentList* agentList, int agentIndex); + ~AgentListIterator() {}; + + AgentListIterator& operator=(const AgentListIterator& otherValue); + + bool operator==(const AgentListIterator& otherValue); + bool operator!= (const AgentListIterator& otherValue); + + Agent& operator*(); + + AgentListIterator& operator++(); + AgentListIterator& operator++(int); +private: + const AgentList* _agentList; + int _agentIndex; +}; #endif /* defined(__hifi__AgentList__) */ diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 1d2b961d93..572963b94e 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -129,17 +129,9 @@ void eraseVoxelTreeAndCleanupAgentVisitData() { Agent *thisAgent = (Agent *)&AgentList::getInstance()->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); - // clean up the agent visit data 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); } } @@ -185,10 +177,6 @@ void *distributeVoxelsToListeners(void *args) { viewFrustum.dump(); } - // 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; @@ -226,10 +214,6 @@ void *distributeVoxelsToListeners(void *args) { 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