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:
parent
cd7c40f5af
commit
c67cd62ecf
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user