/*!

\page kernel_resources Salome Kernel resources for developer



This document describes the development environment for 
C++ and Python. Makefiles generation and usage are 
introduced in another document: "using the %SALOME 
configuration and building system environment". 
Development environment is intended here as: trace and 
debug macros usage; %SALOME exceptions usage, in C++ and 
Python; user CORBA exceptions usage, in C++ and Python, 
with and without Graphical User Interface; some general 
purpose services such as singleton, used for CORBA 
connection and disconnection.

\section S2_kernel_res Trace and debug Utilities

During the development process, an execution log is 
useful to identify problems. This log contains 
messages, variables values, source files names and line 
numbers. It is recommended to verify assertions on 
variables values and if necessary, to stop the 
execution at debug time, in order to validate all parts 
of code.

\subsection subsection21 Two modes: debug and release

The goal of debug mode is to check as many features as 
possible during the early stages of the development 
process. The purpose of the utilities provided in 
%SALOME is to help the developer to add detailed traces 
and check variables values, without writing a lot of code.

When the code is assumed to be valid, the release mode 
optimizes execution, in terms of speed, memory, and 
display only user level messages.

But, some informations must always be displayed in both 
modes: especially messages concerning environment or 
internal errors, with version identification. When an 
end user is confronted to such a message, he may refer 
to a configuration documentation or send the message to 
the people in charge of %SALOME installation, or to the 
development team, following the kind of error.

\subsection subsection22 C++ Macros for trace and debug

%SALOME provides C++ macros for trace and debug. These 
macros are in:

\code
KERNEL_SRC/src/SALOMELocalTrace/utilities.h
\endcode

This file must be included in C++ source. Some 
macros are activated only in debug mode, others are 
always activated. To activate the debug mode, _DEBUG_
must be defined, which is the case when %SALOME 
Makefiles are generated from configure, without 
options. When _DEBUG_ is undefined (release mode: 
configure --disable-debug --enable-production), the 
debug mode macros are defined empty (they do nothing). 
So, when switching from debug to release, it is 
possible (and recommended) to let the macro calls 
unchanged in the source.

All the macros generate trace messages, stored in a 
circular buffer pool. %A separate %thread reads the 
messages in the buffer pool, and, depending on options 
given at %SALOME start, writes the messages on the 
standard output, a file, or send them via CORBA, in 
case of a multi machine configuration.

Three informations are systematically added in front of 
the information displayed:
- the %thread number from which the message come from;
- the name of the source file in which the macros is set;
- the line number of the source file at which the macro 
  is set.

\subsection subsection23 Macros defined in debug and release modes

- <b>INFOS_COMPILATION</b>\n
   The C++ macro INFOS_COMPILATION writes on the trace 
   buffer pool informations about the compiling process: 
   - the name of the compiler : g++, KCC, CC, pgCC;
   - the date and the time of the compiling processing process.
   .
   This macro INFOS_COMPILATION does not have any 
   argument. Moreover, it is defined in both compiling 
   mode : _DEBUG_ and _RELEASE_.\n
   Example:
   \code
#include "utilities.h"
int main(int argc , char **argv) 
{ 
  INFOS_COMPILATION;
  ...
}
  \endcode

- <b>INFOS</b>\n
   In both compiling mode _DEBUG_ and _RELEASE_, The C++ 
   macro INFOS writes on the trace buffer pool %the string 
   which has been passed in argument by the user.\n
   Example:
   \code
#include "utilities.h"
int main(int argc , char **argv)
{ 
  ... 
  INFOS("NORMAL END OF THE PROCESS"); 
  return 0; 
}
   \endcode
   Displays:
   \code
main.cxx [5] : NORMAL END OF THE PROCESS
   \endcode

- <b>INTERRUPTION(str)</b>\n
   In both compiling mode _DEBUG_ and _RELEASE_, The C++ 
   macro INTERRUPTION writes on the trace buffer pool the 
   %string, with a special ABORT type. When the %thread in 
   charge of collecting messages finds this message, it 
   terminates the application, after message treatment.

- <b>IMMEDIATE_ABORT(str)</b>\n
   In both compiling mode _DEBUG_ and _RELEASE_, The C++ 
   macro IMMEDIATE_ABORT writes the message str immediately on 
   standard error and exits the application. Remaining 
   messages not treated by the message collector %thread 
   are lost.

\subsection subsection24 Macros defined only in debug mode

- <b>MESSAGE(str)</b>\n
   In _DEBUG_ compiling mode only, the C++ macro MESSAGE 
   writes on the trace buffer pool the %string which has 
   been passed in argument by the user. In _RELEASE_ 
   compiling mode, this macro is blank.\n
   Example:
   \code
#include "utilities.h" 
#include <string> 

using namespace std; 

int main(int argc , char **argv) 
{ 
  ... 
  const char *str = "Salome";
  MESSAGE(str);
  ... const string st; 
  st = "Aster"; 
  MESSAGE(c_str(st+" and CASTEM")); 
  return 0;
}

   \endcode
   Displays:
   \code
- Trace main.cxx [8] : Salome
- Trace main.cxx [12] : Aster and CASTEM
   \endcode

- <b>BEGIN_OF(func_name)</b>\n
   In _DEBUG_ compiling mode, The C++ macro BEGIN_OF 
   appends the %string "Begin of " to the one passed in 
   argument by the user and displays the result on the 
   trace buffer pool. In _RELEASE_ compiling mode, this 
   macro is blank.\n
   Example:
   \code
#include "utilities.h" 
int main(int argc , char **argv) 
{ 
  BEGIN_OF(argv[0]);
  return 0;
}
   \endcode
   Displays:
   \code
     - Trace main.cxx [3] : Begin of a.out
   \endcode

- <b>END_OF(func_name)</b>\n
   In _DEBUG_ compiling mode, The C++ macro END_OF appends 
   the %string "Normal end of " to the one passed in 
   argument by the user and displays the result on the 
   trace buffer pool. In _RELEASE_ compiling mode, this 
   macro is blank.\n
   Example:
   \code
#include "utilities.h" 
int main(int argc , char **argv) 
{ 
  END_OF(argv[0]);
  return 0; 
}
  \endcode
   Displays:
   \code
- Trace main.cxx [4] : Normal end of a.out
   \endcode

- <b>SCRUTE(var)</b>\n
   In _DEBUG_ compiling mode, The C++ macro SCRUTE 
   displays its argument which is an application variable 
   followed by the value of the variable. In _RELEASE_ 
   compiling mode, this macro is blank.\n
   Example:
   \code
#include "utilities.h"
int main(int argc , char **argv) 
{ 
  const int i=999;
  if( i > 0 ) SCRUTE(i) ; i=i+1;
  return 0;
}
   \endcode
   Displays:
   \code
- Trace main.cxx [5] : i=999
   \endcode

- <b>ASSERT(condition)</b>\n
   In _DEBUG_ compiling mode only, The C++ macro ASSERT 
   checks the expression passed in argument to be not 
   NULL. If it is NULL the condition is written with the 
   macro INTERRUPTION (see above). The process exits after 
   trace of this last message. In _RELEASE_ compiling 
   mode, this macro is blank. N.B. : if ASSERT is already 
   defined, this macro is ignored.\n
   Example:
   \code
#include "utilities.h" 
... 
const char *ptrS = fonc();
ASSERT(ptrS!=NULL); 
cout << strlen(ptrS); 
float table[10];
int k;
... 
ASSERT(k<10);
cout << table[k];
   \endcode

\section S3_kernel_res Exceptions

\subsection subsection31 C++ exceptions: class SALOME_Exception

\subsubsection subsubsection311 Definition

The class SALOME_Exception provides a generic method to 
send a message, with optional source file name and line 
number. This class is intended to serve as a base class 
for all kinds of exceptions %SALOME code. All the 
exceptions derived from SALOME_Exception could be 
handled in a single catch, in which the message 
associated to the exception is displayed, or sent to a 
log file.

The class SALOME_Exception inherits its behavior from 
the STL class exception.

\subsubsection subsubsection312 Usage

The header %SALOME/src/utils/utils_SALOME_Exception.hxx 
must be included in the C++ source, when raised or trapped:

\code
#include "utils_SALOME_Exception.hxx"
\endcode

The SALOME_Exception constructor is:

\code
SALOME_Exception( const char *text,
                  const char *fileName=0, 
                  const unsigned int lineNumber=0 );
\endcode

The exception is raised like this:

\code
throw SALOME_Exception("my pertinent message");
\endcode

or like this:

\code
throw SALOME_Exception(LOCALIZED("my pertinent message"));
\endcode

where LOCALIZED is a macro provided with 
utils_SALOME_Exception.hxx which gives file name and 
line number.

The exception is handled like this:

\code
   try
{
  ...
}
catch (const SALOME_Exception &ex)
{
  cerr << ex.what() <<endl;
}
\endcode

The what() method overrides the one defined in the STL 
exception class.

\subsection subsection32 CORBA exceptions

\subsubsection subsubsection321 Definition

The idl SALOME_Exception provides a generic CORBA 
exception for %SALOME, with an attribute that gives an 
exception type,a message, plus optional source file 
name and line number. 

This idl is intended to serve for all user CORBA 
exceptions raised in %SALOME code, as IDL specification 
does not support exception inheritance. So, all the 
user CORBA exceptions from %SALOME could be handled in a 
single catch.

The exception types defined in idl are:

  - COMM CORBA communication problem,

  - BAD_PARAM Bad User parameters,

  - INTERNAL_ERROR application level problem (often irrecoverable).

CORBA system and user exceptions already defined in the 
packages used within %SALOME, such as OmniORB 
exceptions, must be handled separately.

\subsubsection subsubsection322 Usage
<b>CORBA servant, C++</b>

   The CORBA Server header for SALOME_Exception and a 
   macro to throw the exception are provided with the 
   header KERNEL_SRC/src/Utils/Utils_CorbaException.hxx:

   \code
#include "Utils_CorbaException.hxx"
   \endcode

   The exception is raised with a macro which appends file 
   name and line number:

   \code
if (myStudyName.size() == 0)
  THROW_SALOME_CORBA_EXCEPTION("No Study Name given", 
                               SALOME::BAD_PARAM);
   \endcode

<b>CORBA Client, GUI Qt C++ (NO MORE AVAILABLE in %SALOME 3.x and later)</b>

   The CORBA Client header for SALOME_Exception and a Qt 
   function header that displays a message box are 
   provided in:

     KERNEL_SRC/src/SALOMEGUI/SALOMEGUI_QtCatchCorbaException.hxx

   \code
#include "SALOMEGUI_QtCatchCorbaException.hxx"
   \endcode

   %A typical exchange with a CORBA Servant will be:

   \code
try
{
 ... // one ore more CORBA calls
}

catch (const SALOME::SALOME_Exception & S_ex)
{
  QtCatchCorbaException(S_ex);
}
   \endcode

<b>CORBA Client, C++, without GUI</b>

  Nothing specific has been provided to the developer 
  yet. See the idl or the Qt function 
  SALOMEGUI_QtCatchCorbaException.hxx to see how to get 
  the information given by the exception %object.

\section S4_kernel_res Miscellaneous tools

\subsection subsection41 Singleton
\subsubsection subsubsection411 Definition

%A singleton is an application data which is created and 
deleted only once at the end of the application 
process. The C++ compiler allows the user to create a 
static singleton data before the first executable 
statement. They are deleted after the last statement execution.

The SINGLETON_ template class deals with dynamic 
singleton. It is useful for functor objects. For 
example, an %object that connects the application to a 
system at creation and disconnects the application at deletion.

\subsubsection subsubsection412 Usage

To create a single instance of a POINT %object:

\code
# include "Utils_SINGLETON.hxx"
... 
POINT *ptrPoint=SINGLETON_<POINT>::Instance() ; 
assert(ptrPoint!=NULL) ;
\endcode

No need to delete ptrPoint. Deletion is achieved 
automatically at exit. If the user tries to create more 
than one singleton by using the class method 
SINGLETON_<TYPE>::Instance(), the pointer is returned 
with the same value even if this is done in different 
functions (threads ?):

\code
POINT *p1=SINGLETON_<POINT>::Instance() ;
... 
POINT *p2=SINGLETON_<POINT>::Instance() ; 

assert(p1==p2)
\endcode

\subsubsection subsubsection413 Design description

Here are the principles features of the singleton 
design:
- the user creates an %object of class TYPE by using the 
  class method SINGLETON_<TYPE>::Instance() which 
  returns a pointer to the single %object ;
- to create an %object, SINGLETON_<TYPE>::Instance() 
  uses the default constructor of class TYPE ;
- at the same time, this class method creates a 
  destructor %object which is added to the generic list 
  of destructor objects to be executed at the end of 
  the application (atexit) ;
- at the end of the application process all the 
  deletions are performed by the Nettoyage() C function 
  which executes the destruction objects end then 
  deletes the destructions objects themselves ;
- the Nettoyage() C  function using atexit() C  function 
  is embedded in a static single %object ATEXIT_().


*/
