1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-06 18:26:22 +03:00

0025057: Message_Algorithm fails to find messages defined for base class

New method HasMsg() is added in Message_MsgFile class to check if message with given key is registered.
That method is used in Message_Algorithm to check if message is defined on given level of class hierarchy.

Generation of error message in Message_MsgFile::Msg() is revised: now it includes a message key and gets added to the registry, to avoid re-generation in case of multiple requests.
Access to message registry maintained by the Message_MsgFile class is protected from concurrent access by mutex.
This commit is contained in:
abv 2014-07-08 16:11:16 +04:00 committed by bugmaster
parent cd7c40f5af
commit c67cd62ecf
3 changed files with 36 additions and 22 deletions

View File

@ -224,7 +224,7 @@ void Message_Algorithm::SendStatusMessages (const Message_ExecStatus& theStatus,
// find message, iterating by base classes if necessary // find message, iterating by base classes if necessary
TCollection_AsciiString aMsgName = aClassName + aSuffix; TCollection_AsciiString aMsgName = aClassName + aSuffix;
Handle(Standard_Type) aType = DynamicType(); Handle(Standard_Type) aType = DynamicType();
while (Message_MsgFile::Msg(aMsgName).Length() == 0 && !aType.IsNull()) while (! Message_MsgFile::HasMsg(aMsgName) && !aType.IsNull())
{ {
Standard_AncestorIterator it(aType); Standard_AncestorIterator it(aType);
aType.Nullify(); aType.Nullify();
@ -233,7 +233,7 @@ void Message_Algorithm::SendStatusMessages (const Message_ExecStatus& theStatus,
aType = it.Value(); aType = it.Value();
TCollection_AsciiString aClassName1 (aType->Name()); TCollection_AsciiString aClassName1 (aType->Name());
TCollection_AsciiString aMsgName1 = aClassName1 + aSuffix; TCollection_AsciiString aMsgName1 = aClassName1 + aSuffix;
if (Message_MsgFile::Msg(aMsgName1).Length() != 0) if (Message_MsgFile::HasMsg(aMsgName1))
{ {
aMsgName = aMsgName1; aMsgName = aMsgName1;
break; break;

View File

@ -74,6 +74,9 @@ is
-- If there already was defined the message identified by the -- If there already was defined the message identified by the
-- same keyword, it is replaced with the new one. -- same keyword, it is replaced with the new one.
HasMsg (myclass; key: AsciiString from TCollection) returns Boolean;
---Purpose: Returns True if message with specified keyword is registered
Msg (myclass; key: CString) returns ExtendedString from TCollection; Msg (myclass; key: CString) returns ExtendedString from TCollection;
---C++: return const & ---C++: return const &
Msg (myclass; key: AsciiString from TCollection) returns ExtendedString from TCollection; Msg (myclass; key: AsciiString from TCollection) returns ExtendedString from TCollection;

View File

@ -19,6 +19,7 @@
#include <OSD_Environment.hxx> #include <OSD_Environment.hxx>
#include <TCollection_AsciiString.hxx> #include <TCollection_AsciiString.hxx>
#include <TCollection_ExtendedString.hxx> #include <TCollection_ExtendedString.hxx>
#include <Standard_Mutex.hxx>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
@ -31,6 +32,9 @@ static Message_DataMapOfExtendedString& msgsDataMap ()
return aDataMap; return aDataMap;
} }
// mutex used to prevent concurrent access to message registry
static Standard_Mutex theMutex;
typedef enum typedef enum
{ {
MsgFile_WaitingKeyword, MsgFile_WaitingKeyword,
@ -310,8 +314,8 @@ Standard_Boolean Message_MsgFile::AddMsg (const TCollection_AsciiString& theKeyw
const TCollection_ExtendedString& theMessage) const TCollection_ExtendedString& theMessage)
{ {
Message_DataMapOfExtendedString& aDataMap = ::msgsDataMap(); Message_DataMapOfExtendedString& aDataMap = ::msgsDataMap();
// if (aDataMap.IsBound (theKeyword))
// return Standard_False; Standard_Mutex::Sentry aSentry (theMutex);
aDataMap.Bind (theKeyword, theMessage); aDataMap.Bind (theKeyword, theMessage);
return Standard_True; return Standard_True;
} }
@ -328,7 +332,18 @@ const TCollection_ExtendedString &Message_MsgFile::Msg (const Standard_CString t
} }
//======================================================================= //=======================================================================
//function : getMsg //function : HasMsg
//purpose :
//=======================================================================
Standard_Boolean Message_MsgFile::HasMsg (const TCollection_AsciiString& theKeyword)
{
Standard_Mutex::Sentry aSentry (theMutex);
return ::msgsDataMap().IsBound (theKeyword);
}
//=======================================================================
//function : Msg
//purpose : retrieve the message previously defined for the given keyword //purpose : retrieve the message previously defined for the given keyword
//======================================================================= //=======================================================================
@ -336,23 +351,19 @@ const TCollection_ExtendedString &Message_MsgFile::Msg (const TCollection_AsciiS
{ {
// find message in the map // find message in the map
Message_DataMapOfExtendedString& aDataMap = ::msgsDataMap(); Message_DataMapOfExtendedString& aDataMap = ::msgsDataMap();
if (aDataMap.IsBound (theKeyword)) Standard_Mutex::Sentry aSentry (theMutex);
return aDataMap.Find (theKeyword);
// if not found, generate error message // if message is not found, generate error message and add it to the map to minimize overhead
// to minimize risk of data races when running concurrently, set the static variables // on consequent calls with the same key
// only if they are empty; this gives a possibility to enforce calling this method if (! aDataMap.IsBound(theKeyword))
// upfront to initialize these variables and only read access them afterwards. However {
// theKeyword is no longer appended. aDefPrefix remained unchanged to not break some // text of the error message can be itself defined in the map
// logs which might expect the previous value static const TCollection_AsciiString aPrefixCode("Message_Msg_BadKeyword");
static const TCollection_ExtendedString aDefPrefix ("Unknown message invoked with the keyword"); static const TCollection_ExtendedString aDefPrefix("Unknown message invoked with the keyword ");
static const TCollection_AsciiString aPrefixCode ("Message_Msg_BadKeyword"); TCollection_AsciiString aErrorMessage = (aDataMap.IsBound(aPrefixCode) ? aDataMap(aPrefixCode) : aDefPrefix);
static TCollection_ExtendedString aFailureMessage; aErrorMessage += theKeyword;
if (aFailureMessage.Length() == 0) { aDataMap.Bind (theKeyword, aErrorMessage); // do not use AddMsg() here to avoid mutex deadlock
if (aDataMap.IsBound (aPrefixCode))
aFailureMessage = aDataMap.Find (aPrefixCode);
else
aFailureMessage = aDefPrefix;
} }
return aFailureMessage;
return aDataMap (theKeyword);
} }