void Server::run()
{
- pthread_t thread;
- pthread_create(&thread, NULL, Server::do_work_thunk, this);
+ should_stop = false;
+
+ // Joinable is already the default, but it's good to be certain.
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+ pthread_create(&worker_thread, &attr, Server::do_work_thunk, this);
+}
+
+void Server::stop()
+{
+ {
+ MutexLock lock(&mutex);
+ should_stop = true;
+ }
+
+ if (pthread_join(worker_thread, NULL) == -1) {
+ perror("pthread_join");
+ exit(1);
+ }
}
void *Server::do_work_thunk(void *arg)
{
for ( ;; ) {
int nfds = epoll_wait(epoll_fd, events, EPOLL_MAX_EVENTS, EPOLL_TIMEOUT_MS);
-
- MutexLock lock(&mutex); // We release the mutex between iterations.
if (nfds == -1) {
perror("epoll_wait");
exit(1);
}
-
+
+ MutexLock lock(&mutex); // We release the mutex between iterations.
+
+ if (should_stop) {
+ return;
+ }
+
for (int i = 0; i < nfds; ++i) {
int fd = events[i].data.fd;
assert(clients.count(fd) != 0);
// Start a new thread that handles clients.
void run();
+
+ // Stop the thread.
+ void stop();
+
void add_client(int sock);
void add_stream(const std::string &stream_id);
void set_header(const std::string &stream_id, const std::string &header);
void add_data(const std::string &stream_id, const char *data, size_t bytes);
private:
+ pthread_t worker_thread;
+
+ // All variables below this line are protected by the mutex.
pthread_mutex_t mutex;
+ // If the thread should stop or not.
+ bool should_stop;
+
// Map from stream ID to stream.
std::map<std::string, Stream> streams;