// $Header: /cvs/gled-1.2/GledCore/Gled/GThread.cxx,v 1.6 2005/03/11 17:50:16 matevz Exp $
// Copyright (C) 1999-2005, Matevz Tadel. All rights reserved.
// This file is part of GLED, released under GNU General Public License version 2.
// For the licensing terms see $GLEDSYS/LICENSE or http://www.gnu.org/.
#include "GThread.h"
#include <pthread.h>
#include <stdio.h>
ClassImp(GThread)
map<pthread_t, GThread*> GThread::sIdMap;
GMutex GThread::sIDLock;
pthread_key_t GThread::TSD_Self;
pthread_key_t GThread::TSD_Owner;
pthread_key_t GThread::TSD_MIR;
/**************************************************************************/
GThread::GThread(GThread_foo f, void* a, bool d) :
mStartFoo(f), mArg(a), bDetached(d)
{
mId = 0;
}
GThread::~GThread()
{
// This should be clean up foo; Thread can die b4 object does
// but ... as well ... object can die b4 thread does
sIDLock.Lock(); sIdMap.erase(mId); sIDLock.Unlock();
}
void GThread::DeleteIfDetached()
{
GThread* self = GThread::get_self();
if(self->GetDetached()) {
pthread_setspecific(TSD_Self, 0);
delete self;
}
}
/**************************************************************************/
GThread* GThread::wrap_and_register_self(ZMirEmittingEntity* owner)
{
GThread* t = new GThread(0,0,false);
t->mId = pthread_self();
sIDLock.Lock();
sIdMap[ t->mId ] = t;
sIDLock.Unlock();
setup_tsd(owner);
return t;
}
/**************************************************************************/
void GThread::init_tsd()
{
pthread_key_create(&TSD_Self, 0);
pthread_key_create(&TSD_Owner, 0);
pthread_key_create(&TSD_MIR, 0);
}
void GThread::setup_tsd(ZMirEmittingEntity* owner)
{
pthread_setspecific(TSD_Self, Self());
set_owner(owner);
set_mir(0);
}
void GThread::cleanup_tsd()
{
set_mir(0);
set_owner(0);
pthread_setspecific(TSD_Self, 0);
}
GThread* GThread::get_self()
{
return (GThread*)pthread_getspecific(TSD_Self);
}
void GThread::set_owner(ZMirEmittingEntity* owner)
{
pthread_setspecific(TSD_Owner, owner);
}
ZMirEmittingEntity* GThread::get_owner()
{
return (ZMirEmittingEntity*)pthread_getspecific(TSD_Owner);
}
void GThread::set_mir(ZMIR* mir)
{
pthread_setspecific(TSD_MIR, mir);
}
ZMIR* GThread::get_mir()
{
return (ZMIR*)pthread_getspecific(TSD_MIR);
}
/**************************************************************************/
int GThread::Spawn()
{
pthread_attr_t attr;
pthread_attr_init(&attr);
if(bDetached)
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
int ret;
sIDLock.Lock();
if( (ret = pthread_create(&mId, &attr, mStartFoo, mArg)) ) {
perror("GThread::Spawn");
goto end;
}
bRunning = true;
ISdebug(D_THRMUT, GForm("GThread::Spawn Setting id %u to %p", mId, this));
sIdMap[mId] = this;
end:
sIDLock.Unlock();
return ret;
}
int GThread::Join(void** tret)
{
int ret = pthread_join(mId, tret);
if(ret) perror("GThread::Join");
return ret;
}
int GThread::Kill(Signal signal)
{
int ret = pthread_kill(mId, (Int_t)signal);
if(ret) perror("GThread::Kill");
return ret;
}
int GThread::Cancel()
{
int ret = pthread_cancel(mId);
if(ret) perror("GThread::Cancel");
return ret;
}
int GThread::Detach()
{
int ret = pthread_detach(mId);
if(ret) perror("GThread::Detach");
else bDetached = true;
return ret;
}
/**************************************************************************/
// Static functions; to be called from within thread.
/**************************************************************************/
GThread::CState GThread::SetCancelState(CState s)
{
int ex_val;
if(s == CS_Enable)
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &ex_val);
else
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &ex_val);
return ex_val == PTHREAD_CANCEL_ENABLE ? CS_Enable : CS_Disable;
}
/**************************************************************************/
GThread::CType GThread::SetCancelType(CType t)
{
int ex_val;
if(t == CT_Async)
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &ex_val);
else
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &ex_val);
return ex_val == PTHREAD_CANCEL_DEFERRED ? CT_Deferred : CT_Async;
}
/**************************************************************************/
void GThread::TestCancel()
{
pthread_testcancel();
}
void GThread::Exit(void* ret)
{
GThread* self = get_self();
if(self) self->bRunning = false;
pthread_exit(ret);
}
/**************************************************************************/
GThread* GThread::Self()
{
//ISdebug(D_THRMUT,_s<<"Self gives " << pthread_self() <<" w/ "<< mIdMap[ pthread_self() ]));
int foo;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &foo);
sIDLock.Lock(); GThread* t = sIdMap[ pthread_self() ]; sIDLock.Unlock();
pthread_setcancelstate(foo, 0);
return t;
}
GThread* GThread::TSDSelf()
{
return get_self();
}
unsigned long GThread::RawSelf()
{
return pthread_self();
}
ROOT page - Home page - Class index - Class Hierarchy - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.