[Compare-exchange loop] Как бы сделали вы?
От: Sinix  
Дата: 27.05.10 01:17
Оценка: 5 (1)
Сейчас выглядит так:
    public static T Modify<T>(ref object field, Func<T, T> selector) where T: class
    {
      T current;
      T newValue;
      do
      {
        current = (T)Thread.VolatileRead(ref field);
        newValue = selector(current);
      }
      while (object.ReferenceEquals(
        Interlocked.CompareExchange(ref field, current, newValue),
        current));

      return newValue;
    }


Не устраивает object field. Увы, у Thread.VolatileRead нет generic-перегрузки. Есть идеи, как обойти?
Re: [Compare-exchange loop] Как бы сделали вы?
От: Jolly Roger  
Дата: 27.05.10 01:47
Оценка:
Здравствуйте, Sinix, Вы писали:

Так?

    public static T Modify<T>(ref T field, Func<T, T> selector) where T: class
    {
      T current;
      T newValue;
      do
      {
        current = field;
        Thread.MemoryBarrier();
        newValue = selector(current);
      }
      while (object.ReferenceEquals(
        Interlocked.CompareExchange(ref field, current, newValue),
        current));

      return newValue;
    }
"Нормальные герои всегда идут в обход!"
Re: [Compare-exchange loop] Как бы сделали вы?
От: Sinix  
Дата: 27.05.10 01:50
Оценка: +1 :)
Здравствуйте, Sinix, Вы писали:

UPD. Туплю — можно же отказаться от VolatileRead.

+Конечно же !object.ReferenceEquals(
Re[2]: [Compare-exchange loop] Как бы сделали вы?
От: Sinix  
Дата: 27.05.10 01:53
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

JR>Здравствуйте, Sinix, Вы писали:


JR>Так?


А нужен ли здесь MemoryBarrier? Если current получит старое значение — пойдёт на второй заход, там же CompareExchange.
Re: [Compare-exchange loop] Как бы сделали вы?
От: Sinix  
Дата: 27.05.10 02:00
Оценка: +1
Здравствуйте, Sinix, Вы писали:
UPD 2. А ещё умнее — посмотреть на подписку событий в 4м шарпе и сделать 1-в-1.
Re[3]: [Compare-exchange loop] Как бы сделали вы?
От: Jolly Roger  
Дата: 27.05.10 02:09
Оценка: 14 (1) +1
Здравствуйте, Sinix, Вы писали:

S>А нужен ли здесь MemoryBarrier? Если current получит старое значение — пойдёт на второй заход, там же CompareExchange.


Так Вы же результат CompareExchange не запоминаете. Без него нужно так, я думаю:

public static T Modify<T>(ref T field, Func<T, T> selector) where T: class
    {
      T current;
      T newValue;
      T current2 = field;
      do
      {
        current = current2;
        newValue = selector(current);
        current2 = Interlocked.CompareExchange<T>(ref field, current, newValue)
      }
      while (!object.ReferenceEquals(current2, current));

      return newValue;
    }
"Нормальные герои всегда идут в обход!"
Re[4]: [Compare-exchange loop] Как бы сделали вы?
От: Sinix  
Дата: 27.05.10 03:28
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

Да. Примерно так работает подписчики событий. Уже подглядел и исправил.
Re[5]: [Compare-exchange loop] Как бы сделали вы?
От: Jolly Roger  
Дата: 27.05.10 04:14
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Jolly Roger, Вы писали:


S>Да. Примерно так работает подписчики событий. Уже подглядел и исправил.


Так это, как сказал здесь remark
Автор: remark
Дата: 01.03.10
фактически стандартная реализация.

А как Вы посмотрели? Что-то то я не могу в рефлекторе их найти, не соображу, где искать
"Нормальные герои всегда идут в обход!"
Re[6]: [Compare-exchange loop] Как бы сделали вы?
От: Jolly Roger  
Дата: 27.05.10 04:18
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

JR>Так это, как сказал здесь remark
Автор: remark
Дата: 01.03.10
фактически стандартная реализация.


Да, забыл сказать, к чему я ссылку-то привёл — оценку скорее remark'у стоит ставить, нежели мне
"Нормальные герои всегда идут в обход!"
Re[6]: [Compare-exchange loop] Как бы сделали вы?
От: Sinix  
Дата: 27.05.10 04:26
Оценка: 10 (1)
Здравствуйте, Jolly Roger, Вы писали:

JR>А как Вы посмотрели?


Компилируем и смотрим.
  Скрытый текст
// public event EventHandler AAA ->

public event EventHandler AAA
{
    add
    {
        EventHandler handler2;
        EventHandler aAA = this.AAA;
        do
        {
            handler2 = aAA;
            EventHandler handler3 = (EventHandler) Delegate.Combine(handler2, value);
            aAA = Interlocked.CompareExchange<EventHandler>(ref this.AAA, handler3, handler2);
        }
        while (aAA != handler2);
    }
    remove
    {
        EventHandler handler2;
        EventHandler aAA = this.AAA;
        do
        {
            handler2 = aAA;
            EventHandler handler3 = (EventHandler) Delegate.Remove(handler2, value);
            aAA = Interlocked.CompareExchange<EventHandler>(ref this.AAA, handler3, handler2);
        }
        while (aAA != handler2);
    }
}


Или (аналогично вашему коду).

    public static T Modify<T>(ref T field, Func<T, T> selector) where T: class
    {
      T result;
      T prevValue;
      T actualValue = field;

      do
      {
        prevValue = actualValue;
        result = selector(prevValue);
        actualValue = Interlocked.CompareExchange(ref field, result, prevValue);
      }
      while (actualValue != prevValue);

      return result;
    }


P.S. А с каких пор field — ключевое слово c#? Подсветку надо бы поправить.
Re[7]: [Compare-exchange loop] Как бы сделали вы?
От: Jolly Roger  
Дата: 27.05.10 04:42
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Компилируем и смотрим.


Действительно, однозначно ступил

PS Может заодно подскажете, как скрытый текст в ответ вставлять?
"Нормальные герои всегда идут в обход!"
Re[8]: [Compare-exchange loop] Как бы сделали вы?
От: Sinix  
Дата: 27.05.10 04:50
Оценка: 10 (1) :)
Здравствуйте, Jolly Roger, Вы писали:

JR>PS Может заодно подскажете, как скрытый текст в ответ вставлять?


Тестирование форматтера
Автор: AndrewVK
Дата: 22.01.10
.
*намёк: к чему я ссылку-то привёл (с)

А также
  Скрытый текст
нажимаем "ответить на сообщение" и смотрим тег
Re[7]: [Compare-exchange loop] Как бы сделали вы?
От: Пельмешко Россия blog
Дата: 27.05.10 06:10
Оценка: 14 (1) :)
Здравствуйте, Sinix, Вы писали:

S>P.S. А с каких пор field — ключевое слово c#? Подсветку надо бы поправить.


Ох, с давних-давних пор

17.2 Attribute specification

Attribute specification is the application of a previously defined attribute to a declaration. An attribute is a piece of additional declarative information that is specified for a declaration. Attributes can be specified at global scope (to specify attributes on the containing assembly or module) and for type-declarations (§9.6), class-member-declarations (§10.1.5), interface-member-declarations (§13.2), struct-member-declarations (§11.2), enum-member-declarations (§14.3), accessor-declarations (§10.7.2), event-accessor-declarations (§10.8.1), and formal-parameter-lists (§10.6.1)

global-attribute-target:
   assembly
   module

attribute-target:
   field
   event
   method
   param
   property
   return
   type
Re[8]: [Compare-exchange loop] Как бы сделали вы?
От: Sinix  
Дата: 27.05.10 06:29
Оценка:
Здравствуйте, Пельмешко, Вы писали:

S>>P.S. А с каких пор field — ключевое слово c#? Подсветку надо бы поправить.

П>Ох, с давних-давних пор
Тьху ты

Если стремиться к совершенству, то contextual keyword надо бы подсвечивать в соответствующих местах. Только кому оно надо.
Re[8]: [Compare-exchange loop] Как бы сделали вы?
От: _FRED_ Черногория
Дата: 27.05.10 06:41
Оценка:
Здравствуйте, Пельмешко, Вы писали:

S>>P.S. А с каких пор field — ключевое слово c#? Подсветку надо бы поправить.


П>Ох, с давних-давних пор

П>17.2 Attribute specification


И где там сказано про "field — ключевое слово"?
Help will always be given at Hogwarts to those who ask for it.
Re[9]: [Compare-exchange loop] Как бы сделали вы?
От: _FRED_ Черногория
Дата: 27.05.10 06:45
Оценка: +1
Здравствуйте, Sinix, Вы писали:

S>>>P.S. А с каких пор field — ключевое слово c#? Подсветку надо бы поправить.

П>>Ох, с давних-давних пор
S>Тьху ты

S>Если стремиться к совершенству, то contextual keyword надо бы подсвечивать в соответствующих местах. Только кому оно надо.


"field" — это и не contextual keyword (Список кейвордов и контекстуал кейвордов здесь). А форматер, говорят, на регексах [пока ] сделан, так что лучше уж так, ИМХО, чем вообще никак.

Хотя вот что касается атрибут-таргетов, я бы их в [c#]/[/c#] не закрашивал — именно из-за "прямолинейности" реализации.
Help will always be given at Hogwarts to those who ask for it.
Re: [Compare-exchange loop] Как бы сделали вы?
От: MxMsk Португалия  
Дата: 27.05.10 06:51
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Сейчас выглядит так:

S>
S>    public static T Modify<T>(ref object field, Func<T, T> selector) where T: class
S>    {
S>      T current;
S>      T newValue;
S>      do
S>      {
S>        current = (T)Thread.VolatileRead(ref field);
S>        newValue = selector(current);
S>      }
S>      while (object.ReferenceEquals(
S>        Interlocked.CompareExchange(ref field, current, newValue),
S>        current));

S>      return newValue;
S>    }
S>


Господа, я прошу прощения за свой вопрос, но что вообще этот код делает? В смысле "какую задачу решаем"? Чего-то этот CompareExchange мне мозг кривит и теряю суть
Re[2]: [Compare-exchange loop] Как бы сделали вы?
От: Jolly Roger  
Дата: 27.05.10 07:18
Оценка: 11 (2)
Здравствуйте, MxMsk, Вы писали:

MM>Здравствуйте, Sinix, Вы писали:


S>>Сейчас выглядит так:

S>>
S>>    public static T Modify<T>(ref object field, Func<T, T> selector) where T: class
S>>    {
S>>      T current;
S>>      T newValue;
S>>      do
S>>      {
S>>        current = (T)Thread.VolatileRead(ref field);
S>>        newValue = selector(current);
S>>      }
S>>      while (object.ReferenceEquals(
S>>        Interlocked.CompareExchange(ref field, current, newValue),
S>>        current));

S>>      return newValue;
S>>    }
S>>


MM>Господа, я прошу прощения за свой вопрос, но что вообще этот код делает? В смысле "какую задачу решаем"? Чего-то этот CompareExchange мне мозг кривит и теряю суть


CompareExchange проверяет, что с момента предыдущего чтения переменной field её значение не изменилось, а такая ситуация возможна в многопоточном коде, если, например, два потока одновременно вызовут данную функцию. Если значение field не изменилось, то CompareExchange сохраняет в неё новое значение. Если-же изменилось, то это значит, что newValue уже устарело и её нужно вычислить заново.
"Нормальные герои всегда идут в обход!"
Re[2]: [Compare-exchange loop] Как бы сделали вы?
От: Sinix  
Дата: 27.05.10 07:55
Оценка: 5 (1)
Здравствуйте, MxMsk, Вы писали:


MM>Господа, я прошу прощения за свой вопрос, но что вообще этот код делает? В смысле "какую задачу решаем"? Чего-то этот CompareExchange мне мозг кривит и теряю суть


[КО] Обновляет значение поля [/КО]

Только атомарно, lock-free и thread-safe (если остальные обращения также идут ч/з interlocked). Малоприменимо.

CompareExchange работает примерно так
lock(field)
{
  return field == current?
    (field = newValue) : // мозг спит, полноценный if-else писать лень.
    field
}


Разумеется, на практике оно превращается в одну инструкцию процессора.
Re[3]: [Compare-exchange loop] Как бы сделали вы?
От: MxMsk Португалия  
Дата: 27.05.10 16:52
Оценка:
Здравствуйте, Sinix, Вы писали:

S>CompareExchange работает примерно так

Не, ну что делает CompareExchange я знаю Просто вот именно в этом примере потерял нить. Может утро такое было В любом случае темка интересная
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.