В чем причина того, что Task.IsCompleted использует кэшированные флаги? - PullRequest
4 голосов
/ 26 марта 2020

Я просматривал некоторые детали реализации Task в System.Threading.Tasks (. NET standard 2.0) и наткнулся на этот интересный фрагмент кода:

internal volatile int m_stateFlags;

...

public bool IsCompleted
{
  get
  {
    int stateFlags = m_stateFlags; // enable inlining of IsCompletedMethod by "cast"ing away the volatiliy
    return IsCompletedMethod(stateFlags);
  }
}

// Similar to IsCompleted property, but allows for the use of a cached flags value
// rather than reading the volatile m_stateFlags field.
private static bool IsCompletedMethod(int flags)
{
  return (flags & TASK_STATE_COMPLETED_MASK) != 0;
}

Я понимаю из Чтение справочного руководства C# о том, что существует volatile для предотвращения оптимизации компилятора / среды выполнения / аппаратного обеспечения, которая может привести к переупорядочению операций чтения / записи в поле. Зачем в этом конкретном случае c указывать поле как volatile, чтобы игнорировать его при чтении, назначая его переменной?

Кажется, намеревался, но причина этого неясна для меня. Кроме того, «отбрасывание» волатильности - обычная практика? В каком сценарии ios я бы хотел сделать это по сравнению со сценарием ios Я абсолютно хочу этого избежать?

Любая информация, которая поможет мне понять этот фрагмент кода, более ценится.

Спасибо,

1 Ответ

2 голосов
/ 26 марта 2020

volatile - это синтаксический сахар Volatile.Read и Volatile.Write. Это гарантирует, что любые процессоры будут видеть те же данные в то же время.

Таким образом, выполняется только одно чтение изменчивой переменной. Тогда это может использоваться несколько раз в свойстве, методе (теряя изменчивую природу). Похоже, что он делает снимок переменной и выполняет несколько вычислений для ее значения.

internal volatile int m_stateFlags;

public bool IsCompleted
{
  get
  {
      int stateFlags = m_stateFlags;
      return IsCompletedMethod(stateFlags);
  }
}
...