// -*- mode:C++; tab-width:2; c-basic-offset:2; indent-tabs-mode:nil -*-
//
// Copyright (C) 2000-2005 by Roger Rene Kommer / artefaktur, Kassel, Germany.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public License (LGPL).
//
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// License ACDK-FreeLicense document enclosed in the distribution
// for more for more details.
// This file is part of the Artefaktur Component Development Kit:
// ACDK
//
// Please refer to
// - http://www.acdk.de
// - http://www.artefaktur.com
// - http://acdk.sourceforge.net
// for more information.
//
// $Header: /cvsroot/acdk/acdk/acdk_core/src/acdk/lang/Thread.h,v 1.28 2005/04/22 11:13:56 kommer Exp $
#ifndef acdk_lang_Thread_h
#define acdk_lang_Thread_h
#include <acdk.h>
#include "Runnable.h"
#include "ThreadImpl.h"
#include "ThreadGroup.h"
#include "ThreadLocalImpl.h"
#include "sys/core_semaphore.h"
#include "sys/core_fastmutex.h"
namespace acdk {
namespace lang {
//============================= class Thread ===========================//
ACDK_DECL_CLASS(Thread);
ACDK_DECL_CLASS(ThreadGroup);
/** The Type or Creator of a Thread */
enum ThreadType
{
/** Thread was created by User */
UserThreadType,
/** Thread was created by System / Unknown */
SystemThreadType,
/** Thread is Main-Thread */
MainThreadType
};
ACDK_DEF_LIB_ENUM(ACDK_CORE_PUBLIC, ThreadType);
/**
This is base implementation to start and manage Thread.
Use not the default constructor Thread().
If you use thread functionality of ACDK it is important
to use the System::main funktionality for proper initialization.
See also acdk::lang::Runnable here in Package #acdk::lang.
@author Roger Rene Kommer
@version $Revision: 1.28 $
@date $Date: 2005/04/22 11:13:56 $
*/
class ACDK_CORE_PUBLIC Thread
: extends ::acdk::lang::Object,
implements ::acdk::lang::Runnable
{
ACDK_WITH_METAINFO(Thread)
public:
enum State
{
Created,
Running,
Suspended,
Terminated,
Detached
};
private:
RRunnable _runnable;
RString _name;
Thread::State _state;
bool _isDaemon;
/// thread should be interrupted
bool _interrupted;
/// this lock is currently waiting
MonitorInterface* _currentMonitor;
ThreadType _type;
RThreadGroup _group;
static sys::core_atomicop _threadCount;
RThrowable _exceptionToThrow;
/// for protecting setting/reading internal state
typedef sys::core_fastmutex InternalMutexType;
InternalMutexType _internalMutex;
#ifdef POSIX_THREADS
/**
used to wait in start until
Thread finisished initializing
*/
acdk::lang::Object _startSync;
#endif //POSIX_THREADS
public:
/** Construct an user Thread */
Thread(IN(RRunnable) target = Nil, IN(RString) name = Nil);
/** Construct an user Thread */
Thread(IN(RThreadGroup) group, IN(RRunnable) target = Nil, IN(RString) name = Nil);
/** Construct an system or main Thread */
Thread(ThreadType type, IN(RString) name = Nil);
foreign virtual ~Thread();
/// reimplemented from String
virtual RString toString();
virtual void join(int millis = -1, int nanos = 0) THROWS1(RIllegalArgumentException);
/**
Interrupt this thread
*/
virtual void interrupt();
/**
return true if this thread has interrupted signal set
*/
virtual bool isInterrupted();
/**
return true if currentThread() is interrupted
*/
static bool interrupted();
/**
return true if thread is running
*/
bool isAlive();
/**
start the thread
*/
virtual void start();
/**
overload this method to implement
working code for this thread
*/
virtual void run();
/**
return the priority of this thread
*/
virtual int getPriority();
/**
sets the priority of this thread
0 (hight) - 5 (low)
*/
virtual void setPriority(int newPriority);
/**
force switch to another thread
*/
static void yield();
/**
Sleep the current threads
@param millis milli seconds
@param nanaos nano seconds
*/
static void sleep(int millis, int nanaos = 0);
/**
return the current thread
*/
static RThread currentThread();
/**
return the threadgroup associated with this thread
*/
RThreadGroup getThreadGroup();
/**
delegate to ThreadGroup::activeCount if exists
otherwise return 1
*/
static int activeCount();
/**
non static version of activeCount()
*/
int getActiveCount();
/**
return stack frames in this thread.
This method only works with currentThread.
@deprectated
*/
virtual int countStackFrames();
/**
@deprecated should not be used
*/
foreign static unsigned int getStackBase() { return sys::ObjectHeap::stackBase(); }
/**
Kills this thread, without releasing any resource
*/
virtual void destroy();
/**
calls stop(new ThreadDeath())
@see void stop(IN(RThrowable) obj);
*/
virtual void stop();
/**
The given exception will be thrown in the thread either it
is in a waiting situation (inside wait, sleep, join, etc.)
or the thread is calling the Thread::checkForPendingException().
If the given exception is not of type ThreadDeath or InterruptedException
the stop() method will try to load the extended metainfo for this
exception type to throw the instance.
*/
virtual void stop(IN(RThrowable) exception);
/**
Suspends the thread.
If calling inside this thread the thread stops until
the thread will be resumed outside this thread.
Calling suspend() may result in a deadlock situtation if the thread
currently holds a lock on thread-shared ressources
*/
virtual void suspend();
/**
weak up thread previously suspended with suspend()
*/
virtual void resume();
/**
List all threads of current threadgroup
*/
static int enumerate(IN(RThreadArray) tarray);
/**
calls acdk::lang::System::printStackTrace()
*/
static void dumpStack();
/**
set this thread to a deamon thread
*/
virtual void setDaemon(bool on) { _isDaemon = on; }
virtual bool isDaemon() { return _isDaemon; }
virtual void setName(RString str);
/**
return the known threads, whereas main thread not included
*/
inline static int getThreadCount()
{
return _threadCount.read();
}
/**
internal helper
*/
void doSleep(int millis);
/** a new system thread was dedected */
static void newSystemThread(ThreadType type = SystemThreadType);
/** remove this system thread */
static void removeSystemThread();
/** checks if all thread are registered, removes zombies */
static void checkSystemThreads();
inline static bool isSingleThreaded() { return _threadCount.read() == 0; }
/// System should be friend of it, but include-chain disallows it.
foreign void _saveStackBase(unsigned int sp)
{
sys::ObjectHeap::saveStackBase(sp);
}
/**
after basic operations (like sleep) it calls checkForThreadException()
and if a throwable was set with setThreadExceptionToThrow this exception
will be raised
*/
inline void setThreadExceptionToThrow(IN(RThrowable) ex) { _exceptionToThrow = ex; }
inline RThrowable getThreadExceptionToThrow() { return _exceptionToThrow; }
/**
throws a previously set exception
@throw IllegalThreadStateException if called outside this thread
*/
inline void checkForThreadException()
{
if (_exceptionToThrow == Nil)
return;
_invokeThreadException();
}
/// calls currentThread()->checkForThreadException()
static void checkForPendingException()
{
currentThread()->checkForThreadException();
}
/**
internal helper
*/
bool _readResetIsInterrupted();
/** set current waiting monitor */
foreign static void setCurrentMonitor(MonitorInterface* monitor)
{
Thread::currentThread()->setCurrentWaitingMonitor(monitor);
}
foreign inline void setCurrentWaitingMonitor(MonitorInterface* monitor)
{
sys::core_lock_guard<InternalMutexType> _lock(_internalMutex);
_currentMonitor = monitor;
}
foreign inline Thread::State _getState() const { return _state; }
foreign inline void _setState(Thread::State state) { _state = state; }
protected:
void _invokeThreadException();
void _run();
foreign ThreadID _threadID;
public:
foreign ThreadID threadID() { return _threadID; }
foreign const ThreadID threadID() const { return _threadID; }
private:
#ifdef POSIX_THREADS
foreign static void* _posixThreadFunc(void* arg);
public:
//foreign acdk::lang::Object _joinWaitMonitor;
#endif //POSIX_THREADS
#ifdef WIN32_THREADS
#ifdef __BORLANDC__
#define _stdcall __stdcall
#endif
foreign static /*DWORD WINAPI*/ unsigned int _stdcall _Win32ThreadFunc(void* arg);
foreign HANDLE _threadHandle;
public:
foreign HANDLE threadHandle() { return _threadHandle; }
#endif //WIN32_THREADS
bool _isThisThreadCurrent() { return _threadID.isThisThreadCurrent(); }
foreign static ThreadID currentThreadId();
protected:
void _checkAccess();
};
/**
class to register/deregister waiting monitor
*/
foreign
class ScopedWaitingMonitor
{
MonitorInterface* _monitor;
public:
ScopedWaitingMonitor(MonitorInterface* monitor)
: _monitor(monitor)
{
Thread::setCurrentMonitor(_monitor);
}
~ScopedWaitingMonitor()
{
Thread::setCurrentMonitor(0);
}
};
} // lang
} // acdk
#endif //acdk_lang_Thread_h
|