Вопрос про область действия CER
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 03.05.20 18:16
Оценка:
Накрыли сомнения насчет CER

Мне нужно гарантировано выполнить две операции
1. Удалить из списка
2. Вставить обратно в голову списка

Обе операции безопасны с точки зрения исключений.

RuntimeHelpers.PrepareConstrainedRegions();

try
{
}
finally
{
 List__Remove(x);
 List__PushFront(x);
}

//....
static void List__Remove(Node x)
{
 //....
}

static void List__PushFront(Node x)
{
 //....
}


Когда я из finally вызову методы List__xxxx, там внутри "CER" будет продолжать действовать?

Ну, то есть, всякие внешние "прерыватели" выполнения текущего потока подождут, пока не отработает finally?

Насколько я помню — да.

Но, повторюсь, накрыли сомнения, а снова грузить в себя документацию по этому поводу не хочется
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re: Вопрос про область действия CER
От: romangr Россия  
Дата: 04.05.20 06:37
Оценка: 5 (1)
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Накрыли сомнения насчет CER


КД>
КД>RuntimeHelpers.PrepareConstrainedRegions();

КД>try
КД>{
КД>}
КД>finally
КД>{
КД> List__Remove(x);
КД> List__PushFront(x);
КД>}

КД>//....
КД>static void List__Remove(Node x)
КД>{
КД> //....
КД>}

КД>static void List__PushFront(Node x)
КД>{
КД> //....
КД>}
КД>


КД>Когда я из finally вызову методы List__xxxx, там внутри "CER" будет продолжать действовать?


Насколько я помню нужно весь call graph внутри CER помечать ReliabilityContractAttribute, методы List__Remove и List__PushFront должны стать типа
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
static void List__Remove(Node x)
{
}

[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
static void List__PushFront(Node x)
{
}
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Re[2]: Вопрос про область действия CER
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 04.05.20 07:07
Оценка:
Здравствуйте, romangr, Вы писали:

R>Насколько я помню нужно весь call graph внутри CER помечать ReliabilityContractAttribute, методы List__Remove и List__PushFront должны стать типа


Oh sh... Понакрутят жеж...

У меня почему то в голове стойкое представление что CER — это флаг, который возводится в текущем потоке и не дает его прервать всяким асинхронным исключениям...

Из проблем, с которыми я сталкивался — из finally (CER) нельзя просто так взять и вызвать (виртуальный метод) Dispose. Но можно вызвать обычный/статический метод, который без проблем вызывает Dispose.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[3]: Вопрос про область действия CER
От: romangr Россия  
Дата: 04.05.20 07:14
Оценка: 9 (1)
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Здравствуйте, romangr, Вы писали:


R>>Насколько я помню нужно весь call graph внутри CER помечать ReliabilityContractAttribute, методы List__Remove и List__PushFront должны стать типа


КД>Oh sh... Понакрутят жеж...


Microsoft перехреначил все ссылки на MSDN magazine, но я таки нашел статью — Keep Your Code Running with the Reliability Features of the .NET Framework
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Re[4]: Вопрос про область действия CER
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 04.05.20 08:22
Оценка:
Здравствуйте, romangr, Вы писали:

R>Здравствуйте, Коваленко Дмитрий, Вы писали:


КД>>Здравствуйте, romangr, Вы писали:


R>>>Насколько я помню нужно весь call graph внутри CER помечать ReliabilityContractAttribute, методы List__Remove и List__PushFront должны стать типа


КД>>Oh sh... Понакрутят жеж...


R>Microsoft перехреначил все ссылки на MSDN magazine, но я таки нашел статью — Keep Your Code Running with the Reliability Features of the .NET Framework


Спасибо за ссылку!

Вроде написано по делу. Но, .ля, голова упирается и не хочет это в себя засовывать

  Вот тот код про который упоминал в первом сообщении
 private static void Helper__CacheList__BringToHead(Core_ConnectionOptions node)
 {
  Debug.Assert(!Object.ReferenceEquals(node,null));

  RuntimeHelpers.PrepareConstrainedRegions();       //-------------------- CER

  try
  {
  }
  finally
  {
   Helper__CacheList__Remove__CER(node);
   Helper__CacheList__PushFront__CER(node);
  }//finally                                        //-------------------- /CER
 }//Helper__Cache__BringToHead

 //-----------------------------------------------------------------------
 private static void Helper__CacheList__Remove__CER(Core_ConnectionOptions node)
 {
  Debug.Assert(!Object.ReferenceEquals(node,null));
  
  Debug.Assert(!Object.ReferenceEquals(sm_CacheList__Head,null));
  Debug.Assert(!Object.ReferenceEquals(sm_CacheList__Tail,null));

  if(Object.ReferenceEquals(sm_CacheList__Head,node))
  {
   //Remove from HEAD
   Debug.Assert(Object.ReferenceEquals(node.m_List_Prev,null));

   if(Object.ReferenceEquals(sm_CacheList__Tail,node))
   {
    Debug.Assert(Object.ReferenceEquals(node.m_List_Next,null));

    sm_CacheList__Head=null;
    sm_CacheList__Tail=null;
   }
   else
   {
    Debug.Assert(!Object.ReferenceEquals(sm_CacheList__Head,sm_CacheList__Tail));

    var newHead=node.m_List_Next;

    Debug.Assert(Object.ReferenceEquals(newHead.m_List_Prev,node));

    newHead.m_List_Prev=null;

    sm_CacheList__Head=newHead;
   }//else
  }
  else
  if(Object.ReferenceEquals(sm_CacheList__Tail,node))
  {
   //Remove from TAIL      
   Debug.Assert(Object.ReferenceEquals(node.m_List_Next,null));

   Debug.Assert(!Object.ReferenceEquals(sm_CacheList__Head,node));

   var newTail=node.m_List_Prev;

   Debug.Assert(Object.ReferenceEquals(newTail.m_List_Next,node));

   newTail.m_List_Next=null;

   sm_CacheList__Tail=newTail;
  }
  else
  {
   //Remove middle list item
   Debug.Assert(!Object.ReferenceEquals(sm_CacheList__Head,sm_CacheList__Tail));
   Debug.Assert(!Object.ReferenceEquals(sm_CacheList__Head.m_List_Next,sm_CacheList__Tail));
   Debug.Assert(!Object.ReferenceEquals(sm_CacheList__Head,sm_CacheList__Tail.m_List_Prev));

   Debug.Assert(!Object.ReferenceEquals(sm_CacheList__Head,node));
   Debug.Assert(!Object.ReferenceEquals(sm_CacheList__Tail,node));

   Debug.Assert(!Object.ReferenceEquals(node.m_List_Prev,null));
   Debug.Assert(!Object.ReferenceEquals(node.m_List_Next,null));

   Debug.Assert(Object.ReferenceEquals(node.m_List_Prev.m_List_Next,node));
   Debug.Assert(Object.ReferenceEquals(node.m_List_Next.m_List_Prev,node));

   node.m_List_Prev.m_List_Next=node.m_List_Next;
   node.m_List_Next.m_List_Prev=node.m_List_Prev;
  }//else

  node.m_List_Prev=null;
  node.m_List_Next=null;
 }//Helper__CacheList__Remove__CER

 //-----------------------------------------------------------------------
 private static void Helper__CacheList__PushFront__CER(Core_ConnectionOptions node)
 {
  Debug.Assert(!Object.ReferenceEquals(node,null));
  Debug.Assert(Object.ReferenceEquals(node.m_List_Prev,null));
  Debug.Assert(Object.ReferenceEquals(node.m_List_Next,null));

  if(Object.ReferenceEquals(sm_CacheList__Head,null))
  {
   Debug.Assert(Object.ReferenceEquals(sm_CacheList__Tail,null));

   sm_CacheList__Head=node;
   sm_CacheList__Tail=node;

   return;
  }//if

  Debug.Assert(!Object.ReferenceEquals(sm_CacheList__Head,null));
  Debug.Assert(!Object.ReferenceEquals(sm_CacheList__Tail,null));

  Debug.Assert(!Object.ReferenceEquals(sm_CacheList__Head,node));

  node.m_List_Next=sm_CacheList__Head;

  sm_CacheList__Head.m_List_Prev=node;

  sm_CacheList__Head=node;
 }//Helper__CacheList__PushFront__CER

Я вот теперь думаю, чтобы устранить какие-либо сомнения — эти два метода (Remove и PushFront) стоит встроить прямо в блок finally?
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.