@@ -870,19 +870,22 @@ void MCUIDC::updatemenubar(Boolean force)
870870// message in the right place.
871871void MCUIDC::doaddmessage (MCObject *optr, MCNameRef mptr, real8 time, uint4 id, MCParameter *params)
872872{
873+ // MW-2014-05-14: [[ Bug 12294 ]] Rejigged to correct flaws.
874+
875+ // If we are at capacity, then extend the message list.
873876 if (nmessages == maxmessages)
874877 {
875878 maxmessages++;
876879 MCU_realloc ((char **)&messages, nmessages, maxmessages, sizeof (MCMessageList));
877880 }
878881
882+ // Find where in the list to insert the pending message.
879883 int t_index;
880884 for (t_index = 0 ; t_index < nmessages; t_index++)
881885 if (messages[t_index] . time > time)
882886 break ;
883887
884- // MW-2014-04-29: [[ Bug 12294 ]] Moved 1 too few MCMessageList structurs causing over-release of
885- // MCNameRefs and pending message lost (i.e. intermittantly flaky and unstable engine).
888+ // Move all messages in the range [t_index, nmessages) up one.
886889 MCMemoryMove (&messages[t_index + 1 ], &messages[t_index], (nmessages - t_index) * sizeof (MCMessageList));
887890
888891 messages[t_index].object = optr;
@@ -897,23 +900,31 @@ void MCUIDC::doaddmessage(MCObject *optr, MCNameRef mptr, real8 time, uint4 id,
897900// MW-2014-04-16: [[ Bug 11690 ]] Shift a message to a new time in the future.
898901int MCUIDC::doshiftmessage (int index, real8 newtime)
899902{
900- if (index == nmessages - 1 )
901- return index;
903+ assert (index < nmessages);
902904
903- int t_index;
904- for (t_index = index + 1 ; t_index < nmessages; t_index++)
905- if (messages[t_index] . time > newtime)
905+ // MW-2014-05-14: [[ Bug 12294 ]] Rejigged to correct flaws.
906+
907+ // Find the first message after the new time.
908+ uindex_t t_index;
909+ for (t_index = index; t_index < nmessages - 1 ; t_index++)
910+ if (messages[t_index + 1 ] . time > newtime)
906911 break ;
907912
913+ if (t_index == index)
914+ return index;
915+
916+ // Save the current message.
908917 MCMessageList t_msg;
909918 t_msg = messages[index];
910919
920+ // Move all messages in the range [index + 1, t_index) down one.
911921 MCMemoryMove (&messages[index], &messages[index + 1 ], (t_index - index) * sizeof (MCMessageList));
912922
923+ // Move the target message to its new location.
913924 messages[t_index] = t_msg;
914925 messages[t_index] . time = newtime;
915926
916- return index ;
927+ return t_index ;
917928}
918929
919930void MCUIDC::delaymessage (MCObject *optr, MCNameRef mptr, char *p1, char *p2)
@@ -964,9 +975,11 @@ void MCUIDC::cancelmessageindex(uint2 i, Boolean dodelete)
964975 }
965976 MCNameDelete (messages[i] . message);
966977 }
978+
979+ // MW-2014-05-14: [[ Bug 12294 ]] Use a memmove here (more efficient as the MCMessageList struct can be moved).
980+ MCMemoryMove (&messages[i], &messages[i + 1 ], (nmessages - (i + 1 )) * sizeof (MCMessageList));
981+
967982 nmessages--;
968- while (i++ < nmessages)
969- messages[i - 1 ] = messages[i];
970983}
971984
972985void MCUIDC::cancelmessageid (uint4 id)
@@ -982,11 +995,11 @@ void MCUIDC::cancelmessageid(uint4 id)
982995
983996void MCUIDC::cancelmessageobject (MCObject *optr, MCNameRef mptr)
984997{
985- uint2 i;
986- for (i = 0 ; i < nmessages ; i++ )
987- if (messages[i].object == optr
988- && (mptr == NULL || MCNameIsEqualTo (messages[i].message , mptr, kMCCompareCaseless )))
989- cancelmessageindex (i-- , True);
998+ // MW-2014-05-14: [[ Bug 12294 ]] Cancel list in reverse order to minimize movement.
999+ for (uindex_t i = nmessages ; i > 0 ; i-- )
1000+ if (messages[i - 1 ].object == optr
1001+ && (mptr == NULL || MCNameIsEqualTo (messages[i - 1 ].message , mptr, kMCCompareCaseless )))
1002+ cancelmessageindex (i - 1 , True);
9901003}
9911004
9921005void MCUIDC::listmessages (MCExecPoint &ep)
@@ -1024,7 +1037,7 @@ Boolean MCUIDC::handlepending(real8& curtime, real8& eventtime, Boolean dispatch
10241037
10251038 if (!dispatch && messages[i] . id == 0 && MCNameIsEqualTo (messages[i] . message, MCM_idle, kMCCompareCaseless ))
10261039 {
1027- i = doshiftmessage (i, curtime + MCidleRate / 1000.0 );
1040+ doshiftmessage (i, curtime + MCidleRate / 1000.0 );
10281041 continue ;
10291042 }
10301043
0 commit comments