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-перегрузки. Есть идеи, как обойти?
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;
}
Здравствуйте, 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;
}
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#? Подсветку надо бы поправить.
Здравствуйте, 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
Здравствуйте, 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.
Здравствуйте, 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 мне мозг кривит и теряю суть
Здравствуйте, 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 уже устарело и её нужно вычислить заново.
MM>Господа, я прошу прощения за свой вопрос, но что вообще этот код делает? В смысле "какую задачу решаем"? Чего-то этот CompareExchange мне мозг кривит и теряю суть
[КО] Обновляет значение поля [/КО]
Только атомарно, lock-free и thread-safe (если остальные обращения также идут ч/з interlocked). Малоприменимо.
CompareExchange работает примерно так
lock(field)
{
return field == current?
(field = newValue) : // мозг спит, полноценный if-else писать лень.field
}
Разумеется, на практике оно превращается в одну инструкцию процессора.
Здравствуйте, Sinix, Вы писали:
S>CompareExchange работает примерно так
Не, ну что делает CompareExchange я знаю Просто вот именно в этом примере потерял нить. Может утро такое было В любом случае темка интересная