#c #gcc
#c #gcc
Вопрос:
Я хочу использовать c для предстоящего проекта, и, пробуя некоторые концепции, которые мне понадобятся, я столкнулся со следующей проблемой. Допустим, у меня есть такая структура:
struct SomeStruct
{
int fixedValue;
int changingValue;
};
В main я помещу экземпляр этой структуры в глобальный указатель и заполню элемент fixedValue . Затем будет несколько потоков, считывающих это фиксированное значение и изменяющих значение изменения. Таким образом, изменение значения должно быть эксклюзивным для каждого потока, т. Е. Каждый поток имеет свой собственный. В идеале я ищу что-то вроде __thread, что позволило бы мне это сделать. Конечно, я мог бы преобразовать changingValue в массив, но это сделало бы код намного более запутанным. Таким образом, мне интересно, есть ли более элегантное решение.
Спасибо!
Комментарии:
1. Что это? Все они будут изменять структуру, или каждый поток должен иметь свою собственную структуру? Ваши спецификации противоречат друг другу.
2. Я не могу представить, как поместить прямое потоковое локальное хранилище в качестве элемента структуры. Альтернативами являются помещение всего этого в TLS или, что, вероятно, лучше, использование
int *changingValue
в качестве указателя на отдельные локальные значения потока.3. @ikegami: будет одна структура, каждый поток должен иметь одно фиксированное значение, но иметь свое собственное изменяющееся значение
4. Они прекрасно объяснили себя: им нужна центральная единая структура, все потоки разделяют
fixedValue
, но каждый поток получает свой собственныйchangingValue
.5. Они прекрасно объяснили себя; проблема в том, что то, что они хотят, невозможно.
Ответ №1:
То, что вы просите, невозможно, потому что ваши требования противоречат друг другу. Вы не можете использовать malloc
для выделения блока памяти, достаточно большого для хранения двух int
, но при этом выделять достаточно памяти для хранения произвольного количества int
объектов, использующих то же malloc
самое .
Комментарии:
1. Ну, то, что я искал, — это в основном синтаксический сахар. Конечно, вам нужно было бы выделить достаточно места, я просто искал способ, которым разработчик мог бы сделать это за меня. Я мог бы изменить changingValue на указатель, malloc, сколько мне нужно места, и убедиться, что потоки просто обращаются к их соответствующему индексу.
2. Повторите «вам нужно будет выделить достаточно места «, нет смысла выделять больше памяти, чем будет использовать структура.
3. Re «то, что я искал, — это в основном синтаксический сахар «, нет, вы специально запросили использование структуры, которая слишком мала, чтобы содержать необходимую информацию.
4. Да, но для структуры потребуется больше места, вот в чем дело. Очевидно, я искал что-то, что сделало бы это за меня. Погода, это может быть сделано с помощью модификатора, такого как __thread, или с использованием некоторой структуры данных ThreadStruct, или просто не реализовано на языке c, был мой вопрос.
5. Повторите » Да, но для структуры потребуется больше места «, нет смысла выделять больше памяти, чем будет использоваться структура.
Ответ №2:
Все подобъекты объекта O имеют тот же класс хранилища, что и O (если таковые имеются). Из этого следует, что если объекты O1 и O2 являются подобъектами одного и того же объекта, то они имеют один и тот же класс хранения, что и друг у друга. Это отражается в том факте, что C не разрешает в объявлениях структур или членов объединения указывать спецификаторы класса хранилища ( static
, extern
, auto
, _Thread_local
, и т.д.). Вместо этого C17 говорит:
Если объект aggregate или union объявлен со спецификатором класса хранения, отличным от
typedef
, свойства, полученные из спецификатора класса хранения, за исключением привязки, также применяются к элементам объекта, и так далее рекурсивно для любых объектов-членов aggregate или union .
(C2017, 6.7.1 / 8)
Вы говорите,
В main я добавлю экземпляр этой структуры в глобальный указатель
, но это не достигнет вашей цели предоставления как одного объекта, общего для потоков, так и нескольких отдельных объектов для каждого потока. Более того, неясно, почему вы вообще собираетесь выделять объект, а не просто объявлять его напрямую.
Если потоки должны совместно fixedValue
использоваться и иметь свои собственные changingValue
s, то они не могут быть полезными членами одной и той же структуры. Вам нужно их разделить. Более того, хотя C имеет встроенную поддержку локального хранилища потоков, начиная с C11, обычно проще и лучше использовать другие механизмы для предоставления данных для каждого потока, такие как локальные переменные функции потока.
Комментарии:
1. Мне нужно выделить его динамически, поскольку мне понадобится более одной такой структуры на основе пользовательского ввода. Я просто упростил пример. Представьте себе что-то вроде инструмента моделирования или решателя. Каждая структура представляет некоторый объект, причем fixedValue является каким-то идентификатором, а changingValue может быть какой-то стоимостью, которую симуляция присваивает этому объекту. Каждый поток будет работать с одним и тем же экземпляром, предоставленным пользователем.
2. Основной поток анализирует этот экземпляр, устанавливает (внешний) идентификатор в фиксированное значение, а затем создает несколько рабочих потоков, которые пытаются найти решение проблемы, тем самым присваивая стоимость changingValue для их решения. Разные потоки могут находить разные решения и, следовательно, назначать этому объекту разную стоимость.
3. @Gorid, если вы хотите отдельное
changingValue
для каждого потока, вам нужно как-то выделить отдельное для каждого потока. Если вы хотите, чтобы основной поток мог получить доступ ко всем из них позже, как это звучит, то ни локальное хранилище потока, ни переменные, локальные для функции потока, не подойдут — основной поток должен явно предоставить хранилище для каждого дочернего элемента для использования.