1
0
mirror of https://github.com/Zygo/bees.git synced 2025-05-18 13:55:44 +02:00
bees/include/crucible/process.h
Zygo Blaxell e66086516f bees: dynamic thread pool size based on system load average
Add -g / --loadavg-target parameter to track system load and add or
remove bees worker threads dynamically to keep system load close to the
loadavg target.  Thread count may vary from zero to the maximum
specified by -c or -C, and is adjusted every 5 seconds.

This is better than implementing a similar load average scheme from
outside of the process (though that is still possible) because the
in-process load tracker does not disrupt the performance timing feedback
mechanisms as a freezer cgroup or SIGSTOP would when controlling bees
from outside.  The internal load average tracker can also adjust the
number of active threads while an external tracker can only choose from
the maximum or zero.

Also fix a bug where a Task could deadlock waiting for itself to exit
if it tries to insert a new Task after the number of worker threads has
been set to zero.

Also correct usage message for --scan-mode (values are 0..2) since
we are touching adjacent lines anyway.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
2018-09-14 23:50:03 -04:00

82 lines
2.0 KiB
C++

#ifndef CRUCIBLE_PROCESS_H
#define CRUCIBLE_PROCESS_H
#include "crucible/resource.h"
#include <functional>
#include <memory>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
namespace crucible {
using namespace std;
// Like thread, but for processes.
// TODO: thread has a few warts for this usage:
// - can't create one from its native_handle,
// - can't destroy one without joining/detaching it first
// - can't implement detach correctly without crossing threshold of insanity
// - WTF is native_handle() not const?
struct Process {
// These parts are for compatibility with std::thread
using id = ::pid_t;
using native_handle_type = ::pid_t;
~Process();
Process();
template <class Fn, class... Args>
Process(Fn fn, Args... args) :
Process()
{
do_fork(function<int()>([&]() { return fn(args...); }));
}
Process(const Process &) = delete;
Process(Process &&move_from);
bool joinable();
void detach();
native_handle_type native_handle();
id get_id();
// Modified thread members for Process
// join() calls waitpid(), returns status or exception (std::thread returns void)
using status_type = int;
status_type join();
// New members for Process
// kill() terminates a process in the usual Unix way
void kill(int sig = SIGTERM);
// take over ownership of an already-forked native process handle
Process(id pid);
private:
id m_pid;
void do_fork(function<int()>);
};
template <>
struct ResourceTraits<Process::id, Process> {
Process::id get_key(const Process &res) const { return (const_cast<Process&>(res)).native_handle(); }
shared_ptr<Process> make_resource(const Process::id &id) const { return make_shared<Process>(id); }
bool is_null_key(const Process::id &key) const { return !key; }
Process::id get_null_key() const { return 0; }
};
typedef ResourceHandle<Process::id, Process> Pid;
pid_t gettid();
double getloadavg1();
double getloadavg5();
double getloadavg15();
}
#endif // CRUCIBLE_PROCESS_H