на случай, если кто-нибудь столкнется с этой проблемой в будущем: оказывается, что режимы codemirror обычно не имеют встроенных разумных настроек по умолчанию или, по крайней мере, они не загружаются по умолчанию при использовании CodeMirror.getMode(...)
. В моем случае мне пришлось перейти с
const innerModes = {
js: CodeMirror.getMode({}, { name: "javascript" }),
py: CodeMirror.getMode({}, { name: "python" }),
md: CodeMirror.getMode({}, { name: "markdown" }),
css: CodeMirror.getMode({}, { name: "css" }),
raw: CodeMirror.getMode({}, { name: "text/plain" }),
fetch: CodeMirror.getMode({}, { name: "fetch" })
};
на:
const innerModes = {
js: CodeMirror.getMode(
{ indentUnit: 2, statementIndent: 2 },
{ name: "javascript" }
),
py: CodeMirror.getMode(
{ indentUnit: 4, hangingIndent: 4 },
{ name: "python" }
),
md: CodeMirror.getMode({}, { name: "markdown" }),
css: CodeMirror.getMode({ indentUnit: 2 }, { name: "css" }),
raw: CodeMirror.getMode({}, { name: "text/plain" }),
fetch: CodeMirror.getMode({}, { name: "fetch" })
};
Это не позволило NaN
выйти из функции отступа подрежимов. 116]
InterlockedIncrement/Decrement на процессорах x86 (x86's lock add/dec) автоматически создает барьер памяти /барьер памяти , который дает видимость всем потокам (i. e., все потоки могут видеть его обновление в порядке очереди, например, последовательность памяти). Барьер памяти делает возможным завершение всех ожидающих загрузки/сохранения памяти. volatile
не имеет отношения к этому вопросу, хотя C# и Java (и некоторые компиляторы C/C++) усиливают volatile
для создания барьера памяти. Но, при блокировке уже есть барьер памяти от процессора.
Пожалуйста, взгляните также на мой другой ответ в стековом переполнении.
Обратите внимание, что я предположил, что InterlockedIncrement/Decrement (Блокировка/Инкремент/Инкремент) C# является имманентным отображением дополнения/декадры блокировки x86.
На самом деле они не. Если Вы хотите безопасно изменить counter
, затем Вы делаете корректную вещь. Но если Вы хотите читать counter
непосредственно необходимо объявить это как volatile
. Иначе компилятор не имеет никакой причины верить этому counter
изменится потому что Interlocked
операции находятся в коде, который это не могло бы видеть.
Взаимно блокируемый гарантирует, что только 1 поток за один раз может обновить значение. Чтобы гарантировать, что другие потоки могут считать правильное значение (и не кэшируемое значение) отмечают его как энергозависимый.
общедоступный энергозависимый международный Счетчик;
Могу ли я предположить, что изменение, сделанное Блокировкой, будет видно во всех потоках?
Это зависит от того, как вы читаете значение. Если вы "просто" прочитаете его, то нет, это не всегда будет видно в других потоках, если только вы не пометите его как изменчивое. Однако это вызывает раздражающее предупреждение.
В качестве альтернативы (и предпочтительного IMO), прочтите его, используя другую заблокированную инструкцию. Она всегда будет видеть обновленное значение во всех потоках:
int readvalue = Interlocked.CompareExchange(ref counter, 0, 0);
, которое возвращает прочитанное значение, и если оно было 0, то меняет его на 0.
Motivation: предупреждение намекает, что что-то не так; комбинация двух техник (volatile & interlocked) не была предназначена для этого.
Обновление: похоже, что другим подходом к надежному 32-битному чтению без использования "volatile" является использование Thread.VolatileRead
, как предлагалось в этом ответе . Есть также некоторые доказательства того, что я совершенно не прав в использовании Interlocked
для 32-битных чтений, например this Connect issue, хотя мне интересно, не является ли это различие немного педантичным по своей природе.
На самом деле я имею в виду: не используйте этот ответ в качестве единственного источника; я сомневаюсь в этом.