Ориентированные на многопотоковое исполнение статические переменные без mutexing?

«Не вызывать виртуальные методы из конструкторов». Это только иногда PITA, но только потому, что в C # я не могу решить, в какой точке конструктора вызывать конструктор моего базового класса. Почему бы и нет? Инфраструктура .NET позволяет это, так что есть веская причина для C #, чтобы не позволять это?

Черт!

13
задан Community 23 May 2017 в 12:09
поделиться

5 ответов

Вы правы, что подобная статическая инициализация не является поточно-ориентированной ( здесь - это статья, в которой обсуждается, во что компилятор ее превратит)

На данный момент, не существует стандартного, поточно-безопасного, переносимого способа инициализации статических синглтонов. Можно использовать блокировку с двойной проверкой, но вам понадобятся потенциально непереносимые библиотеки потоков (см. Обсуждение здесь ).

Вот несколько вариантов, если безопасность потоков является обязательной:

  1. Не используйте Ленивый (загружен): инициализировать во время статической инициализации. Это может быть проблемой, если другая статика вызовет эту функцию в своем конструкторе, поскольку порядок статической инициализации не определен (см. здесь ).
  2. Используйте boost (как вы сказали) или Loki
  3. Roll ваш собственный синглтон на поддерживаемых вами платформах (вероятно, следует избегать, если вы эксперт по потокам)
  4. Блокируйте мьютекс каждый раз, когда вам нужен доступ. Это может быть очень медленным.

Пример для 1:

// in a cpp:
namespace {
    Dog dog("Lassie");
}

Dog* MyClass::BadMethod()
{
  return &dog;
}

Пример для 4:

Dog* MyClass::BadMethod()
{
  static scoped_ptr<Dog> pdog;
  {
     Lock l(Mutex);
     if(!pdog.get())
       pdog.reset(new Dog("Lassie"));
  }
  return pdog.get();
}
10
ответ дан 1 December 2019 в 22:40
поделиться

Не уверен, что вы имеете в виду или нет, но вы можете удалить зависимость ускорения в системах POSIX, вызвав вместо этого pthread_once . Я полагаю, вам нужно было бы сделать что-то другое в Windows, но избегать этого, в первую очередь, у boost есть библиотека потоков, и почему люди платят цену, зависящую от нее.

Выполнение чего-либо «поточно-безопасно» неотъемлемо связан с реализацией ваших потоков. Вы должны зависеть от чего-то , даже если это только платформо-зависимая модель памяти. В чистом C ++ 03 просто невозможно предположить что-либо о потоках, которые выходят за рамки языка.

4
ответ дан 1 December 2019 в 22:40
поделиться

Один из способов сделать это, не требующий мьютекса для обеспечения безопасности потоков, - это сделать синглтон статическим файлом, а не статической функцией:

static Dog dog("Lassie");
Dog* MyClass::BadMethod()
{
  return &dog;
}

The Dog экземпляр будет инициализирован перед запуском основного потока. Статические переменные файла имеют известную проблему с порядком инициализации, но пока Dog не полагается на какие-либо другие статические параметры, определенные в другой единице трансляции, это не должно вызывать беспокойства.

3
ответ дан 1 December 2019 в 22:40
поделиться

Комментарий Мартина Коничека, чтобы полностью отключить выбор элементов самым простым способом:

<ListView>
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="Focusable" Value="false"/>
        </Style>
    </ListView.ItemContainerStyle>
    ...
</ListView>

Однако, если вам по-прежнему требуются функциональные возможности ListView, например возможность выбора элемента, вы можете визуально отключить стиль выбранного элемента следующим образом:

Вы можете сделать это несколькими способами, от изменения ListViewItem ControlTemplate , чтобы просто установить стиль (намного проще). Затем вы создаете MyInit () для создания и уничтожения одного объекта каждого типа, который содержит одну из этих статик.

Единственная альтернатива - наложить еще одно ограничение на то, как они могут использовать ваш сгенерированный код (используйте Boost, потоки Win32 и т. Д.). На мой взгляд, любое из этих решений приемлемо - можно создавать правила, которым они должны следовать.

Если они не следуют правилам, изложенным в вашей документации, то все ставки отменены. Правило, согласно которому они должны вызывать функцию инициализации или зависеть от Boost, для меня не является необоснованным.

Можно создавать правила, которым они должны следовать.

Если они не соблюдают правила, изложенные в вашей документации, то все ставки отключены. Правило, согласно которому они должны вызывать функцию инициализации или зависеть от Boost, для меня не является необоснованным.

Можно создавать правила, которым они должны следовать.

Если они не соблюдают правила, изложенные в вашей документации, то все ставки отключены. Правило, согласно которому они должны вызывать функцию инициализации или зависеть от Boost, для меня не является необоснованным.

2
ответ дан 1 December 2019 в 22:40
поделиться

AFAIK, единственный раз, когда это было сделано безопасно и без мьютексов или предварительной инициализации глобальных экземпляров, было в Мэтью Уилсон Imperfect C ++ , в котором обсуждается, как это сделать с помощью «спинового мьютекса». Я не приблизился к своей копии, поэтому сейчас не могу сказать вам более точно.

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

2
ответ дан 1 December 2019 в 22:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: