Commits

dbacchet committed e435635

added thread pool utils/sample

  • Participants
  • Parent commits fbcf2c3

Comments (0)

Files changed (25)

File sources/SConscript

 	SConscript( 'blendelf/SConscript',
 	            exports={'env':env_local} )
 
+# build utils
+SConscript( 'utils/SConscript',
+            exports={'env':env_local} )
+
 # build bf2
 SConscript( 'bf2/SConscript',
             exports={'env':env_local} )

File sources/tools/mesh_importer/renderer.cpp

 {
     glPushAttrib(GL_LIGHTING_BIT);
     glDisable(GL_LIGHTING);
+
     float dx = (xmax-xmin)/nx;
     float dy = (ymax-ymin)/ny;
     float dz = (zmax-zmin)/nz;
         float xval=xmin+i*dx;
         if (fabs(xval)<1e-6) continue;
         glBegin(GL_LINES);
-            glColor3f(0.8f,0.0f,0.0f);
+            glColor3f(0.5f,0.0f,0.0f);
             glVertex3f(xval,0.0f,zmin);
             glVertex3f(xval,0.0f,zmax);
         glEnd();
         float zval=zmin+j*dz;
         if (fabs(zval)<1e-6) continue;
         glBegin(GL_LINES);
-            glColor3f(0.8f,0.0f,0.0f);
+            glColor3f(0.5f,0.0f,0.0f);
             glVertex3f(xmin,0.0f,zval);
             glVertex3f(xmax,0.0f,zval);
         glEnd();        
     {
         float xval=xmin+i*dx;
         glBegin(GL_LINES);
-            glColor3f(0.0f,0.8f,0.0f);
+            glColor3f(0.0f,0.5f,0.0f);
             glVertex3f(xval,ymin,0.0f);
             glVertex3f(xval,ymax,0.0f);
         glEnd();
         float yval=ymin+j*dy;
         if (fabs(yval)<1e-6) continue;
         glBegin(GL_LINES);
-            glColor3f(0.0f,0.8f,0.0f);
+            glColor3f(0.0f,0.5f,0.0f);
             glVertex3f(xmin,yval,0.0f);
             glVertex3f(xmax,yval,0.0f);
         glEnd();        
         float yval=ymin+i*dy;
         if (fabs(yval)<1e-6) continue;
         glBegin(GL_LINES);
-            glColor3f(0.0f,0.0f,0.8f);
+            glColor3f(0.0f,0.0f,0.5f);
             glVertex3f(0.0f,yval,zmin);
             glVertex3f(0.0f,yval,zmax);
         glEnd();
         float zval=zmin+j*dz;
         if (fabs(zval)<1e-6) continue;
         glBegin(GL_LINES);
-            glColor3f(0.0f,0.0f,0.8f);
+            glColor3f(0.0f,0.0f,0.5f);
             glVertex3f(0.0f,ymin,zval);
             glVertex3f(0.0f,ymax,zval);
         glEnd();        
     }
+
     // bold axes
     glLineWidth(3.0f);
     glBegin(GL_LINES);
     glEnd();
     glLineWidth(1.0f);
 
-    glPopAttrib();
+    glPopAttrib();	// lighting
 }    
 
 // ----------------------------------------------------------------------------

File sources/utils/SConscript

+# coding: utf-8
+# sources build Sconscript
+# 2011, Davide Bacchet (davide.bacchet@gmail.com)
+# $LastChangedDate: 2011-05-12 12:03:21 +0200 (Mon, 12 May 2008) $
+# $LastChangedBy: dbacc $
+
+
+import os,sys
+
+Import('env')
+env_local = env.Clone()
+
+SConscript( 'threadpool/SConscript', exports={'env':env_local} )
+
+

File sources/utils/threadpool/KMLock__.h

+//////////////////////////////////////////////////////////////////////////
+// KMLock.h
+//
+// Author: Keith Maggio
+// Purpose:	Container to interface with CRITICAL_SECTION.
+//			Can be used later on to switch between CRITICAL SECTION
+//			for Windows, and another critical section-like class
+//			for another platform.
+// Free for use and modification.
+// Revision 1, July 4th, 2010
+//////////////////////////////////////////////////////////////////////////
+#ifndef _KM_LOCK_H_
+#define _KM_LOCK_H_
+
+#define WINDOWS_LEAN_AND_MEAN
+#include <Windows.h>
+
+namespace kmp{
+namespace threading{
+
+class KMLock
+{
+private:
+	CRITICAL_SECTION m_critsec;
+public:
+	KMLock()
+	{
+		::InitializeCriticalSection(&m_critsec);
+	}
+
+	~KMLock()
+	{
+		::DeleteCriticalSection(&m_critsec);
+	}
+
+	void Lock()
+	{
+		::EnterCriticalSection(&m_critsec);
+	}
+
+	void Unlock()
+	{
+		::LeaveCriticalSection(&m_critsec);
+	}
+protected:
+};
+}}
+
+#endif

File sources/utils/threadpool/KMQueue.h

+//////////////////////////////////////////////////////////////////////////
+// KMThreadPool_Win32.h
+//
+// Author: Keith Maggio
+// Purpose: Our Threadpool Singleton class.
+// Free for use and modification.
+// Revision 1, September 5th, 2010
+//////////////////////////////////////////////////////////////////////////
+#ifndef _KM_QUEUE_H_
+#define _KM_QUEUE_H_
+
+#include "amp/amp_mutex.h"
+using namespace kmp::threading;
+
+namespace kmp{ 
+namespace threading{ 
+namespace algorithms{
+
+    // Thread-Safe Two-Lock Queue
+    // Based on the algorithm presented by Maged M. Michael & Michael L. Scott
+    // http://www.cs.rochester.edu/u/scott/papers/1996_PODC_queues.pdf
+    template<typename TYPE>
+    class KMQueue
+    {
+    private:
+        struct tNode
+        {
+            TYPE element;
+            tNode* next;
+
+            tNode(TYPE _elem, tNode* _next) : element(_elem), next(_next)
+            {}
+            tNode(TYPE _elem) : element(_elem), next(NULL)
+            {}
+        };
+
+        // Members
+        tNode* _head;  // The head acts as a dummy/invalidated pointer. When an item is the head,
+                        // then it's scheduled for deletion on the next pop (if it's not the last node
+                        // in the queue).
+        tNode* _tail;
+        amp_mutex_t _headLock;
+        amp_mutex_t _tailLock;
+
+        // Deactivated Functions
+        KMQueue(KMQueue&)
+        {}
+
+        KMQueue& operator = (KMQueue&)
+        {}
+
+
+    public:
+        KMQueue()
+        {
+            amp_mutex_create(&_headLock,AMP_DEFAULT_ALLOCATOR);
+            amp_mutex_create(&_tailLock,AMP_DEFAULT_ALLOCATOR);
+            tNode* dummy = new tNode(NULL, NULL);
+            _head = _tail = dummy;
+        }
+
+        ~KMQueue()
+        {
+            while(pop());
+            delete _head;
+        }
+
+        bool empty()
+        {
+            if(_head->next != NULL)
+                return false;
+            return true;
+        }
+
+        void push(TYPE item)
+        {
+            tNode* node = new tNode(item);
+            amp_mutex_lock(_tailLock);
+            {
+                _tail->next = node;
+                _tail = node;
+            }
+            amp_mutex_unlock(_tailLock);
+        }
+
+        TYPE pop()
+        {
+            tNode* node;
+            TYPE value;
+            amp_mutex_lock(_headLock);
+            {
+                node = _head;
+                tNode* newHead = node->next;
+                if(newHead == NULL)
+                {
+                    // If only the head is left, then the queue is empty
+                    // (Remember, the _head is considered invalidated)
+                    amp_mutex_unlock(_headLock);
+                    return NULL;
+                }
+                value = newHead->element;
+                _head = newHead;
+            }
+            amp_mutex_unlock(_headLock);
+            delete node;
+            return value;
+
+        }
+
+    };
+}}}
+#endif

File sources/utils/threadpool/KMTask.h

+//////////////////////////////////////////////////////////////////////////
+// KMTask.h
+//
+// Author: Keith Maggio
+// Purpose:	Container for task data. Adds ease-of-use when adding 
+//			additional functionality, like dependancies and such.
+// Free for use and modification.
+// Revision 1, July 4th, 2010
+//////////////////////////////////////////////////////////////////////////
+#ifndef _KM_TASK_H_
+#define _KM_TASK_H_
+
+#include "KMUtility.h"
+using namespace kmp::threading::utility;
+
+namespace kmp{
+namespace threading{
+
+class KMTask
+{
+private:
+	KMTaskFunc		m_task;
+	IKMTaskData*	m_data;
+public:
+	KMTask(KMTaskFunc task, IKMTaskData* data)
+	{
+		m_task = task;
+		m_data = data;
+	}
+
+	~KMTask()
+	{
+		if(m_data!=NULL)
+			delete m_data;
+		m_data = NULL;
+		m_task = NULL;
+	}
+
+	KMTaskFunc		GetTask()	{	return m_task;	}
+	IKMTaskData*	GetData()	{	return m_data;	}
+protected:
+};
+
+}}
+#endif

File sources/utils/threadpool/KMThreadPool_Win32.cpp

+#include "KMThreadPool_Win32.h"
+#include"KMThread_Win32.h"
+using namespace kmp::threading;
+
+KMThreadpool KMThreadpool::m_instance;
+
+void KMThreadpool::Initialize(unsigned int uiTryMinNumThreads,
+				unsigned int uiTryMaxNumThreads)
+{
+	unsigned int i;
+
+	//Create the threads
+	m_vthreads.assign(uiTryMinNumThreads, NULL);
+
+	//Initialize the min number of threads
+	for(i = 0; i < uiTryMinNumThreads; ++i)
+	{
+		m_vthreads[i] = new KMThread();
+		m_vthreads[i]->Begin();
+		if(m_vthreads[i]->isRunning())
+		{
+			++m_nactive;
+		}
+	}
+
+	//Try to initialize the max number of threads. If one fails,
+	//we stop.
+	for(i = uiTryMinNumThreads; i < uiTryMaxNumThreads; ++i)
+	{
+		KMThread* trythread = new KMThread();
+		trythread->Begin();
+		if(trythread->isRunning())
+		{
+			m_vthreads.push_back(trythread);
+			++m_nactive;
+		}
+		else
+		{
+			delete trythread;
+			break;
+		}
+	}
+
+
+}
+
+void KMThreadpool::Shutdown()
+{
+	KMTask* deltask;
+	KMThread* delthread;
+
+	// Stop the delegation of tasks
+	if(m_bprocess != false)
+	{
+		m_bprocess = false;
+	}
+	//Clear the threads
+	while(!m_vthreads.empty())
+	{
+		delthread = m_vthreads.back();
+		m_vthreads.pop_back();
+		delthread->End();
+		delete delthread;
+	}
+	//Clear the tasks
+	while(!m_qtaskList.empty())//isEmpty())
+	{
+		//deltask = m_qtaskList.front();
+		deltask = m_qtaskList.pop();
+		delete deltask;
+	}
+}
+
+void KMThreadpool::AddTask(KMTaskFunc task, IKMTaskData* data)
+{
+	KMTask* newTask = new KMTask(task,data);
+	m_qtaskList.push(newTask);
+}
+
+unsigned int  KMThreadpool::getNumDormantThreads()
+{
+	unsigned int i, dormant = 0;
+	for(i = 0; i < m_vthreads.size(); ++i)
+	{
+		if(m_vthreads[i]->isRunning() && m_vthreads[i]->isPaused())
+		{
+			++dormant;
+		}
+	}
+
+	return dormant;
+}
+
+void KMThreadpool::BeginProcessing()
+{
+	m_bprocess = true;
+}
+
+void KMThreadpool::StopProcessing()
+{
+	m_bprocess = false;
+}

File sources/utils/threadpool/KMThreadPool_Win32.h

+//////////////////////////////////////////////////////////////////////////
+// KMThreadPool_Win32.h
+//
+// Author: Keith Maggio
+// Purpose:	Our Threadpool Singleton class.
+// Free for use and modification.
+// Revision 2, September 6th, 2010
+//////////////////////////////////////////////////////////////////////////
+#ifndef KM_THREADPOOL_H_
+#define KM_THREADPOOL_H_
+
+#define WINDOWS_LEAN_AND_MEAN
+#include <windows.h>
+
+#include<iostream>
+using std::cout;
+
+#include<queue>
+#include<vector>
+using std::queue;
+using std::vector;
+
+#include"KMTask.h"
+#include"KMUtility.h"
+//#include"KMLocklessQueue.h"
+#include "KMQueue.h"
+using namespace kmp::threading::utility;
+using namespace kmp::threading::algorithms;
+
+namespace kmp{
+namespace threading{
+
+class KMThread;
+
+class KMThreadpool
+{
+	//Nested Classes
+	
+private:
+	//queue<KMTask*>		m_qtaskList;
+	//KMLocklessQueue<KMTask*> m_qtaskList;
+	KMQueue<KMTask*>	m_qtaskList;
+	vector<KMThread*>	m_vthreads;
+	unsigned int		m_nactive;
+	unsigned int		m_ndormant;
+
+	volatile bool m_bprocess;
+
+	// Friend to the threads so we can access the tasks directly.
+	friend class KMThread;
+
+	//Singleton
+	static KMThreadpool m_instance;
+	KMThreadpool()
+	{
+		//KMTask* dummy = new KMTask(NULL, NULL);
+		//m_qtaskList = KMLocklessQueue<KMTask*>(dummy);
+		m_bprocess = false;
+	}
+	KMThreadpool(const KMThreadpool&);
+	KMThreadpool& operator = (const KMThreadpool&);
+	~KMThreadpool()
+	{
+		Shutdown();
+	}
+public:
+
+	static KMThreadpool* getInstance()   {	return &m_instance;			}
+	unsigned int  getActiveThreads()	 {	return m_nactive;			}
+	bool          hasWaitingTasks()		 {	return !m_qtaskList.empty();}
+	unsigned int  getNumDormantThreads();
+	bool		  IsProcessing()		 {	return m_bprocess;			}
+	//size_t  getNumQueuedTasks()			 {	return m_qtaskList.size();	}
+
+	void Initialize(unsigned int uiTryMinNumThreads,
+					unsigned int uiTryMaxNumThreads);
+
+	void Shutdown();
+	void AddTask(KMTaskFunc task, IKMTaskData* data);
+
+	void BeginProcessing();
+	void StopProcessing();
+
+protected:
+};
+}}
+
+#endif

File sources/utils/threadpool/KMThread_Win32.cpp

+#include "KMThread_Win32.h"
+using namespace kmp::threading;
+
+KMThread::KMThread()
+{
+	m_hthread = NULL;
+
+	m_ptask = NULL;
+	m_pthreadpool = NULL;
+
+	m_brunning = false;
+	m_uithreadID = 0;
+	m_dwexit = 0;
+	// create mutex
+	amp_mutex_create(&_lock,AMP_DEFAULT_ALLOCATOR);
+}
+
+KMThread::~KMThread()
+{
+	End();
+}
+
+void KMThread::SetTask(KMTask* task)
+{
+	m_ptask = task;
+}
+
+void KMThread::Begin()
+{
+	// Set our thread pool
+	m_pthreadpool = KMThreadpool::getInstance();
+#if defined( _WIN32 )
+	// Start the thread.
+	m_hthread = (HANDLE)_beginthreadex( NULL,
+		0,
+		&cThreadProc,
+		(void*)this,
+		0,
+		&m_uithreadID );
+
+	m_brunning = true;
+	if( m_hthread == NULL )
+	{
+		// You can add extra error-handling here.
+		m_brunning = false;
+	}
+#endif /* defined( _WIN32 ) */
+}
+
+void KMThread::End()
+{
+#if defined( _WIN32 )
+	if( m_hthread != NULL )
+	{
+		m_brunning = false;
+		WaitForSingleObject( m_hthread, INFINITE );
+		DWORD ExitCode;
+		GetExitCodeThread( m_hthread, &ExitCode );
+		m_dwexit = ExitCode;
+		CloseHandle( m_hthread );
+		m_hthread = NULL;
+	}
+#endif /* defined( _WIN32 ) */
+}
+
+DWORD KMThread::ThreadProc()
+{
+	m_ptask = NULL;
+
+	// The main thread-loop. As long as this loop
+	// is running, the thread stays alive.
+	while(m_brunning)
+	{
+
+		Sleep(1);
+
+		// The thread pauses when it finishes a task.
+		// Adding a task resumes it.
+		if(m_ptask != NULL)
+		{
+			amp_mutex_lock(_lock);
+			{
+				KMTaskFunc task = m_ptask->GetTask();
+				IKMTaskData* data = m_ptask->GetData();
+				// Run the actual task
+				if(task != NULL && data != NULL)
+				{
+					task(data);
+				}
+				// Task is complete.
+				m_bpaused = true;
+				delete m_ptask;
+				m_ptask = NULL;
+			}
+			amp_mutex_unlock(_lock);
+		}
+		
+		// If we're finished with our task, grab a new one.
+		if(/*m_bpaused == true && */m_ptask == NULL &&
+			m_pthreadpool->IsProcessing() == true)
+		{
+			m_ptask = m_pthreadpool->m_qtaskList.pop();
+		}
+	}
+
+	return 0;
+}

File sources/utils/threadpool/KMThread_Win32.h

+//////////////////////////////////////////////////////////////////////////
+// KMThread_Win32.h
+//
+// Author: Keith Maggio
+// Purpose: Container for all thread-based actions
+// Free for use and modification.
+// Revision 1, September 5th, 2010
+//////////////////////////////////////////////////////////////////////////
+#ifndef KM_THREAD_H_
+#define KM_THREAD_H_
+
+#define WINDOWS_LEAN_AND_MEAN
+#include <windows.h>
+#include<process.h>
+
+#include<iostream>
+using std::cout;
+
+#include"KMThreadPool_Win32.h"
+#include"KMTask.h"
+#include"KMUtility.h"
+using namespace kmp::threading;
+using namespace kmp::threading::utility;
+
+#include "amp/amp_mutex.h"
+
+namespace kmp{
+namespace threading{
+
+class KMThread
+{
+private:
+    //Nested Classes
+    //SpinLock
+    
+//private:
+    KMThreadpool*       m_pthreadpool;
+
+    HANDLE              m_hthread;
+    amp_mutex_t         _lock;
+    KMTask*             m_ptask;
+
+    bool                m_brunning;
+    bool                m_bpaused;
+    unsigned int        m_uithreadID;
+    DWORD               m_dwexit;
+
+public:
+    bool            isRunning()     {   return m_brunning;      }
+    bool            isPaused()      {   return m_bpaused;       }
+    unsigned int    getThreadID()   {   return m_uithreadID;    }
+    DWORD           getExitCode()   {   return m_dwexit;        }
+    
+    void            Lock()          {   amp_mutex_lock(_lock);  }
+    void            Unlock()        {   amp_mutex_unlock(_lock);}
+
+    void            Pause()         {   m_bpaused = true;       }
+    void            Resume()        {   m_bpaused = false;      }
+
+    KMThread();
+    ~KMThread();
+    void SetTask(KMTask* task);
+    void Begin();
+    void End();
+    DWORD ThreadProc();
+protected:
+    static unsigned __stdcall cThreadProc(LPVOID _pThis)
+    {
+        return ((KMThread*)_pThis)->ThreadProc();
+    }
+};
+}}
+#endif

File sources/utils/threadpool/KMUtility.h

+//////////////////////////////////////////////////////////////////////////
+// KMUtility.h
+//
+// Author: Keith Maggio
+// Purpose:	Serves as a namespace to hold smaller data structures.
+// Free for use and modification.
+// Revision 1, July 4th, 2010
+//////////////////////////////////////////////////////////////////////////
+#ifndef KM_UTILITY_H_
+#define KM_UTILITY_H_
+
+namespace kmp{
+namespace threading{
+namespace utility
+{
+	//Class Interfaces
+	class IKMTaskData 
+	{
+	public:
+		IKMTaskData() {}
+		IKMTaskData(const IKMTaskData&) {}
+		IKMTaskData& operator = (const IKMTaskData&) {}
+		virtual ~IKMTaskData() = 0 {};
+	};
+
+	//Type Definitions
+	typedef void (*KMTaskFunc)(IKMTaskData*);
+
+}
+}}
+#endif

File sources/utils/threadpool/SConscript

+# coding: utf-8
+# 2012, Davide Bacchet (davide.bacchet@gmail.com)
+# $LastChangedDate: 2011-05-12 12:03:21 +0200 (Mon, 12 May 2008) $
+# $LastChangedBy: dbacc $
+
+
+import os, sys, fnmatch
+import pyutils
+import thirdparty
+
+Import('env')
+env_local = env.Clone()
+
+
+            
+# include dirs
+env_local.AppendUnique(CPPPATH = ['.'] )
+
+
+# add 3rdparty parameters
+thirdparty.osdeps.addOSToEnv(env_local)
+thirdparty.amp.addAmpToEnv(env_local)
+                                  
+# get list of files
+files = []
+files.append(Glob('./*.c*'))
+
+# build library
+threadpool_lib  = env_local.StaticLibrary('threadpool',files)
+
+
+
+
+Return('threadpool_lib')
+

File sources/utils/threadpool/orig/KMLock__.h

+//////////////////////////////////////////////////////////////////////////
+// KMLock.h
+//
+// Author: Keith Maggio
+// Purpose:	Container to interface with CRITICAL_SECTION.
+//			Can be used later on to switch between CRITICAL SECTION
+//			for Windows, and another critical section-like class
+//			for another platform.
+// Free for use and modification.
+// Revision 1, July 4th, 2010
+//////////////////////////////////////////////////////////////////////////
+#ifndef _KM_LOCK_H_
+#define _KM_LOCK_H_
+
+#define WINDOWS_LEAN_AND_MEAN
+#include <Windows.h>
+
+namespace kmp{
+namespace threading{
+
+class KMLock
+{
+private:
+	CRITICAL_SECTION m_critsec;
+public:
+	KMLock()
+	{
+		::InitializeCriticalSection(&m_critsec);
+	}
+
+	~KMLock()
+	{
+		::DeleteCriticalSection(&m_critsec);
+	}
+
+	void Lock()
+	{
+		::EnterCriticalSection(&m_critsec);
+	}
+
+	void Unlock()
+	{
+		::LeaveCriticalSection(&m_critsec);
+	}
+protected:
+};
+}}
+
+#endif

File sources/utils/threadpool/orig/KMQueue.h

+//////////////////////////////////////////////////////////////////////////
+// KMThreadPool_Win32.h
+//
+// Author: Keith Maggio
+// Purpose: Our Threadpool Singleton class.
+// Free for use and modification.
+// Revision 1, September 5th, 2010
+//////////////////////////////////////////////////////////////////////////
+#ifndef _KM_QUEUE_H_
+#define _KM_QUEUE_H_
+
+#include "amp/amp_mutex.h"
+using namespace kmp::threading;
+
+namespace kmp{ 
+namespace threading{ 
+namespace algorithms{
+
+    // Thread-Safe Two-Lock Queue
+    // Based on the algorithm presented by Maged M. Michael & Michael L. Scott
+    // http://www.cs.rochester.edu/u/scott/papers/1996_PODC_queues.pdf
+    template<typename TYPE>
+    class KMQueue
+    {
+    private:
+        struct tNode
+        {
+            TYPE element;
+            tNode* next;
+
+            tNode(TYPE _elem, tNode* _next) : element(_elem), next(_next)
+            {}
+            tNode(TYPE _elem) : element(_elem), next(NULL)
+            {}
+        };
+
+        // Members
+        tNode* _head;  // The head acts as a dummy/invalidated pointer. When an item is the head,
+                        // then it's scheduled for deletion on the next pop (if it's not the last node
+                        // in the queue).
+        tNode* _tail;
+        amp_mutex_t _headLock;
+        amp_mutex_t _tailLock;
+
+        // Deactivated Functions
+        KMQueue(KMQueue&)
+        {}
+
+        KMQueue& operator = (KMQueue&)
+        {}
+
+
+    public:
+        KMQueue()
+        {
+            amp_mutex_create(&_headLock,AMP_DEFAULT_ALLOCATOR);
+            amp_mutex_create(&_tailLock,AMP_DEFAULT_ALLOCATOR);
+            tNode* dummy = new tNode(NULL, NULL);
+            _head = _tail = dummy;
+        }
+
+        ~KMQueue()
+        {
+            while(pop());
+            delete _head;
+        }
+
+        bool empty()
+        {
+            if(_head->next != NULL)
+                return false;
+            return true;
+        }
+
+        void push(TYPE item)
+        {
+            tNode* node = new tNode(item);
+            amp_mutex_lock(_tailLock);
+            {
+                _tail->next = node;
+                _tail = node;
+            }
+            amp_mutex_unlock(_tailLock);
+        }
+
+        TYPE pop()
+        {
+            tNode* node;
+            TYPE value;
+            amp_mutex_lock(_headLock);
+            {
+                node = _head;
+                tNode* newHead = node->next;
+                if(newHead == NULL)
+                {
+                    // If only the head is left, then the queue is empty
+                    // (Remember, the _head is considered invalidated)
+                    amp_mutex_unlock(_headLock);
+                    return NULL;
+                }
+                value = newHead->element;
+                _head = newHead;
+            }
+            amp_mutex_unlock(_headLock);
+            delete node;
+            return value;
+
+        }
+
+    };
+}}}
+#endif

File sources/utils/threadpool/orig/KMTask.h

+//////////////////////////////////////////////////////////////////////////
+// KMTask.h
+//
+// Author: Keith Maggio
+// Purpose:	Container for task data. Adds ease-of-use when adding 
+//			additional functionality, like dependancies and such.
+// Free for use and modification.
+// Revision 1, July 4th, 2010
+//////////////////////////////////////////////////////////////////////////
+#ifndef _KM_TASK_H_
+#define _KM_TASK_H_
+
+#include "KMUtility.h"
+using namespace kmp::threading::utility;
+
+namespace kmp{
+namespace threading{
+
+class KMTask
+{
+private:
+	KMTaskFunc		m_task;
+	IKMTaskData*	m_data;
+public:
+	KMTask(KMTaskFunc task, IKMTaskData* data)
+	{
+		m_task = task;
+		m_data = data;
+	}
+
+	~KMTask()
+	{
+		if(m_data!=NULL)
+			delete m_data;
+		m_data = NULL;
+		m_task = NULL;
+	}
+
+	KMTaskFunc		GetTask()	{	return m_task;	}
+	IKMTaskData*	GetData()	{	return m_data;	}
+protected:
+};
+
+}}
+#endif

File sources/utils/threadpool/orig/KMThreadPool_Win32.cpp

+#include "KMThreadPool_Win32.h"
+#include"KMThread_Win32.h"
+using namespace kmp::threading;
+
+KMThreadpool KMThreadpool::m_instance;
+
+void KMThreadpool::Initialize(unsigned int uiTryMinNumThreads,
+				unsigned int uiTryMaxNumThreads)
+{
+	unsigned int i;
+
+	//Create the threads
+	m_vthreads.assign(uiTryMinNumThreads, NULL);
+
+	//Initialize the min number of threads
+	for(i = 0; i < uiTryMinNumThreads; ++i)
+	{
+		m_vthreads[i] = new KMThread();
+		m_vthreads[i]->Begin();
+		if(m_vthreads[i]->isRunning())
+		{
+			++m_nactive;
+		}
+	}
+
+	//Try to initialize the max number of threads. If one fails,
+	//we stop.
+	for(i = uiTryMinNumThreads; i < uiTryMaxNumThreads; ++i)
+	{
+		KMThread* trythread = new KMThread();
+		trythread->Begin();
+		if(trythread->isRunning())
+		{
+			m_vthreads.push_back(trythread);
+			++m_nactive;
+		}
+		else
+		{
+			delete trythread;
+			break;
+		}
+	}
+
+
+}
+
+void KMThreadpool::Shutdown()
+{
+	KMTask* deltask;
+	KMThread* delthread;
+
+	// Stop the delegation of tasks
+	if(m_bprocess != false)
+	{
+		m_bprocess = false;
+	}
+	//Clear the threads
+	while(!m_vthreads.empty())
+	{
+		delthread = m_vthreads.back();
+		m_vthreads.pop_back();
+		delthread->End();
+		delete delthread;
+	}
+	//Clear the tasks
+	while(!m_qtaskList.empty())//isEmpty())
+	{
+		//deltask = m_qtaskList.front();
+		deltask = m_qtaskList.pop();
+		delete deltask;
+	}
+}
+
+void KMThreadpool::AddTask(KMTaskFunc task, IKMTaskData* data)
+{
+	KMTask* newTask = new KMTask(task,data);
+	m_qtaskList.push(newTask);
+}
+
+unsigned int  KMThreadpool::getNumDormantThreads()
+{
+	unsigned int i, dormant = 0;
+	for(i = 0; i < m_vthreads.size(); ++i)
+	{
+		if(m_vthreads[i]->isRunning() && m_vthreads[i]->isPaused())
+		{
+			++dormant;
+		}
+	}
+
+	return dormant;
+}
+
+void KMThreadpool::BeginProcessing()
+{
+	m_bprocess = true;
+}
+
+void KMThreadpool::StopProcessing()
+{
+	m_bprocess = false;
+}

File sources/utils/threadpool/orig/KMThreadPool_Win32.h

+//////////////////////////////////////////////////////////////////////////
+// KMThreadPool_Win32.h
+//
+// Author: Keith Maggio
+// Purpose:	Our Threadpool Singleton class.
+// Free for use and modification.
+// Revision 2, September 6th, 2010
+//////////////////////////////////////////////////////////////////////////
+#ifndef KM_THREADPOOL_H_
+#define KM_THREADPOOL_H_
+
+#define WINDOWS_LEAN_AND_MEAN
+#include <windows.h>
+
+#include<iostream>
+using std::cout;
+
+#include<queue>
+#include<vector>
+using std::queue;
+using std::vector;
+
+#include"KMTask.h"
+#include"KMUtility.h"
+//#include"KMLocklessQueue.h"
+#include "KMQueue.h"
+using namespace kmp::threading::utility;
+using namespace kmp::threading::algorithms;
+
+namespace kmp{
+namespace threading{
+
+class KMThread;
+
+class KMThreadpool
+{
+	//Nested Classes
+	
+private:
+	//queue<KMTask*>		m_qtaskList;
+	//KMLocklessQueue<KMTask*> m_qtaskList;
+	KMQueue<KMTask*>	m_qtaskList;
+	vector<KMThread*>	m_vthreads;
+	unsigned int		m_nactive;
+	unsigned int		m_ndormant;
+
+	volatile bool m_bprocess;
+
+	// Friend to the threads so we can access the tasks directly.
+	friend class KMThread;
+
+	//Singleton
+	static KMThreadpool m_instance;
+	KMThreadpool()
+	{
+		//KMTask* dummy = new KMTask(NULL, NULL);
+		//m_qtaskList = KMLocklessQueue<KMTask*>(dummy);
+		m_bprocess = false;
+	}
+	KMThreadpool(const KMThreadpool&);
+	KMThreadpool& operator = (const KMThreadpool&);
+	~KMThreadpool()
+	{
+		Shutdown();
+	}
+public:
+
+	static KMThreadpool* getInstance()   {	return &m_instance;			}
+	unsigned int  getActiveThreads()	 {	return m_nactive;			}
+	bool          hasWaitingTasks()		 {	return !m_qtaskList.empty();}
+	unsigned int  getNumDormantThreads();
+	bool		  IsProcessing()		 {	return m_bprocess;			}
+	//size_t  getNumQueuedTasks()			 {	return m_qtaskList.size();	}
+
+	void Initialize(unsigned int uiTryMinNumThreads,
+					unsigned int uiTryMaxNumThreads);
+
+	void Shutdown();
+	void AddTask(KMTaskFunc task, IKMTaskData* data);
+
+	void BeginProcessing();
+	void StopProcessing();
+
+protected:
+};
+}}
+
+#endif

File sources/utils/threadpool/orig/KMThread_Win32.cpp

+#include "KMThread_Win32.h"
+using namespace kmp::threading;
+
+KMThread::KMThread()
+{
+	m_hthread = NULL;
+
+	m_ptask = NULL;
+	m_pthreadpool = NULL;
+
+	m_brunning = false;
+	m_uithreadID = 0;
+	m_dwexit = 0;
+}
+
+KMThread::~KMThread()
+{
+	End();
+}
+
+void KMThread::SetTask(KMTask* task)
+{
+	m_ptask = task;
+}
+
+void KMThread::Begin()
+{
+	// Set our thread pool
+	m_pthreadpool = KMThreadpool::getInstance();
+#if defined( _WIN32 )
+	// Start the thread.
+	m_hthread = (HANDLE)_beginthreadex( NULL,
+		0,
+		&cThreadProc,
+		(void*)this,
+		0,
+		&m_uithreadID );
+
+	m_brunning = true;
+	if( m_hthread == NULL )
+	{
+		// You can add extra error-handling here.
+		m_brunning = false;
+	}
+#endif /* defined( _WIN32 ) */
+}
+
+void KMThread::End()
+{
+#if defined( _WIN32 )
+	if( m_hthread != NULL )
+	{
+		m_brunning = false;
+		WaitForSingleObject( m_hthread, INFINITE );
+		DWORD ExitCode;
+		GetExitCodeThread( m_hthread, &ExitCode );
+		m_dwexit = ExitCode;
+		CloseHandle( m_hthread );
+		m_hthread = NULL;
+	}
+#endif /* defined( _WIN32 ) */
+}
+
+DWORD KMThread::ThreadProc()
+{
+	m_ptask = NULL;
+
+	// The main thread-loop. As long as this loop
+	// is running, the thread stays alive.
+	while(m_brunning)
+	{
+
+		Sleep(1);
+
+		// The thread pauses when it finishes a task.
+		// Adding a task resumes it.
+		if(m_ptask != NULL)
+		{
+			amp_mutex_lock(_lock);
+			{
+				KMTaskFunc task = m_ptask->GetTask();
+				IKMTaskData* data = m_ptask->GetData();
+				// Run the actual task
+				if(task != NULL && data != NULL)
+				{
+					task(data);
+				}
+				// Task is complete.
+				m_bpaused = true;
+				delete m_ptask;
+				m_ptask = NULL;
+			}
+			amp_mutex_unlock(_lock);
+		}
+		
+		// If we're finished with our task, grab a new one.
+		if(/*m_bpaused == true && */m_ptask == NULL &&
+			m_pthreadpool->IsProcessing() == true)
+		{
+			m_ptask = m_pthreadpool->m_qtaskList.pop();
+		}
+	}
+
+	return 0;
+}

File sources/utils/threadpool/orig/KMThread_Win32.h

+//////////////////////////////////////////////////////////////////////////
+// KMThread_Win32.h
+//
+// Author: Keith Maggio
+// Purpose: Container for all thread-based actions
+// Free for use and modification.
+// Revision 1, September 5th, 2010
+//////////////////////////////////////////////////////////////////////////
+#ifndef KM_THREAD_H_
+#define KM_THREAD_H_
+
+#define WINDOWS_LEAN_AND_MEAN
+#include <windows.h>
+#include<process.h>
+
+#include<iostream>
+using std::cout;
+
+#include"KMThreadPool_Win32.h"
+#include"KMTask.h"
+#include"KMUtility.h"
+using namespace kmp::threading;
+using namespace kmp::threading::utility;
+
+#include "amp/amp_mutex.h"
+
+namespace kmp{
+namespace threading{
+
+class KMThread
+{
+private:
+    //Nested Classes
+    //SpinLock
+    
+//private:
+    KMThreadpool*       m_pthreadpool;
+
+    HANDLE              m_hthread;
+    amp_mutex_t         _lock;
+    KMTask*             m_ptask;
+
+    bool                m_brunning;
+    bool                m_bpaused;
+    unsigned int        m_uithreadID;
+    DWORD               m_dwexit;
+
+public:
+    bool            isRunning()     {   return m_brunning;      }
+    bool            isPaused()      {   return m_bpaused;       }
+    unsigned int    getThreadID()   {   return m_uithreadID;    }
+    DWORD           getExitCode()   {   return m_dwexit;        }
+    
+    void            Lock()          {   amp_mutex_lock(_lock);  }
+    void            Unlock()        {   amp_mutex_unlock(_lock);}
+
+    void            Pause()         {   m_bpaused = true;       }
+    void            Resume()        {   m_bpaused = false;      }
+
+    KMThread();
+    ~KMThread();
+    void SetTask(KMTask* task);
+    void Begin();
+    void End();
+    DWORD ThreadProc();
+protected:
+    static unsigned __stdcall cThreadProc(LPVOID _pThis)
+    {
+        return ((KMThread*)_pThis)->ThreadProc();
+    }
+};
+}}
+#endif

File sources/utils/threadpool/orig/KMUtility.h

+//////////////////////////////////////////////////////////////////////////
+// KMUtility.h
+//
+// Author: Keith Maggio
+// Purpose:	Serves as a namespace to hold smaller data structures.
+// Free for use and modification.
+// Revision 1, July 4th, 2010
+//////////////////////////////////////////////////////////////////////////
+#ifndef KM_UTILITY_H_
+#define KM_UTILITY_H_
+
+namespace kmp{
+namespace threading{
+namespace utility
+{
+	//Class Interfaces
+	class IKMTaskData 
+	{
+	public:
+		IKMTaskData() {}
+		IKMTaskData(const IKMTaskData&) {}
+		IKMTaskData& operator = (const IKMTaskData&) {}
+		virtual ~IKMTaskData() = 0 {};
+	};
+
+	//Type Definitions
+	typedef void (*KMTaskFunc)(IKMTaskData*);
+
+}
+}}
+#endif

File temp/SConscript

 SConscript( 'test_slb/SConscript', exports='env' )
 # build amp threading test app
 SConscript( 'test_threading/SConscript', exports='env' )
+# build amp thread pool test app
+SConscript( 'test_threadpool/SConscript', exports='env' )
 # build json test app
 SConscript( 'test_json/SConscript', exports='env' )
 # build enet test app

File temp/test_threadpool/SConscript

+# coding: utf-8
+# 2011, Davide Bacchet (davide.bacchet@gmail.com)
+# $LastChangedDate: 2011-05-12 12:03:21 +0200 (Mon, 12 May 2008) $
+# $LastChangedBy: dbacc $
+
+
+import os, sys, fnmatch
+import pyutils
+import thirdparty
+
+Import('env')
+env_local = env.Clone()
+
+# include dirs
+env_local.AppendUnique(CPPPATH = ['.',
+                                  '#/sources/utils/threadpool'] )
+env_local.AppendUnique(LIBPATH = ['../../sources/utils/threadpool'] )
+                       
+# add 3rdparty parameters
+thirdparty.amp.addAmpToEnv(env_local)
+thirdparty.osdeps.addOSToEnv(env_local)
+
+# get list of files
+files_test = Glob('*.c*')
+
+# additional libraries
+libs = []
+libs.append('threadpool')
+env_local.AppendUnique(LIBS=libs)
+
+threadpool_test  = env_local.Program('test_threadpool',files_test,PDB='test_threadpool.pdb')
+
+Return('threadpool_test')
+

File temp/test_threadpool/Timer.cpp

+#include "Timer.h"
+
+Timer::Timer()
+{
+	QueryPerformanceFrequency(&_freq);
+}
+
+Timer::~Timer()
+{
+
+}
+
+
+float Timer::GetElapsedTime()
+{
+	LARGE_INTEGER current;
+	QueryPerformanceCounter(&current);
+
+	return float(current.QuadPart - _start.QuadPart) / float(_freq.QuadPart);
+} 

File temp/test_threadpool/Timer.h

+//////////////////////////////////////////////////////////////////////////
+//	Palpable Aftertaste's Timer Class
+//	by Keith Maggio
+//	
+//	Purpose:	Generates elapsed time and calculates FPS
+//////////////////////////////////////////////////////////////////////////
+
+#ifndef _PA_TIMER
+#define _PA_TIMER
+
+#include <windows.h>
+#include <ctime>
+
+class Timer
+{
+private:
+	LARGE_INTEGER	_start;
+	LARGE_INTEGER	_freq;
+	
+public:
+	Timer();
+	~Timer();
+
+	float GetElapsedTime();
+
+	//////////////////////////////////////////////////////////////////////////
+	//	Reset
+	//	Purpose:	Resets the timer. 
+	//				Called in a function that updates every frame, reset when necessary.
+	//////////////////////////////////////////////////////////////////////////
+	void Reset() { QueryPerformanceCounter(&_start); }
+	
+};
+
+#endif

File temp/test_threadpool/main.cpp

+//////////////////////////////////////////////////////////////////////////
+// Main.cpp
+//
+// Author: Keith Maggio
+// Purpose:	Main program entrance.
+// Free for use and modification.
+// Revision 1, July 4th, 2010
+//////////////////////////////////////////////////////////////////////////
+#include <ctime>
+#include "KMUtility.h"
+#include "KMThreadPool_Win32.h"
+using kmp::threading::KMThreadpool;
+using kmp::threading::utility::IKMTaskData;
+
+// Visual Leak Detector. If you don't have it, comment this line out
+// (Or download it - it's free!)
+//#include <vld.h>
+
+// Time keeping
+#include "Timer.h"
+
+#define MAX_TASKS 500 // Change this to modify the number of tasks
+
+//////////////////////////////////////////////////////////////////////////
+// This is our sample derived data class.
+class SampleTask : public IKMTaskData
+{
+public:
+	int tasknum;
+	SampleTask() {}
+	SampleTask(int data) { tasknum = data; }
+	~SampleTask() {}
+};
+
+void Sample1(IKMTaskData* data)
+{
+	// Once we have the sample data, we cast it
+	// To the type we need.
+	SampleTask* _data = (SampleTask*)data;
+	// printf("S%d\n", _data->tasknum);	// When the task started
+	for(int i=0;i<20000000;++i);
+	// printf("F%d\n", _data->tasknum);	// When the task finishes
+}
+
+void Sample2(IKMTaskData* data)
+{
+	SampleTask* _data = (SampleTask*)data;
+	// printf("S%d\n", _data->tasknum);
+	for(int i=0;i<500000;++i);
+	// printf("F%d\n", _data->tasknum);
+}
+//////////////////////////////////////////////////////////////////////////
+
+int main()
+{
+	int addTask = 0;
+	KMThreadpool* pool = KMThreadpool::getInstance();
+	// Initialize the threadpool.
+	pool->Initialize(4,8);
+	printf("Thread pool Initialized with %d threads.\n", pool->getActiveThreads());
+	system("pause");
+
+	// Add tasks to our threadpool.
+	for(int i = 0; i < MAX_TASKS; ++i)
+	{
+		SampleTask* data = new SampleTask(i);
+		if(i%2==0)
+			pool->AddTask(Sample1, data);
+		else
+			pool->AddTask(Sample2, data);
+	}
+
+	// See how long it takes to execute
+	Timer elapsed;
+	pool->BeginProcessing();
+	elapsed.Reset();
+	while(true)
+	{
+		// Check to see if all tasks are completed. This is
+		// only for this sample program. In others, the
+		// pool will be shut down once the program exits.
+		if( pool->getActiveThreads()==pool->getNumDormantThreads() && !pool->hasWaitingTasks())
+			break;
+
+		// Cut-off in the middle of execution
+		if(GetAsyncKeyState(VK_ESCAPE))
+			break;
+	}
+
+	float imediatefinish = elapsed.GetElapsedTime();
+	pool->StopProcessing();
+	// Fin
+	pool->Shutdown();
+	printf("Thread Pool has finished in %f seconds.\n", imediatefinish);
+	printf("CPU Time (ExecutionTime/NumberOfThreads+NumberOfProcessors) is %f seconds\n     on a duel-core processor. ",
+			(imediatefinish/(pool->getActiveThreads()+2)));
+	system("pause");
+	return 0;
+}