Skip to content

Instantly share code, notes, and snippets.

@mythosil
Created July 29, 2011 10:04
Show Gist options
  • Save mythosil/1113553 to your computer and use it in GitHub Desktop.
Save mythosil/1113553 to your computer and use it in GitHub Desktop.
prefork sample
#include <iostream>
#include <vector>
#include <ctime> /* time */
#include <csignal> /* signal, kill */
#include <unistd.h> /* fork, usleep */
#include <sys/wait.h> /* wait */
#include <sys/types.h> /* pid_t */
using namespace std;
class prefork {
private:
unsigned int max_workers;
unsigned int max_requests_per_child;
useconds_t fork_usleep;
vector<pid_t> workers;
unsigned int num_workers;
void init_signal();
virtual void worker_process() = 0;
public:
prefork(unsigned int max_workers,
unsigned int max_requests_per_child)
: max_workers(max_workers),
max_requests_per_child(max_requests_per_child) {
fork_usleep = 0;
num_workers = 0;
}
prefork(unsigned int max_workers,
unsigned int max_requests_per_child,
useconds_t fork_usleep)
: max_workers(max_workers),
max_requests_per_child(max_requests_per_child),
fork_usleep(fork_usleep) {
num_workers = 0;
}
~prefork() {}
void run();
void set_fork_usleep(unsigned int fork_usleep);
void kill_all();
void kill_child();
};
/* for signal handling */
prefork* prefork_obj;
void signal_kill_all(int sig)
{
prefork_obj->kill_all();
}
void signal_kill_child(int sig)
{
prefork_obj->kill_child();
}
/***********************/
void prefork::run()
{
prefork_obj = this;
init_signal();
while (true) {
while (num_workers >= max_workers) {
int status;
pid_t pid = wait(&status);
num_workers--;
}
pid_t pid = fork();
if (pid == 0) {
prefork_obj = this;
signal(SIGTERM, signal_kill_child);
for (int i = 0; i < max_requests_per_child; i++)
worker_process();
exit(0);
}
workers.push_back(pid);
num_workers++;
usleep(fork_usleep);
}
}
void prefork::set_fork_usleep(useconds_t fork_usleep)
{
this->fork_usleep = fork_usleep;
}
void prefork::init_signal()
{
signal(SIGINT, signal_kill_all);
signal(SIGTERM, signal_kill_all);
}
void prefork::kill_all()
{
for (int i = 0; i < workers.size(); i++)
kill(workers[i], SIGTERM);
workers.clear();
exit(0);
}
void prefork::kill_child()
{
exit(0);
}
/*********************************/
class processor : public prefork {
private:
void worker_process() {
srand(time(0));
for (int i = 0; i < 3; i++) {
cout << "PID = " << getpid() << endl;
sleep(rand() % 3 + 1);
}
}
public:
processor(unsigned int max_workers, unsigned int max_requests_per_child)
: prefork(max_workers, max_requests_per_child) {}
~processor() {}
};
int main(int argc, const char* argv[])
{
unsigned int max_workers = 5;
unsigned int max_requests_per_child = 3;
processor p(max_workers, max_requests_per_child);
p.set_fork_usleep(1000000);
p.run();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment