Локальное хранилище Thread позволяет многопоточным приложениям иметь отдельный экземпляр данного элемента данных для каждого потока. Если однопоточное приложение будет использовать статические или глобальные данные, это может привести к спорам, тупику или повреждению данных в многопоточном приложении. Одним из примеров является переменная C<errno
>, используемая для хранения кода ошибки, связанного с функциями из библиотеки Standard C. Это обычная практика (и требуется POSIX) для компиляторов, которые поддерживают многопоточные приложения, чтобы обеспечить отдельный экземпляр<errno
>для каждого потока, чтобы избежать различных потоков, конкурирующих для чтения или обновления значения.
Хотя компиляторы часто предоставляют эту возможность в виде расширений синтаксиса деклараций (например, аннотации<__declspec(thread)
>или<thread
>
на<static
>или объявления переменных пространства имен), такая поддержка не является переносимой и часто ограничена каким-либо образом, например, только поддерживающими типами POD.
<boost::thread_specific_ptr
>обеспечивает переносной механизм для хранения потоков, который работает на всех компиляторах, поддерживаемых.Подъем.Подъем. Каждый экземпляр<boost::thread_specific_ptr
>представляет собой указатель на объект (например,<errno
>), где каждая нить должна иметь различное значение. Значение для текущего потока может быть получено с помощью функции<get()
>члена или с помощью операторов<*
>и<->
>отсчета указателей. Первоначально указатель имеет значение<NULL
>в каждом потоке, но значение для текущего потока может быть установлено с помощью функции члена<reset()
>.
Если значение указателя для текущей нити изменяется с помощью<reset()
>, то предыдущее значение разрушается путем вызова процедуры очистки. Альтернативно, сохраненное значение может быть сброшено до<NULL
>, а предыдущее значение возвращено вызовом функции<release()
>, что позволяет приложению взять на себя ответственность за уничтожение объекта.
При выходе нити уничтожаются предметы, связанные с каждым<boost::thread_specific_ptr
>экземпляром. По умолчанию объект, на который указывает указатель<p
>, разрушается путем вызова<deletep
>, но это может быть отменено для конкретного примера<boost::thread_specific_ptr
>, обеспечивая рутину очистки конструктору. В этом случае объект разрушается путем вызова<func(p)
>, где<func
>- это процедура очистки, подаваемая конструктору. Функции очистки называются в неуказанном порядке. Если процедура очистки устанавливает значение, связанное с экземпляром<boost::thread_specific_ptr
>, который уже был очищен, это значение добавляется в список очистки. Очистка заканчивается, когда нет выдающихся примеров<boost::thread_specific_ptr
>с ценностями.
Примечание: на некоторых платформах очистка потоковых данных не выполняется для потоков, созданных с помощью собственного API платформы. На этих платформах такая очистка производится только для потоков, которые начинаются с<boost::thread
>, если<boost::on_thread_exit()
>не называется вручную из этой нити.
Повышаю. Thread использует адрес экземпляра<thread_specific_ptr
>в качестве ключа конкретных указателей потока. Это позволяет избежать создания/уничтожения ключа, который будет нуждаться в замке для защиты от условий гонки. Это имеет небольшую ответственность за производительность, так как доступ должен быть выполнен с использованием ассоциативного контейнера.
namespace boost
{
template <typename T>
class thread_specific_ptr
{
public:
thread_specific_ptr();
explicit thread_specific_ptr(void (*cleanup_function)(T*));
~thread_specific_ptr();
T* get() const;
T* operator->() const;
T& operator*() const;
T* release();
void reset(T* new_value=0);
};
}
- Requires:
<deletethis->get()
>Хорошо сформирован.
- Effects:
Постройте<thread_specific_ptr
>объект для хранения указателя на объект типа<T
>, специфичный для каждой нити. Функция очистки по умолчанию<delete
>будет использоваться для уничтожения любых потоковых объектов, когда<reset()
>называется, или поток выходит.
- Throws:
<boost::thread_resource_error
>Если произошла ошибка.
- Requires:
<cleanup_function(this->get())
>Никаких исключений.
- Effects:
Постройте<thread_specific_ptr
>объект для хранения указателя на объект типа<T
>, специфичный для каждой нити. Поставляемые<cleanup_function
>будут использоваться для уничтожения любых нитей-местных объектов, когда<reset()
>называется, или нитей выходит.
- Throws:
<boost::thread_resource_error
>Если произошла ошибка.
- Requires:
Все конкретные экземпляры потока, связанные с этим потоком_specific_ptr (за исключением, возможно, одного, связанного с этим потоком), должны быть нулевыми.
- Effects:
Призывает<this->reset()
>очистить связанное значение для текущей нити и разрушает<*this
>.
- Throws:
Ничего.
- Remarks:
Требование обусловлено тем, что для удаления всех этих экземпляров реализация должна быть вынуждена поддерживать список всех потоков, имеющих ассоциированный конкретный ptr, что противоречит цели потока конкретных данных.
![[Note]](/img/note.png) |
Note |
Необходимо позаботиться о том, чтобы любые потоки, все еще работающие после того, как экземпляр<boost::thread_specific_ptr >был уничтожен, не вызывали никаких функций участника на этом экземпляре. |
- Returns:
Указатель, связанный с текущей нитью.
- Throws:
Ничего.
![[Note]](/img/note.png) |
Note |
Начальное значение, связанное с экземпляром<boost::thread_specific_ptr >, составляет<NULL >для каждой нити. |
- Returns:
<this->get()
>
- Throws:
Ничего.
- Requires:
<this->get
>не является<NULL
>.
- Returns:
<*(this->get())
>
- Throws:
Ничего.
- Effects:
Если<this->get()!=new_value
>и<this->get()
>не являются<NULL
>, ссылайтесь<deletethis->get()
>или<cleanup_function(this->get())
>соответственно. Храните<new_value
>как указатель, связанный с текущей нитью.
- Postcondition:
<this->get()==new_value
>
- Throws:
<boost::thread_resource_error
>Если произошла ошибка.
- Effects:
Возврат<this->get()
>и хранение<NULL
>в качестве указателя, связанного с текущей нитью, без вызова функции очистки.
- Postcondition:
<this->get()==0
>
- Throws:
Ничего.