coriolis/hurricane/doc/hurricane/GenericLocator.dox

160 lines
5.1 KiB
C++

// -*- C++ -*-
namespace Hurricane {
/*! \class GenericLocator
* \brief GenericLocator description (\b API)
*
* \section secGenericLocatorIntro Introduction
*
* Locators are powerful objects but present a major weakness.
* You must handle them through a pointer variable and not
* forget to release the allocated locator after use.
\code
Locator<Net*>* locator = cellGetNets().GetLocator();
...
// use
...
delete locator;
\endcode
* Fortunately, the type GenericLocator\c \<Type\> corrects this
* weakness. Indeed a generic locator creates at its
* construction (or by assignment) a clone of the given locator
* and releases, when deleted (or when assigned to an other
* locator) the previously allocated one. More, when initialized
* with an already allocated locator, it takes in charge to
* release it. Therefore you only need to write:
\code
GenericLocator<Net*> locator = cellGetNets().GetLocator();
...
// use
...
\endcode
* \remark It's possible to bring within a GenericLocator\c \<Type\>
* variable any kind of locator of elements of the same Type
* (and also an other generic locator).
*/
/*! \section secGenericLocatorUsageExamples Usage examples
*
* Let's take the examples used in the Locator class and see
* what they become.
*
* The following example shows how to visit the nets of a given
* cell.
\code
Cell* cell = ...; // we get a cell
if (cell) {
GenericLocator<Net*> locator = CellGetNets().GetLocator();
while (locator.IsValid()) {
Net* net = locator.GetElement();
assert(netGetCell() == cell);
locator.Progress();
}
}
\endcode
* And this one, how to print all net pairs.
\code
Cell* cell = ...; // we get a cell
if (cell) {
GenericLocator<Net*> locator1 = CellGetNets().GetLocator();
while (locator1.IsValid()) {
Net* net1 = locator1.GetElement();
GenericLocator<Net*> locator2 = locator1;
// or GenericLocator<Net*> locator2 = locator1.GetClone();
while (locator2.IsValid()) {
Net* net2 = locator2.GetElement();
cerr << net1 << " " << net2 << endl;
locator2.Progress();
}
locator1Progress();
}
}
\endcode
* \remark Those examples are used here to describe generic locator
* behaviours. We will see later how code them in a much simpler
* way with the for_each macros.
*/
/*! \section secGenericLocatorHowWorksTheMacroFor_each How works the macro for_each
*
* When explaining Collection class we used some macros. We can
* now describe the way they are implemented.
*
* <b>Macro for_each implementation</b>
\code
#define for_each(Type, variable, collection)\
/*******************************************/\
{\
GenericLocator<Type> _locator = collection.GetLocator();\
while (_locator.IsValid()) {\
Type variable = _locator.GetElement();\
_locator.Progress();
\endcode
* This macro stores within a generic locator type variable the
* locator provided by the given collection. The remaining code
* is classic.
*
*
* \remark The locator allocated by the GetLocator() call is released by
* the destructor of the generic locator which, itself, will be
* called automatically because it is allocated within the
* execution stack.
*
* <b>Macro end_for implementation</b> This macro is mandatory
* in order to close the lexical blocks opened by the for_each
* macro.
\code
#define end_for\
/**************/\
}\
}
\endcode
* <b>Important observation</b> When you write the following :
\code
for_each(Net*, net, cellGetNets()) {
// body
end_for;
}
\endcode
* The body is processed between for_each and end_for macros,
* therefore after the binding of the variable to its element,
* but also once the locator has progressed. It is therefore
* possible to write, without risk the following :
\code
for_each(Net*, net, cellGetNets()) {
netDelete();
end_for;
}
\endcode
* Nevertheless you must take care in some cases. For instance
* you should not write :
\code
for_each(Component*, component, netGetComponents()) {
componentDelete();
end_for;
}
\endcode
* Because the deletion of a component might lead to the
* deletion of some related component, which could be the next
* one, where the locator is currently positionned. The locator
* becomes then invalid and the issue is fatal. It is cleaner to
* write :
\code
Components components = netGetComponents();
while (!components.IsEmpty()) components.GetFirst()Delete();
\endcode
*/
}