2015-09-10 2 views
14

Сегодня я пытался объяснить коллеге, что ||= не является потокобезопасным в МРТ. Я решил, что посмотрю на источник Ruby, чтобы попытаться посмотреть, могу ли я указать место, где планировщик Ruby мог бы переключать контекст потока, но у меня возникли проблемы с навигацией по коду. Я надеялся, что кто-то более опытный сможет пройти через файлы, которые попали.Как MRI анализирует оператор `|| =`?

До сих пор я знаю, что Bison принимает parse.y и создает файл parse.c, который вызывает некоторые основные функции. Я вижу, что || разобран как tOROP, но потом я немного потерял то, что произойдет дальше

Также есть какой-то инструмент вроде Ripper, который я могу использовать, чтобы сделать этот процесс немного проще? (И на этой ноте было бы полезно, если бы кто-то мог указать мне, где определяется исходный код Ripper)

+1

Это неатомная операция, поэтому она не является потокобезопасной. Какой здесь конкретный вопрос? Если вам нужна безопасность потоков, вы должны попросить об этом. – tadman

+0

Что делает его неатомным? Я хотел бы иметь возможность следить за исходным кодом, чтобы узнать, что делает это правдой. –

+3

Так же, как 'x + = 1' является неатомным. Для этого требуется чтение, сравнение и (условное) назначение. 'x || = y' эффективно' x = x || y' или 'x = y, если только (x)' в зависимости от того, как именно вы хотите получить. Обратите внимание, что в обоих случаях перед назначением требуется чтение и сравнение (не * false *). В этом промежутке может случиться что-нибудь. Возможно, вам захочется взглянуть на то, что байт-код MRI выражает это утверждение, чтобы знать, что происходит внутри. – tadman

ответ

1

Забыв парсер, если вы посмотрите на код in compile.c here, вы увидите, как инструкции сгенерированы для обработки назначение или операцию. Каждый вызов ADD_INSNL испускает инструкцию. На строке 4553 вы видите , если условие, которое проверяет значение LHS после того, как оно было прочитано кодом, испускаемым вызовом макроса COMPILE по строке 4546, чтобы решить, следует ли назначать новое значение. В течение этого времени другой поток может контролировать и изменять значение, которое было прочитано, поэтому назначение выполняется (или не выполняется), когда это не должно быть.

Как для создания NODE_OP_ASGN_OR, обратитесь к вызову NEW_OP_ASGN_OR (определенному в node.h), вызванному из parse.y в функции new_op_assign_gen().

Надеемся, номера строк не изменятся слишком быстро и недействительны для этих URL-адресов.

Смежные вопросы