Difference between revisions of "User:Kr/A Thread's Life/Example Code"
m (Now creates randomly activities and daemons ...) |
|||
Line 1: | Line 1: | ||
<code>[cpp] | <code>[cpp] | ||
+ | // | ||
+ | // gcc -g main.c -o main.bin -lpthread | ||
+ | // | ||
+ | |||
#include <stdlib.h> | #include <stdlib.h> | ||
#include <stdio.h> | #include <stdio.h> | ||
#include <pthread.h> | #include <pthread.h> | ||
+ | #include <string.h> | ||
− | + | typedef struct Daemon Daemon; | |
− | + | ||
− | + | struct Daemon { | |
+ | Daemon * previous_; | ||
+ | Daemon * next_; | ||
+ | pthread_t hd_; | ||
+ | }; | ||
+ | |||
+ | static Daemon * firstDaemon_ = NULL; | ||
+ | static unsigned int daemons_ = 0; | ||
+ | static pthread_mutex_t daemons_mutex_ = PTHREAD_MUTEX_INITIALIZER; | ||
+ | |||
+ | static Daemon * new_daemon(void) { | ||
+ | Daemon * daemon = malloc(sizeof(Daemon)); | ||
− | if ( | + | pthread_mutex_lock(&daemons_mutex_); |
+ | |||
+ | daemon->previous_ = NULL; | ||
+ | daemon->next_ = firstDaemon_; | ||
+ | |||
+ | if (firstDaemon_) | ||
+ | firstDaemon_->previous_ = daemon; | ||
+ | |||
+ | firstDaemon_ = daemon; | ||
+ | |||
+ | ++ daemons_; | ||
+ | |||
+ | pthread_mutex_unlock(&daemons_mutex_); | ||
+ | |||
+ | return daemon; | ||
+ | } | ||
+ | |||
+ | static void end_of_daemon(void * context) { | ||
+ | Daemon * daemon = (Daemon *)context; | ||
+ | |||
+ | pthread_mutex_lock(&daemons_mutex_); | ||
+ | -- daemons_; | ||
+ | |||
+ | if (daemon->next_) | ||
+ | daemon->next_->previous_ = daemon->previous_; | ||
+ | |||
+ | if (daemon->previous_) | ||
+ | daemon->previous_->next_ = daemon->next_; | ||
+ | |||
+ | if (firstDaemon_ == daemon) | ||
+ | firstDaemon_ = daemon->next_; | ||
+ | |||
+ | pthread_mutex_unlock(&daemons_mutex_); | ||
+ | |||
+ | free(daemon); | ||
+ | |||
+ | // This thread is not in the list of daemons anymore, | ||
+ | // and therefor can't be joined. | ||
+ | pthread_detach(pthread_self()); | ||
+ | } | ||
+ | |||
+ | static void create_a_daemon(void); | ||
+ | |||
+ | static void * daemon_func(void * para) { | ||
+ | pthread_cleanup_push (end_of_daemon, para); | ||
+ | |||
+ | int n = 10; | ||
+ | while (n) { | ||
+ | sleep(1); | ||
+ | |||
+ | if (rand() < (RAND_MAX / (daemons_ + 1))) | ||
+ | create_a_daemon(); | ||
+ | |||
+ | -- n; | ||
+ | } | ||
+ | |||
+ | pthread_cleanup_pop(1); | ||
+ | |||
+ | return NULL; | ||
+ | } | ||
+ | |||
+ | static void join_daemons(void) { | ||
+ | fprintf(stderr, "%s ... ", __PRETTY_FUNCTION__, pthread_self()); | ||
+ | |||
+ | pthread_mutex_lock(&daemons_mutex_); | ||
+ | while (firstDaemon_) { | ||
+ | pthread_t hd; | ||
+ | |||
+ | memcpy(&hd, &firstDaemon_->hd_, sizeof(pthread_t)); | ||
+ | |||
+ | pthread_mutex_unlock(&daemons_mutex_); | ||
+ | |||
+ | // We may want to cancel a thread actively during termination: | ||
+ | pthread_cancel(hd); | ||
+ | // respectively | ||
+ | //pthread_kill(); | ||
+ | |||
+ | pthread_join(hd, NULL); | ||
+ | |||
+ | pthread_mutex_lock(&daemons_mutex_); | ||
+ | } | ||
+ | pthread_mutex_unlock(&daemons_mutex_); | ||
+ | |||
+ | fprintf(stderr, "done\n"); | ||
+ | } | ||
+ | |||
+ | static void create_a_daemon(void) { | ||
+ | Daemon * daemon = new_daemon(); | ||
+ | pthread_create(&daemon->hd_, NULL, daemon_func, daemon); | ||
+ | } | ||
+ | |||
+ | |||
+ | static unsigned int activities_ = 1; // The "main" thread is the first "activity". | ||
+ | static pthread_mutex_t activity_mutex_ = PTHREAD_MUTEX_INITIALIZER; | ||
+ | |||
+ | static void new_activity(void) { | ||
+ | pthread_mutex_lock(&activity_mutex_); | ||
+ | ++ activities_; | ||
+ | pthread_mutex_unlock(&activity_mutex_); | ||
+ | } | ||
+ | |||
+ | static void end_of_activity(void) { | ||
+ | int use_exit = 0; | ||
+ | pthread_mutex_lock(&activity_mutex_); | ||
+ | -- activities_; | ||
+ | use_exit = activities_ == 0; | ||
+ | pthread_mutex_unlock(&activity_mutex_); | ||
+ | |||
+ | // Terminate the process, if this was the last "activity"! | ||
+ | if (use_exit) | ||
exit(0); | exit(0); | ||
Line 18: | Line 142: | ||
} | } | ||
− | static void | + | static void create_an_activity(void); |
+ | |||
+ | static void * activity(void * gr) { | ||
+ | int n = 3; | ||
+ | while (n) { | ||
+ | sleep(1); | ||
+ | |||
+ | if (rand() < (RAND_MAX / (activities_ + 1))) | ||
+ | create_an_activity(); | ||
+ | |||
+ | if (rand() < (RAND_MAX / (daemons_ + 1))) | ||
+ | create_a_daemon(); | ||
+ | |||
+ | -- n; | ||
+ | } | ||
+ | |||
+ | end_of_activity(); | ||
+ | } | ||
+ | |||
+ | static void create_an_activity(void) { | ||
pthread_attr_t attr; | pthread_attr_t attr; | ||
Line 25: | Line 168: | ||
pthread_t bt; | pthread_t bt; | ||
− | pthread_create(&bt, &attr, | + | pthread_create(&bt, &attr, activity, NULL); |
pthread_attr_destroy(&attr); | pthread_attr_destroy(&attr); | ||
+ | |||
+ | new_activity(); | ||
} | } | ||
− | static void * | + | static void * print_daemon(void * gr) { |
− | fprintf(stderr, "% | + | while (1) { |
+ | fprintf(stderr, "activities: %u daemons: %u\n", activities_, daemons_); | ||
− | + | sleep(1); | |
+ | } | ||
pthread_exit(NULL); | pthread_exit(NULL); | ||
} | } | ||
− | |||
− | static void | + | static pthread_t print_daemon_hd; |
+ | |||
+ | static void join_print_daemon(void) { | ||
fprintf(stderr, "%s - tid: %x\n", __PRETTY_FUNCTION__, pthread_self()); | fprintf(stderr, "%s - tid: %x\n", __PRETTY_FUNCTION__, pthread_self()); | ||
// You may want to cancel a thread actively during termination: | // You may want to cancel a thread actively during termination: | ||
− | pthread_cancel( | + | pthread_cancel(print_daemon_hd); |
// respectively | // respectively | ||
//pthread_kill(); | //pthread_kill(); | ||
− | pthread_join( | + | fprintf(stderr, "%s - joining print daemon ...\n", __PRETTY_FUNCTION__); |
+ | pthread_join(print_daemon_hd, NULL); | ||
} | } | ||
− | static void | + | static void create_print_daemon(void) { |
− | pthread_create(& | + | pthread_create(&print_daemon_hd, NULL, print_daemon, NULL); |
− | atexit( | + | atexit(join_print_daemon); |
} | } | ||
static void print_something(void) { | static void print_something(void) { | ||
− | fprintf(stderr, "% | + | fprintf(stderr, "activities: %u daemons: %u\n", activities_, daemons_); |
} | } | ||
int main(void) { | int main(void) { | ||
+ | srand (time (0)); | ||
+ | |||
atexit(print_something); | atexit(print_something); | ||
+ | atexit(join_daemons); | ||
− | + | create_print_daemon(); | |
+ | create_a_daemon(); | ||
+ | create_an_activity(); | ||
− | + | sleep(3); | |
+ | create_a_daemon(); | ||
− | + | sleep(5); | |
+ | end_of_activity(); | ||
return 0; | return 0; | ||
} | } | ||
</code> | </code> |
Revision as of 13:25, 4 September 2007
[cpp]
//
// gcc -g main.c -o main.bin -lpthread
//
- include <stdlib.h>
- include <stdio.h>
- include <pthread.h>
- include <string.h>
typedef struct Daemon Daemon;
struct Daemon {
Daemon * previous_; Daemon * next_;
pthread_t hd_;
};
static Daemon * firstDaemon_ = NULL; static unsigned int daemons_ = 0; static pthread_mutex_t daemons_mutex_ = PTHREAD_MUTEX_INITIALIZER;
static Daemon * new_daemon(void) {
Daemon * daemon = malloc(sizeof(Daemon)); pthread_mutex_lock(&daemons_mutex_);
daemon->previous_ = NULL; daemon->next_ = firstDaemon_;
if (firstDaemon_) firstDaemon_->previous_ = daemon;
firstDaemon_ = daemon;
++ daemons_;
pthread_mutex_unlock(&daemons_mutex_);
return daemon;
}
static void end_of_daemon(void * context) {
Daemon * daemon = (Daemon *)context;
pthread_mutex_lock(&daemons_mutex_); -- daemons_;
if (daemon->next_) daemon->next_->previous_ = daemon->previous_;
if (daemon->previous_) daemon->previous_->next_ = daemon->next_;
if (firstDaemon_ == daemon) firstDaemon_ = daemon->next_;
pthread_mutex_unlock(&daemons_mutex_);
free(daemon);
// This thread is not in the list of daemons anymore, // and therefor can't be joined. pthread_detach(pthread_self());
}
static void create_a_daemon(void);
static void * daemon_func(void * para) {
pthread_cleanup_push (end_of_daemon, para);
int n = 10; while (n) { sleep(1); if (rand() < (RAND_MAX / (daemons_ + 1))) create_a_daemon();
-- n; }
pthread_cleanup_pop(1);
return NULL;
}
static void join_daemons(void) {
fprintf(stderr, "%s ... ", __PRETTY_FUNCTION__, pthread_self());
pthread_mutex_lock(&daemons_mutex_); while (firstDaemon_) { pthread_t hd;
memcpy(&hd, &firstDaemon_->hd_, sizeof(pthread_t));
pthread_mutex_unlock(&daemons_mutex_);
// We may want to cancel a thread actively during termination: pthread_cancel(hd); // respectively //pthread_kill();
pthread_join(hd, NULL);
pthread_mutex_lock(&daemons_mutex_); } pthread_mutex_unlock(&daemons_mutex_);
fprintf(stderr, "done\n");
}
static void create_a_daemon(void) {
Daemon * daemon = new_daemon(); pthread_create(&daemon->hd_, NULL, daemon_func, daemon);
}
static unsigned int activities_ = 1; // The "main" thread is the first "activity".
static pthread_mutex_t activity_mutex_ = PTHREAD_MUTEX_INITIALIZER;
static void new_activity(void) {
pthread_mutex_lock(&activity_mutex_); ++ activities_; pthread_mutex_unlock(&activity_mutex_);
}
static void end_of_activity(void) {
int use_exit = 0; pthread_mutex_lock(&activity_mutex_); -- activities_; use_exit = activities_ == 0; pthread_mutex_unlock(&activity_mutex_);
// Terminate the process, if this was the last "activity"! if (use_exit) exit(0);
else pthread_exit(NULL);
}
static void create_an_activity(void);
static void * activity(void * gr) {
int n = 3; while (n) { sleep(1); if (rand() < (RAND_MAX / (activities_ + 1))) create_an_activity();
if (rand() < (RAND_MAX / (daemons_ + 1))) create_a_daemon();
-- n; }
end_of_activity();
}
static void create_an_activity(void) {
pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, 1); pthread_t bt; pthread_create(&bt, &attr, activity, NULL); pthread_attr_destroy(&attr); new_activity();
}
static void * print_daemon(void * gr) {
while (1) { fprintf(stderr, "activities: %u daemons: %u\n", activities_, daemons_);
sleep(1); }
pthread_exit(NULL);
}
static pthread_t print_daemon_hd;
static void join_print_daemon(void) {
fprintf(stderr, "%s - tid: %x\n", __PRETTY_FUNCTION__, pthread_self());
// You may want to cancel a thread actively during termination: pthread_cancel(print_daemon_hd); // respectively //pthread_kill();
fprintf(stderr, "%s - joining print daemon ...\n", __PRETTY_FUNCTION__); pthread_join(print_daemon_hd, NULL);
}
static void create_print_daemon(void) {
pthread_create(&print_daemon_hd, NULL, print_daemon, NULL); atexit(join_print_daemon);
}
static void print_something(void) {
fprintf(stderr, "activities: %u daemons: %u\n", activities_, daemons_);
}
int main(void) {
srand (time (0));
atexit(print_something); atexit(join_daemons);
create_print_daemon(); create_a_daemon(); create_an_activity();
sleep(3); create_a_daemon();
sleep(5); end_of_activity();
return 0;
}