initial transition from vector to multi-dimensional array in AgentList

This commit is contained in:
Stephen Birarda 2013-04-25 13:11:13 -07:00
parent 9802940f8c
commit 836d286b75
7 changed files with 226 additions and 145 deletions

View file

@ -301,20 +301,19 @@ void Head::simulate(float deltaTime) {
// if the avatar being simulated is mine, then loop through // if the avatar being simulated is mine, then loop through
// all the other avatars to get information about them... // all the other avatars to get information about them...
//------------------------------------------------------------- //-------------------------------------------------------------
if ( _isMine ) if ( _isMine ) {
{
_nearOtherAvatar = false; _nearOtherAvatar = false;
float closestDistance = 10000.0f; float closestDistance = 10000.0f;
AgentList * agentList = AgentList::getInstance(); AgentList* agentList = AgentList::getInstance();
//_numOtherAvatars = 0; //_numOtherAvatars = 0;
for(std::vector<Agent>::iterator agent = agentList->getAgents().begin(); for(AgentListIterator agent = agentList->begin();
agent != agentList->getAgents().end(); agent != agentList->end();
agent++) { agent++) {
if (( agent->getLinkedData() != NULL && ( agent->getType() == AGENT_TYPE_AVATAR ) )) { if ((*agent).getLinkedData() != NULL && (*agent).getType() == AGENT_TYPE_AVATAR) {
Head *otherAvatar = (Head *)agent->getLinkedData(); Head *otherAvatar = (Head *)(*agent).getLinkedData();
// if ( _numOtherAvatars < MAX_OTHER_AVATARS ) // if ( _numOtherAvatars < MAX_OTHER_AVATARS )
{ {

View file

@ -907,11 +907,11 @@ void display(void)
// Render avatars of other agents // Render avatars of other agents
AgentList *agentList = AgentList::getInstance(); AgentList *agentList = AgentList::getInstance();
for(std::vector<Agent>::iterator agent = agentList->getAgents().begin(); for(AgentListIterator agent = agentList->begin();
agent != agentList->getAgents().end(); agent != agentList->end();
agent++) { agent++) {
if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) { if ((*agent).getLinkedData() != NULL && (*agent).getType() == AGENT_TYPE_AVATAR) {
Head *avatar = (Head *)agent->getLinkedData(); Head *avatar = (Head *)(*agent).getLinkedData();
avatar->render(0); avatar->render(0);
} }
} }
@ -980,12 +980,13 @@ void display(void)
glPointSize(1.0f); glPointSize(1.0f);
char agents[100]; char agents[100];
int totalAgents = AgentList::getInstance()->getAgents().size(); AgentList *agentList = AgentList::getInstance();
int totalAvatars = 0, totalServers = 0; int totalAvatars = 0, totalServers = 0;
for (int i = 0; i < totalAgents; i++) {
(AgentList::getInstance()->getAgents()[i].getType() == AGENT_TYPE_AVATAR) for (AgentListIterator agent = agentList->begin(); agent != agentList->end(); agent++) {
? totalAvatars++ : totalServers++; (*agent).getType() == AGENT_TYPE_AVATAR ? totalAvatars++ : totalServers++;
} }
sprintf(agents, "Servers: %d, Avatars: %d\n", totalServers, totalAvatars); sprintf(agents, "Servers: %d, Avatars: %d\n", totalServers, totalAvatars);
drawtext(WIDTH-150,20, 0.10, 0, 1.0, 0, agents, 1, 0, 0); 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... //loop through all the other avatars and simulate them...
AgentList * agentList = AgentList::getInstance(); AgentList * agentList = AgentList::getInstance();
for(std::vector<Agent>::iterator agent = agentList->getAgents().begin(); agent != agentList->getAgents().end(); agent++) for(AgentListIterator agent = agentList->begin(); agent != agentList->end(); agent++) {
{ if ((*agent).getLinkedData() != NULL) {
if (agent->getLinkedData() != NULL) Head *avatar = (Head *)(*agent).getLinkedData();
{
Head *avatar = (Head *)agent->getLinkedData();
avatar->simulate(deltaTime); avatar->simulate(deltaTime);
} }
} }

View file

@ -22,7 +22,19 @@
using shared_lib::printLog; 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) { if (agentPublicSocket != NULL) {
publicSocket = new sockaddr; publicSocket = new sockaddr;
memcpy(publicSocket, agentPublicSocket, sizeof(sockaddr)); memcpy(publicSocket, agentPublicSocket, sizeof(sockaddr));
@ -46,12 +58,11 @@ Agent::Agent(sockaddr *agentPublicSocket, sockaddr *agentLocalSocket, char agent
activeSocket = NULL; activeSocket = NULL;
linkedData = NULL; linkedData = NULL;
_bytesReceivedMovingAverage = NULL; _bytesReceivedMovingAverage = NULL;
deleteMutex = new pthread_mutex_t;
pthread_mutex_init(deleteMutex, NULL);
} }
Agent::Agent(const Agent &otherAgent) { Agent::Agent(const Agent &otherAgent) {
_isAlive = otherAgent._isAlive;
if (otherAgent.publicSocket != NULL) { if (otherAgent.publicSocket != NULL) {
publicSocket = new sockaddr; publicSocket = new sockaddr;
memcpy(publicSocket, otherAgent.publicSocket, sizeof(sockaddr)); memcpy(publicSocket, otherAgent.publicSocket, sizeof(sockaddr));
@ -92,9 +103,6 @@ Agent::Agent(const Agent &otherAgent) {
} else { } else {
_bytesReceivedMovingAverage = NULL; _bytesReceivedMovingAverage = NULL;
} }
deleteMutex = new pthread_mutex_t;
pthread_mutex_init(deleteMutex, NULL);
} }
Agent& Agent::operator=(Agent otherAgent) { Agent& Agent::operator=(Agent otherAgent) {
@ -105,6 +113,7 @@ Agent& Agent::operator=(Agent otherAgent) {
void Agent::swap(Agent &first, Agent &second) { void Agent::swap(Agent &first, Agent &second) {
using std::swap; using std::swap;
swap(first._isAlive, second._isAlive);
swap(first.publicSocket, second.publicSocket); swap(first.publicSocket, second.publicSocket);
swap(first.localSocket, second.localSocket); swap(first.localSocket, second.localSocket);
swap(first.activeSocket, second.activeSocket); swap(first.activeSocket, second.activeSocket);
@ -114,13 +123,9 @@ void Agent::swap(Agent &first, Agent &second) {
swap(first.firstRecvTimeUsecs, second.firstRecvTimeUsecs); swap(first.firstRecvTimeUsecs, second.firstRecvTimeUsecs);
swap(first.lastRecvTimeUsecs, second.lastRecvTimeUsecs); swap(first.lastRecvTimeUsecs, second.lastRecvTimeUsecs);
swap(first._bytesReceivedMovingAverage, second._bytesReceivedMovingAverage); swap(first._bytesReceivedMovingAverage, second._bytesReceivedMovingAverage);
swap(first.deleteMutex, second.deleteMutex);
} }
Agent::~Agent() { Agent::~Agent() {
// the deleteMutex isn't destroyed here
// that's handled by the agent list silent agent removal thread
delete publicSocket; delete publicSocket;
delete localSocket; delete localSocket;
delete linkedData; delete linkedData;

View file

@ -31,8 +31,6 @@ public:
bool matches(sockaddr *otherPublicSocket, sockaddr *otherLocalSocket, char otherAgentType); bool matches(sockaddr *otherPublicSocket, sockaddr *otherLocalSocket, char otherAgentType);
pthread_mutex_t *deleteMutex;
char getType() const; char getType() const;
const char* getTypeName() const; const char* getTypeName() const;
void setType(char newType); void setType(char newType);
@ -58,6 +56,9 @@ public:
AgentData* getLinkedData(); AgentData* getLinkedData();
void setLinkedData(AgentData *newData); void setLinkedData(AgentData *newData);
bool isAlive() const { return _isAlive; };
void setAlive(bool isAlive) { _isAlive = isAlive; };
void recordBytesReceived(int bytesReceived); void recordBytesReceived(int bytesReceived);
float getAverageKilobitsPerSecond(); float getAverageKilobitsPerSecond();
float getAveragePacketsPerSecond(); float getAveragePacketsPerSecond();
@ -73,9 +74,11 @@ private:
double lastRecvTimeUsecs; double lastRecvTimeUsecs;
SimpleMovingAverage* _bytesReceivedMovingAverage; SimpleMovingAverage* _bytesReceivedMovingAverage;
AgentData* linkedData; 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__) */ #endif /* defined(__hifi__Agent__) */

View file

@ -59,11 +59,15 @@ AgentList* AgentList::getInstance() {
return _sharedInstance; 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() { AgentList::~AgentList() {
@ -73,10 +77,6 @@ AgentList::~AgentList() {
stopPingUnknownAgentsThread(); stopPingUnknownAgentsThread();
} }
std::vector<Agent>& AgentList::getAgents() {
return agents;
}
UDPSocket& AgentList::getAgentSocket() { UDPSocket& AgentList::getAgentSocket() {
return agentSocket; return agentSocket;
} }
@ -108,10 +108,9 @@ void AgentList::processAgentData(sockaddr *senderAddress, unsigned char *packetD
void AgentList::processBulkAgentData(sockaddr *senderAddress, unsigned char *packetData, int numTotalBytes) { void AgentList::processBulkAgentData(sockaddr *senderAddress, unsigned char *packetData, int numTotalBytes) {
// find the avatar mixer in our agent list and update the lastRecvTime from it // 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) { if (bulkSendAgent) {
Agent *bulkSendAgent = &agents[bulkSendAgentIndex];
bulkSendAgent->setLastRecvTimeUsecs(usecTimestampNow()); bulkSendAgent->setLastRecvTimeUsecs(usecTimestampNow());
bulkSendAgent->recordBytesReceived(numTotalBytes); bulkSendAgent->recordBytesReceived(numTotalBytes);
} }
@ -128,17 +127,18 @@ void AgentList::processBulkAgentData(sockaddr *senderAddress, unsigned char *pac
currentPosition += unpackAgentId(currentPosition, &agentID); currentPosition += unpackAgentId(currentPosition, &agentID);
memcpy(packetHolder + 1, currentPosition, numTotalBytes - (currentPosition - startPosition)); 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 // we're missing this agent, we need to add it to the list
addOrUpdateAgent(NULL, NULL, AGENT_TYPE_AVATAR, agentID); addOrUpdateAgent(NULL, NULL, AGENT_TYPE_AVATAR, agentID);
// theoretically if we can lock the vector we could assume this is size - 1 // TODO: this is a really stupid way to do this
matchingAgentIndex = indexOfMatchingAgent(agentID); // Add a reverse iterator and go from the end of the list
matchingAgent = agentWithID(agentID);
} }
currentPosition += updateAgentWithData(&agents[matchingAgentIndex], currentPosition += updateAgentWithData(matchingAgent,
packetHolder, packetHolder,
numTotalBytes - (currentPosition - startPosition)); 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) { int AgentList::updateAgentWithData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes) {
// find the agent by the sockaddr // find the agent by the sockaddr
int agentIndex = indexOfMatchingAgent(senderAddress); Agent* matchingAgent = agentWithAddress(senderAddress);
if (agentIndex != -1) { if (matchingAgent) {
return updateAgentWithData(&agents[agentIndex], packetData, dataBytes); return updateAgentWithData(matchingAgent, packetData, dataBytes);
} else { } else {
return 0; return 0;
} }
@ -171,24 +171,24 @@ int AgentList::updateAgentWithData(Agent *agent, unsigned char *packetData, int
return agent->getLinkedData()->parseData(packetData, dataBytes); return agent->getLinkedData()->parseData(packetData, dataBytes);
} }
int AgentList::indexOfMatchingAgent(sockaddr *senderAddress) { Agent* AgentList::agentWithAddress(sockaddr *senderAddress) {
for(std::vector<Agent>::iterator agent = agents.begin(); agent != agents.end(); agent++) { for(AgentListIterator agent = begin(); agent != end(); agent++) {
if (agent->getActiveSocket() != NULL && socketMatch(agent->getActiveSocket(), senderAddress)) { if ((*agent).getActiveSocket() != NULL && socketMatch((*agent).getActiveSocket(), senderAddress)) {
return agent - agents.begin(); return &*agent;
} }
} }
return -1; return NULL;
} }
int AgentList::indexOfMatchingAgent(uint16_t agentID) { Agent* AgentList::agentWithID(uint16_t agentID) {
for(std::vector<Agent>::iterator agent = agents.begin(); agent != agents.end(); agent++) { for(AgentListIterator agent = begin(); agent != end(); agent++) {
if (agent->getAgentId() == agentID) { if ((*agent).getAgentId() == agentID) {
return agent - agents.begin(); return &*agent;
} }
} }
return -1; return NULL;
} }
uint16_t AgentList::getLastAgentId() { 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) { bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, char agentType, uint16_t agentId) {
std::vector<Agent>::iterator agent; AgentListIterator agent = end();
if (publicSocket != NULL) { if (publicSocket != NULL) {
for (agent = agents.begin(); agent != agents.end(); agent++) { for (agent = begin(); agent != end(); agent++) {
if (agent->matches(publicSocket, localSocket, agentType)) { if ((*agent).matches(publicSocket, localSocket, agentType)) {
// we already have this agent, stop checking // we already have this agent, stop checking
break; break;
} }
} }
} else {
agent = agents.end();
} }
if (agent == agents.end()) { if (agent == end()) {
// we didn't have this agent, so add them // 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)) { if (socketMatch(publicSocket, localSocket)) {
// likely debugging scenario with two agents on local network // likely debugging scenario with two agents on local network
// set the agent active right away // 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 // this is an audio mixer
// for now that means we need to tell the audio class // for now that means we need to tell the audio class
// to use the local socket information the domain server gave us // to use the local socket information the domain server gave us
sockaddr_in *publicSocketIn = (sockaddr_in *)publicSocket; sockaddr_in *publicSocketIn = (sockaddr_in *)publicSocket;
audioMixerSocketUpdate(publicSocketIn->sin_addr.s_addr, publicSocketIn->sin_port); audioMixerSocketUpdate(publicSocketIn->sin_addr.s_addr, publicSocketIn->sin_port);
} else if (newAgent.getType() == AGENT_TYPE_VOXEL) { } else if (newAgent->getType() == AGENT_TYPE_VOXEL) {
newAgent.activatePublicSocket(); newAgent->activatePublicSocket();
} }
printLog("Added agent - "); addAgentToList(newAgent);
Agent::printLog(newAgent);
pthread_mutex_lock(&vectorChangeMutex);
agents.push_back(newAgent);
pthread_mutex_unlock(&vectorChangeMutex);
return true; return true;
} else { } 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 // 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 // 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 // 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) { void AgentList::broadcastToAgents(unsigned char *broadcastData, size_t dataBytes, const char* agentTypes, int numAgentTypes) {
for(std::vector<Agent>::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. // 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 // 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) { void AgentList::handlePingReply(sockaddr *agentAddress) {
for(std::vector<Agent>::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 // 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 // prioritize the private address so that we prune erroneous local matches
if (socketMatch(agent->getPublicSocket(), agentAddress)) { if (socketMatch((*agent).getPublicSocket(), agentAddress)) {
agent->activatePublicSocket(); (*agent).activatePublicSocket();
break; break;
} else if (socketMatch(agent->getLocalSocket(), agentAddress)) { } else if (socketMatch((*agent).getLocalSocket(), agentAddress)) {
agent->activateLocalSocket(); (*agent).activateLocalSocket();
break; break;
} }
} }
@ -307,8 +316,8 @@ void AgentList::handlePingReply(sockaddr *agentAddress) {
Agent* AgentList::soloAgentOfType(char agentType) { Agent* AgentList::soloAgentOfType(char agentType) {
if (memchr(SOLO_AGENT_TYPES, agentType, sizeof(SOLO_AGENT_TYPES)) != NULL) { if (memchr(SOLO_AGENT_TYPES, agentType, sizeof(SOLO_AGENT_TYPES)) != NULL) {
for(std::vector<Agent>::iterator agent = agents.begin(); agent != agents.end(); agent++) { for(AgentListIterator agent = begin(); agent != end(); agent++) {
if (agent->getType() == agentType) { if ((*agent).getType() == agentType) {
return &*agent; return &*agent;
} }
} }
@ -327,15 +336,15 @@ void *pingUnknownAgents(void *args) {
while (!pingUnknownAgentThreadStopFlag) { while (!pingUnknownAgentThreadStopFlag) {
gettimeofday(&lastSend, NULL); gettimeofday(&lastSend, NULL);
for(std::vector<Agent>::iterator agent = agentList->getAgents().begin(); for(AgentListIterator agent = agentList->begin();
agent != agentList->getAgents().end(); agent != agentList->end();
agent++) { agent++) {
if (agent->getActiveSocket() == NULL if ((*agent).getActiveSocket() == NULL
&& (agent->getPublicSocket() != NULL && agent->getLocalSocket() != NULL)) { && ((*agent).getPublicSocket() != NULL && (*agent).getLocalSocket() != NULL)) {
// ping both of the sockets for the agent so we can figure out // ping both of the sockets for the agent so we can figure out
// which socket we can use // which socket we can use
agentList->getAgentSocket().send(agent->getPublicSocket(), &PACKET_HEADER_PING, 1); agentList->getAgentSocket().send((*agent).getPublicSocket(), &PACKET_HEADER_PING, 1);
agentList->getAgentSocket().send(agent->getLocalSocket(), &PACKET_HEADER_PING, 1); agentList->getAgentSocket().send((*agent).getLocalSocket(), &PACKET_HEADER_PING, 1);
} }
} }
@ -359,31 +368,21 @@ void AgentList::stopPingUnknownAgentsThread() {
} }
void *removeSilentAgents(void *args) { void *removeSilentAgents(void *args) {
std::vector<Agent> *agents = (std::vector<Agent> *)args; AgentList *agentList = (AgentList *)args;
double checkTimeUSecs, sleepTime; double checkTimeUSecs, sleepTime;
while (!silentAgentThreadStopFlag) { while (!silentAgentThreadStopFlag) {
checkTimeUSecs = usecTimestampNow(); checkTimeUSecs = usecTimestampNow();
for(std::vector<Agent>::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) {
if ((checkTimeUSecs - agent->getLastRecvTimeUsecs()) > AGENT_SILENCE_THRESHOLD_USECS
&& agent->getType() != AGENT_TYPE_VOXEL
&& pthread_mutex_trylock(agentDeleteMutex) == 0) {
printLog("Killing agent - "); printLog("Killing agent - ");
Agent::printLog(*agent); Agent::printLog(*agent);
// make sure the vector isn't currently adding an agent (*agent).setAlive(false);
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);
} else { } else {
agent++; agent++;
} }
@ -402,7 +401,7 @@ void *removeSilentAgents(void *args) {
} }
void AgentList::startSilentAgentRemovalThread() { void AgentList::startSilentAgentRemovalThread() {
pthread_create(&removeSilentAgentsThread, NULL, removeSilentAgents, (void *)&agents); pthread_create(&removeSilentAgentsThread, NULL, removeSilentAgents, (void *)this);
} }
void AgentList::stopSilentAgentRemovalThread() { void AgentList::stopSilentAgentRemovalThread() {
@ -464,12 +463,74 @@ void AgentList::stopDomainServerCheckInThread() {
pthread_join(checkInWithDomainServerThread, NULL); pthread_join(checkInWithDomainServerThread, NULL);
} }
int unpackAgentId(unsigned char *packedData, uint16_t *agentId) { AgentListIterator AgentList::begin() const {
memcpy(agentId, packedData, sizeof(uint16_t)); Agent** agentBucket = NULL;
return sizeof(uint16_t);
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) { AgentListIterator AgentList::end() const {
memcpy(packStore, &agentId, sizeof(uint16_t)); Agent** agentBucket = _agentBuckets[(_numAgents - 1) / AGENTS_PER_BUCKET];
return sizeof(uint16_t);
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);
} }

View file

@ -9,8 +9,8 @@
#ifndef __hifi__AgentList__ #ifndef __hifi__AgentList__
#define __hifi__AgentList__ #define __hifi__AgentList__
#include <vector>
#include <stdint.h> #include <stdint.h>
#include <iterator>
#include "Agent.h" #include "Agent.h"
#include "UDPSocket.h" #include "UDPSocket.h"
@ -19,6 +19,9 @@
#include "pthread.h" #include "pthread.h"
#endif #endif
const int MAX_NUM_AGENTS = 10000;
const int AGENTS_PER_BUCKET = 100;
const int MAX_PACKET_SIZE = 1500; const int MAX_PACKET_SIZE = 1500;
const unsigned int AGENT_SOCKET_LISTEN_PORT = 40103; const unsigned int AGENT_SOCKET_LISTEN_PORT = 40103;
const int AGENT_SILENCE_THRESHOLD_USECS = 2 * 1000000; 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 char DOMAIN_IP[100]; // IP Address will be re-set by lookup on startup
extern const int DOMAINSERVER_PORT; extern const int DOMAINSERVER_PORT;
class AgentListIterator;
class AgentList { class AgentList {
public: public:
static AgentList* createInstance(char ownerType, unsigned int socketListenPort = AGENT_SOCKET_LISTEN_PORT); static AgentList* createInstance(char ownerType, unsigned int socketListenPort = AGENT_SOCKET_LISTEN_PORT);
static AgentList* getInstance(); static AgentList* getInstance();
AgentListIterator begin() const;
AgentListIterator end() const;
void(*linkedDataCreateCallback)(Agent *); void(*linkedDataCreateCallback)(Agent *);
void(*audioMixerSocketUpdate)(in_addr_t, in_port_t); void(*audioMixerSocketUpdate)(in_addr_t, in_port_t);
std::vector<Agent>& getAgents(); int size() { return _numAgents; }
UDPSocket& getAgentSocket(); UDPSocket& getAgentSocket();
uint16_t getLastAgentId(); uint16_t getLastAgentId();
@ -44,8 +53,8 @@ public:
int updateList(unsigned char *packetData, size_t dataBytes); int updateList(unsigned char *packetData, size_t dataBytes);
int indexOfMatchingAgent(sockaddr *senderAddress); Agent* agentWithAddress(sockaddr *senderAddress);
int indexOfMatchingAgent(uint16_t agentID); Agent* agentWithID(uint16_t agentID);
bool addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, char agentType, uint16_t agentId); bool addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, char agentType, uint16_t agentId);
@ -67,6 +76,8 @@ public:
void stopDomainServerCheckInThread(); void stopDomainServerCheckInThread();
void startPingUnknownAgentsThread(); void startPingUnknownAgentsThread();
void stopPingUnknownAgentsThread(); void stopPingUnknownAgentsThread();
friend AgentListIterator;
private: private:
static AgentList* _sharedInstance; static AgentList* _sharedInstance;
@ -75,10 +86,13 @@ private:
AgentList(AgentList const&); // Don't implement, needed to avoid copies of singleton 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 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; UDPSocket agentSocket;
char ownerType; char ownerType;
unsigned int socketListenPort; unsigned int socketListenPort;
std::vector<Agent> agents;
uint16_t lastAgentId; uint16_t lastAgentId;
pthread_t removeSilentAgentsThread; pthread_t removeSilentAgentsThread;
pthread_t checkInWithDomainServerThread; pthread_t checkInWithDomainServerThread;
@ -87,7 +101,23 @@ private:
void handlePingReply(sockaddr *agentAddress); void handlePingReply(sockaddr *agentAddress);
}; };
int unpackAgentId(unsigned char *packedData, uint16_t *agentId); class AgentListIterator : public std::iterator<std::input_iterator_tag, Agent> {
int packAgentId(unsigned char *packStore, uint16_t agentId); 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__) */ #endif /* defined(__hifi__AgentList__) */

View file

@ -129,17 +129,9 @@ void eraseVoxelTreeAndCleanupAgentVisitData() {
Agent *thisAgent = (Agent *)&AgentList::getInstance()->getAgents()[i]; Agent *thisAgent = (Agent *)&AgentList::getInstance()->getAgents()[i];
VoxelAgentData *agentData = (VoxelAgentData *)(thisAgent->getLinkedData()); 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 // clean up the agent visit data
delete agentData->rootMarkerNode; delete agentData->rootMarkerNode;
agentData->rootMarkerNode = new MarkerNode(); 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(); 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; stopOctal = NULL;
packetCount = 0; packetCount = 0;
totalBytesSent = 0; totalBytesSent = 0;
@ -226,10 +214,6 @@ void *distributeVoxelsToListeners(void *args) {
delete agentData->rootMarkerNode; delete agentData->rootMarkerNode;
agentData->rootMarkerNode = new MarkerNode(); 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 // dynamically sleep until we need to fire off the next set of voxels