gpt4 book ai didi

c++ - 两个线程各自获取自己的存储在映射中的对象拷贝

转载 作者:搜寻专家 更新时间:2023-10-31 00:44:29 24 4
gpt4 key购买 nike

标题说明了一切,我认为将对象存储在对象容器中将允许轻松的跨线程类成员访问,因为它实质上将对象存储在由对象容器管理的内存空间中,在这个案例 map 。这是不正确的吗?因为正在发生以下情况;

客户端类:

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*/
};

map

typedef std::map<std::string, Client> clientMap;
clientMap clientmap;
  1. 服务器启动
  2. Boost 线程已启动 (1),它会不断检查值。这个想法是,如果服务器上发生某些事情,所有符合条件的客户端都会收到通知。为了实现这一点,消息被添加到客户端类的双端队列中。
  3. 服务器不断接受新的客户端连接,每个连接都有自己的线程 (ClientThread)。
  4. 客户端对象在该线程内创建(2)
  5. 客户端类的构造启动了另一个线程,该线程不断发送存储在客户端类对象的双端队列 (3) 中的消息。

(1) 在main()中创建的boost线程

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) 创建客户端对象并将其添加到 map 中

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)将deque中的所有消息发送给客户端的线程

//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);
}
}
}

如您所见,我添加了一段代码,用于计算类外线程和类内线程中的双端队列。它们都报告了不同的计数器,并且未发送来自类(class)外线程的消息。

enter image description here

所以看起来观察线程 (1) 有自己的 Client 对象实例,即使它存储在映射内部。或者那个方向的东西。

我可能在指针方面做错了什么。有什么想法吗?

最佳答案

您正在复制 Client s 进入 map ,是的,但是无论何时你读出它们,你都在隐式地创建新的 Client通过复制 map 中的那些。新拷贝将具有单独的快照队列。

您可能想使用 std::map<std::string, Client *>std::map<std::string *, Client *> , 并分配你所有的 Client使用new Client(...) (与相应的 delete 秒)。然后,对于您放入 map 中的每个客户,可能只有一个 Client。具有指向它的多个指针拷贝的实例。

关于c++ - 两个线程各自获取自己的存储在映射中的对象拷贝,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8569813/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com