/*
 * @(#)Thread.cpp
 *
 * This file is part of webCDwriter - Network CD Writing.
 *
 * Copyright (C) 2002-2004 Jörg P. M. Haeger
 *
 * webCDwriter is free software. See CDWserver.cpp for details.
 *
 * Jörg Haeger, 22.04.2002
 */

#include <pthread.h>
#include <unistd.h>
#include "Thread.h"

Thread::Thread() {
	pthread_mutex_lock(&mutex);
	activeThreads++;
	pthread = pthread_self();
	id = nextID++;
	pthread_mutex_unlock(&mutex);
}

int Thread::activeThreads = 0;
int Thread::nextID = getpid();
pthread_key_t Thread::key;
pthread_mutex_t Thread::mutex = PTHREAD_MUTEX_INITIALIZER;
const Thread *Thread::mainThread = init();

Thread::~Thread() {
	pthread_mutex_lock(&mutex);
	activeThreads--;
	pthread_mutex_unlock(&mutex);
}

const Thread *Thread::currentThread() {
	if (activeThreads == 0)
		return NULL;

	return (Thread *) pthread_getspecific(key);
}

int Thread::ID() const {
	return id;
}

const Thread *Thread::init() {
	pthread_key_create(&key, NULL);
	const Thread *thread = new Thread();
	pthread_setspecific(key, thread);
	return thread;
}

void Thread::run() {
}

void *Thread::run(void *arg) {
	Thread *thread = (Thread *) arg;
	pthread_setspecific(key, thread);
	thread->pthread = pthread_self();

	int pid = getpid();
	if (pid != mainThread->id)
		// if it's possible to distinguish threads by the pid, use it
		thread->id = pid;

	thread->run();
	delete thread;
	pthread_exit(NULL);
	return NULL;
}

void Thread::start() {
	pthread_t thread;
	if (pthread_create(&thread, NULL, &run, this) == 0)
		pthread_detach(thread);
}

void Thread::updateFirstThread(pid_t pid) {
	if (activeThreads == 1) {
		if (pid != mainThread->id) {
			delete mainThread;
			nextID = pid;
			mainThread = new Thread();
			pthread_setspecific(key, mainThread);
		}
	}
}
