--- linuxsampler/trunk/src/common/Thread.h 2004/04/27 09:21:58 56 +++ linuxsampler/trunk/src/common/Thread.h 2007/11/15 01:15:12 1482 @@ -3,6 +3,7 @@ * LinuxSampler - modular, streaming capable sampler * * * * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * + * Copyright (C) 2005 - 2007 Christian Schoenebeck * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -20,44 +21,125 @@ * MA 02111-1307 USA * ***************************************************************************/ -#ifndef __THREAD_H__ -#define __THREAD_H__ +#ifndef __LS_THREAD_H__ +#define __LS_THREAD_H__ + +//FIXME: this is a temorary solution because of problems with condition variables we use a polling lock in SignalStartThread() +#if defined(WIN32) +#define WIN32_SIGNALSTARTTHREAD_WORKAROUND 1 +#endif #include #include #include + +#if defined(WIN32) +#include +#else #include #include #include #include +#endif #include +#include "Condition.h" + +namespace LinuxSampler { + /// Abstract base class for classes that need to run in an own thread. class Thread { public: - Thread(bool RealTime, int PriorityMax, int PriorityDelta); + Thread(bool LockMemory, bool RealTime, int PriorityMax, int PriorityDelta); virtual ~Thread(); virtual int StartThread(); virtual int StopThread(); + virtual int SignalStartThread(); virtual int SignalStopThread(); - virtual bool IsRunning() { return Running; } + virtual bool IsRunning(); virtual int SetSchedulingPriority(); //FIXME: should be private + virtual int LockMemory(); //FIXME: should be private virtual void EnableDestructor(); //FIXME: should be private virtual int Destructor(); //FIXME: should be private virtual int Main() = 0; ///< This method needs to be implemented by the descendant and is the entry point for the new thread. FIXME: should be protected + + /** + * Allocates an aligned block of memory. Allocated memory blocks + * need to be freed using freeAlignedMem(). + * + * @param boundary - the alignement boundary, usually a power of 2 + * e.g. 4 but it can be an arbitrary number + * between 1 and 128 + * @param size - size in bytes to be allocated + * @returns pointer to the allocated memory block + */ + static void* allocAlignedMem(size_t boundary, size_t size) { + unsigned char *ptr = (unsigned char *)malloc(size+boundary); + size_t offset = boundary - ((size_t)ptr % boundary); + ptr[offset-1] = (unsigned char)offset; + return (ptr + offset); + } + + /** + * Frees an aligned block of memory allocated with allocAlignedMem() + * + * @param ptr - pointer to the memory block + */ + static void freeAlignedMem(void *ptr) { + unsigned char *p = (unsigned char *)ptr; + p -= p[-1]; + free(p); + } + + /** + * Locks a region of memory in physical RAM. + * + * @param addr - address of the memory block + * @param size - size of the memory block + * @return true if the locking succeded, otherwise false + */ + static bool lockMemory(void *addr, size_t size) { + #if defined(WIN32) + return VirtualLock(addr, size); + #else + return !mlock(addr, size); + #endif + } + + /** + * Unlocks a region of memory in physical RAM. + * + * @param addr - address of the memory block + * @param size - size of the memory block + * @return true if the unlocking succeded, otherwise false + */ + static bool unlockMemory(void *addr, size_t size) { + #if defined(WIN32) + return VirtualUnlock(addr, size); + #else + return !munlock(addr, size); + #endif + } + private: + #if defined(WIN32) + HANDLE hThread; + DWORD lpThreadId; + #if defined(WIN32_SIGNALSTARTTHREAD_WORKAROUND) + bool win32isRunning; + #endif + #else + pthread_attr_t __thread_attr; pthread_t __thread_id; pthread_key_t __thread_destructor_key; - pthread_mutex_t __thread_state_mutex; - pthread_cond_t __thread_exit_condition; + #endif + Condition RunningCondition; int PriorityMax; int PriorityDelta; - bool Running; bool isRealTime; + bool bLockedMemory; }; -// Callback functions for the POSIX thread API -void* __pthread_launcher(void* thread); -void __pthread_destructor(void* thread); +} // namespace LinuxSampler -#endif // __THREAD_H__ +#endif // __LS_THREAD_H__