Указатель на значение в std :: map - PullRequest
3 голосов
/ 16 июля 2009

У меня есть std :: map, которая используется несколькими потоками для хранения данных. Карта объявлена ​​так:

std::map<int, Call> calls;

Из каждого потока мне нужно получить блокировку мьютекса, получить указатель или ссылку на объект, принадлежащий этому потоку, а затем снять блокировку мьютекса. После этого я могу изменить объект, потому что каждый объект используется только одним потоком. Как только поток умирает, соответствующая пара на карте также будет удалена.

Я хотел бы знать, как лучше всего это реализовать. Я думал о двух путях:

1) Я знаю, что это может выглядеть безумно безумно, но все же

std::map<int, Call> calls;
...

{
    mutex.lock();
    Call* callptr = &calls[id];
    mutex.unlock();

   // use callptr
}

или 2) Я думаю, что этот выглядит более разумным

std::map<int, std::auto_ptr<Call> > calls;

...

{
    mutex.lock();
    std::auto_ptr<Call> callptr = map[id];
    mutex.unlock();

    // use callptr

    mutex.lock();
    map[id] = callptr;
    mutex.unlock();
}

Потоки на самом деле создаются в другой DLL, и у меня нет кода для этого. Этот dll, который я пишу, теперь импортируется этим dll и используется. Так что это должно быть реализовано только с помощью std :: map, но кто-нибудь может сказать мне, подходит ли один из этих методов или есть способы сделать его более стабильным.

Спасибо

Ответы [ 3 ]

5 голосов
/ 16 июля 2009

Вы должны использовать итераторы:

mutex.lock();

std::map<int, Call>::iterator callptr = calls.find(id);
callptr->second.foo();
...

mutex.unlock();

Ваше первое решение с указателями проблематично, потому что время жизни объекта на карте неопределенно - оно может быть перемещено, когда дерево перебалансировано, когда элементы вставлены или удалены.

Ваше второе решение вообще не будет работать, потому что std::auto_ptr не соответствует требованиям для mapped_type из std::map - в основном потому, что его конструктор копирования и operator= фактически не копируют. Вероятно, вы не получите ошибку компилятора, но вы получите очень странное поведение во время выполнения.

3 голосов
/ 16 июля 2009

По мне Тема Локальное хранилище - лучший вариант для вас.

Если вам нужны специфичные для потока данные, вы можете использовать Thread Local Storage и полностью исключить необходимость в блокировке карты и мьютекса.

2 голосов
/ 16 июля 2009

Не используйте auto_ptr в контейнерах STL. DO NOT. Разработчики на самом деле обязаны попытаться использовать его там при ошибке компиляции. Стандартные контейнеры имеют тенденцию копировать вещи вокруг. С auto_ptr это очень неправильно.

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