защищенные элементы структуры данных, передаваемые по значению через функции - PullRequest
0 голосов
/ 21 декабря 2018

У меня есть сетевое приложение, в котором несколько пользователей сохраняют свои 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.В этом случае, если один запрос пользователя обрабатывается на сервере, запрос другого пользователя не будет обработан.(из-за блокировки защищает всю карту).Есть ли какой-нибудь способ точной блокировки зерна в такой ситуации?

Спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...