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
// 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<Agent>::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 )
{

View file

@ -907,11 +907,11 @@ void display(void)
// Render avatars of other agents
AgentList *agentList = AgentList::getInstance();
for(std::vector<Agent>::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<Agent>::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);
}
}

View file

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

View file

@ -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__) */

View file

@ -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<Agent>& 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<Agent>::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<Agent>::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<Agent>::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<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.
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<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
// 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<Agent>::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<Agent>::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<Agent> *agents = (std::vector<Agent> *)args;
AgentList *agentList = (AgentList *)args;
double checkTimeUSecs, sleepTime;
while (!silentAgentThreadStopFlag) {
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
&& 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);
}

View file

@ -9,8 +9,8 @@
#ifndef __hifi__AgentList__
#define __hifi__AgentList__
#include <vector>
#include <stdint.h>
#include <iterator>
#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<Agent>& 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<Agent> 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<std::input_iterator_tag, Agent> {
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__) */

View file

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