(file) Return to strand.c CVS log (file) (dir) Up to [OMI] / omi / base

   1 krisbash 1.1 /*
   2              **==============================================================================
   3              **
   4              ** Open Management Infrastructure (OMI)
   5              **
   6              ** Copyright (c) Microsoft Corporation
   7              ** 
   8              ** Licensed under the Apache License, Version 2.0 (the "License"); you may not 
   9              ** use this file except in compliance with the License. You may obtain a copy 
  10              ** of the License at 
  11              **
  12              **     http://www.apache.org/licenses/LICENSE-2.0 
  13              **
  14              ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15              ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
  16              ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
  17              ** MERCHANTABLITY OR NON-INFRINGEMENT. 
  18              **
  19              ** See the Apache 2 License for the specific language governing permissions 
  20              ** and limitations under the License.
  21              **
  22 krisbash 1.1 **==============================================================================
  23              */
  24              #include <base/Strand.h>
  25              #include <base/log.h>
  26              #include <omi_error/errorutil.h>
  27              
  28              //------------------------------------------------------------------------------------------------------------
  29              // Debugging aid
  30              //------------------------------------------------------------------------------------------------------------
  31              
  32              #if defined(STRAND_ENABLE_DEBUG)
  33              StrandBaseDebugInfo _Strand_BaseNameDebugInfo[Strand_NumMethods+5] = { 
  34                  {"<unnamed>",           '@' }, 
  35                  {"S",                   '*' },
  36                  {"CompleteOpenAsync",   '$' }, 
  37                  {"Timer",               '&' }, 
  38                  {"Cancel",              'N' }, 
  39                  {"CancelSelf",          'n' }, 
  40                  {"PostControl",         'T' }, 
  41                  {"Post",                'P' }, 
  42                  {"PostOther",           'p' }, 
  43 krisbash 1.1     {"Ack",                 'A' }, 
  44                  {"AckOther",            'a' }, 
  45                  {"Close",               'C' }, 
  46                  {"CloseOther",          'c' }, 
  47                  {"<Aux0>",              '0' }, 
  48                  {"<Aux1>",              '1' }, 
  49                  {"<Aux2>",              '2' },
  50                  {"<Aux3>",              '3' },
  51                  {"<Aux4>",              '4' },
  52                  {"ERROR!",              '!' },
  53                  {"ERROR!",              '!' },
  54                  {"ERROR!",              '!' } };
  55              StrandBaseDebugInfo _StrandBoth_BaseNameDebugInfo[StrandBoth_NumMethods+5] = { 
  56                  {"<unnamed(both)>",     '@' },
  57                  {"SB",                  '*' },
  58                  {"CompleteOpenAsync",   '$' }, 
  59                  {"Timer",               '&' },
  60                  {"Cancel_Left",         'N' }, 
  61                  {"Cancel_Right",        'E' }, 
  62                  {"CancelSelf_Both",     'n' },
  63                  {"PostControl_Left",    'T' }, 
  64 krisbash 1.1     {"PostControl_Right",   'R' }, 
  65                  {"Post_Left",           'P' },
  66                  {"Post_Right",          'S' }, 
  67                  {"PostOther_Left",      'p' }, 
  68                  {"PostOther_Right",     's' }, 
  69                  {"Ack_Left",            'A' }, 
  70                  {"Ack_Right",           'K' }, 
  71                  {"AckOther_Left",       'a' }, 
  72                  {"AckOther_Right",      'k' },
  73                  {"Close_Left",          'C' }, 
  74                  {"Close_Right",         'L' }, 
  75                  {"CloseOther_Left",     'c' }, 
  76                  {"CloseOther_Right",    'l' }, 
  77                  {"<Aux0_Left>",         '0' }, 
  78                  {"<Aux1_Left>",         '1' },
  79                  {"<Aux2_Left>",         '2' }, 
  80                  {"<Aux3_Left>",         '3' }, 
  81                  {"<Aux4_Left>",         '4' }, 
  82                  {"<Aux0_Right>",        '5' },
  83                  {"<Aux1_Right>",        '6' }, 
  84                  {"<Aux2_Right>",        '7' },
  85 krisbash 1.1     {"<Aux3_Right>",        '8' }, 
  86                  {"<Aux4_Right>",        '9' },
  87                  {"ERROR!",              '!' },
  88                  {"ERROR!",              '!' },
  89                  {"ERROR!",              '!' } };
  90              StrandBaseDebugInfo _StrandMany_BaseNameDebugInfo[StrandMany_NumMethods+5] = { 
  91                  {"<unnamed(many)>",     '@' }, 
  92                  {"SM",                  '*' },
  93                  {"CompleteOpenAsync",   '$' }, 
  94                  {"Timer",               '&' }, 
  95                  {"Cancel(M)",           'N' }, 
  96                  {"CancelSelf(M)",       'n' }, 
  97                  {"CancelInternal",      'E' }, 
  98                  {"PostControl(M)",      'T' }, 
  99                  {"PostControlInternal", 't' }, 
 100                  {"Post(M)",             'P' }, 
 101                  {"PostOther(M)",        'p' }, 
 102                  {"PostInternal",        'S' }, 
 103                  {"Ack(M)",              'A' }, 
 104                  {"AckOther(M)",         'a' }, 
 105                  {"AckInternal",         'K' }, 
 106 krisbash 1.1     {"EntryOperation",      '#' },
 107                  {"Close(M)",            'C' }, 
 108                  {"CloseOther(M)",       'c' }, 
 109                  {"CloseInternal",       'L' }, 
 110                  {"<Aux0(M)>",           '0' }, 
 111                  {"<Aux1(M)>",           '1' }, 
 112                  {"<Aux2(M)>",           '2' },
 113                  {"<Aux3(M)>",           '3' },
 114                  {"<Aux4(M)>",           '4' },
 115                  {"ERROR!",              '!' },
 116                  {"ERROR!",              '!' },
 117                  {"ERROR!",              '!' } };
 118              char * _StrandMany_BaseEntryOperationDebugInfo[StrandMany_NumEntryOperations+3] = { 
 119                  "Add", 
 120                  "Cancel", 
 121                  "PostControl", 
 122                  "Post", 
 123                  "Close", 
 124                  "<Aux0>", 
 125                  "<Aux1>", 
 126                  "<Aux2>",
 127 krisbash 1.1     "<Aux3>",
 128                  "<Aux4>",
 129                  "Deleted", 
 130                  "ERROR!",
 131                  "ERROR!",
 132                  "ERROR!" };
 133              
 134              #if defined(CONFIG_OS_WINDOWS)
 135              #define SPRINTF_FUNC                    sprintf_s
 136              #define STRCPY_FUNC(orig, size, dest)   strcpy_s( (orig), (size), (dest) )
 137              #else
 138              #define SPRINTF_FUNC                    snprintf
 139              #define STRCPY_FUNC(orig, size, dest)   strncpy( (orig), (dest), (size) )
 140              #endif
 141              
 142              
 143              static char * _StrandLogScheduledState( 
 144                  _In_                    ptrdiff_t                   state, 
 145                  _In_                    StrandBaseDebugInfo const * baseDebugInfo, 
 146                                          size_t                      size,
 147                  _Out_writes_(size+4)    char *                      buffer )
 148 krisbash 1.1 {
 149                  ptrdiff_t mask = 1;
 150                  size_t pos = 0;
 151                  size_t bufferPos = 0;
 152              
 153                  buffer[bufferPos++] = baseDebugInfo[1].name[0];
 154                  if( '\0' != baseDebugInfo[1].name[1] )
 155                  {
 156                      buffer[bufferPos++] = baseDebugInfo[1].name[1];
 157                  }
 158                  buffer[bufferPos++] = ':';
 159                  
 160                  while( pos < size )
 161                  {
 162                      if( ( mask & state ) != 0 )
 163                      {
 164                          buffer[bufferPos++] = baseDebugInfo[pos+1].letter;
 165                      }
 166                      mask <<= 1;
 167                      ++pos;
 168                  }
 169 krisbash 1.1     buffer[bufferPos] = '\0';
 170              
 171                  return buffer;
 172              }
 173                  
 174              #define _STRANDLOGINFOSTATE_SIZE    33                                  // 15 + 16 digits(pointer) + possible 0x prefix
 175              #define _STRANDLOGINFOSTATE_MAXSIZE ((_STRANDLOGINFOSTATE_SIZE*2)+13)   // + two state characters + 10 digits(parent) + terminator
 176              
 177              MI_INLINE int _StrandLogInfoState( _In_ InteractionInfo * info, _Out_writes_z_(_STRANDLOGINFOSTATE_SIZE+1) char * buffer )
 178              {
 179                  return SPRINTF_FUNC( buffer, _STRANDLOGINFOSTATE_SIZE, ", %c t:%c%c%co:%c%c %p",
 180                      info->opened ? 'O' : '-',
 181                      info->thisClosedOther ? 'C' : '-',
 182                      info->thisAckPending ? 'A' : '-',
 183                      info->ackPassthru  ? 'P' : ' ',
 184                      info->otherClosedThis ? 'C' : '-',
 185                      info->otherAckPending ? 'A' : '-',
 186                      info->interaction.other );
 187              }
 188              
 189              MI_INLINE int _StrandLogStrandState( _In_ Strand* self, _Out_writes_(2) char * buffer )
 190 krisbash 1.1 {
 191                  int written = 0;
 192                  if( self->canceled )
 193                  {
 194                      buffer[written++] = 'N';
 195                  }
 196                  if( self->delayFinish )
 197                  {
 198                      buffer[written++] = 'D';
 199                  }
 200                  if( 0 == written )
 201                  {
 202                      buffer[written++] = '-';
 203                  }
 204                  
 205                  return written;
 206              }
 207              
 208              MI_INLINE int _StrandLogStrandStateParent( _In_ StrandMany* self, _Out_writes_(10) char * buffer )
 209              {
 210                  return SPRINTF_FUNC( buffer, 10, "%d", (unsigned int)self->numEntries );
 211 krisbash 1.1 }
 212              
 213              MI_INLINE int _StrandLogInfoStateSingle( _In_ Strand* self, _Out_writes_z_(_STRANDLOGINFOSTATE_MAXSIZE) char * buffer )
 214              {
 215                  int written = _StrandLogStrandState( self, buffer );
 216                  DEBUG_ASSERT( written > 0 && written <= 2 );
 217                  return _StrandLogInfoState( &self->info, buffer+written ) + written;
 218              }
 219              
 220              MI_INLINE int _StrandLogInfoStateBoth( _In_ StrandBoth* self, _Out_writes_z_(_STRANDLOGINFOSTATE_MAXSIZE) char * buffer )
 221              {
 222                  int written = _StrandLogStrandState( &self->base, buffer );
 223                  DEBUG_ASSERT( written > 0 && written <= 2 );
 224                  written += _StrandLogInfoState( &self->base.info, buffer+written );
 225                  DEBUG_ASSERT( written > 1 && written <= _STRANDLOGINFOSTATE_SIZE+2 );
 226                  return _StrandLogInfoState( &self->infoRight, buffer+written ) + written;
 227              }
 228              
 229              MI_INLINE int _StrandLogInfoStateParent( _In_ StrandMany* self, _Out_writes_z_(_STRANDLOGINFOSTATE_MAXSIZE) char * buffer )
 230              {
 231                  int written = _StrandLogStrandStateParent( self, buffer );
 232 krisbash 1.1     DEBUG_ASSERT( written > 0 && written <= 10 );
 233                  written += _StrandLogStrandState( &self->strand, buffer+written );
 234                  DEBUG_ASSERT( written > 1 && written <= 12 );
 235                  return _StrandLogInfoState( &self->strand.info, buffer+written ) + written;
 236              }
 237              
 238              MI_INLINE void _StrandLogInfoState_Store( _In_ Strand* strand, _Out_writes_z_(_STRANDLOGINFOSTATE_MAXSIZE) char * buffer )
 239              {
 240                  if( STRAND_TYPE_MIDDLE == (strand)->strandType )
 241                  {
 242                      _StrandLogInfoStateBoth( (StrandBoth*)(strand), buffer);
 243                  }
 244                  else if( STRAND_ISTYPE_PARENT( strand ) )
 245                  {
 246                      _StrandLogInfoStateParent( FromOffset(StrandMany,strand,strand), buffer );
 247                  }
 248                  else
 249                  {
 250                      _StrandLogInfoStateSingle( strand, buffer );
 251                  }
 252              }
 253 krisbash 1.1 
 254              void _StrandLogWithName( _In_ Strand* self, _In_ const char * operation )
 255              {
 256                  trace_Strand_Action( self, STRAND_DEBUG_GETNAME(self), operation );
 257              }
 258              
 259              void _Strand_AssertOnStrand( _In_ Strand* strand )
 260              {
 261                  ThreadID threadId = Thread_ID();
 262                  if( !Thread_Equal(&threadId,&((strand)->testThreadId)) )
 263                  {
 264                      DEBUG_ASSERT( Thread_Equal(&threadId,&((strand)->threadId)) );
 265                      STRAND_ASSERTEXECUTING( strand ); \
 266                  }
 267              } 
 268              #endif
 269                  
 270              #if defined(STRAND_ENABLE_DEBUG)
 271              #define STRAND_DEBUG_GETSTATE_USED   \
 272                  char _buffer_STRAND_DEBUG_GETSTATE[StrandBoth_NumMethods+6]
 273              #define STRAND_DEBUG_GETSTATE( strand, state ) \
 274 krisbash 1.1     _StrandLogScheduledState( state, STRAND_DEBUG_GETBASEINFO(strand), STRAND_DEBUG_GETINFOSIZE(strand)+1, _buffer_STRAND_DEBUG_GETSTATE )
 275              #define STRAND_DEBUG_GETINFOSTATE_USED \
 276                  char _buffer_STRAND_DEBUG_GETINFOSTATE[_STRANDLOGINFOSTATE_MAXSIZE]
 277              #define STRAND_DEBUG_GETINFOSTATE_STORE(strand) \
 278                  _StrandLogInfoState_Store( strand,_buffer_STRAND_DEBUG_GETINFOSTATE) 
 279              #define STRAND_DEBUG_GETINFOSTATE_STORED        (_buffer_STRAND_DEBUG_GETINFOSTATE)
 280              // Note that this uses same buffer as STRAND_DEBUG_GETSTATE
 281              #define STRAND_DEBUG_GETNAME_STORE( strand ) \
 282                  STRCPY_FUNC( _buffer_STRAND_DEBUG_GETSTATE, StrandBoth_NumMethods+6, STRAND_DEBUG_GETNAME(strand) )
 283              #define STRAND_DEBUG_GETNAME_STORED             (_buffer_STRAND_DEBUG_GETSTATE)
 284              
 285              MI_INLINE
 286              void _Strand_TracePostMsg( _In_ Strand* self, _In_ Message* msg, _In_ const char * info )
 287              {
 288                  DEBUG_ASSERT( NULL != self );
 289                  DEBUG_ASSERT( NULL != msg );
 290                  // TODO why is linux crashing when passing info into the trace function on x86?
 291                  MI_UNUSED(info);
 292                  if( PostResultMsgTag == msg->tag )
 293                  {
 294                      PostResultMsg* msgResult = (PostResultMsg*)msg;
 295 krisbash 1.1         trace_Strand_TracePostResult(self, msg, msg->tag, msg->operationId, msgResult->result);
 296                  }
 297                  else
 298                  {
 299                      trace_Strand_TracePost(self, msg, msg->tag, MessageName(msg->tag), msg->operationId);
 300                  }
 301              }
 302              
 303              #else
 304              #define STRAND_DEBUG_GETSTATE_USED   
 305              #define STRAND_DEBUG_GETSTATE( strand, state )  ""
 306              #define STRAND_DEBUG_GETINFOSTATE_USED
 307              #define STRAND_DEBUG_GETINFOSTATE_STORE(strand)
 308              #define STRAND_DEBUG_GETINFOSTATE_STORED        ""
 309              #define STRAND_DEBUG_GETNAME_STORE( strand )
 310              #define STRAND_DEBUG_GETNAME_STORED             ""
 311              
 312              MI_INLINE
 313              void _Strand_TracePostMsg( _In_ Strand* self, _In_ Message* msg, _In_ const char * info )
 314              {
 315              }
 316 krisbash 1.1 
 317              #endif
 318              
 319              #if defined(STRAND_ENABLE_DEBUG)
 320              #define STRAND_SETDEBUG( strand, strandDebugInfo )   (strand)->debug = strandDebugInfo; STRAND_LOGWITHNAME( strand, "Initialize Itself" )
 321              #else
 322              #define STRAND_SETDEBUG( strand, strandDebugInfo )   
 323              #endif
 324              
 325              #if STRAND_ENABLE_DEBUG == 2
 326              static void _StrandLogState( _In_ Strand* self, _In_ const char * infoName, _In_ InteractionInfo * info )
 327              {
 328                  trace_StrandFlags(
 329                      self, 
 330                      STRAND_DEBUG_GETNAME(self), 
 331                      infoName, 
 332                      info->interaction.other,
 333                      info->opened,
 334                      info->thisClosedOther,
 335                      info->thisAckPending,
 336                      info->otherClosedThis,
 337 krisbash 1.1         info->otherAckPending,
 338                      info->ackPassthru );
 339              }
 340              
 341              #define STRAND_DEBUGSTATE( strand )         _StrandLogState( (strand), "S.:", &((strand)->info) )
 342              #define STRAND_DEBUGSTATE_LEFT( strand )    _StrandLogState( &((strand)->base), "S.Left", &((strand)->base.info) ); \
 343                                                          _StrandLogState( &((strand)->base), "S.(Right)", &((strand)->infoRight) )
 344              #define STRAND_DEBUGSTATE_RIGHT( strand )   _StrandLogState( &((strand)->base), "S.Right", &((strand)->infoRight) ); \
 345                                                          _StrandLogState( &((strand)->base), "S.(Left)", &((strand)->base.info) )
 346              #else
 347              #define STRAND_DEBUGSTATE( strand )
 348              #define STRAND_DEBUGSTATE_LEFT( strand )
 349              #define STRAND_DEBUGSTATE_RIGHT( strand )
 350              #endif
 351              
 352              //------------------------------------------------------------------------------------------------------------
 353              #define _GetMethodBit( bitIndex )   ((ptrdiff_t)1 << ((bitIndex)-1))
 354              
 355              //------------------------------------------------------------------------------------------------------------
 356              void _StrandInteraction_Cancel( _In_ Interaction* interaction ) 
 357              {
 358 krisbash 1.1     Strand* self = Strand_FromInteraction( interaction );
 359                  _Strand_Schedule( self, BitCancel );
 360              }
 361              
 362              //------------------------------------------------------------------------------------------------------------
 363              void _StrandInteraction_PostControl( _In_ Interaction* interaction, _In_ Message* msg ) 
 364              {
 365                  Strand* self = Strand_FromInteraction( interaction );
 366                  Message_AddRef( msg );  // since the actual message use can be delayed
 367                  self->info.stored.controlMsg = msg;
 368                  _Strand_Schedule( self, BitPostControl );
 369              }
 370              
 371              //------------------------------------------------------------------------------------------------------------
 372              void _StrandInteraction_Post( _In_ Interaction* interaction, _In_ Message* msg )
 373              {
 374                  Strand* self = Strand_FromInteraction( interaction );
 375                  Message_AddRef( msg );  // since the actual message use can be delayed
 376                  self->info.stored.msg = msg;
 377                  _Strand_Schedule( self, BitPost );
 378              }
 379 krisbash 1.1 
 380              //------------------------------------------------------------------------------------------------------------
 381              void _StrandInteraction_Ack( _In_ Interaction* interaction )
 382              {
 383                  Strand* self = Strand_FromInteraction( interaction );
 384                  _Strand_Schedule( self, BitAck );
 385              }
 386              
 387              //------------------------------------------------------------------------------------------------------------
 388              void _StrandInteraction_Close( _In_ Interaction* interaction )
 389              {
 390                  Strand* self = Strand_FromInteraction( interaction );
 391                  _Strand_Schedule( self, BitClose );
 392              }
 393              
 394              //------------------------------------------------------------------------------------------------------------
 395              void _StrandInteraction_Left_Cancel( _In_ Interaction* interaction ) 
 396              {
 397                  Strand* self = Strand_FromInteraction( interaction );
 398                  _Strand_Schedule( self, BitCancel_Left );
 399              }
 400 krisbash 1.1 
 401              //------------------------------------------------------------------------------------------------------------
 402              void _StrandInteraction_Left_PostControl( _In_ Interaction* interaction, _In_ Message* msg ) 
 403              {
 404                  Strand* self = Strand_FromInteraction( interaction );
 405                  Message_AddRef( msg );  // since the actual message use can be delayed
 406                  self->info.stored.controlMsg = msg;
 407                  _Strand_Schedule( self, BitPostControl_Left );
 408              }
 409              
 410              //------------------------------------------------------------------------------------------------------------
 411              void _StrandInteraction_Left_Post( _In_ Interaction* interaction, _In_ Message* msg )
 412              {
 413                  Strand* self = Strand_FromInteraction( interaction );
 414                  Message_AddRef( msg );  // since the actual message use can be delayed
 415                  self->info.stored.msg = msg;
 416                  _Strand_Schedule( self, BitPost_Left );
 417              }
 418              
 419              //------------------------------------------------------------------------------------------------------------
 420              void _StrandInteraction_Left_Ack( _In_ Interaction* interaction )
 421 krisbash 1.1 {
 422                  Strand* self = Strand_FromInteraction( interaction );
 423                  _Strand_Schedule( self, BitAck_Left );
 424              }
 425              
 426              //------------------------------------------------------------------------------------------------------------
 427              void _StrandInteraction_Left_Close( _In_ Interaction* interaction )
 428              {
 429                  Strand* self = Strand_FromInteraction( interaction );
 430                  _Strand_Schedule( self, BitClose_Left );
 431              }
 432              
 433              //------------------------------------------------------------------------------------------------------------
 434              void _StrandInteraction_Right_Cancel( _In_ Interaction* interaction ) 
 435              {
 436                  StrandBoth* self = Strand_FromInteractionRight( interaction );
 437                  _Strand_Schedule( (Strand*)self, BitCancel_Right );
 438              }
 439              
 440              //------------------------------------------------------------------------------------------------------------
 441              void _StrandInteraction_Right_PostControl( _In_ Interaction* interaction, _In_ Message* msg ) 
 442 krisbash 1.1 {
 443                  StrandBoth* self = Strand_FromInteractionRight( interaction );
 444                  Message_AddRef( msg );  // since the actual message use can be delayed
 445                  self->infoRight.stored.controlMsg = msg;
 446                  _Strand_Schedule( (Strand*)self, BitPostControl_Right );
 447              }
 448              
 449              //------------------------------------------------------------------------------------------------------------
 450              void _StrandInteraction_Right_Post( _In_ Interaction* interaction, _In_ Message* msg )
 451              {
 452                  StrandBoth* self = Strand_FromInteractionRight( interaction );
 453                  Message_AddRef( msg );  // since the actual message use can be delayed
 454                  self->infoRight.stored.msg = msg;
 455                  _Strand_Schedule( (Strand*)self, BitPost_Right );
 456              }
 457              
 458              //------------------------------------------------------------------------------------------------------------
 459              void _StrandInteraction_Right_Ack( _In_ Interaction* interaction )
 460              {
 461                  StrandBoth* self = Strand_FromInteractionRight( interaction );
 462                  _Strand_Schedule( (Strand*)self, BitAck_Right );
 463 krisbash 1.1 }
 464              
 465              //------------------------------------------------------------------------------------------------------------
 466              void _StrandInteraction_Right_Close( _In_ Interaction* interaction )
 467              {
 468                  StrandBoth* self = Strand_FromInteractionRight( interaction );
 469                  _Strand_Schedule( (Strand*)self, BitClose_Right );
 470              }
 471              
 472              //------------------------------------------------------------------------------------------------------------
 473              void _StrandInteraction_Many_Cancel( _In_ Interaction* interaction ) 
 474              {
 475                  Strand* self = Strand_FromInteraction( interaction );
 476                  _Strand_Schedule( self, BitCancel_Many );
 477              }
 478              
 479              //------------------------------------------------------------------------------------------------------------
 480              void _StrandInteraction_Many_PostControl( _In_ Interaction* interaction, _In_ Message* msg ) 
 481              {
 482                  Strand* self = Strand_FromInteraction( interaction );
 483                  Message_AddRef( msg );  // since the actual message use can be delayed
 484 krisbash 1.1     self->info.stored.controlMsg = msg;
 485                  _Strand_Schedule( self, BitPostControl_Many );
 486              }
 487              
 488              //------------------------------------------------------------------------------------------------------------
 489              void _StrandInteraction_Many_Post( _In_ Interaction* interaction, _In_ Message* msg )
 490              {
 491                  Strand* self = Strand_FromInteraction( interaction );
 492                  Message_AddRef( msg );  // since the actual message use can be delayed
 493                  self->info.stored.msg = msg;
 494                  _Strand_Schedule( self, BitPost_Many );
 495              }
 496              
 497              //------------------------------------------------------------------------------------------------------------
 498              void _StrandInteraction_Many_Ack( _In_ Interaction* interaction )
 499              {
 500                  Strand* self = Strand_FromInteraction( interaction );
 501                  _Strand_Schedule( self, BitAck_Many );
 502              }
 503              
 504              //------------------------------------------------------------------------------------------------------------
 505 krisbash 1.1 void _StrandInteraction_Many_Close( _In_ Interaction* interaction )
 506              {
 507                  Strand* self = Strand_FromInteraction( interaction );
 508                  _Strand_Schedule( self, BitClose_Many );
 509              }
 510              
 511              //------------------------------------------------------------------------------------------------------------
 512              MI_INLINE
 513              MI_Boolean _StrandMethodImp_CheckFinished( _In_ InteractionInfo* info ) 
 514              {
 515                  return 
 516                      info->thisClosedOther
 517                      && !info->thisAckPending
 518                      && info->otherClosedThis
 519                      && !info->otherAckPending;
 520              }
 521              
 522              //------------------------------------------------------------------------------------------------------------
 523              MI_INLINE
 524              MI_Boolean _StrandMethodImp_Cancel( _In_ Strand* self, _In_ InteractionInfo* info) 
 525              {
 526 krisbash 1.1     DEBUG_ASSERT( !self->canceled );
 527              
 528                  self->canceled = MI_TRUE;
 529              
 530                  if( NULL != info->userFT->Cancel )
 531                  {
 532                      (*info->userFT->Cancel)(self);
 533                  }
 534              
 535                  return MI_FALSE;
 536              }
 537              
 538              //------------------------------------------------------------------------------------------------------------
 539              MI_INLINE
 540              MI_Boolean _StrandMethodImp_PostControl( _In_ Strand* self, _In_ InteractionInfo* info) 
 541              {
 542                  DEBUG_ASSERT( info->opened );
 543                  DEBUG_ASSERT( !info->otherClosedThis );
 544                  DEBUG_ASSERT( NULL != info->userFT->PostControl );
 545                  DEBUG_ASSERT( NULL != info->stored.controlMsg );
 546                  
 547 krisbash 1.1     info->userFT->PostControl( self, info->stored.controlMsg );
 548                  Message_Release( info->stored.controlMsg );  // now we can remove the reference added on _StrandInteraction_*
 549                  
 550                  return MI_FALSE;
 551              }
 552              
 553              //------------------------------------------------------------------------------------------------------------
 554              MI_INLINE
 555              MI_Boolean _StrandMethodImp_Post( _In_ Strand* self, _In_ InteractionInfo* info)
 556              {
 557                  DEBUG_ASSERT( info->opened );
 558                  DEBUG_ASSERT( !info->otherClosedThis );
 559                  DEBUG_ASSERT( NULL != info->userFT->Post );
 560                  DEBUG_ASSERT( NULL != info->stored.msg );
 561                  DEBUG_ASSERT( !info->otherAckPending );
 562              
 563                  info->otherAckPending = MI_TRUE;
 564                  info->userFT->Post( self, info->stored.msg );
 565                  Message_Release( info->stored.msg );  // now we can remove the reference added on _StrandInteraction_*
 566              
 567                  return MI_FALSE;
 568 krisbash 1.1 }
 569              
 570              //------------------------------------------------------------------------------------------------------------
 571              MI_INLINE
 572              MI_Boolean _StrandMethodImp_Ack( _In_ Strand* self, _In_ InteractionInfo* info)
 573              {
 574                  // note that info->otherClosedThis may be true here 
 575                  DEBUG_ASSERT( info->thisAckPending );
 576                  DEBUG_ASSERT( info->opened );
 577              
 578                  info->thisAckPending = MI_FALSE;
 579              
 580                  if( NULL != info->userFT->Ack )
 581                  {
 582                      info->userFT->Ack( self );
 583                  }
 584                  
 585                  return MI_FALSE;
 586              }
 587              
 588              //------------------------------------------------------------------------------------------------------------
 589 krisbash 1.1 MI_INLINE
 590              MI_Boolean _StrandMethodImp_Close( _In_ Strand* self, _In_ InteractionInfo* info)
 591              {
 592                  DEBUG_ASSERT( info->opened );
 593                  DEBUG_ASSERT( !info->otherClosedThis );
 594              
 595                  info->otherClosedThis = MI_TRUE;
 596              
 597                  if( NULL != info->userFT->Close )
 598                  {
 599                      (*info->userFT->Close)(self);
 600                  }
 601                  
 602                  return MI_FALSE;
 603              }
 604              
 605              //------------------------------------------------------------------------------------------------------------
 606              MI_INLINE
 607              MI_Boolean _StrandMethodImp_PostOther( _In_ InteractionInfo* info)
 608              {
 609                  _Strand_Post_Imp( info, info->otherMsg );
 610 krisbash 1.1     Message_Release( info->otherMsg );  // now we can remove the reference added on Strand_SchedulePost*
 611                  info->otherMsg = NULL;
 612                  return MI_FALSE;
 613              }
 614              
 615              //------------------------------------------------------------------------------------------------------------
 616              MI_Boolean _StrandMethod_CheckFinished( _In_ Strand* self ) 
 617              {
 618                  return _StrandMethodImp_CheckFinished( &self->info ) && !self->delayFinish;
 619              }
 620              
 621              //------------------------------------------------------------------------------------------------------------
 622              MI_Boolean _StrandMethod_Timer( _In_ Strand* self) 
 623              {
 624                  TimerReason reason;
 625                  
 626                  DEBUG_ASSERT( NULL != self->timer );
 627                  DEBUG_ASSERT( NULL != self->info.userFT->Timer );
 628                  
 629                  STRAND_DEBUGSTATE( self );
 630              
 631 krisbash 1.1     reason = self->timer->reason;
 632              
 633                  Timer_Close(self->timer);
 634                  self->timer = NULL;
 635                  (*self->info.userFT->Timer)(self, reason);
 636              
 637                  // A canceled timer shouldn't be re-started
 638                  DEBUG_ASSERT( NULL == self->timer || reason != TimerReason_Canceled );
 639                  
 640                  return MI_FALSE;
 641              }
 642              
 643              //------------------------------------------------------------------------------------------------------------
 644              // Internal use
 645              void _Strand_CancelPropagate(
 646                  _In_ Strand *   self);
 647              
 648              // Internal use
 649              MI_INLINE
 650              void _Strand_CompleteOpenAsyncImp( 
 651                  _In_        Strand *            self,
 652 krisbash 1.1     _In_        InteractionInfo*    info )
 653              {    
 654                  STRAND_ASSERTONSTRAND(self);
 655                  DEBUG_ASSERT( !info->opened );
 656                  
 657                  info->opened = MI_TRUE;
 658              
 659                  if( self->canceled )
 660                  {
 661                      _Strand_CancelPropagate( self );
 662                  }
 663              }
 664              
 665              MI_Boolean _StrandMethod_CompleteOpenAsync( _In_ Strand* self) 
 666              {
 667                  STRAND_DEBUGSTATE( self );
 668              
 669                  _Strand_CompleteOpenAsyncImp( self, &self->info );
 670                  return MI_FALSE;
 671              }
 672              
 673 krisbash 1.1 //------------------------------------------------------------------------------------------------------------
 674              MI_Boolean _StrandMethod_Cancel( _In_ Strand* self) 
 675              {
 676                  STRAND_DEBUGSTATE( self );
 677              
 678                  if( !self->canceled )
 679                  {
 680                      if( STRAND_TYPE_RIGHTMOST == self->strandType && self->info.opened && !self->info.thisClosedOther )
 681                      {
 682                          // return it to the other side
 683                          self->info.interaction.other->ft->Cancel( self->info.interaction.other );
 684                      }
 685              
 686                      _StrandMethodImp_Cancel(self, &self->info );
 687                  }    
 688                  return MI_FALSE;
 689              }
 690              
 691              //------------------------------------------------------------------------------------------------------------
 692              MI_Boolean _StrandMethod_PostControl( _In_ Strand* self) 
 693              {
 694 krisbash 1.1     _Strand_TracePostMsg(self, self->info.stored.controlMsg, "(Control)");
 695                  STRAND_DEBUGSTATE( self );
 696              
 697                  return _StrandMethodImp_PostControl(self, &self->info );
 698              }
 699              
 700              //------------------------------------------------------------------------------------------------------------
 701              MI_Boolean _StrandMethod_Post( _In_ Strand* self)
 702              {
 703                  _Strand_TracePostMsg(self, self->info.stored.msg, "");
 704                  STRAND_DEBUGSTATE( self );
 705              
 706                  return _StrandMethodImp_Post(self, &self->info );
 707              }
 708              
 709              //------------------------------------------------------------------------------------------------------------
 710              MI_Boolean _StrandMethod_Ack( _In_ Strand* self)
 711              {
 712                  STRAND_DEBUGSTATE( self );
 713              
 714                  return _StrandMethodImp_Ack(self, &self->info );
 715 krisbash 1.1 }
 716              
 717              //------------------------------------------------------------------------------------------------------------
 718              MI_Boolean _StrandMethod_Close( _In_ Strand* self)
 719              {
 720                  STRAND_DEBUGSTATE( self );
 721              
 722                  return _StrandMethodImp_Close(self, &self->info );
 723              }
 724              
 725              //------------------------------------------------------------------------------------------------------------
 726              MI_Boolean _StrandMethod_PostOther( _In_ Strand* self)
 727              {
 728                  MI_Boolean res = _StrandMethodImp_PostOther( &self->info );
 729                  STRAND_LOGWITHNAME( self, "Returning from PostOther" );
 730                  return res;
 731              }
 732              
 733              //------------------------------------------------------------------------------------------------------------
 734              MI_Boolean _StrandMethod_AckOther( _In_ Strand* self)
 735              {
 736 krisbash 1.1     _Strand_Ack_Imp( &self->info );
 737                  STRAND_LOGWITHNAME( self, "Returning from AckOther" );
 738                  return MI_FALSE;
 739              }
 740              
 741              //------------------------------------------------------------------------------------------------------------
 742              MI_Boolean _StrandMethod_CloseOther( _In_ Strand* self)
 743              {
 744                  _Strand_Close_Imp( &self->info );
 745                  STRAND_LOGWITHNAME( self, "Returning from CloseOther" );
 746                  return MI_FALSE;
 747              }
 748              
 749              //------------------------------------------------------------------------------------------------------------
 750              MI_Boolean _StrandMethod_CancelSelf( _In_ Strand* self)
 751              {
 752                  Strand_Cancel( self );
 753                  STRAND_LOGWITHNAME( self, "Returning from CancelSelf" );
 754                  return MI_FALSE;
 755              }
 756              
 757 krisbash 1.1 //------------------------------------------------------------------------------------------------------------
 758              MI_Boolean _StrandMethod_Aux0( _In_ Strand* self)
 759              {
 760                  DEBUG_ASSERT( NULL != self->info.userFT->Aux0 );
 761                  self->info.userFT->Aux0( self );
 762                  return MI_FALSE;
 763              }
 764              
 765              //------------------------------------------------------------------------------------------------------------
 766              MI_Boolean _StrandMethod_Aux1( _In_ Strand* self)
 767              {
 768                  DEBUG_ASSERT( NULL != self->info.userFT->Aux1 );
 769                  self->info.userFT->Aux1( self );
 770                  return MI_FALSE;
 771              }
 772              
 773              //------------------------------------------------------------------------------------------------------------
 774              MI_Boolean _StrandMethod_Aux2( _In_ Strand* self)
 775              {
 776                  DEBUG_ASSERT( NULL != self->info.userFT->Aux2 );
 777                  self->info.userFT->Aux2( self );
 778 krisbash 1.1     return MI_FALSE;
 779              }
 780              
 781              //------------------------------------------------------------------------------------------------------------
 782              MI_Boolean _StrandMethod_Aux3( _In_ Strand* self)
 783              {
 784                  DEBUG_ASSERT( NULL != self->info.userFT->Aux3 );
 785                  self->info.userFT->Aux3( self );
 786                  return MI_FALSE;
 787              }
 788              
 789              //------------------------------------------------------------------------------------------------------------
 790              MI_Boolean _StrandMethod_Aux4( _In_ Strand* self)
 791              {
 792                  DEBUG_ASSERT( NULL != self->info.userFT->Aux4 );
 793                  self->info.userFT->Aux4( self );
 794                  return MI_FALSE;
 795              }
 796              
 797              //------------------------------------------------------------------------------------------------------------
 798              MI_Boolean _StrandMethod_Both_CheckFinished( _In_ Strand* self_) 
 799 krisbash 1.1 {
 800                  StrandBoth* self = (StrandBoth*)self_;
 801              
 802                  if (self->asyncOpenInProgress)
 803                      return MI_FALSE;
 804              
 805                  return _StrandMethodImp_CheckFinished( &self->base.info ) 
 806                      && ((!self->infoRight.opened) ||  _StrandMethodImp_CheckFinished( &self->infoRight )) //check right interation state only if its opeened
 807                      && !self->base.delayFinish;
 808              }
 809              
 810              //------------------------------------------------------------------------------------------------------------
 811              MI_Boolean _StrandMethod_Both_CompleteOpenAsync( _In_ Strand* self_) 
 812              {
 813                  StrandBoth* self = (StrandBoth*)self_;
 814                  STRAND_DEBUGSTATE( self );
 815              
 816                  _Strand_CompleteOpenAsyncImp( &self->base, &self->infoRight );
 817                  self->asyncOpenInProgress = MI_FALSE;
 818                  return MI_FALSE;
 819              }
 820 krisbash 1.1 
 821              //------------------------------------------------------------------------------------------------------------
 822              MI_Boolean _StrandMethod_Left_Cancel( _In_ Strand* self_) 
 823              {
 824                  StrandBoth* self = (StrandBoth*)self_;
 825              
 826                  STRAND_DEBUGSTATE_LEFT( self );
 827                  
 828                  if( !self->base.canceled  )
 829                  {
 830                      // We pass to the right only if we have not been cancel already becase in that case it has go to the right already
 831                      // (cancelations always flow to the right first)
 832                      // Note that we need to check this first as the canceled below may close the interaction with the right side
 833                      if( self->infoRight.opened && !self->infoRight.thisClosedOther )
 834                      {
 835                          self->infoRight.interaction.other->ft->Cancel( self->infoRight.interaction.other );
 836                      }
 837                      
 838                      _StrandMethodImp_Cancel(self_, &self->base.info );
 839                  }
 840                  return MI_FALSE;
 841 krisbash 1.1 }
 842              
 843              //------------------------------------------------------------------------------------------------------------
 844              MI_Boolean _StrandMethod_Left_PostControl( _In_ Strand* self_) 
 845              {
 846                  StrandBoth* self = (StrandBoth*)self_;
 847              
 848                  _Strand_TracePostMsg(self_, self->base.info.stored.controlMsg, "(Control Left)");
 849                  STRAND_DEBUGSTATE_LEFT( self );
 850              
 851                  if( NULL == self->base.info.userFT->PostControl && self->infoRight.opened )
 852                  {
 853                      DEBUG_ASSERT( !self->infoRight.thisClosedOther );
 854                      // post passing thru to the other side
 855                      StrandBoth_PostControlRight( self, self->base.info.stored.controlMsg ); 
 856                      Message_Release( self->base.info.stored.controlMsg );  // now we can remove the reference added on _StrandInteraction_*
 857                      return MI_FALSE;
 858                  }
 859                  else
 860                  {
 861                      return _StrandMethodImp_PostControl(self_, &self->base.info );
 862 krisbash 1.1     }
 863              }
 864              
 865              //------------------------------------------------------------------------------------------------------------
 866              MI_Boolean _StrandMethod_Left_Post( _In_ Strand* self_)
 867              {
 868                  StrandBoth* self = (StrandBoth*)self_;
 869              
 870                  _Strand_TracePostMsg(self_, self->base.info.stored.msg, "Left");
 871                  STRAND_DEBUGSTATE_LEFT( self );
 872              
 873                  if( NULL == self->base.info.userFT->Post && self->infoRight.opened )
 874                  {
 875                      DEBUG_ASSERT( !self->infoRight.thisClosedOther );
 876                      // post passing thru to the other side
 877                      StrandBoth_PostPassthruRight( self, self->base.info.stored.msg ); 
 878                      Message_Release( self->base.info.stored.msg );  // now we can remove the reference added on _StrandInteraction_*
 879                      return MI_FALSE;
 880                  }
 881                  else
 882                  {
 883 krisbash 1.1         return _StrandMethodImp_Post(self_, &self->base.info );
 884                  }
 885              }
 886              
 887              //------------------------------------------------------------------------------------------------------------
 888              MI_Boolean _StrandMethod_Left_Ack( _In_ Strand* self_)
 889              {
 890                  StrandBoth* self = (StrandBoth*)self_;
 891              
 892                  STRAND_DEBUGSTATE_LEFT( self );
 893                  DEBUG_ASSERT( self->base.info.opened );
 894                  
 895                  if( self->base.info.ackPassthru || NULL == self->base.info.userFT->Ack )
 896                  {
 897                      DEBUG_ASSERT( self->base.info.thisAckPending );
 898                      self->base.info.thisAckPending = MI_FALSE;
 899              
 900                      if( self->infoRight.otherAckPending )
 901                      {        
 902                          self->base.info.ackPassthru = MI_FALSE;
 903                          StrandBoth_AckRight( self );
 904 krisbash 1.1         }
 905                      else
 906                      {
 907                          DEBUG_ASSERT( !self->base.info.ackPassthru );
 908                      }
 909                      
 910                      return MI_FALSE;
 911                  }
 912                  else
 913                  {
 914                      return _StrandMethodImp_Ack(self_, &self->base.info );
 915                  }
 916              }
 917              
 918              //------------------------------------------------------------------------------------------------------------
 919              MI_Boolean _StrandMethod_Left_Close( _In_ Strand* self_)
 920              {
 921                  StrandBoth* self = (StrandBoth*)self_;
 922              
 923                  STRAND_DEBUGSTATE_LEFT( self );
 924              
 925 krisbash 1.1     if( NULL == self->base.info.userFT->Close )
 926                  {
 927                      // we take care of sending the close as passthru
 928                      if( self->infoRight.opened && !self->infoRight.thisClosedOther )
 929                      {
 930                          StrandBoth_CloseRight( self );
 931                      }
 932                  }
 933                  
 934                  return _StrandMethodImp_Close(self_, &self->base.info );
 935              }
 936              
 937              //------------------------------------------------------------------------------------------------------------
 938              MI_Boolean _StrandMethod_Right_Cancel( _In_ Strand* self_) 
 939              {
 940                  StrandBoth* self = (StrandBoth*)self_;
 941              
 942                  STRAND_DEBUGSTATE_RIGHT( self );
 943                  
 944                  // We need to check this first as the canceled below may close the interaction with the left side
 945                  if( self->base.info.opened && !self->base.info.thisClosedOther && !self->leftCanceled )
 946 krisbash 1.1     {
 947                      self->leftCanceled = MI_TRUE;
 948                      // We pass to the left even if we have been cancel already becase thet should be the cancelation coming back from the right
 949                      self->base.info.interaction.other->ft->Cancel( self->base.info.interaction.other );
 950                  }
 951                  
 952                  if( !self->base.canceled )
 953                  {
 954                      _StrandMethodImp_Cancel(self_, &self->infoRight );
 955                  }
 956                  return MI_FALSE;
 957              }
 958              
 959              //------------------------------------------------------------------------------------------------------------
 960              MI_Boolean _StrandMethod_Right_PostControl( _In_ Strand* self_) 
 961              {
 962                  StrandBoth* self = (StrandBoth*)self_;
 963              
 964                  _Strand_TracePostMsg(self_, self->infoRight.stored.controlMsg, "(Control Right)");
 965                  STRAND_DEBUGSTATE_RIGHT( self );
 966              
 967 krisbash 1.1     if( NULL == self->infoRight.userFT->PostControl && self->base.info.opened )
 968                  {
 969                      DEBUG_ASSERT( !self->base.info.thisClosedOther );
 970                      // post passing thru to the other side
 971                      StrandBoth_PostControlLeft( self, self->infoRight.stored.controlMsg ); 
 972                      Message_Release( self->infoRight.stored.controlMsg );  // now we can remove the reference added on _StrandInteraction_*
 973                      return MI_FALSE;
 974                  }
 975                  else
 976                  {
 977                      return _StrandMethodImp_PostControl(self_, &self->infoRight );
 978                  }
 979              }
 980              
 981              //------------------------------------------------------------------------------------------------------------
 982              MI_Boolean _StrandMethod_Right_Post( _In_ Strand* self_)
 983              {
 984                  StrandBoth* self = (StrandBoth*)self_;
 985              
 986                  _Strand_TracePostMsg(self_, self->infoRight.stored.msg, "Right");
 987                  STRAND_DEBUGSTATE_RIGHT( self );
 988 krisbash 1.1 
 989                  if( NULL == self->infoRight.userFT->Post && self->base.info.opened )
 990                  {
 991                      DEBUG_ASSERT( !self->base.info.thisClosedOther );
 992                      // post passing thru to the other side
 993                      StrandBoth_PostPassthruLeft( self, self->infoRight.stored.msg ); 
 994                      Message_Release( self->infoRight.stored.msg );  // now we can remove the reference added on _StrandInteraction_*
 995                      return MI_FALSE;
 996                  }
 997                  else
 998                  {
 999                      return _StrandMethodImp_Post(self_, &self->infoRight );
1000                  }
1001              }
1002              
1003              //------------------------------------------------------------------------------------------------------------
1004              MI_Boolean _StrandMethod_Right_Ack( _In_ Strand* self_)
1005              {
1006                  StrandBoth* self = (StrandBoth*)self_;
1007              
1008                  STRAND_DEBUGSTATE_RIGHT( self );
1009 krisbash 1.1     DEBUG_ASSERT( self->infoRight.opened );
1010              
1011                  if( self->infoRight.ackPassthru || NULL == self->infoRight.userFT->Ack )
1012                  {
1013                      DEBUG_ASSERT( self->infoRight.thisAckPending );
1014                     
1015                      self->infoRight.thisAckPending = MI_FALSE;
1016                      
1017                      if( self->base.info.otherAckPending )
1018                      {        
1019                          self->infoRight.ackPassthru = MI_FALSE;
1020                          StrandBoth_AckLeft( self );
1021                      }
1022                      else
1023                      {
1024                          DEBUG_ASSERT( !self->infoRight.ackPassthru );
1025                      }
1026                      
1027                      return MI_FALSE;
1028                  }
1029                  else
1030 krisbash 1.1     {
1031                      return _StrandMethodImp_Ack(self_, &self->infoRight );
1032                  }
1033              }
1034              
1035              //------------------------------------------------------------------------------------------------------------
1036              MI_Boolean _StrandMethod_Right_Close( _In_ Strand* self_)
1037              {
1038                  StrandBoth* self = (StrandBoth*)self_;
1039              
1040                  STRAND_DEBUGSTATE_RIGHT( self );
1041              
1042                  if( NULL == self->infoRight.userFT->Close )
1043                  {
1044                      // we take care of sending the close as passthru
1045                      if( self->base.info.opened && !self->base.info.thisClosedOther )
1046                      {
1047                          StrandBoth_CloseLeft( self );
1048                      }
1049                  }
1050                  
1051 krisbash 1.1     return _StrandMethodImp_Close(self_, &self->infoRight );
1052              }
1053              
1054              //------------------------------------------------------------------------------------------------------------
1055              MI_Boolean _StrandMethod_Right_PostOther( _In_ Strand* self_)
1056              {
1057                  StrandBoth* self = (StrandBoth*)self_;
1058              
1059                  MI_Boolean res = _StrandMethodImp_PostOther( &self->infoRight );
1060                  STRAND_LOGWITHNAME( self_, "Returning from PostOther(Right)" );
1061                  return res;
1062              }
1063              
1064              //------------------------------------------------------------------------------------------------------------
1065              MI_Boolean _StrandMethod_Right_AckOther( _In_ Strand* self_)
1066              {
1067                  StrandBoth* self = (StrandBoth*)self_;
1068              
1069                  _Strand_Ack_Imp( &self->infoRight );
1070                  STRAND_LOGWITHNAME( self_, "Returning from AckOther(Right)" );
1071                  return MI_FALSE;
1072 krisbash 1.1 }
1073              
1074              //------------------------------------------------------------------------------------------------------------
1075              MI_Boolean _StrandMethod_Right_CloseOther( _In_ Strand* self_)
1076              {
1077                  StrandBoth* self = (StrandBoth*)self_;
1078              
1079                  _Strand_Close_Imp( &self->infoRight );
1080                  STRAND_LOGWITHNAME( self_, "Returning from CloseOther(Right)" );
1081                  return MI_FALSE;
1082              }
1083              
1084              //------------------------------------------------------------------------------------------------------------
1085              MI_Boolean _StrandMethod_Both_CancelSelf( _In_ Strand* self_)
1086              {
1087                  StrandBoth* self = (StrandBoth*)self_;
1088              
1089                  Strand_Cancel( &self->base );
1090                  STRAND_LOGWITHNAME( self_, "Returning from CancelSelf(Both)" );
1091                  return MI_FALSE;
1092              }
1093 krisbash 1.1 
1094              //------------------------------------------------------------------------------------------------------------
1095              MI_Boolean _StrandMethod_Right_Aux0( _In_ Strand* self_)
1096              {
1097                  StrandBoth* self = (StrandBoth*)self_;
1098                  DEBUG_ASSERT( NULL != self->infoRight.userFT->Aux0 );
1099              
1100                  self->infoRight.userFT->Aux0( self_ );
1101                  return MI_FALSE;
1102              }
1103              
1104              MI_Boolean _StrandMethod_Right_Aux1( _In_ Strand* self_)
1105              {
1106                  StrandBoth* self = (StrandBoth*)self_;
1107                  DEBUG_ASSERT( NULL != self->infoRight.userFT->Aux1 );
1108              
1109                  self->infoRight.userFT->Aux1( self_ );
1110                  return MI_FALSE;
1111              }
1112              
1113              MI_Boolean _StrandMethod_Right_Aux2( _In_ Strand* self_)
1114 krisbash 1.1 {
1115                  StrandBoth* self = (StrandBoth*)self_;
1116                  DEBUG_ASSERT( NULL != self->infoRight.userFT->Aux2 );
1117                  
1118                  self->infoRight.userFT->Aux2( self_ );
1119                  return MI_FALSE;
1120              }
1121              
1122              MI_Boolean _StrandMethod_Right_Aux3( _In_ Strand* self_)
1123              {
1124                  StrandBoth* self = (StrandBoth*)self_;
1125                  DEBUG_ASSERT( NULL != self->infoRight.userFT->Aux3 );
1126                  
1127                  self->infoRight.userFT->Aux3( self_ );
1128                  return MI_FALSE;
1129              }
1130              
1131              MI_Boolean _StrandMethod_Right_Aux4( _In_ Strand* self_)
1132              {
1133                  StrandBoth* self = (StrandBoth*)self_;
1134                  DEBUG_ASSERT( NULL != self->infoRight.userFT->Aux4 );
1135 krisbash 1.1     
1136                  self->infoRight.userFT->Aux4( self_ );
1137                  return MI_FALSE;
1138              }
1139              
1140              //------------------------------------------------------------------------------------------------------------
1141              typedef enum _EntryOperationAction
1142              {
1143                  EOContinue,
1144                  EORetry,
1145                  EODeleted
1146              } EntryOperationAction;
1147              
1148              typedef EntryOperationAction (*StrandEntryOperation)( _In_ StrandMany* );
1149              
1150              EntryOperationAction _StrandEntryOperation_Add( _In_ StrandMany* self )
1151              {
1152                  MI_Boolean failed = MI_FALSE;
1153                  MI_Boolean added = MI_FALSE;
1154                  Message * msg = self->currentEntry->strand.info.stored.msg;
1155              
1156 krisbash 1.1     DEBUG_ASSERT( NULL != self->userInternalFT->NewEntry );
1157              
1158                  if( self->strand.canceled  )
1159                  {
1160                      trace_StrandEntryOperation_AddCanceled(
1161                          (unsigned int)self->numEntries,
1162                          self, 
1163                          STRAND_DEBUG_GETNAME(&self->strand), 
1164                          &self->currentEntry->strand, 
1165                          STRAND_DEBUG_GETNAME(&self->currentEntry->strand) );
1166                      failed = MI_TRUE;
1167                      // we dont even call the user method in this case
1168                  }
1169                  else
1170                  {
1171                      if( HashMap_Insert( &self->many, &self->currentEntry->bucket ) )
1172                      {
1173                          trace_StrandEntryOperation_AddFailed(
1174                              (unsigned int)self->numEntries,
1175                              self, 
1176                              STRAND_DEBUG_GETNAME(&self->strand), 
1177 krisbash 1.1                 &self->currentEntry->strand, 
1178                              STRAND_DEBUG_GETNAME(&self->currentEntry->strand) );
1179                          failed = MI_TRUE;
1180                      }
1181                      else
1182                      {
1183                          ++(self->numEntries);
1184              
1185                          trace_StrandEntryOperation_Add(
1186                              (unsigned int)self->numEntries,
1187                              self, 
1188                              STRAND_DEBUG_GETNAME(&self->strand), 
1189                              &self->currentEntry->strand, 
1190                              STRAND_DEBUG_GETNAME(&self->currentEntry->strand) );
1191                          
1192                          added = MI_TRUE;
1193                      }
1194              
1195                      if( NULL != self->userInternalFT && NULL != self->userInternalFT->NewEntry )
1196                      {
1197                          self->userInternalFT->NewEntry( self, self->currentEntry, msg, &failed );
1198 krisbash 1.1         }
1199                  }
1200                  
1201                  if( NULL != msg )
1202                  {
1203                      if( failed || NULL == self->userInternalFT || NULL == self->userInternalFT->AddedToParent )
1204                      {
1205                          self->currentEntry->strand.info.stored.msg = NULL;
1206                          Message_Release(msg);
1207                      }
1208                      // Else: We dont release the message in this case (we keep it on 'stored')
1209                      // It will be deleted once the AddedToParent method is executed
1210                  }
1211              
1212                  if( failed )
1213                  {
1214                      if( added )
1215                      {
1216                          StrandMany_DeleteEntry( self->currentEntry );
1217                      }
1218                      else
1219 krisbash 1.1         {
1220                          SList_Free( self->currentEntry );
1221                      }
1222                      return EODeleted;
1223                  }
1224                  
1225                  return EOContinue;
1226              }
1227              
1228              EntryOperationAction _StrandEntryOperation_Cancel( _In_ StrandMany* self )
1229              {
1230                  trace_StrandEntryOperation_Cancel( self, STRAND_DEBUG_GETNAME(&self->strand),self->strand.canceled );
1231              
1232                  if( !self->strand.canceled )
1233                  {
1234                      // since we are in the middle, always forward to the other side
1235                      self->strand.info.interaction.other->ft->Cancel( self->strand.info.interaction.other );
1236                      _StrandMethodImp_Cancel( &self->strand, &self->strand.info );
1237                  }
1238                  else if( self->strand.strandType == STRAND_TYPE_PARENTLEFT )
1239                  {
1240 krisbash 1.1         // since we are in the left-middle this can be cancelation coming back from right, 
1241                      // so pass back to the left
1242                      self->strand.info.interaction.other->ft->Cancel( self->strand.info.interaction.other );
1243                  }
1244                  
1245                  return EOContinue;
1246              }
1247              
1248              EntryOperationAction _StrandEntryOperation_PostControl( _In_ StrandMany* self )
1249              {
1250                  DEBUG_ASSERT( NULL != self->currentEntry->toParent.controlMsg );
1251                  
1252                  if( self->strand.info.thisClosedOther )
1253                  {
1254                      trace_StrandEntryOperation_PostControl_PostIgnored(
1255                          self, 
1256                          STRAND_DEBUG_GETNAME(&self->strand), 
1257                          self->currentEntry->toParent.controlMsg);
1258                  }
1259                  else
1260                  {
1261 krisbash 1.1         trace_StrandEntryOperation_PostControl_ToParent(
1262                          self, 
1263                          STRAND_DEBUG_GETNAME(&self->strand), 
1264                          self->currentEntry->toParent.controlMsg);
1265              
1266                      if( NULL != self->userInternalFT && NULL != self->userInternalFT->EntryPostControl )
1267                      {
1268                          self->userInternalFT->EntryPostControl( self, self->currentEntry->toParent.controlMsg );
1269                      }
1270                      else
1271                      {
1272                          Strand_Post( &self->strand, self->currentEntry->toParent.controlMsg );
1273                      }
1274                  }
1275                  Message_Release( self->currentEntry->toParent.controlMsg ); // ref added on StrandEntry_PostControlParent
1276                  self->currentEntry->toParent.controlMsg = NULL;
1277                  return EOContinue;
1278              }
1279              
1280              EntryOperationAction _StrandEntryOperation_Post( _In_ StrandMany* self )
1281              {
1282 krisbash 1.1     DEBUG_ASSERT( NULL != self->currentEntry->toParent.msg );
1283              
1284                  if( self->strand.info.thisClosedOther )
1285                  {
1286                      trace_StrandEntryOperation_Post_IgnoredAfterClose(
1287                          self, 
1288                          STRAND_DEBUG_GETNAME(&self->strand), 
1289                          self->currentEntry->toParent.msg);
1290                      Message_Release( self->currentEntry->toParent.msg ); // ref added on StrandEntry_PostParent
1291                      self->currentEntry->toParent.msg = NULL;
1292                      return EOContinue;
1293                  }
1294                  
1295                  if( !self->strand.info.thisAckPending )
1296                  {
1297                      trace_StrandEntryOperation_Post_ToParent(
1298                          self, 
1299                          STRAND_DEBUG_GETNAME(&self->strand), 
1300                          self->currentEntry->toParent.msg);
1301              
1302                      if( NULL != self->userInternalFT && NULL != self->userInternalFT->EntryPost )
1303 krisbash 1.1         {
1304                          self->userInternalFT->EntryPost( self, self->currentEntry->toParent.msg );
1305                      }
1306                      else
1307                      {
1308                          Strand_Post( &self->strand, self->currentEntry->toParent.msg );
1309                      }
1310                      Message_Release( self->currentEntry->toParent.msg ); // ref added on StrandEntry_PostParent
1311                      self->currentEntry->toParent.msg = NULL;
1312                      return EOContinue;
1313                  }
1314                  else
1315                  {
1316              //        trace_StrandEntryOperation_Post_CannotPostWaitingOnAck(
1317              //            self, 
1318              //            STRAND_DEBUG_GETNAME(&self->strand), 
1319              //            self->currentEntry->toParent.msg);
1320                      return EORetry;
1321                  }
1322              }
1323              
1324 krisbash 1.1 EntryOperationAction _StrandEntryOperation_Close( _In_ StrandMany* self )
1325              {
1326                  trace_StrandEntryOperation_Close(
1327                      self, 
1328                      STRAND_DEBUG_GETNAME(&self->strand),
1329                      self->strand.info.thisClosedOther );
1330              
1331                  if( !self->strand.info.thisClosedOther )
1332                  {
1333                      if( NULL != self->userInternalFT && NULL != self->userInternalFT->EntryClose )
1334                      {
1335                          self->userInternalFT->EntryClose( self );
1336                      }
1337                      else
1338                      {
1339                          Strand_Close( &self->strand );
1340                      }
1341                  }
1342                  
1343                  return EOContinue;
1344              }
1345 krisbash 1.1 
1346              EntryOperationAction _StrandEntryOperation_Deleted( _In_ StrandMany* self )
1347              {
1348                  trace_StrandEntryOperation_Deleted(
1349                      self, 
1350                      STRAND_DEBUG_GETNAME(&self->strand), 
1351                      self->currentEntry, 
1352                      STRAND_DEBUG_GETNAME(&self->currentEntry->strand) );
1353              
1354                  StrandMany_DeleteEntry(self->currentEntry);
1355              
1356                  if( NULL != self->userInternalFT && NULL != self->userInternalFT->EntryDeleted )
1357                  {
1358                      self->userInternalFT->EntryDeleted( self );
1359                  }
1360                  
1361                  return EODeleted;
1362              }
1363              
1364              EntryOperationAction _StrandEntryOperation_Aux0( _In_ StrandMany* self )
1365              {
1366 krisbash 1.1     DEBUG_ASSERT( NULL != self->strand.info.userFT->Aux0 );
1367                  self->strand.info.userFT->Aux0( &self->strand );
1368                  return EOContinue;
1369              }
1370              
1371              EntryOperationAction _StrandEntryOperation_Aux1( _In_ StrandMany* self )
1372              {
1373                  DEBUG_ASSERT( NULL != self->strand.info.userFT->Aux1 );
1374                  self->strand.info.userFT->Aux1( &self->strand );
1375                  return EOContinue;
1376              }
1377              
1378              EntryOperationAction _StrandEntryOperation_Aux2( _In_ StrandMany* self )
1379              {
1380                  DEBUG_ASSERT( NULL != self->strand.info.userFT->Aux2 );
1381                  self->strand.info.userFT->Aux2( &self->strand );
1382                  return EOContinue;
1383              }
1384              
1385              EntryOperationAction _StrandEntryOperation_Aux3( _In_ StrandMany* self )
1386              {
1387 krisbash 1.1     DEBUG_ASSERT( NULL != self->strand.info.userFT->Aux3 );
1388                  self->strand.info.userFT->Aux3( &self->strand );
1389                  return EOContinue;
1390              }
1391              
1392              EntryOperationAction _StrandEntryOperation_Aux4( _In_ StrandMany* self )
1393              {
1394                  DEBUG_ASSERT( NULL != self->strand.info.userFT->Aux4 );
1395                  self->strand.info.userFT->Aux4( &self->strand );
1396                  return EOContinue;
1397              }
1398              
1399              //------------------------------------------------------------------------------------------------------------
1400              static StrandEntryOperation _StrandEntryOperations_FT[] = { 
1401                  _StrandEntryOperation_Add,    
1402                  _StrandEntryOperation_Cancel, 
1403                  _StrandEntryOperation_PostControl, 
1404                  _StrandEntryOperation_Post, 
1405                  _StrandEntryOperation_Close,
1406                  _StrandEntryOperation_Aux0,
1407                  _StrandEntryOperation_Aux1,
1408 krisbash 1.1     _StrandEntryOperation_Aux2,
1409                  _StrandEntryOperation_Aux3,
1410                  _StrandEntryOperation_Aux4,
1411                  _StrandEntryOperation_Deleted,
1412                  NULL, // just give some overflow NULL methods for safety
1413                  NULL, 
1414                  NULL };    
1415              
1416              //------------------------------------------------------------------------------------------------------------
1417              size_t _StrandMany_HashMapHashProc(const HashBucket* bucket)
1418              {
1419                  return (size_t)bucket;
1420              }
1421              
1422              int _StrandMany_HashMapEqualProc(_In_ const HashBucket* bucket1, _In_ const HashBucket* bucket2)
1423              {
1424                  return bucket1 == bucket2;
1425              }
1426              
1427              void _StrandMany_HashMapReleaseProc(_In_ HashBucket* bucket1)
1428              {
1429 krisbash 1.1     // nothing to do here (entry is deleted on _StrandMethod_RunPendingOperations)
1430              }
1431              
1432              //------------------------------------------------------------------------------------------------------------
1433              void StrandMany_CancelAllEntries( _In_ StrandMany* self )
1434              {
1435                  StrandEntry* entry;
1436                  STRAND_ASSERTONSTRAND( &self->strand );
1437                  
1438                  StrandMany_BeginIteration( self );
1439                  while( NULL != (entry = StrandMany_Iterate( self )) )
1440                  {
1441                      StrandMany_CancelEntry( entry );
1442                  }
1443              }
1444              
1445              void StrandMany_CloseAllEntries( _In_ StrandMany* self )
1446              {
1447                  StrandEntry* entry;
1448                  STRAND_ASSERTONSTRAND( &self->strand );
1449              
1450 krisbash 1.1     StrandMany_BeginIteration( self );
1451                  while( NULL != (entry = StrandMany_Iterate( self )) )
1452                  {
1453                      StrandMany_CloseEntry( entry );
1454                  }
1455              }
1456              
1457              void StrandMany_PostEntry( _In_ StrandEntry* entry, _In_ Message* msg )
1458              {
1459                  STRAND_ASSERTONSTRAND( &entry->parent->strand );
1460                  
1461                  Message_AddRef( msg );  // add ref before assigning and scheduling
1462                  entry->fromParent.msg = msg;
1463                  _Strand_Schedule( &entry->strand, BitPostInternal );
1464              }
1465              
1466              void StrandMany_PostAll( _In_ StrandMany* self, _In_ Message* msg )
1467              {
1468                  StrandEntry* entry;
1469              
1470                  STRAND_ASSERTONSTRAND( &self->strand );
1471 krisbash 1.1     
1472                  StrandMany_BeginIteration( self );
1473                  while( NULL != (entry = StrandMany_Iterate( self )) )
1474                  {
1475                      StrandMany_PostEntry( entry, msg );
1476                  }
1477              }
1478              
1479              MI_Boolean StrandMany_PostFindEntry( _In_ StrandMany* self, _In_ Message* msg )
1480              {
1481                  StrandEntry* entry;
1482              
1483                  STRAND_ASSERTONSTRAND( &self->strand );
1484                  DEBUG_ASSERT( NULL != self->findEntryProc );
1485                  
1486                  entry = self->findEntryProc( self, msg );
1487                  if( NULL != entry )
1488                  {
1489                      StrandMany_PostEntry( entry, msg );
1490                      return MI_TRUE;
1491                  }
1492 krisbash 1.1     else
1493                  {
1494                      return MI_FALSE;
1495                  }
1496              }
1497              
1498              void StrandMany_PostControlEntry( _In_ StrandEntry* entry, _In_ Message* msg )
1499              {
1500                  STRAND_ASSERTONSTRAND( &entry->parent->strand );
1501                  
1502                  Message_AddRef( msg );  // add ref before assigning and scheduling
1503                  entry->fromParent.controlMsg = msg;
1504                  _Strand_Schedule( &entry->strand, BitPostControlInternal );
1505              }
1506              
1507              void StrandMany_PostControlAll( _In_ StrandMany* self, _In_ Message* msg )
1508              {
1509                  StrandEntry* entry;
1510                  
1511                  STRAND_ASSERTONSTRAND( &self->strand );
1512                  
1513 krisbash 1.1     StrandMany_BeginIteration( self );
1514                  while( NULL != (entry = StrandMany_Iterate( self )) )
1515                  {
1516                      StrandMany_PostControlEntry( entry, msg );
1517                  }
1518              }
1519              
1520              MI_Boolean StrandMany_PostControlFindEntry( _In_ StrandMany* self, _In_ Message* msg )
1521              {
1522                  StrandEntry* entry;
1523              
1524                  STRAND_ASSERTONSTRAND( &self->strand );
1525                  DEBUG_ASSERT( NULL != self->findEntryProc );
1526                  
1527                  entry = self->findEntryProc( self, msg );
1528                  if( NULL != entry )
1529                  {
1530                      StrandMany_PostControlEntry( entry, msg );
1531                      return MI_TRUE;
1532                  }
1533                  else
1534 krisbash 1.1     {
1535                      return MI_FALSE;
1536                  }
1537              }
1538              
1539              //------------------------------------------------------------------------------------------------------------
1540              void _StrandEntry_ScheduleParent( _In_ StrandEntry* self, EntryOperationMaskType entryOperationBit )
1541              {
1542                  // this can be called during creation (StrandEntry_ScheduleAdd) so we cannot call STRAND_ASSERTONSTRAND( &self->strand );
1543                  if( 0 == self->operationScheduled )
1544                  {
1545                      self->operationScheduled = entryOperationBit;
1546                      SList_PushAtomic( &self->parent->pending, &self->entry );
1547                      _Strand_ScheduleEntryOperation( &self->parent->strand, MI_TRUE, &self->strand, entryOperationBit );
1548                  }
1549                  else
1550                  {
1551                      DEBUG_ASSERT( 0 == (self->operationsPending & entryOperationBit) );
1552                      self->operationsPending |= entryOperationBit;
1553                  }
1554              }
1555 krisbash 1.1 
1556              void StrandEntry_PostParent( _In_ StrandEntry* self, _In_ Message* msg )
1557              {
1558                  STRAND_ASSERTONSTRAND( &self->strand );
1559                  DEBUG_ASSERT( NULL == self->toParent.msg );
1560                  Message_AddRef( msg );
1561                  self->toParent.msg = msg;
1562                  _StrandEntry_ScheduleParent( self, BitEntryPost );
1563              }
1564              
1565              void StrandEntry_PostParentPassthru( _In_ StrandEntry* self, _In_ Message* msg )
1566              {
1567                  DEBUG_ASSERT( !self->ackPassthru );
1568                  self->ackPassthru = MI_TRUE;
1569                  StrandEntry_PostParent( self, msg );
1570              }
1571              
1572              void StrandEntry_PostControlParent( _In_ StrandEntry* self, _In_ Message* msg )
1573              {
1574                  STRAND_ASSERTONSTRAND( &self->strand );
1575                  DEBUG_ASSERT( NULL == self->toParent.controlMsg );
1576 krisbash 1.1     Message_AddRef( msg );
1577                  self->toParent.controlMsg = msg;
1578                  _StrandEntry_ScheduleParent( self, BitEntryPostControl );
1579              }
1580              
1581              //------------------------------------------------------------------------------------------------------------
1582              #ifdef _PREFAST_
1583              #pragma prefast (push)
1584              #pragma prefast (disable: 26001) // bogus "we know the strand points to the middle of the StrandMany struct" and Linux sal parser doesnt recognize something like _Readable_elements_(_Inexpressible_(StrandMany))
1585              #endif /* _PREFAST_ */
1586              
1587              MI_Boolean _StrandMethod_Parent_CheckFinished( _In_ Strand* self_ ) 
1588              {
1589                  StrandMany* self = StrandMany_FromStrand(self_);
1590                  
1591                  return ( 0 == self->numEntries ) && _StrandMethodImp_CheckFinished( &self->strand.info ) && !self->strand.delayFinish;
1592              }
1593              
1594              MI_Boolean _StrandMethod_Parent_Cancel( _In_ Strand* self_)
1595              {
1596                  StrandMany* self = StrandMany_FromStrand(self_);
1597 krisbash 1.1 
1598                  STRAND_DEBUGSTATE( self_ );
1599                  
1600                  if( !self->strand.canceled )
1601                  {
1602                      // if it is on the right, we dont need to pass cancel to the right
1603                      // if it is on the left, canceling entries passes cancel to the right
1604                  
1605                      // now cancel all entries
1606                      StrandMany_CancelAllEntries( self );
1607                      
1608                      _StrandMethodImp_Cancel( &self->strand, &self->strand.info );
1609                  }
1610              
1611                  return MI_FALSE;
1612              }
1613              
1614              MI_Boolean _StrandMethod_Parent_PostControl( _In_ Strand* self_) 
1615              {
1616                  StrandMany* self = StrandMany_FromStrand(self_);
1617                  
1618 krisbash 1.1     _Strand_TracePostMsg(self_, self->strand.info.stored.controlMsg, "(Control Parent)");
1619                  STRAND_DEBUGSTATE( self_ );
1620                  DEBUG_ASSERT( NULL != self->strand.info.stored.controlMsg );
1621              
1622                  if( NULL != self->strand.info.userFT->PostControl )
1623                  {
1624                      self->strand.info.userFT->PostControl( &self->strand, self->strand.info.stored.controlMsg );
1625                  }
1626                  else
1627                  {
1628                      if( NULL == self->findEntryProc )
1629                      {
1630                          // Since we dont have true searching capabilities sent to all entries
1631                          StrandMany_PostControlAll( self, self->strand.info.stored.controlMsg );
1632                      }
1633                      else
1634                      {
1635                          MI_Boolean ret = StrandMany_PostControlFindEntry( self, self->strand.info.stored.controlMsg );
1636                          if (!ret)
1637                          {
1638                              DEBUG_ASSERT( ret );
1639 krisbash 1.1             }
1640                      }
1641                  }
1642                  
1643                  Message_Release( self->strand.info.stored.controlMsg );  // now we can remove the reference added on _StrandInteraction_*
1644                  self->strand.info.stored.controlMsg = NULL;
1645                  
1646                  return MI_FALSE;
1647              }
1648              
1649              MI_Boolean _StrandMethod_Parent_Post( _In_ Strand* self_)
1650              {
1651                  StrandMany* self = StrandMany_FromStrand( self_);
1652                  Message* storedmsg = self->strand.info.stored.msg;
1653                  _Strand_TracePostMsg(self_, storedmsg, "(Parent)");
1654                  STRAND_DEBUGSTATE( self_ );
1655                  DEBUG_ASSERT( !self->strand.info.otherAckPending );
1656                  DEBUG_ASSERT( NULL != storedmsg );
1657              
1658                  self->strand.info.stored.msg = NULL;
1659                  self->strand.info.otherAckPending = MI_TRUE;
1660 krisbash 1.1 
1661                  if( NULL != self->strand.info.userFT->Post )
1662                  {
1663                      self->strand.info.userFT->Post( &self->strand, storedmsg );
1664                  }
1665                  else
1666                  {
1667                      if( NULL == self->findEntryProc )
1668                      {
1669                          // Since we dont have true searching capabilities sent to all entries
1670                          StrandMany_PostAll( self, storedmsg );
1671                      }
1672                      else
1673                      {
1674                          MI_Boolean ret = StrandMany_PostFindEntry( self, storedmsg );
1675                          if (!ret)
1676                          {
1677                              DEBUG_ASSERT( ret );
1678                          }
1679                      }
1680              
1681 krisbash 1.1         Strand_Ack( &self->strand );
1682                  }
1683                  
1684                  Message_Release( storedmsg );  // now we can remove the reference added on _StrandInteraction_*
1685              
1686                  return MI_FALSE;
1687              }
1688              
1689              #ifdef _PREFAST_
1690              #pragma prefast (pop)
1691              #endif /* _PREFAST_ */
1692              
1693              void _StrandMethod_Parent_RunPendingOperations( _In_ StrandMany * self )
1694              {
1695                  unsigned long bitIndex;
1696                  SListHead retryList;
1697                  SListEntry * retryEntry;
1698              
1699                  DEBUG_ASSERT( NULL == self->currentEntry );
1700              
1701                  SList_Init( &retryList );
1702 krisbash 1.1     self->pendingRetry = MI_FALSE;
1703                  
1704                  while( NULL != ( self->currentEntry = (StrandEntry*)SList_PopAtomic( &self->pending ) ) )
1705                  {    
1706                      bitIndex = GetFirstSetLSB( self->currentEntry->operationScheduled );
1707                      DEBUG_ASSERT( bitIndex );
1708              
1709              //        trace_Strand_RunPendingOp(
1710              //            &self->strand, 
1711              //            STRAND_DEBUG_GETNAME(&self->strand), 
1712              //            bitIndex, 
1713              //            STRAND_DEBUG_GETOPERATIONINDEX(&self->strand,bitIndex) );
1714                          
1715                      switch( (*_StrandEntryOperations_FT[ bitIndex-1 ])(self) )
1716                      {
1717                      case EORetry:
1718              //            trace_Strand_RunPendingOp_CannotComplete(
1719              //                &self->strand, 
1720              //                STRAND_DEBUG_GETNAME(&self->strand), 
1721              //                bitIndex, 
1722              //                STRAND_DEBUG_GETOPERATIONINDEX(&self->strand,bitIndex) );
1723 krisbash 1.1                 
1724                          // We will retry when ack arrives
1725                          self->pendingRetry = MI_TRUE;
1726                          SList_PushAtomic( &retryList, &self->currentEntry->entry );
1727                          break;
1728                      case EODeleted:
1729                          // Special case, we delete the entry here and we do not send back any completion to the entry
1730                          trace_Strand_RunPendingOp_EntryDeleted(
1731                              &self->strand, 
1732                              STRAND_DEBUG_GETNAME(&self->strand), 
1733                              bitIndex, 
1734                              STRAND_DEBUG_GETOPERATIONINDEX(&self->strand,bitIndex) );
1735                          break;
1736                      case EOContinue:
1737                          // schedule completion to entry
1738                          _Strand_ScheduleEntryOperation( &self->currentEntry->strand, MI_FALSE, &self->strand, self->currentEntry->operationScheduled );
1739                          break;
1740                      default:
1741                          DEBUG_ASSERT( MI_FALSE );
1742                      }
1743                  }
1744 krisbash 1.1 
1745                  // push back into the list the ones we couldn't execute
1746                  while( NULL != ( retryEntry = SList_PopAtomic( &retryList ) ) )
1747                  {    
1748                      SList_PushAtomic( &self->pending, retryEntry );
1749                  }
1750                  
1751                  self->currentEntry = NULL;
1752              }
1753              
1754              MI_Boolean _StrandMethod_Parent_Ack( _In_ Strand* self_)
1755              {
1756                  StrandMany* self = StrandMany_FromStrand(self_);
1757              
1758                  STRAND_DEBUGSTATE( self_ );
1759              
1760                  _StrandMethodImp_Ack( &self->strand, &self->strand.info );
1761              
1762                  // Check if there is any entry waiting to be processed
1763                  if( self->pendingRetry )
1764                  {
1765 krisbash 1.1         // Can't run _StrandMethod_RunPendingOperations directly,
1766                      // because otherwise that can do a Post and then 
1767                      // the Ack to that post may come while we have not leave
1768                      // the current Ack (and therefore schedule will assert 
1769                      // because it would try to schedule an Ack while other is 
1770                      // already running)
1771                      _Strand_ScheduleEntryOperation(&self->strand, MI_TRUE, NULL, 0 );
1772                  }
1773                  // Note that there is no problem if some entry race to insert something in the list
1774                  // after the check, as that entry will also schedule the EntryOperation itself
1775              
1776                  return MI_FALSE;
1777              }
1778              
1779              MI_Boolean _StrandMethod_Parent_EntryOperation( _In_ Strand* self_)
1780              {
1781                  StrandMany* self = StrandMany_FromStrand(self_);
1782              
1783                  _StrandMethod_Parent_RunPendingOperations( self );
1784                  
1785                  return MI_FALSE;
1786 krisbash 1.1 }
1787              
1788              MI_Boolean _StrandMethod_Parent_Close( _In_ Strand* self_)
1789              {
1790                  StrandMany* self = StrandMany_FromStrand(self_);
1791              
1792                  STRAND_DEBUGSTATE( self_ );
1793              
1794                  _StrandMethodImp_Close( &self->strand, &self->strand.info );
1795              
1796                  // now if there is no method close all entries 
1797                  if( NULL == self->strand.info.userFT->Close )
1798                  {
1799                      StrandMany_CloseAllEntries( self );
1800                  }
1801                  
1802                  return MI_FALSE;
1803              }
1804              
1805              MI_Boolean _StrandMethod_Parent_CancelInternal( _In_ Strand* self_)
1806              {
1807 krisbash 1.1     DEBUG_ASSERT( MI_FALSE );    // this should never be scheduled on the parent but a EntryOperation should be used instead
1808                  return MI_FALSE;
1809              }
1810              
1811              MI_Boolean _StrandMethod_Parent_PostControlInternal( _In_ Strand* self_)
1812              {
1813                  DEBUG_ASSERT( MI_FALSE );    // this should never be scheduled on the parent but a EntryOperation should be used instead
1814                  return MI_FALSE;
1815              }
1816              
1817              MI_Boolean _StrandMethod_Parent_PostInternal( _In_ Strand* self_)
1818              {
1819                  DEBUG_ASSERT( MI_FALSE );    // this should never be scheduled on the parent but a EntryOperation should be used instead
1820                  return MI_FALSE;
1821              }
1822              
1823              MI_Boolean _StrandMethod_Parent_AckInternal( _In_ Strand* self_)
1824              {
1825                  DEBUG_ASSERT( MI_FALSE );    // this should never be scheduled on the parent (EntryOperation cannot be used either)
1826                  return MI_FALSE;
1827              }
1828 krisbash 1.1 
1829              MI_Boolean _StrandMethod_Parent_CloseInternal( _In_ Strand* self_)
1830              {
1831                  DEBUG_ASSERT( MI_FALSE );    // this should never be scheduled on the parent but a EntryOperation should be used instead
1832                  return MI_FALSE;
1833              }
1834              
1835              //------------------------------------------------------------------------------------------------------------
1836              MI_Boolean _StrandMethod_Entry_CheckFinished( _In_ Strand* self_ ) 
1837              {
1838                  StrandEntry* self = StrandEntry_FromStrand(self_);
1839                  
1840                  return ( 0 == self->operationScheduled ) && ( 0 == self->operationsPending ) && _StrandMethodImp_CheckFinished( &self->strand.info ) && !self->strand.delayFinish;
1841              }
1842              
1843              MI_Boolean _StrandMethod_Entry_Cancel( _In_ Strand* self_)
1844              {
1845                  StrandEntry* self = StrandEntry_FromStrand(self_);
1846                  
1847                  STRAND_DEBUGSTATE( self_ );
1848              
1849 krisbash 1.1     if( !self->strand.canceled )
1850                  {
1851                      self->strand.canceled = MI_TRUE;
1852              
1853                      // if it is on the right, we dont need to pass cancel to the right
1854                      // if it is on the left, canceling parent passes cancel to the right
1855                      
1856                      if( NULL != self->strand.info.userFT->Cancel )
1857                      {
1858                          (*self->strand.info.userFT->Cancel)(self_);
1859                      }
1860                      else
1861                      {
1862                          StrandEntry_CancelParent(self);
1863                      }
1864                  }
1865              
1866                  return MI_FALSE;
1867              }
1868              
1869              MI_Boolean _StrandMethod_Entry_PostControl( _In_ Strand* self_) 
1870 krisbash 1.1 {
1871                  StrandEntry* self = StrandEntry_FromStrand(self_);
1872                  
1873                  _Strand_TracePostMsg(self_, self->strand.info.stored.controlMsg, "(Control Entry)");
1874                  STRAND_DEBUGSTATE( self_ );
1875                  DEBUG_ASSERT( NULL != self->strand.info.stored.controlMsg );
1876              
1877                  if( NULL != self->strand.info.userFT->PostControl )
1878                  {
1879                      self->strand.info.userFT->PostControl( &self->strand, self->strand.info.stored.controlMsg );
1880                  }
1881                  else
1882                  {
1883                      StrandEntry_PostControlParent( self, self->strand.info.stored.controlMsg );
1884                  }
1885                  
1886                  Message_Release( self->strand.info.stored.controlMsg );  // now we can remove the reference added on _StrandInteraction_*
1887                  self->strand.info.stored.controlMsg = NULL;
1888                  
1889                  return MI_FALSE;
1890              }
1891 krisbash 1.1 
1892              MI_Boolean _StrandMethod_Entry_Post( _In_ Strand* self_)
1893              {
1894                  StrandEntry* self = StrandEntry_FromStrand(self_);
1895                  Message* storedmsg = self->strand.info.stored.msg;
1896                  _Strand_TracePostMsg(self_, storedmsg, "(Entry)");
1897                  STRAND_DEBUGSTATE( self_ );
1898                  DEBUG_ASSERT( !self->strand.info.otherAckPending );
1899                  DEBUG_ASSERT( NULL != storedmsg );
1900                  self->strand.info.stored.msg = NULL;
1901                  self->strand.info.otherAckPending = MI_TRUE;
1902              
1903                  if( NULL != self->strand.info.userFT->Post )
1904                  {
1905                      self->strand.info.userFT->Post( &self->strand, storedmsg );
1906                  }
1907                  else
1908                  {
1909                      StrandEntry_PostParentPassthru( self, storedmsg );
1910                  }
1911              
1912 krisbash 1.1     Message_Release( storedmsg );  // now we can remove the reference added on _StrandInteraction_*  
1913              
1914                  return MI_FALSE;
1915              }
1916              
1917              MI_Boolean _StrandMethod_Entry_Ack( _In_ Strand* self_)
1918              {
1919                  STRAND_DEBUGSTATE( self_ );
1920              
1921                  _StrandMethodImp_Ack( self_, &self_->info );
1922              
1923                  return MI_FALSE;
1924              }
1925              
1926              #ifdef _PREFAST_
1927              #pragma prefast (push)
1928              #pragma prefast (disable: 26001) // bogus "we know the strand points to the middle of the StrandEntry struct" and Linux sal parser doesnt recognize something like _Readable_elements_(_Inexpressible_(StrandEntry))
1929              #endif /* _PREFAST_ */
1930              
1931              MI_Boolean _StrandMethod_Entry_EntryOperation( _In_ Strand* self_)
1932              {
1933 krisbash 1.1     StrandEntry* self = StrandEntry_FromStrand(self_);
1934                  EntryOperationMaskType operationLastScheduled = self->operationScheduled;
1935              
1936                  if( 0 != self->operationsPending )
1937                  {
1938                      // schedule the next one
1939                      unsigned long bitIndex;
1940                      EntryOperationMaskType entryOperationBit;
1941                      
1942                      bitIndex = GetFirstSetLSB( self->operationsPending );
1943                      DEBUG_ASSERT( bitIndex );
1944                      entryOperationBit = (EntryOperationMaskType)_GetMethodBit( bitIndex );
1945                      
1946                      self->operationScheduled = entryOperationBit;
1947                      self->operationsPending &= (~entryOperationBit);
1948                      
1949                      SList_PushAtomic( &self->parent->pending, &self->entry );
1950                      _Strand_ScheduleEntryOperation( &self->parent->strand, MI_TRUE, &self->strand, entryOperationBit );
1951                  }
1952                  else
1953                  {
1954 krisbash 1.1         self->operationScheduled = 0;
1955                  }
1956                  
1957                  if( BitEntryPost == operationLastScheduled )
1958                  {
1959                      if( NULL != self->parent->userInternalFT && NULL != self->parent->userInternalFT->ParentAck )
1960                      {
1961                          self->parent->userInternalFT->ParentAck( self );
1962                      }
1963                      else if( self->ackPassthru )
1964                      {
1965                          // Now we can send the Ack to the interaction
1966                          Strand_Ack(self_);
1967                      }
1968                      self->ackPassthru = MI_FALSE;
1969                  }
1970                  else if( BitEntryAdd == operationLastScheduled && NULL != self->parent->userInternalFT && NULL != self->parent->userInternalFT->AddedToParent )
1971                  {
1972                      Message* storedmsg = self->strand.info.stored.msg;
1973                      self->strand.info.stored.msg = NULL;
1974                      self->parent->userInternalFT->AddedToParent( self, storedmsg );
1975 krisbash 1.1         if( NULL != storedmsg )
1976                      {
1977                          _Strand_TracePostMsg(self_, storedmsg, "(EntryAddedToParent)");
1978                          Message_Release( storedmsg );  // now we can finally remove the reference added on ScheduleAdd            
1979                      }
1980                  }
1981              
1982                  return MI_FALSE;
1983              }
1984              
1985              MI_Boolean _StrandMethod_Entry_Close( _In_ Strand* self_)
1986              {
1987                  STRAND_DEBUGSTATE( self_ );
1988              
1989                  _StrandMethodImp_Close( self_, &self_->info );
1990              
1991                  return MI_FALSE;
1992              }
1993              
1994              MI_Boolean _StrandMethod_Entry_CancelInternal( _In_ Strand* self_)
1995              {
1996 krisbash 1.1     StrandEntry* self = StrandEntry_FromStrand(self_);
1997              
1998                  trace_StrandMethod_Entry_CancelInternal( self_, STRAND_DEBUG_GETNAME(self_) );
1999              
2000                  if( !self_->canceled )
2001                  {
2002                      if( self_->info.opened )
2003                      {
2004                          if( !self_->info.thisClosedOther )
2005                          {
2006                              // since we are in the middle, forward to the other side
2007                              self_->info.interaction.other->ft->Cancel( self_->info.interaction.other );
2008                          }
2009                          _StrandMethodImp_Cancel( self_, &self_->info );
2010                      }
2011                      else
2012                      {
2013                          // If it was not even opened we dont even call the cancel method
2014                          self_->canceled = MI_TRUE;
2015                      }
2016                  }
2017 krisbash 1.1     else if( self->parent->strand.strandType == STRAND_TYPE_PARENTRIGHT && self_->info.opened && !self_->info.thisClosedOther )
2018                  {
2019                      // since we are in the left-middle this can be cancelation coming back from right, 
2020                      // so pass back to the left
2021                      self_->info.interaction.other->ft->Cancel( self_->info.interaction.other );
2022                  }
2023                  return MI_FALSE;
2024              }
2025              
2026              MI_Boolean _StrandMethod_Entry_PostControlInternal( _In_ Strand* self_)
2027              {
2028                  StrandEntry* self = StrandEntry_FromStrand(self_);
2029              
2030                  DEBUG_ASSERT( NULL != self->fromParent.controlMsg );
2031              
2032                  trace_StrandMethod_Entry_PostControlInternal(self_, STRAND_DEBUG_GETNAME(self_), self->fromParent.controlMsg);
2033              
2034                  if( NULL != self->parent->userInternalFT && NULL != self->parent->userInternalFT->ParentPostControl )
2035                  {
2036                      self->parent->userInternalFT->ParentPostControl( self, self->fromParent.controlMsg );
2037                  }
2038 krisbash 1.1     else
2039                  {
2040                      Strand_PostControl( self_, self->fromParent.controlMsg );
2041                  }
2042              
2043                  Message_Release( self->fromParent.controlMsg ); // ref added on StrandMany_PostControlEntry
2044                  self->fromParent.controlMsg = NULL;
2045              
2046                  return MI_FALSE;
2047              }
2048              
2049              MI_Boolean _StrandMethod_Entry_PostInternal( _In_ Strand* self_)
2050              {
2051                  StrandEntry* self = StrandEntry_FromStrand( self_);
2052              
2053                  DEBUG_ASSERT( NULL != self->fromParent.msg );
2054                  DEBUG_ASSERT( !self->strand.info.thisAckPending );  // user is responsible to manage flow control if there are secondary messages
2055              
2056                  trace_StrandMethod_Entry_PostInternal(self_, STRAND_DEBUG_GETNAME(self_), self->fromParent.msg);
2057              
2058                  if( NULL != self->parent->userInternalFT && NULL != self->parent->userInternalFT->ParentPost )
2059 krisbash 1.1     {
2060                      self->parent->userInternalFT->ParentPost( self, self->fromParent.msg );
2061                  }
2062                  else
2063                  {
2064                      Strand_Post( self_, self->fromParent.msg );
2065                  }
2066              
2067                  Message_Release( self->fromParent.msg ); // ref added on StrandMany_PostEntry
2068                  self->fromParent.msg = NULL;
2069              
2070                  return MI_FALSE;
2071              }
2072              
2073              #ifdef _PREFAST_
2074              #pragma prefast (pop)
2075              #endif /* _PREFAST_ */
2076              
2077              MI_Boolean _StrandMethod_Entry_AckInternal( _In_ Strand* self_)
2078              {
2079                  trace_StrandMethod_Entry_AckInternal( self_, STRAND_DEBUG_GETNAME(self_) );
2080 krisbash 1.1 
2081                  Strand_Ack( self_ );
2082              
2083                  return MI_FALSE;
2084              }
2085              
2086              MI_Boolean _StrandMethod_Entry_CloseInternal( _In_ Strand* self_)
2087              {
2088                  StrandEntry* self = StrandEntry_FromStrand(self_);
2089              
2090                  trace_StrandMethod_Entry_CloseInternal(
2091                      self_, 
2092                      STRAND_DEBUG_GETNAME(self_),
2093                      self_->info.opened,
2094                      self_->info.thisClosedOther );
2095              
2096                  if( NULL != self->parent->userInternalFT && NULL != self->parent->userInternalFT->ParentClose )
2097                  {
2098                      self->parent->userInternalFT->ParentClose( self );
2099                  }
2100                  else if( self_->info.opened && !self_->info.thisClosedOther )
2101 krisbash 1.1     {
2102                      Strand_Close( self_ );
2103                  }
2104              
2105                  return MI_FALSE;
2106              }
2107              
2108              //------------------------------------------------------------------------------------------------------------
2109              static InteractionFT _StrandInteraction_FT = { 
2110                  _StrandInteraction_Post, 
2111                  _StrandInteraction_PostControl, 
2112                  _StrandInteraction_Ack, 
2113                  _StrandInteraction_Cancel, 
2114                  _StrandInteraction_Close };
2115              
2116              //------------------------------------------------------------------------------------------------------------
2117              static InteractionFT _StrandInteraction_Left_FT = { 
2118                  _StrandInteraction_Left_Post, 
2119                  _StrandInteraction_Left_PostControl, 
2120                  _StrandInteraction_Left_Ack, 
2121                  _StrandInteraction_Left_Cancel, 
2122 krisbash 1.1     _StrandInteraction_Left_Close };
2123              
2124              //------------------------------------------------------------------------------------------------------------
2125              static InteractionFT _StrandInteraction_Right_FT = { 
2126                  _StrandInteraction_Right_Post, 
2127                  _StrandInteraction_Right_PostControl, 
2128                  _StrandInteraction_Right_Ack, 
2129                  _StrandInteraction_Right_Cancel, 
2130                  _StrandInteraction_Right_Close };
2131              
2132              //------------------------------------------------------------------------------------------------------------
2133              static InteractionFT _StrandInteraction_Many_FT = { 
2134                  _StrandInteraction_Many_Post, 
2135                  _StrandInteraction_Many_PostControl, 
2136                  _StrandInteraction_Many_Ack, 
2137                  _StrandInteraction_Many_Cancel, 
2138                  _StrandInteraction_Many_Close };
2139              
2140              //------------------------------------------------------------------------------------------------------------
2141              static StrandMethod _StrandMethods_FT[] = { 
2142                  _StrandMethod_CheckFinished, 
2143 krisbash 1.1     _StrandMethod_CompleteOpenAsync, 
2144                  _StrandMethod_Timer, 
2145                  _StrandMethod_Cancel, 
2146                  _StrandMethod_CancelSelf,
2147                  _StrandMethod_PostControl, 
2148                  _StrandMethod_Post, 
2149                  _StrandMethod_PostOther,
2150                  _StrandMethod_Ack, 
2151                  _StrandMethod_AckOther,
2152                  _StrandMethod_Close,
2153                  _StrandMethod_CloseOther,
2154                  _StrandMethod_Aux0,
2155                  _StrandMethod_Aux1,
2156                  _StrandMethod_Aux2,
2157                  _StrandMethod_Aux3,
2158                  _StrandMethod_Aux4,
2159                  NULL, // just give some overflow NULL methods for safety
2160                  NULL, 
2161                  NULL };    
2162              
2163              //------------------------------------------------------------------------------------------------------------
2164 krisbash 1.1 static StrandMethod _StrandMethods_Both_FT[] = { 
2165                  _StrandMethod_Both_CheckFinished, 
2166                  _StrandMethod_Both_CompleteOpenAsync,
2167                  _StrandMethod_Timer, 
2168                  _StrandMethod_Left_Cancel, 
2169                  _StrandMethod_Right_Cancel, 
2170                  _StrandMethod_Both_CancelSelf,
2171                  _StrandMethod_Left_PostControl, 
2172                  _StrandMethod_Right_PostControl, 
2173                  _StrandMethod_Left_Post, 
2174                  _StrandMethod_Right_Post, 
2175                  _StrandMethod_PostOther,
2176                  _StrandMethod_Right_PostOther,
2177                  _StrandMethod_Left_Ack, 
2178                  _StrandMethod_Right_Ack, 
2179                  _StrandMethod_AckOther,
2180                  _StrandMethod_Right_AckOther,
2181                  _StrandMethod_Left_Close,
2182                  _StrandMethod_Right_Close,
2183                  _StrandMethod_CloseOther,
2184                  _StrandMethod_Right_CloseOther,
2185 krisbash 1.1     _StrandMethod_Aux0,
2186                  _StrandMethod_Aux1,
2187                  _StrandMethod_Aux2,
2188                  _StrandMethod_Aux3,
2189                  _StrandMethod_Aux4,
2190                  _StrandMethod_Right_Aux0,
2191                  _StrandMethod_Right_Aux1,
2192                  _StrandMethod_Right_Aux2,
2193                  _StrandMethod_Right_Aux3,
2194                  _StrandMethod_Right_Aux4,
2195                  NULL, // just give some overflow NULL methods for safety
2196                  NULL, 
2197                  NULL };    
2198              
2199              //------------------------------------------------------------------------------------------------------------
2200              static StrandMethod _StrandMethods_Parent_FT[] = { 
2201                  _StrandMethod_Parent_CheckFinished, 
2202                  _StrandMethod_CompleteOpenAsync,
2203                  _StrandMethod_Timer, 
2204                  _StrandMethod_Parent_Cancel, 
2205                  _StrandMethod_CancelSelf,
2206 krisbash 1.1     _StrandMethod_Parent_CancelInternal, 
2207                  _StrandMethod_Parent_PostControl, 
2208                  _StrandMethod_Parent_PostControlInternal, 
2209                  _StrandMethod_Parent_Post, 
2210                  _StrandMethod_PostOther,
2211                  _StrandMethod_Parent_PostInternal, 
2212                  _StrandMethod_Parent_Ack, 
2213                  _StrandMethod_AckOther,
2214                  _StrandMethod_Parent_AckInternal,
2215                  _StrandMethod_Parent_EntryOperation,
2216                  _StrandMethod_Parent_Close,
2217                  _StrandMethod_CloseOther,
2218                  _StrandMethod_Parent_CloseInternal,
2219                  _StrandMethod_Aux0,
2220                  _StrandMethod_Aux1,
2221                  _StrandMethod_Aux2,
2222                  _StrandMethod_Aux3,
2223                  _StrandMethod_Aux4,
2224                  NULL, // just give some overflow NULL methods for safety
2225                  NULL, 
2226                  NULL };    
2227 krisbash 1.1 
2228              //------------------------------------------------------------------------------------------------------------
2229              static StrandMethod _StrandMethods_Entry_FT[] = { 
2230                  _StrandMethod_Entry_CheckFinished, 
2231                  _StrandMethod_CompleteOpenAsync,
2232                  _StrandMethod_Timer, 
2233                  _StrandMethod_Entry_Cancel, 
2234                  _StrandMethod_CancelSelf,
2235                  _StrandMethod_Entry_CancelInternal, 
2236                  _StrandMethod_Entry_PostControl, 
2237                  _StrandMethod_Entry_PostControlInternal, 
2238                  _StrandMethod_Entry_Post, 
2239                  _StrandMethod_PostOther,
2240                  _StrandMethod_Entry_PostInternal, 
2241                  _StrandMethod_Entry_Ack, 
2242                  _StrandMethod_AckOther,
2243                  _StrandMethod_Entry_AckInternal,
2244                  _StrandMethod_Entry_EntryOperation,
2245                  _StrandMethod_Entry_Close,
2246                  _StrandMethod_CloseOther,
2247                  _StrandMethod_Entry_CloseInternal,
2248 krisbash 1.1     _StrandMethod_Aux0,
2249                  _StrandMethod_Aux1,
2250                  _StrandMethod_Aux2,
2251                  _StrandMethod_Aux3,
2252                  _StrandMethod_Aux4,
2253                  NULL, // just give some overflow NULL methods for safety
2254                  NULL, 
2255                  NULL };    
2256              
2257              //------------------------------------------------------------------------------------------------------------
2258              MI_INLINE
2259              void _Strand_EnterStrand( _In_ Strand* self )
2260              {
2261                  trace_Strand_EnterStrand( self, STRAND_DEBUG_GETNAME(self) );
2262                  
2263                  DEBUG_ASSERT( NULL == self->strandStealedFlag );
2264                  DEBUG_ASSERT( 0 == self->stateScheduled );
2265                  self->stateScheduled = BitExecuting;
2266              
2267                  _Strand_SetCurrentStrandThread( self );
2268              }
2269 krisbash 1.1 
2270              // Only used internally 
2271              MI_INLINE
2272              void _Strand_ExitStrand( _In_ Strand* self )
2273              {
2274                  trace_Strand_ExitStrand( self, STRAND_DEBUG_GETNAME(self) );
2275                  
2276                  DEBUG_ASSERT( NULL == self->strandStealedFlag );
2277                  DEBUG_ASSERT( BitExecuting == self->stateScheduled );
2278                  self->stateScheduled = 0;
2279              
2280                  _Strand_ExitCurrentStrandThread( self );
2281              }
2282              
2283              MI_INLINE
2284              Strand* _Strand_Create(
2285                                  size_t          structSize,
2286                  _Inout_         StrandFlags*    flags )
2287              {
2288                  Strand* self;
2289              
2290 krisbash 1.1     DEBUG_ASSERT( structSize >= sizeof(Strand) );
2291                  
2292                  /* Allocate heap space for Strand */
2293                  if( 0 != (*flags & STRAND_FLAG_NOZEROALLOCATED) )
2294                  {
2295                      *flags &= (~STRAND_FLAG_NOZEROALLOCATED);    // To indicate Strand*_Init that it does need to zero the strand fields
2296                      self = PAL_Malloc( structSize );
2297                  }
2298                  else
2299                  {
2300                      *flags |= STRAND_FLAG_NOZEROALLOCATED;       // To indicate Strand*_Init that it doesnt need to zero the strand fields
2301                      self = PAL_Calloc( 1, structSize );
2302                  }
2303              
2304                  return self;
2305              }
2306              
2307              MI_INLINE
2308              void _Strand_CreateEnterStrand(
2309              #if defined(STRAND_ENABLE_DEBUG)
2310                  _In_        StrandDebugInfo debug,
2311 krisbash 1.1 #endif
2312                  _In_        Strand*         self)
2313              {
2314                  STRAND_SETDEBUG( self, debug );
2315              
2316                  _Strand_EnterStrand(self);
2317              }
2318              
2319              MI_INLINE
2320              void _Strand_CreateExitStrand(
2321                  _In_        Strand*         self)
2322              {
2323                  if( 0 == (self->flags & STRAND_FLAG_ENTERSTRAND) )
2324                  {
2325                      _Strand_ExitStrand(self);
2326                  }
2327              }
2328              
2329              //------------------------------------------------------------------------------------------------------------
2330              Strand* Strand_New(
2331              #if defined(STRAND_ENABLE_DEBUG)
2332 krisbash 1.1     _In_        StrandDebugInfo         debug,
2333              #endif
2334                  _In_        StrandFT *              userFT,
2335                              size_t                  structSize,
2336                              StrandFlags             flags,
2337                  _In_opt_    InteractionOpenParams*  interactionOpenParams )
2338              {
2339                  Strand* self;
2340              
2341                  if( 0 == structSize )
2342                      structSize = sizeof( Strand );
2343              
2344                  self = _Strand_Create( structSize, &flags );        
2345              
2346                  if( self )
2347                  {
2348                      Strand_Init( STRAND_PASSDEBUG(debug) self, userFT, flags, interactionOpenParams );
2349                  }
2350                  
2351                  return self;
2352              }
2353 krisbash 1.1 
2354              void Strand_Init(
2355              #if defined(STRAND_ENABLE_DEBUG)
2356                  _In_        StrandDebugInfo         debug,
2357              #endif
2358                  _Out_       Strand*                 self,
2359                  _In_        StrandFT*               userFT,
2360                              StrandFlags             flags,
2361                  _In_opt_    InteractionOpenParams*  interactionOpenParams )
2362              {
2363                  DEBUG_ASSERT(self);
2364                  DEBUG_ASSERT(userFT);
2365              
2366                  if( 0 == (flags & STRAND_FLAG_NOZEROALLOCATED) )
2367                  {
2368                      // Clear all fields in case previously they have not been cleared
2369                      memset(self, 0, sizeof(Strand) );
2370                  }
2371              
2372                  self->strandMethods = _StrandMethods_FT;
2373                  self->flags = flags;
2374 krisbash 1.1     self->info.interaction.ft = &_StrandInteraction_FT; 
2375                  self->info.userFT = userFT;
2376                  
2377                  _Strand_CreateEnterStrand( STRAND_PASSDEBUG(debug) self );
2378                  
2379                  if( NULL != interactionOpenParams || 0 != (flags & STRAND_FLAG_DELAYACCEPTOPEN) )
2380                  {
2381                      // we are being opened on the right most
2382                      self->strandType = STRAND_TYPE_RIGHTMOST;
2383                      if( 0 == (flags & STRAND_FLAG_DELAYACCEPTOPEN) )
2384                      {
2385                          Strand_AcceptOpen( self, interactionOpenParams );
2386                      }
2387                  }
2388                  else
2389                  {
2390                      if( ( flags & STRAND_FLAG_NOINTERACTION ) != 0 )
2391                      {
2392                          self->strandType = STRAND_TYPE_NOINTERACTION;
2393                          self->info.thisClosedOther = self->info.otherClosedThis = MI_TRUE;
2394                      }
2395 krisbash 1.1         else
2396                      {
2397                          self->strandType = STRAND_TYPE_LEFTMOST;
2398                      }
2399                  }
2400              
2401                  _Strand_CreateExitStrand( self );
2402              }
2403              
2404              //------------------------------------------------------------------------------------------------------------
2405              StrandBoth* StrandBoth_New(
2406              #if defined(STRAND_ENABLE_DEBUG)
2407                  _In_        StrandDebugInfo         debug,
2408              #endif
2409                  _In_        StrandFT*               userLeftFT,
2410                  _In_        StrandFT*               userRightFT,
2411                              size_t                  structSize,
2412                              StrandFlags             flags,
2413                  _In_opt_    InteractionOpenParams*  interactionOpenParams )
2414              {
2415                  StrandBoth* self;
2416 krisbash 1.1 
2417                  if( 0 == structSize )
2418                      structSize = sizeof( StrandBoth );
2419                      
2420                  DEBUG_ASSERT( structSize >= sizeof(StrandBoth) );
2421                  
2422                  self = (StrandBoth*) _Strand_Create( structSize, &flags );
2423              
2424                  if( NULL != self )
2425                  {
2426                      StrandBoth_Init( STRAND_PASSDEBUG(debug) self, userLeftFT, userRightFT, flags, interactionOpenParams );
2427                  }
2428              
2429                  return self;
2430              }
2431              
2432              //------------------------------------------------------------------------------------------------------------
2433              void StrandBoth_Init(
2434              #if defined(STRAND_ENABLE_DEBUG)
2435                  _In_        StrandDebugInfo         debug,
2436              #endif
2437 krisbash 1.1     _Out_       StrandBoth*             self,
2438                  _In_        StrandFT*               userLeftFT,
2439                  _In_        StrandFT*               userRightFT,
2440                              StrandFlags             flags,
2441                  _In_opt_    InteractionOpenParams*  interactionOpenParams )
2442              {
2443                  DEBUG_ASSERT(userLeftFT);
2444                  DEBUG_ASSERT(userRightFT);
2445                  // close should be the same for both
2446                  DEBUG_ASSERT( userLeftFT->Finish == userRightFT->Finish || NULL == userRightFT->Finish );
2447                  DEBUG_ASSERT( NULL != interactionOpenParams || 0 != (flags & STRAND_FLAG_DELAYACCEPTOPEN) );
2448                  
2449                  if( 0 == (flags & STRAND_FLAG_NOZEROALLOCATED) )
2450                  {
2451                      // Clear all fields in case previously they have not been cleared
2452                      memset(self, 0, sizeof(StrandBoth) );
2453                  }
2454              
2455                  self->base.strandType = STRAND_TYPE_MIDDLE;
2456                  self->base.strandMethods = _StrandMethods_Both_FT;
2457                  self->base.flags = flags;
2458 krisbash 1.1     
2459                  self->base.info.interaction.ft = &_StrandInteraction_Left_FT; 
2460                  self->base.info.userFT = userLeftFT;
2461                  
2462                  self->infoRight.interaction.ft = &_StrandInteraction_Right_FT; 
2463                  self->infoRight.userFT = userRightFT;
2464              
2465                  _Strand_CreateEnterStrand( STRAND_PASSDEBUG(debug) &self->base );
2466                  
2467                  if( 0 == (flags & STRAND_FLAG_DELAYACCEPTOPEN) )
2468                  {
2469                      DEBUG_ASSERT( NULL != interactionOpenParams );
2470                      Strand_AcceptOpen( &self->base, interactionOpenParams );
2471                  }
2472                  
2473                  _Strand_CreateExitStrand( &self->base );
2474              }
2475              
2476              //------------------------------------------------------------------------------------------------------------
2477              StrandMany* StrandMany_New(
2478              #if defined(STRAND_ENABLE_DEBUG)
2479 krisbash 1.1     _In_        StrandDebugInfo         debug,
2480              #endif
2481                  _In_        StrandFT*               userParentFT,
2482                  _In_opt_    StrandManyInternalFT*   userInternalFT,
2483                              size_t                  structSize,
2484                              StrandFlags             flags,
2485                  _In_opt_    InteractionOpenParams*  interactionOpenParams,  // if STRAND_FLAG_NOINTERACTION is not used and interactionOpenParams is NULL it is assumed it will open an interaction on the right
2486                              size_t                  numLists,               // numlist for the underlying Hash table, use 1 if it is not going to be searched
2487                  _In_opt_    HashMapHashProc         hash,                   // hashing func for the underlying Hash table, if NULL will use the StrandEntry pointer
2488                  _In_opt_    HashMapEqualProc        equal,                  // equal func for the underlying Hash table, can be NULL if it is not going to be searched or entry ptr comparison is ok
2489                  _In_opt_    FindEntryProc           findEntryProc )         // finds a entry based on a message, can be NULL if msg should not be automatically redirected to entries
2490              {
2491                  StrandMany* self;
2492                  
2493                  DEBUG_ASSERT(userParentFT);
2494              
2495                  if( 0 == structSize )
2496                      structSize = sizeof( StrandMany );
2497              
2498                  DEBUG_ASSERT( structSize >= sizeof(StrandMany) );
2499                  
2500 krisbash 1.1     self = (StrandMany*) SList_Alloc( structSize );
2501              
2502                  if( NULL != self )
2503                  {
2504                      if( 0 != (flags & STRAND_FLAG_NOZEROALLOCATED) )
2505                      {
2506                          // Clear only strand fields 
2507                          memset(self, 0, sizeof(StrandMany) );
2508                      }
2509                      else
2510                      {
2511                          // Clear all allocated fields
2512                          memset(self, 0, structSize );
2513                      }
2514                      
2515                      if( NULL == hash )
2516                          hash = _StrandMany_HashMapHashProc;
2517                      if( NULL == equal )
2518                          equal = _StrandMany_HashMapEqualProc;
2519              
2520                      if( HashMap_Init( &self->many, numLists, hash, equal, _StrandMany_HashMapReleaseProc ) )
2521 krisbash 1.1         {
2522                          SList_Free( self );
2523                          return NULL;
2524                      }
2525              
2526                      SList_Init( &self->pending );
2527                      self->findEntryProc = findEntryProc;
2528              
2529                      self->userInternalFT = userInternalFT;
2530                      self->strand.flags = flags;
2531                      self->strand.strandMethods = _StrandMethods_Parent_FT;
2532                      self->strand.info.interaction.ft = &_StrandInteraction_Many_FT; 
2533                      self->strand.info.userFT = userParentFT;
2534              
2535                      _Strand_CreateEnterStrand( STRAND_PASSDEBUG(debug) &self->strand );
2536                      
2537                      if( 0 == (flags&STRAND_FLAG_NOINTERACTION) )
2538                      {
2539                          if( NULL != interactionOpenParams || 0 != (flags & STRAND_FLAG_DELAYACCEPTOPEN) )
2540                          {
2541                              // Parent is being opened (it is on the left)
2542 krisbash 1.1                 self->strand.strandType = STRAND_TYPE_PARENTLEFT;
2543                              if( 0 == (flags & STRAND_FLAG_DELAYACCEPTOPEN) )
2544                              {
2545                                  Strand_AcceptOpen( &self->strand, interactionOpenParams );
2546                              }
2547                          }
2548                          else
2549                          {
2550                              self->strand.strandType = STRAND_TYPE_PARENTRIGHT;
2551                          }
2552                      }
2553                      else
2554                      {
2555                          DEBUG_ASSERT( NULL == interactionOpenParams );
2556                          self->strand.strandType = STRAND_TYPE_PARENTNOINTERACTION;
2557                          self->strand.info.thisClosedOther = self->strand.info.otherClosedThis = MI_TRUE;
2558                      }
2559              
2560                      _Strand_CreateExitStrand( &self->strand );
2561                  }
2562              
2563 krisbash 1.1     return self;
2564              }
2565              
2566              StrandEntry* StrandEntry_New(
2567              #if defined(STRAND_ENABLE_DEBUG)
2568                  _In_        StrandDebugInfo         debug,
2569              #endif
2570                  _In_        StrandMany*             parent,
2571                  _In_        StrandFT*               userEntryFT,
2572                              size_t                  structSize,
2573                              StrandFlags             flags,
2574                  _In_opt_    InteractionOpenParams*  interactionOpenParams )
2575              {
2576                  StrandEntry* self;
2577                  
2578                  DEBUG_ASSERT( NULL != parent );
2579                  DEBUG_ASSERT( NULL != userEntryFT );
2580              
2581                  if( 0 == structSize )
2582                      structSize = sizeof( StrandEntry );
2583              
2584 krisbash 1.1     DEBUG_ASSERT( structSize >= sizeof(StrandEntry) );
2585                  
2586                  self = (StrandEntry*) SList_Alloc( structSize );
2587              
2588                  if( NULL != self )
2589                  {
2590                      if( 0 != (flags & STRAND_FLAG_NOZEROALLOCATED) )
2591                      {
2592                          // Clear only strand fields 
2593                          memset(self, 0, sizeof(StrandEntry) );
2594                      }
2595                      else
2596                      {
2597                          // Clear all allocated fields
2598                          memset(self, 0, structSize );
2599                      }
2600                      
2601                      self->parent = parent;
2602              
2603                      self->strand.strandMethods = _StrandMethods_Entry_FT;
2604                      self->strand.flags = flags;
2605 krisbash 1.1         self->strand.info.interaction.ft = &_StrandInteraction_Many_FT; 
2606                      self->strand.info.userFT = userEntryFT;
2607                      self->strand.strandType = STRAND_TYPE_ENTRY;
2608              
2609                      _Strand_CreateEnterStrand( STRAND_PASSDEBUG(debug) &self->strand );
2610                      
2611                      if( NULL != interactionOpenParams || 0 != (flags & STRAND_FLAG_DELAYACCEPTOPEN) )
2612                      {
2613                          // Entry is being opened (it is on the left)
2614                          DEBUG_ASSERT( ( flags & STRAND_FLAG_NOINTERACTION ) == 0 );
2615                          DEBUG_ASSERT( parent->strand.strandType == STRAND_TYPE_PARENTRIGHT || parent->strand.strandType == STRAND_TYPE_PARENTNOINTERACTION );
2616                          if( 0 == (flags & STRAND_FLAG_DELAYACCEPTOPEN) )
2617                          {
2618                              Strand_AcceptOpen( &self->strand, interactionOpenParams );
2619                          }
2620                      }
2621                      else
2622                      {
2623                          if( ( flags & STRAND_FLAG_NOINTERACTION ) != 0 )
2624                          {
2625                              self->strand.info.thisClosedOther = self->strand.info.otherClosedThis = MI_TRUE;
2626 krisbash 1.1             }
2627                          else
2628                          {
2629                              DEBUG_ASSERT( parent->strand.strandType == STRAND_TYPE_PARENTLEFT || parent->strand.strandType == STRAND_TYPE_PARENTNOINTERACTION );
2630                          }
2631                      }
2632              
2633                      _Strand_CreateExitStrand( &self->strand );
2634                  }
2635              
2636                  return self;
2637              }
2638              
2639              MI_Result StrandMany_AddEntry(
2640                  _In_        StrandEntry*            self )
2641              {
2642                  STRAND_ASSERTONSTRAND( &self->parent->strand );
2643                  DEBUG_ASSERT( self->strand.info.stored.msg == NULL );
2644                  if( HashMap_Insert( &self->parent->many, &self->bucket ) )
2645                  {
2646                      SList_Free( self );
2647 krisbash 1.1         return MI_RESULT_FAILED;
2648                  }
2649              
2650                  ++(self->parent->numEntries);
2651              
2652                  if( NULL != self->parent->userInternalFT && NULL != self->parent->userInternalFT->AddedToParent )
2653                  {
2654                      STRAND_ASSERTONSTRAND( &self->strand );
2655                      self->parent->userInternalFT->AddedToParent( self, NULL );
2656                  }
2657              
2658                  return MI_RESULT_OK;
2659              }
2660              
2661              void StrandEntry_ScheduleAdd( 
2662                  _In_        StrandEntry*            self,
2663                  _In_opt_    Message *               msg )           // optional initial message
2664              {
2665                  DEBUG_ASSERT( NULL != self );
2666              
2667                  if( NULL != msg )
2668 krisbash 1.1     {
2669                      Message_AddRef(msg);
2670                      self->strand.info.stored.msg = msg;
2671                  }
2672                  _StrandEntry_ScheduleParent(self,BitEntryAdd);
2673              }
2674              
2675              void Strand_Delete( _In_ Strand* self )
2676              {
2677                  if( STRAND_ISTYPE_ENTRY(self) )
2678                  {
2679                      StrandEntry_Delete( StrandEntry_FromStrand(self) );
2680                  }
2681                  else if( STRAND_ISTYPE_PARENT(self) )
2682                  {
2683                      StrandMany_Delete( StrandMany_FromStrand(self) );
2684                  }
2685                  else
2686                  {
2687                      STRAND_LOGWITHNAME( self, "Deleting Strand" );
2688                      PAL_Free( self );
2689 krisbash 1.1     }
2690              }
2691              
2692              void StrandMany_Delete( _In_ StrandMany* self )
2693              {
2694                  SListEntry* entry;
2695                  
2696                  STRAND_LOGWITHNAME( &self->strand, "Deleting StrandMany" );
2697                  
2698                  DEBUG_ASSERT( 0 == self->numEntries );
2699                  DEBUG_ASSERT( NULL == self->currentEntry );
2700              
2701                  HashMap_Destroy( &self->many );
2702              
2703                  entry = SList_FlushAtomic( &self->pending );
2704              
2705                  if (entry != NULL)
2706                  {
2707                      DEBUG_ASSERT( NULL == entry );
2708                  }
2709              
2710 krisbash 1.1     SList_Free( self );
2711              }
2712              
2713              void StrandMany_DeleteEntry( _In_ StrandEntry* entry )
2714              {
2715                  StrandMany* self = entry->parent;
2716                  
2717                  STRAND_ASSERTONSTRAND( &self->strand );
2718                  
2719                  trace_Strand_DeletedEntry( &self->strand, STRAND_DEBUG_GETNAME(&self->strand), &entry->strand, STRAND_DEBUG_GETNAME(&entry->strand) );
2720              
2721                  DEBUG_ASSERT( self->numEntries >= 1 );
2722                  --(self->numEntries);
2723              
2724                  if( HashMap_Remove( &self->many, &entry->bucket ) )
2725                  {
2726                      trace_Strand_CannotDelete( &self->strand, STRAND_DEBUG_GETNAME(&self->strand), &entry->strand, STRAND_DEBUG_GETNAME(&entry->strand) );
2727                      DEBUG_ASSERT( MI_FALSE );   // should not happen
2728                  }
2729              
2730                  SList_Free( entry );
2731 krisbash 1.1 }
2732              
2733              void StrandEntry_Delete( _In_ StrandEntry* self )
2734              {
2735                  STRAND_LOGWITHNAME( &self->strand, "Scheduling deletion of StrandEntry" );
2736              
2737                  DEBUG_ASSERT( 0 == self->operationScheduled );
2738                  
2739                  _StrandEntry_ScheduleParent( self, BitEntryDeleted );
2740              }
2741              
2742              //------------------------------------------------------------------------------------------------------------
2743              void _Strand_CancelPropagate(
2744                  _In_ Strand *   self)
2745              {
2746                  STRAND_ASSERTONSTRAND( self );
2747                  
2748                  switch( self->strandType )
2749                  {
2750                  case STRAND_TYPE_MIDDLE:
2751                      {
2752 krisbash 1.1             StrandBoth * selfBoth = (StrandBoth*)self;
2753                          
2754                          if( selfBoth->infoRight.opened && !selfBoth->infoRight.thisClosedOther )
2755                          {
2756                              STRAND_LOGWITHNAME( self, "Canceling to the right" );
2757                          
2758                              // first go to the right
2759                              selfBoth->infoRight.interaction.other->ft->Cancel( selfBoth->infoRight.interaction.other );
2760                          }
2761                      }
2762                      break;
2763                  case STRAND_TYPE_LEFTMOST:
2764                  case STRAND_TYPE_RIGHTMOST:
2765                  case STRAND_TYPE_PARENTRIGHT:
2766                      {
2767                          if( self->info.opened && !self->info.thisClosedOther )
2768                          {
2769                              STRAND_LOGWITHNAME( self, "Canceling" );
2770                          
2771                              // just go to the other side (start going right or initiate return to the left)
2772                              self->info.interaction.other->ft->Cancel( self->info.interaction.other );
2773 krisbash 1.1             }
2774                      }
2775                      break;
2776                  case STRAND_TYPE_PARENTLEFT:
2777                      {
2778                          StrandMany* stranMany = StrandMany_FromStrand(self);
2779                          
2780                          STRAND_LOGWITHNAME( self, "Canceling all entries to the left" );
2781                          
2782                          StrandMany_CancelAllEntries( stranMany );
2783                      }
2784                  case STRAND_TYPE_ENTRY:
2785                      {
2786                          StrandEntry* entry = StrandEntry_FromStrand(self);
2787              
2788                          if( entry->parent->strand.strandType == STRAND_TYPE_PARENTRIGHT )
2789                          {
2790                              if( NULL == self->info.userFT->Cancel )
2791                              {
2792                                  STRAND_LOGWITHNAME( self, "Canceling parent from entry" );
2793                                  
2794 krisbash 1.1                     StrandEntry_CancelParent( entry );
2795                              }
2796                          }
2797                          else
2798                          {
2799                              if( self->info.opened && !self->info.thisClosedOther )
2800                              {
2801                                  STRAND_LOGWITHNAME( self, "Canceling interaction from entry" );
2802              
2803                                  // start going right 
2804                                  self->info.interaction.other->ft->Cancel( self->info.interaction.other );
2805                              }
2806                          }
2807                      }
2808                      break;
2809                  case STRAND_TYPE_PARENTNOINTERACTION:
2810                  default:
2811                      DEBUG_ASSERT(MI_FALSE);
2812                  }
2813                  STRAND_LOGWITHNAME( self, "Returning from Canceling other (would cancel method if existent) " );
2814              }
2815 krisbash 1.1 
2816              void Strand_Cancel(
2817                  _In_ Strand *   self)
2818              {
2819                  STRAND_ASSERTONSTRAND( self );
2820                  
2821                  if( !self->canceled )
2822                  {
2823                      _Strand_CancelPropagate( self );
2824              
2825                      _StrandMethodImp_Cancel(self, &self->info );
2826                  }
2827              }
2828              
2829              //------------------------------------------------------------------------------------------------------------
2830              ptrdiff_t _EnableMethodBit( _In_ Strand* self, ptrdiff_t methodBit ) 
2831              { 
2832                  ptrdiff_t initialState, newState = ReadWithFence( &self->stateScheduled ); 
2833                  
2834                  do
2835                  {
2836 krisbash 1.1         initialState = newState;
2837                          
2838                      // check if bit already set
2839                      DEBUG_ASSERT( (initialState & methodBit) == 0 );
2840                  }
2841                  while( (newState = Atomic_CompareAndSwap( &self->stateScheduled, initialState, initialState|methodBit )) != initialState );
2842              
2843                  return initialState|methodBit;
2844              }
2845              
2846              //------------------------------------------------------------------------------------------------------------
2847              MI_INLINE ptrdiff_t _DisableMethodBit( _In_ Strand* self, ptrdiff_t methodBit ) 
2848              { 
2849                  return Atomic_And( &self->stateScheduled, ~methodBit ) & (~methodBit); 
2850              }
2851              
2852              //------------------------------------------------------------------------------------------------------------
2853              void _Strand_ExecuteLoop( _In_ Strand* self, ptrdiff_t state )
2854              {
2855                  unsigned long bitIndex;
2856                  MI_Boolean strandStealedFlag;
2857 krisbash 1.1     STRAND_DEBUG_GETSTATE_USED;
2858                  STRAND_DEBUG_GETINFOSTATE_USED;
2859              
2860                  _Strand_SetCurrentStrandThread( self );
2861              
2862                  for(;;)   // check new state loop
2863                  {
2864                      DEBUG_ASSERT( ( state & BitExecuting ) != 0 );
2865              
2866                      // we dont want to check on BitExecuting
2867                      bitIndex = GetFirstSetLSB( state & (~BitExecuting) );
2868                      if( bitIndex ) 
2869                      {
2870                          ptrdiff_t methodBit = _GetMethodBit( bitIndex );
2871                          
2872                          strandStealedFlag = MI_FALSE;
2873                          self->strandStealedFlag = &strandStealedFlag;
2874                          self->currentMethodBit = methodBit;
2875                      
2876                          DEBUG_ASSERT( bitIndex > FirstRealMethodBit );
2877              
2878 krisbash 1.1             STRAND_DEBUG_GETINFOSTATE_STORE(self);
2879                          trace_Strand_ExecLoop(
2880                              self, 
2881                              STRAND_DEBUG_GETNAME(self), 
2882                              state, 
2883                              STRAND_DEBUG_GETSTATE(self, state ), 
2884                              bitIndex, 
2885                              STRAND_DEBUG_GETMETHODINDEX(self,bitIndex),
2886                              STRAND_DEBUG_GETINFOSTATE_STORED );
2887                              
2888                          (*self->strandMethods[ bitIndex-FirstRealMethodBit ])(self);
2889                          
2890                          if( strandStealedFlag )
2891                          {
2892                              // if someone stealed the strand synchronously (Strand_Leave)
2893                              // while the function was being executed then just bail out
2894                              trace_Strand_ExecLoop_Leave(
2895                                  self, 
2896                                  state, 
2897                                  bitIndex, 
2898                                  methodBit);
2899 krisbash 1.1                 return;
2900                          }
2901                          else
2902                          {
2903                              state = _DisableMethodBit( self, methodBit );
2904                              if( BitTimer == methodBit && NULL != self->timer )
2905                              {
2906                                  // timer was restarted inside the timer method, start it now
2907                                  Timer_Start( self->timer, self );
2908                              }
2909                              else if( STRAND_ISTYPE_PARENT( self ) && BitEntryOperation == methodBit  )
2910                              {
2911                                  _StrandMethod_Parent_RunPendingOperations( StrandMany_FromStrand(self) );
2912                              }
2913                          }
2914                      }
2915                      else
2916                      {
2917                          ptrdiff_t newState;
2918                          
2919                          // Nothing else scheduled, we are going to stop executing (if nothing else has changed)
2920 krisbash 1.1 
2921                          MI_Boolean aboutToFinish = _Strand_ShouldFinish(self);    
2922                          
2923                          DEBUG_ASSERT( BitExecuting == state );
2924                          
2925                          /* trace_Strand_ExecLoop( self, state, aboutToFinish ); */
2926                                              
2927                          _Strand_ExitCurrentStrandThread( self );
2928              
2929                          // Get these two before the Atomic_CompareAndSwap (strand may be deleted after that)
2930                          STRAND_DEBUG_GETNAME_STORE(self);
2931                          STRAND_DEBUG_GETINFOSTATE_STORE(self);
2932                          
2933                          newState = Atomic_CompareAndSwap( &self->stateScheduled, state, 0 ); 
2934                          // If the state has not changed (no new method was scheduled) we can stop now
2935                          if( newState == state )
2936                          {
2937                              trace_Strand_ExecLoop_Exits(
2938                                  self, 
2939                                  STRAND_DEBUG_GETNAME_STORED, 
2940                                  state, 
2941 krisbash 1.1                     aboutToFinish,
2942                                  STRAND_DEBUG_GETINFOSTATE_STORED );
2943                              if( aboutToFinish )
2944                              {
2945                                  _Strand_Finish( self );
2946                              }
2947                              return; 
2948                          }
2949                          else
2950                          {
2951                              trace_Strand_ExecLoop_DoesntExit(
2952                                  self, 
2953                                  STRAND_DEBUG_GETNAME(self), 
2954                                  state, 
2955                                  newState, 
2956                                  STRAND_DEBUG_GETSTATE(self, newState),
2957                                  aboutToFinish,
2958                                  STRAND_DEBUG_GETINFOSTATE_STORED );
2959                              state = newState;
2960              
2961                              // revert this
2962 krisbash 1.1                 _Strand_SetCurrentStrandThread( self );
2963                          }
2964                      }
2965                  }
2966              }
2967              
2968              //------------------------------------------------------------------------------------------------------------
2969              // Schedules a method in the strand
2970              //------------------------------------------------------------------------------------------------------------
2971              #if defined(STRAND_ENABLE_DEBUG)
2972              void _Strand_ScheduleImp( 
2973                  _In_        Strand*                 self, 
2974                              unsigned int            methodBit, 
2975                              MI_Boolean              allowMultiSchedule, 
2976                  _In_opt_    Strand*                 fromStrand,  
2977                              EntryOperationMaskType  entryOperationBit )
2978              #else
2979              void _Strand_ScheduleImp(
2980                  _In_        Strand*                 self, 
2981                              unsigned int            methodBit )
2982              #endif
2983 krisbash 1.1 {
2984                  ptrdiff_t initialState, newState = ReadWithFence( &self->stateScheduled ); 
2985                  STRAND_DEBUG_GETSTATE_USED;
2986              
2987                  DEBUG_ASSERT( methodBit > 0 );
2988                  
2989              #if defined(STRAND_ENABLE_DEBUG)
2990                  if( allowMultiSchedule && BitTimer != methodBit )
2991                  {
2992                      trace_Strand_ScheduleParent(
2993                          self, 
2994                          STRAND_DEBUG_GETNAME(self), 
2995                          newState, 
2996                          STRAND_DEBUG_GETSTATE(self, newState), 
2997                          entryOperationBit,
2998                          0 == entryOperationBit ? "<re-scheduled>" : STRAND_DEBUG_GETOPERATION(self, entryOperationBit ),
2999                          fromStrand,
3000                          NULL == fromStrand ? "<self>" : STRAND_DEBUG_GETNAME(fromStrand), 
3001                          methodBit, 
3002                          STRAND_DEBUG_GETMETHOD(self,methodBit) );
3003                  }
3004 krisbash 1.1     else if( NULL != fromStrand )
3005                  {
3006                      trace_Strand_ScheduleEntry(
3007                          self, 
3008                          STRAND_DEBUG_GETNAME(self), 
3009                          newState, 
3010                          STRAND_DEBUG_GETSTATE(self, newState), 
3011                          entryOperationBit,
3012                          STRAND_DEBUG_GETOPERATION(fromStrand, entryOperationBit ),
3013                          fromStrand,
3014                          STRAND_DEBUG_GETNAME(fromStrand), 
3015                          methodBit, 
3016                          STRAND_DEBUG_GETMETHOD(self,methodBit) );
3017                  }
3018                  else
3019                  {
3020                      trace_Strand_Schedule(
3021                          self, 
3022                          STRAND_DEBUG_GETNAME(self), 
3023                          newState, 
3024                          STRAND_DEBUG_GETSTATE(self, newState), 
3025 krisbash 1.1             methodBit, 
3026                          STRAND_DEBUG_GETMETHOD(self,methodBit) );
3027                  }    
3028              #else
3029                  trace_Strand_Schedule2(
3030                      self, 
3031                      newState, 
3032                      methodBit );
3033              #endif
3034                      
3035                  do
3036                  {
3037                      initialState = newState;
3038                          
3039              #if defined(STRAND_ENABLE_DEBUG)
3040                      // check if bit already set
3041                      // otherwise Caller is violating the contract!
3042                      DEBUG_ASSERT( allowMultiSchedule || (initialState & methodBit) == 0 );
3043              #endif
3044                  }
3045                  while( (newState = Atomic_CompareAndSwap( &self->stateScheduled, initialState, initialState|methodBit|BitExecuting )) != initialState );
3046 krisbash 1.1     
3047                  // Check if nobody was executing before now, then start executing
3048                  if( ( initialState & BitExecuting ) == 0 )
3049                  {
3050                      _Strand_ExecuteLoop(self, initialState|methodBit|BitExecuting);
3051                  }
3052              }
3053              
3054              //------------------------------------------------------------------------------------------------------------
3055              void Strand_Leave( _In_ Strand* self )
3056              {
3057                  STRAND_ASSERTONSTRAND( self );
3058              
3059                  trace_Strand_Leave( self, STRAND_DEBUG_GETNAME(self), self->strandStealedFlag );
3060                  
3061                  // If there is an encompasing loop, then set this to false so it will bail out
3062                  if( NULL != self->strandStealedFlag )
3063                  {
3064                      *(self->strandStealedFlag) = MI_TRUE;
3065                  }
3066              
3067 krisbash 1.1     _Strand_ExecuteLoop( self, _DisableMethodBit( self, self->currentMethodBit ) );
3068              }
3069              
3070              //------------------------------------------------------------------------------------------------------------
3071              void Strand_StartTimer( _In_ Strand* self, _In_ Timer* timer, _In_ MI_Uint64 timeusecs )
3072              {
3073                  STRAND_ASSERTONSTRAND( self );
3074                  DEBUG_ASSERT( NULL == self->timer );
3075                  DEBUG_ASSERT( timer );
3076                  
3077                  self->timer = timer;
3078                  Timer_SetTime( timer, timeusecs );   // doesnt start the actual timer
3079                  if( BitTimer != self->currentMethodBit )
3080                  {
3081                      TimerResult result = Timer_Start( timer, self );
3082                      if (TimerResult_Success != result)
3083                      {
3084                          // Cancel timer start request
3085                          self->timer = NULL;
3086                          trace_Strand_Cannot_Start_Timer( timer, self );
3087                      }
3088 krisbash 1.1     }
3089                  else
3090                  {
3091                      trace_Strand_Cannot_Start_Timer( timer, self );
3092                  }
3093              }
3094              
3095              void Strand_FireTimer( _In_ Strand* self )
3096              {
3097                  STRAND_ASSERTONSTRAND( self );
3098                  
3099                  if( NULL != self->timer )
3100                  {
3101                      Timer_Fire( self->timer, self, TimerReason_ManuallyFired );
3102                  }
3103                  else
3104                  {
3105                      trace_Strand_Cannot_Fire_Timer( self );
3106                  }
3107              }
3108              
3109 krisbash 1.1 MI_Boolean Strand_HaveTimer( _In_ Strand* self )
3110              {
3111                  STRAND_ASSERTONSTRAND( self );
3112                  
3113                  if ( self->timer )
3114                      return MI_TRUE;
3115                  else
3116                      return MI_FALSE;
3117              }
3118              
3119              //------------------------------------------------------------------------------------------------------------
3120              void _Strand_AcceptOpenCommon( 
3121                  _In_        Strand*                 self, 
3122                  _In_        Interaction*            interaction )
3123              {    
3124                  STRAND_ASSERTONSTRAND( self );
3125              
3126                  DEBUG_ASSERT( !self->info.otherAckPending );
3127                  DEBUG_ASSERT( !self->info.thisAckPending );
3128                  DEBUG_ASSERT( !self->info.ackPassthru );
3129                  
3130 krisbash 1.1     self->info.interaction.other = interaction;
3131                  interaction->other = &self->info.interaction;
3132                  self->info.opened = MI_TRUE;    
3133                  self->info.thisClosedOther = MI_FALSE;
3134                  self->info.otherClosedThis = MI_FALSE;
3135              }
3136              
3137              void Strand_AcceptOpenAsync( 
3138                  _In_        Strand*                 self, 
3139                  _In_        Strand*                 otherStrand )
3140              {    
3141                  DEBUG_ASSERT( !STRAND_ISTYPE_MIDDLE( otherStrand ) );
3142                  _Strand_AcceptOpenCommon( self, &otherStrand->info.interaction);
3143              
3144                  _Strand_Schedule( otherStrand, BitCompleteOpenAsync );
3145              }
3146              
3147              void Strand_AcceptOpenAsyncFromStrandBoth( 
3148                  _In_        Strand*                 self, 
3149                  _In_        StrandBoth*             otherStrand )
3150              {    
3151 krisbash 1.1     DEBUG_ASSERT( STRAND_ISTYPE_MIDDLE( &otherStrand->base ) );
3152                  _Strand_AcceptOpenCommon( self, &otherStrand->infoRight.interaction );
3153                  otherStrand->asyncOpenInProgress = MI_TRUE;
3154                  _Strand_Schedule( &otherStrand->base, BitCompleteOpenAsync );
3155              }
3156              
3157              void Strand_AcceptOpen( 
3158                  _In_        Strand*                 self, 
3159                  _In_        InteractionOpenParams*  params )
3160              {    
3161                  _Strand_AcceptOpenCommon( self, params->interaction );
3162              
3163                  if( NULL != params->msg )
3164                  {
3165                      self->info.otherAckPending = MI_TRUE;
3166                  }
3167                  if( NULL != params->origin )
3168                  {
3169                      Strand_Leave( params->origin );
3170                  }
3171              }
3172 krisbash 1.1 
3173              static void _DoNothingPost( _In_ Interaction* self, _In_ Message* msg )
3174              {
3175                  MI_UNUSED( self );
3176                  MI_UNUSED( msg );
3177              }
3178              
3179              static void _DoNothingOther( _In_ Interaction* self )
3180              {
3181                  MI_UNUSED( self );
3182              }
3183              
3184              static InteractionFT _failOpenInteractionFT = { 
3185                  _DoNothingPost, 
3186                  _DoNothingPost, 
3187                  _DoNothingOther, 
3188                  _DoNothingOther, 
3189                  _DoNothingOther };
3190              
3191              static Interaction _failOpenInteraction = { &_failOpenInteractionFT, NULL };
3192              
3193 krisbash 1.1 void Strand_FailOpenWithMsg( 
3194                  _In_        InteractionOpenParams*  params,
3195                  _In_opt_    Message*                msg)
3196              {
3197                  params->interaction->other = &_failOpenInteraction;
3198              
3199                  if( NULL != params->origin )
3200                  {
3201                      Strand_Leave( params->origin );
3202                  }
3203                  
3204                  if( NULL != msg )
3205                  {
3206                      params->interaction->ft->Post( params->interaction, msg );
3207                  }
3208                  else
3209                  {
3210                      if( NULL != params->msg )
3211                      {
3212                          DEBUG_ASSERT( Message_IsRequest( params->msg ) );   
3213                          //TODO convert the original request to ResultMsg and post it back
3214 krisbash 1.1             //params->interaction->ft->Post( params->interaction, params->msg );
3215                          // Cancel in the meantime:
3216                      }
3217                      //TODO else
3218                      {
3219                          params->interaction->ft->Cancel( params->interaction );
3220                      }
3221                  }
3222                  if( NULL != params->msg )
3223                  {
3224                      params->interaction->ft->Ack( params->interaction );
3225                  }
3226                  params->interaction->ft->Close( params->interaction );
3227              }
3228              
3229              void Strand_FailOpenWithResult(
3230                  _In_ InteractionOpenParams*  params,
3231                  MI_Result result,
3232                  _In_ MakeResultMessageCallback callback)
3233              {
3234                  PostResultMsg* resultMsg;
3235 krisbash 1.1 
3236                  resultMsg = (*callback)( params->msg, NULL, NULL, MI_RESULT_TYPE_MI, result);
3237              
3238                  if( NULL != resultMsg )
3239                  {
3240                      Strand_FailOpenWithMsg( params, &resultMsg->base );
3241                      PostResultMsg_Release(resultMsg);
3242                  }
3243                  else
3244                  {
3245                      Strand_FailOpen( params );
3246                  }
3247              }

ViewCVS 0.9.2