| Overview | Group | Tree | Graph | Deprecated | Index | Concepts |
As a modeling layer, Concert allows the creation and
destruction of extractables through the methods
IloExtractable::end and
IloExtractableArray::endElements.
The purpose of these methods is to reclaim memory associated
with the deleted objects while
maintaining the safest possible Concert environment.
In this context, a safe Concert
environment is defined by the property that no object points to a
deleted object; a pointer to a deleted object
is referred to as a dangling pointer in C++.
There exist two paradigms to make sure of the safety of the delete operation. The first, linear mode, comes from math programming; in a Concert application, linear mode is possible only on extractable and other objects used in linear programming. The second, safe generic mode, is stricter and is valid on all Concert extractable objects.
You can access both paradigms by calling
IloEnv::setDeleter(IloDeleterMode mode), where mode may be
IloLinearDeleterMode or IloSafeDeleterMode.
Linear Mode
To use linear mode, you must either
IloEnv::setDeleter(IloLinearDeleterMode), orIloEnv::setDeleter, as linear is the default mode.In linear mode, the following behavior is implemented:
IloConversion where it appears.Example
This example tests the linear mode deletion of a variable x.
void TestLinearDeleter() {
IloEnv env;
env.out() << "TestLinearDeleter" << endl;
try {
IloModel model(env);
IloNumVar x(env, 0, 10, "x");
IloNumVar y(env, 0, 10, "y");
IloConstraint con = (x + y <= 0);
IloConstraint con2 = y >= 6;
IloNumVarArray ar(env, 2, x, y);
IloSOS1 sos(env, ar, "sos");
model.add(con);
model.add(con2);
model.add(sos);
env.out() << "Before Delete" << endl;
env.out() << model << endl;
x.end();
con2.end();
env.out() << "After Delete" << endl;
env.out() << model << endl;
} catch (IloException& e) {
cout << "Error : " << e << endl;
}
env.end();
}
The example produces the following output:
TestLinearDeleter
Before Delete
IloModel model0 = {
IloRange rng3( 1 * x + 1 * y ) <= 0
IloRange rng46 <=( 1 * y )
IloSOS1I (sos)
_varArray [x(F)[0..10], y(F)[0..10]]
_valArray []
}
After Delete
IloModel model0 = {
IloRange rng3( 1 * y ) <= 0
IloSOS1I (sos)
_varArray [y(F)[0..10]]
_valArray []
}Safe Generic Mode
To use safe generic mode, you must:
IloEnv::setDeleter(IloSafeDeleterMode), and#include <ilconcert/ilodeleter.h> to your
application.In this mode, the environment builds a dependency graph between all extractable objects. This graph contains all extractable objects created
IloEnv::setDeleter(IloSafeDeleterMode) and IloEnv::unsetDeleter.Objects not managed by this dependency graph are referred to here as "nondeletable". An attempt to delete a nondeletable object will throw an exception.
It is recommended that you create this graph just after the
creation of the environment
and that you refrain from using IloEnv::unsetDeleter
because building an incomplete dependency graph is very error prone and
should only be attempted by advanced users. A clear example of this
incomplete graph is the separation of a model between a nondeletable
base model and deletable extensions of this base model.
Calling IloExtractable::end
on extractable xi will succeed
only if no other extractable object uses extractable xi.
If this is not the case,
a call to IloExtractable::end
will throw an exception
IloDeleter::RequiresAnotherDeletionException
indicating which extractable object
uses the extractable object that you want to delete.
Example
This example shows an attempt to delete one extractable object that is used by another.
void TestSafeDeleter() {
IloEnv env;
env.out() << "TestSafeDeleter" << endl;
env.setDeleter(IloSafeDeleterMode);
try {
IloModel model(env);
IloNumVar x(env, 0, 10);
IloNumVar y(env, 0, 10);
IloConstraint con = (x + y <= 0);
try {
x.end();
} catch (IloDeleter::RequiresAnotherDeletionException &e) {
cout << "Caught " << e << endl;
e.getUsers()[0].end();
e.end();
}
x.end();
} catch (IloException& e) {
cout << "Error : " << e << endl;
}
env.unsetDeleter();
env.end();
}
The example produces the following output:
TestSafeDeleter Caught You cannot end x1(F)[0..10] before IloRange rng3( 1 * x1 + 1 * x2 ) <= 0
To address this situation, you should use the method IloExtractableArray::endElements.
With this method,
all extractable objects in the array are deleted one after another.
Thus, if an extractable object is used by another extractable object
and this other extractable object is deleted before the
first one, the system will not complain and will not throw an exception.
Example
This example illustrates the use of the endElements method
void TestSafeDeleterWithArray() {
IloEnv env;
env.out() << "TestSafeDeleterWithArray" << endl;
env.setDeleter(IloSafeDeleterMode);
try {
IloModel model(env);
IloNumVar x(env, 0, 10);
IloNumVar y(env, 0, 10);
IloConstraint con = (x + y <= 0);
IloExtractableArray ar(env, 2, con, x);
ar.endElements();
} catch (IloException& e) {
cout << "Error : " << e << endl;
}
env.unsetDeleter();
env.end();
}
That example will not throw an exception.
con must appear
before the variable x as it will be deleted before the variable
x.