if your work units are CPU bound, it's best to use processes because typically all threads in a process are running on the same core (at least in Linux).
using a process per CPU core will ensure each process gets an actual CPU core.
The advantage of threads is that it's very easy to share state between them, so if all you really need is to download a file without blocking, or sending a query to a database, threads will be a better option.
in fact, I am just in the middle of writing something that you may find useful: a manager that spawns a few worker processes and restart them if they exit/killed/dies. it's pretty much ready, so here it is:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string>
void termination_handler(int signum)
{
printf("pid %d : signal %d caught in pid %d\n", getpid(), signum, getpid());
kill(0, SIGTERM);
exit(1);
}
int main(int argc ,char** argv)
{
if (argc > 1)
{
printf("pid %d : Worker code running\n", getpid());
sleep(10);
}
else
{
printf("pid %d : manager started\n", getpid());
// manager
const int MAX_INSTANCES = 3;
int numInstances = 0;
struct sigaction new_action;
/* Set up the structure to specify the new action. */
new_action.sa_handler = termination_handler;
sigemptyset(&new_action.sa_mask);
new_action.sa_flags = 0;
sigaction(SIGKILL, &new_action, NULL);
sigaction(SIGTERM, &new_action, NULL);
sigaction(SIGINT, &new_action, NULL);
int status;
int w;
do
{
while (numInstances < MAX_INSTANCES)
{
int pid = fork();
if (pid < 0)
{
printf("fork failed\n");
exit(1);
}
else
{
if (pid == 0)
{
char * const argv1[] = { (char*) argv[0], (char*)"worker",(char *) 0 };
char * const envp1[] = { (char *) 0 };
std::string prog = argv[0];
execve(prog.c_str(), argv1, envp1);
}
else
{
numInstances++;
}
}
}
w = waitpid(0, &status, WUNTRACED | WCONTINUED);
if (w == -1)
{
perror("waitpid");
exit(EXIT_FAILURE);
}
if (WIFEXITED(status))
{
printf("pid %d : child %d exited, status=%d\n",getpid(), w, WEXITSTATUS(status));
numInstances--;
}
else if (WIFSIGNALED(status))
{
printf("pid %d : child %d killed by signal %d\n",getpid(), w, WTERMSIG(status));
numInstances--;
}
else if (WIFSTOPPED(status))
{
printf("pid %d : child %d stopped by signal %d\n",getpid(), w, WSTOPSIG(status));
}
else if (WIFCONTINUED(status))
{
printf("pid %d : child %d continued\n", getpid(), w);
}
}
while (true);
//! WIFEXITED(status) && !WIFSIGNALED(status));
printf("pid %d : manager terminated\n", getpid());
}
return 0;
}