x:run
() starts
a new thread immediately. A thread worker pool starts new threads
in advance, and assigns them to a particular job, with a
queue for waiting requests.
A x::workerpool
is an object that has its own run
() method
that works generally the same way as x::run
(),
however a number of threads get started in advance (actually, the first
time its run
() method gets called):
#include <x/ref.H> #include <x/obj.H> #include <x/threads/workerpool.H> class spaceshipObj : virtual public x::obj { public: spaceshipObj() {} ~spaceshipObj() {} void run(int x, int y); }; typedef x::workerpool<spaceshipObj> fleet_t; fleet_t fleet=fleet_t::create(4, 8, "starship", "army"); // ... fleet->run(100, 200);
The worker pool template class takes a class name parameter that defines
which classes get instantiated for each thread in the worker pool.
The worker pool constructor takes two required parameters: the minimum
number of threads that get started, and the maximum number of threads.
The worker pool object will adjust the number of running threads, as
needed. An instance of the template class gets constructed and
destroyed, as the threads get created and destroyed. In this example,
between four and eight threads, and instances of
spaceshipObj
get instantiated. The template class
must have a default constructor.
The third and the fourth parameters are optional. The third parameter
set the name of each running thread, for logging purposes. The fourth
parameter sets the name of properties
that specify the worker pool parameters:
,
property
::min
,
and
property
::max
.
The above example uses three properties,
property
::namearmy::min
,
army::max
, and
army::name
, to set the minimum and the maximum number
of threads, and their names. The parameters to the constructor serve as
the default value of the corresponding property. In absence of setting
those properties, the parameters to the constructor take effect by
default.
Invoking the worker pool object's run
() forwards
this call, and its parameters (which must be copy-constructible), to the
first available spaceshipObj
instance/thread.
When the object's run
() returns, the thread
goes back in line waiting for another call to
run
(), or the thread may get terminated, if
the thread's services are not required any more.
run
() always returns immediately. If all threads
are busy, the request goes into an internal queue, and goes to
some thread when it becomes available.
When the last reference to the worker pool object itself goes out of
scope, and it gets destroyed, the worker pool
object's destructor stops any threads that are still running.
If a thread is in a middle of a run
() call,
the destructor waits unil the thread returns, and terminates.
If there were calls to the worker pool object's
run
() method that were never forwarded to a
thread, because they were all busy, before the worker pool object got
destroyed, those calls will never occur (and the internal queue that
holds run
()'s parameters gets destroyed,
destroying each passed parameter along with it).
#include <x/ref.H> #include <x/obj.H> #include <x/threads/workerpool.H> class spaceshipObj : virtual public x::obj { public: spaceshipObj() {} ~spaceshipObj() {} void run(int x, int y); }; typedef x::ref<spaceshipObj> spaceship; typedef x::workerpool<> fleet_t; spaceship enterprise=spaceship::create(); fleet_t fleet=fleet_t::create(4, 8, "starship", "army"); // ... fleet->run(enterprise, 100, 200);
The template class parameter to x::workerpool
is optional. The default thread worker pool object implementation
defines
a run
() method that takes at least one
parameter. Its first parameter is any reference-counted object, with
run
() forwarding any remaining parameters to
the object's own run
() method.
The above example constructs a worker pool with a default thread class parameter. This class is simply this:
class x::simpleWorkerThreadObj { public: template<typename objClass, typename baseClass, typename ...Args> inline void run(const ref<objClass, baseClass> &obj, Args && ...args) { obj->run(std::forward<Args>(args)...); } template<typename objClass, typename baseClass, typename ...Args> inline void run(const const_ref<objClass, baseClass> &obj, Args && ...args) { obj->run(std::forward<Args>(args)...); } };
The call to the worker pool object's run
()
method passes a reference to a x::spaceshipObj
as the first parameter. The default implementation of a worker pool
thread class forwards its parameters to the referenced object's own
run
().
This approach is desirable when a worker pool thread class does not have a default constructor. The worker pool is now simply a means of limiting the maximum number of running threads, at the same time.
A reference to the same object may be passed to multiple calls to
run
(). The referenced object's
run
() method may get executed by the same
thread, or by different threads at the same time.