У меня есть сетевое приложение, в котором несколько пользователей сохраняют свои userContext
на сервере.Пользователи непрерывно отправляют различные запросы на сервер, а сервер обрабатывает их асинхронно, используя пул потоков и цикл обработки событий (например, epoll).
Все пользователи имеют свои собственные идентификаторы.Этот идентификатор уникален по отношению к серверу.Сервер сохраняет пользовательский контекст в map<int,userContext>
.Когда сервер получает сообщение от one user
, он декодирует сообщение.Он также находит, что такое request
и userID
и т. Д. Затем сервер обрабатывает запрос и также обновляет (при необходимости, конечный автомат обновляет в userContext current state
) сохраненный userContext в map
.
В моем приложении много таких вызовов процедур (также немногие вложены), и я передаю пользовательский контекст по value
.Я не могу передать reference
значений карты.(тогда защита больше не существует).
Ниже приведен пример реализации userContextStore
и двух процедур.
class userContext {
public:
int id;
int value1;
int value2;
userContext():id(-1),value1(-1),value2(-1){}
userContext(const userContext &context) {
this->id = context.id;
this->value1 = context.value1;
this->value2 = context.value2;
}
};
class contextStore {
public:
map<int,userContext> Map;
std::mutex m;
void update(userContext context,int id) {
lock_guard<std::mutex> lock(m);
if(Map.find(id) != Map.end()) {
Map[id] = context;
return;
}
Map[id] = context;
}
userContext getUserContext(int id) {
lock_guard<std::mutex> lock(m);
userContext context(Map[id]);
return context;
}
void printContext(int id) {
lock_guard<std::mutex> lock(m);
if(Map.find(id) != Map.end()) {
userContext temp(Map[id]);
cout << temp.value1 << endl;
cout << temp.value2 << endl;
}
}
};
void procedureA(contextStore &store,userContext context) {
// do some long processing using the provided context
// change context copy in between
// based on the above processing
context.value1 += 20; // example of a change
int id = context.id;
store.update(context,id);
}
void procedureB(contextStore &store,int id) {
userContext context(store.getUserContext(id));
// do some other long processing
// change context copy in between
context.value1 -= 10; // example of a change
store.update(context,id);
}
Есть ли лучший (возможно, способ избежать многократного копирования объекта) для передачи объектов userContext
дляТребуемая модификация внутри определенного вызова процедуры?
Вторая проблема заключается в том, что я использую толстую блокировку, защищающую весь map
.В этом случае, если один запрос пользователя обрабатывается на сервере, запрос другого пользователя не будет обработан.(из-за блокировки защищает всю карту).Есть ли какой-нибудь способ точной блокировки зерна в такой ситуации?
Спасибо!