Created
July 29, 2011 10:04
-
-
Save mythosil/1113553 to your computer and use it in GitHub Desktop.
prefork sample
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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