Overview | Group | Tree | Graph | Index | Concepts |
This class offers facilities for writing multi-threaded applications. It
allows you to create a specified number of threads and then to execute
different pieces of code on these threads asynchronously. Each thread is
associated with a unique environment that is an instance of
IloEnv
; the code executed by each thread is a Solver goal.
Upon request, the workserver object provides you with the environment or
solver of a thread waiting for work. An instance of IloGoal
can
be constructed in the environment. It can then be extracted to the solver of
the corresponding thread and executed on the thread.
For more information, see Durability.
See Also:
Constructor Summary | |
---|---|
public | IlcWorkServer() |
public | IlcWorkServer(IlcBaseAgentServerI * impl) |
public | IlcWorkServer(const IlcScheduler sched0, IlcInt nbOfThreads, const char * prefix=0) |
Method Summary | |
---|---|
public void | end() |
public IloEnv | getIdleEnv() |
public IloSolver | getIdleSolver() |
public IlcBaseAgentServerI * | getImpl() const |
public void | launch(IloGoal goal) |
public void | operator=(const IlcWorkServer & h) |
Constructor Detail |
---|
This constructor creates an empty handle. You must initialize it before you use it.
This constructor creates a handle object from a pointer to an implementation object.
This constructor creates a work server that starts
nbOfThreads
worker threads. Each worker thread has a different
environment and waits to receive work. If the number of threads is 0, then
no worker thread is created and further calls to the member function
launch
of this IlcWorkServer
will be treated
sequentially.
The created work server will be used to solve solver goals that use the
durable resources of the schedule sched0
. Note that
sched0
must be a durable and closed schedule. If
sched0
is not a durable schedule or is not closed, any attempt
to launch a goal on this work server will raise an error.
The argument prefix
serves as a base for creating names for
the output streams of each thread: the first thread will output in
prefix0.out
, the second in prefix1.out
, etc. If
prefix
is 0, then the default output stream is considered.
nbOfThreads
is ignored and is considered to be zero.Method Detail |
---|
This member function waits for all worker threads to finish their work,
then stops them and calls end()
on each worker's
environment.
This member function returns the environment associated with a thread that is waiting for work. If there is no such thread, this call may block while waiting for a free worker.
This member function returns the solver associated with a thread that is waiting for work. If there is no such thread, this call may block while waiting for a free worker.
This member function returns a pointer to the implementation object of the invoking handle.
The argument goal
must be a solver goal constructed on the
same environment as the solver obtained by a previous call to
getIdleSolver
. The waiting worker whose solver was returned by
the previous call at getIdleSolver
starts working by extracting
and executing the goal
. Calls to getIdleSolver
and
launch
must be interleaved. At the end of the execution of the
goal, the memory allocated on the idle solver is collected.
Example
Let us consider the very simple scheduling problem that consists of creating and scheduling an activity which requires a given durable resource. Suppose that ten instances of this problem are to be solved, each instance characterized by the particular resource it needs. The inherent parallelism of this application can by exploited by solving different instances on different threads.
The following Solver goal defines and solves an instance of the scheduling problem.
#include <ilsched/iloscheduler.h> #include <ilsched/workserv.h> ILCGOAL1(ProblemIlc, IlcDiscreteResource, resource) { IloSolver solver = getSolver(); IlcSchedule schedule(solver, 0, 365); IlcActivity activity(scheduler, 10); scheduler.lock(1, resource); solver.add(activity.requires(resource, 3)); solver.startNewSearch(IlcSetTimes(schedule)); solver.next(); schedule.unlock(1, resource); solver.endSearch(); return 0; } ILOCPGOALWRAPPER2(Problem, solver, IlcScheduler, durableSched, IloDiscreteResource, resource) { return ProblemIlc(solver, durableSched.getDiscreteResource(resource)); } int main(){ // Creating the durable resources in a model: IloEnv env0; IloModel model0(env0); const IloInt nbOfResources = 2; IloDiscreteResource resources[nbOfResources]; for (IloInt i=0; i < nbOfResources; i++) { resources[i] = IloDiscreteResource(env0, 7); model0.add(resources[i]); } // Creating the durable scheduler: IloSolver solver0(env0); IlcScheduler scheduler0(solver0); scheduler0.setDurable(); solver0.extract(model0); scheduler0.close(); // Creating the worker threads: IlcWorkServer server(scheduler0, 3); // Solving ten instances: for (IloInt k=0; k<10; k++){ IloInt resourceIdx = k % nbOfResources; // Getting the solver of a waiting worker thread: IloEnv env = server.getIdleEnv(); // Creating the problem instance: IloGoal instance = Problem(env, scheduler0, resources[resourceIdx]); // Solving it on the corresponding thread: server.launch(instance); } // Stopping all worker threads: server.end(); env0.end(); return 0; }
This operator assigns an address to the handle pointer of the invoking object. That address is the location of the implementation object of the provided argument.