Заголовок вроде говорит сам за себя, я думал, что хранение объекта в контейнере объекта позволит легко получить перекрестный доступ к элементу класса, потому что он по существу хранит объект в памяти, которая управляется контейнером объекта, в этом бывает карта. Это неверно? Потому что происходит следующее:
Класс клиента:
class Client
{
public:
Client(std::string clientID,SOCKET sock,bool quit);
boost::thread_group *group;
/*CUT*/
std::string clientID;
std::deque<std::string> snapShotsQueue;
SOCKET sock;
bool quit;
void sendMessage(std::string);
void threadSend(Client *client);
void checksnapshots();
/*CUT*/
};
Карта
typedef std::map<std::string, Client> clientMap;
clientMap clientmap;
- Сервер запускается
- Запущен вспомогательный поток (1), который постоянно проверяет значения. Идея заключается в том, что если на сервере происходят определенные события, все соответствующие клиенты получают уведомление. Чтобы это произошло, сообщение добавляется в очередь клиентского класса.
- Сервер постоянно принимает новые клиентские соединения, каждый из которых получает свой собственный поток (ClientThread).
- В этом потоке создается клиентский объект (2)
- Конструкция класса клиента запускает еще один поток, который постоянно отправляет сообщения, хранящиеся в deque (3) объекта класса клиента.
(1) Поток поддержки, созданный в main ()
void alwaysWatching()
{
while(1)
{
/*CUT*/
/* When something that needs to be communcated happens, a message will be formed and stored in the string "thaString" and sent to, in this case, all clients*/
for (clientMap::iterator it2 = clientmap.begin(); it2 != clientmap.end(); ++it2)
{
it2->second.snapShotsQueue.push_back(thaString); //Add to client's deque
//Check how many items are in deque
std::cout << "There are now ";
it2->second.checksnapshots();
std::cout << "Snapshots waiting according to outside watcher" << std::endl;
}
/*CUT*/
}
}
(2) Создание и добавление объекта клиента на карту
DWORD WINAPI ClientThread(LPVOID lpParam)
{
SOCKET sock=(SOCKET)lpParam;
/*CUT*/
std::string clientID = "";
std::stringstream ss;
ss << lpParam; //Socket = clientID
clientID = ss.str();
Client client(clientID,sock,false); //Create object for this client
while(1) //This thread is constantly waiting for messages sent by the client
{
/*CUT*/
//Add clientID to map of clients
if(clientAdded == false)
{
/*CUT*/
clientmap.insert(std::pair<std::string,Client>(clientID,client));
clientAdded = true;
/*CUT*/
}
/*CUT*/
return 0;
}
(3) Поток, который отправляет все сообщения в очереди клиенту
//Struct used to create the thread that will keep on sending messages in deque to the client
struct messageSender
{
messageSender(Client *client) : client(client) { }
void operator()()
{
client->threadSend(client);
}
Client *client;
};
//Client constructor
Client::Client(std::string clientIDs,SOCKET socks,bool quits)
{
/*CUT*/
this->group = new boost::thread_group; //Create boost thread group (for later, possibly)
messageSender startit(this); //Prep new thread for sending snapshot updates
group->create_thread(startit); //Start new thread for snapshot updates
/*CUT*/
}
//The actual function that constantly loops through the deque
void Client::threadSend(Client *client)
{
/*CUT*/
while(1)
{
/*CUT*/
std::cout << "There are now ";
client->checksnapshots();
std::cout << "Snapshots waiting according to class thread queue processor" << std::endl;
/*CUT*/
unsigned int i;
for(i=0; i < client->snapShotsQueue.size(); i++)
{
std::string theString;
theString = client->snapShotsQueue.front(); // this gets the front of the deque
client->snapShotsQueue.pop_front(); // this removes the front of the deque
std::cout << "sending: " << theString << std::endl;
client->sendMessage(theString);
}
}
}
Как вы можете видеть, я добавил фрагмент кода, который считает deque как в потоке вне класса, так и внутри класса. Они оба сообщают о различных счетчиках, и сообщения из потока за пределами класса не отправляются.
Таким образом, похоже, что поток наблюдателя (1) имеет свой собственный экземпляр объекта Client, даже если он хранится внутри карты. Или что-то в этом направлении.
Я, вероятно, делаю что-то не так с указателем. Есть идеи?