[hydra-commits] ken.hunt: branch techdemo/ken.hunt/embeddedPythonTest r630 - in /techdemo/tea...
SVN commits to the Hydra project
hydra-commits at lists.digium.com
Thu May 20 14:31:31 CDT 2010
Author: ken.hunt
Date: Thu May 20 14:31:30 2010
New Revision: 630
URL: https://origsvn.digium.com/svn-view/hydra?view=rev&rev=630
Log:
thread testing
Added:
techdemo/team/ken.hunt/embeddedPythonTest/threadtest/
techdemo/team/ken.hunt/embeddedPythonTest/threadtest/CMakeLists.txt (with props)
techdemo/team/ken.hunt/embeddedPythonTest/threadtest/iworkqueue.h (with props)
techdemo/team/ken.hunt/embeddedPythonTest/threadtest/pyworkqueue.cpp (with props)
techdemo/team/ken.hunt/embeddedPythonTest/threadtest/pyworkqueue.h (with props)
techdemo/team/ken.hunt/embeddedPythonTest/threadtest/threadtest.cpp (with props)
Modified:
techdemo/team/ken.hunt/embeddedPythonTest/CMakeLists.txt
techdemo/team/ken.hunt/embeddedPythonTest/bin/install_release.bat
techdemo/team/ken.hunt/embeddedPythonTest/source/Server.cpp
Modified: techdemo/team/ken.hunt/embeddedPythonTest/CMakeLists.txt
URL: https://origsvn.digium.com/svn-view/hydra/techdemo/team/ken.hunt/embeddedPythonTest/CMakeLists.txt?view=diff&rev=630&r1=629&r2=630
==============================================================================
--- techdemo/team/ken.hunt/embeddedPythonTest/CMakeLists.txt (original)
+++ techdemo/team/ken.hunt/embeddedPythonTest/CMakeLists.txt Thu May 20 14:31:30 2010
@@ -5,4 +5,5 @@
hydra_project(embedPythonTest 3.4 CXX CSharp)
add_subdirectory(slice)
-add_subdirectory(source)
+add_subdirectory(source)
+add_subdirectory(threadtest)
Modified: techdemo/team/ken.hunt/embeddedPythonTest/bin/install_release.bat
URL: https://origsvn.digium.com/svn-view/hydra/techdemo/team/ken.hunt/embeddedPythonTest/bin/install_release.bat?view=diff&rev=630&r1=629&r2=630
==============================================================================
--- techdemo/team/ken.hunt/embeddedPythonTest/bin/install_release.bat (original)
+++ techdemo/team/ken.hunt/embeddedPythonTest/bin/install_release.bat Thu May 20 14:31:30 2010
@@ -9,3 +9,5 @@
copy /Y /B ..\build\slice\Media\Release\MediaSinkIf_CXX.dll
copy /Y /B ..\build\slice\Media\Release\MediaTranslationIf_CXX.dll
+copy /Y /B ..\build\threadtest\Release\threadtest.exe
+
Modified: techdemo/team/ken.hunt/embeddedPythonTest/source/Server.cpp
URL: https://origsvn.digium.com/svn-view/hydra/techdemo/team/ken.hunt/embeddedPythonTest/source/Server.cpp?view=diff&rev=630&r1=629&r2=630
==============================================================================
--- techdemo/team/ken.hunt/embeddedPythonTest/source/Server.cpp (original)
+++ techdemo/team/ken.hunt/embeddedPythonTest/source/Server.cpp Thu May 20 14:31:30 2010
@@ -8,8 +8,6 @@
#include "RoutingServiceIf.h"
using namespace std;
-using namespace Hydra;
-
class LookupServiceImpl : public Hydra::Routing::LookupService
{
Added: techdemo/team/ken.hunt/embeddedPythonTest/threadtest/CMakeLists.txt
URL: https://origsvn.digium.com/svn-view/hydra/techdemo/team/ken.hunt/embeddedPythonTest/threadtest/CMakeLists.txt?view=auto&rev=630
==============================================================================
--- techdemo/team/ken.hunt/embeddedPythonTest/threadtest/CMakeLists.txt (added)
+++ techdemo/team/ken.hunt/embeddedPythonTest/threadtest/CMakeLists.txt Thu May 20 14:31:30 2010
@@ -1,0 +1,12 @@
+
+hydra_component_init(threadtest CXX)
+INCLUDE(findPythonInterp)
+INCLUDE(findPythonLibs)
+get_filename_component(PY_LOC ${PYTHON_LIBRARIES} PATH)
+LINK_DIRECTORIES(${PY_LOC})
+include_directories(${PYTHON_INCLUDE_DIRS})
+hydra_component_add_file(threadtest threadtest.cpp)
+hydra_component_add_file(threadtest pyworkqueue.cpp)
+hydra_component_add_boost_libraries(threadtest core)
+hydra_component_build_standalone(threadtest)
+hydra_component_install(threadtest)
Propchange: techdemo/team/ken.hunt/embeddedPythonTest/threadtest/CMakeLists.txt
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: techdemo/team/ken.hunt/embeddedPythonTest/threadtest/CMakeLists.txt
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: techdemo/team/ken.hunt/embeddedPythonTest/threadtest/CMakeLists.txt
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: techdemo/team/ken.hunt/embeddedPythonTest/threadtest/iworkqueue.h
URL: https://origsvn.digium.com/svn-view/hydra/techdemo/team/ken.hunt/embeddedPythonTest/threadtest/iworkqueue.h?view=auto&rev=630
==============================================================================
--- techdemo/team/ken.hunt/embeddedPythonTest/threadtest/iworkqueue.h (added)
+++ techdemo/team/ken.hunt/embeddedPythonTest/threadtest/iworkqueue.h Thu May 20 14:31:30 2010
@@ -1,0 +1,33 @@
+#pragma once
+#ifndef _IWORKQUEUE_H
+#define _IWORKQUEUE_H
+
+#include "boost/shared_ptr.hpp"
+
+namespace hydra
+{
+class IWorkQueue
+{
+public:
+
+ class IWork
+ {
+ public:
+ virtual void DoWork() = 0;
+ };
+
+ typedef boost::shared_ptr<IWork> IWorkPtr;
+
+ virtual void Enqueue(IWorkPtr w) = 0;
+ virtual void Terminate() = 0;
+ virtual void Join() = 0;
+
+protected:
+ IWorkQueue() {}; // Hide the constructor for interface
+};
+typedef IWorkQueue::IWorkPtr IWorkPtr;
+
+};
+
+#endif
+
Propchange: techdemo/team/ken.hunt/embeddedPythonTest/threadtest/iworkqueue.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: techdemo/team/ken.hunt/embeddedPythonTest/threadtest/iworkqueue.h
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: techdemo/team/ken.hunt/embeddedPythonTest/threadtest/iworkqueue.h
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: techdemo/team/ken.hunt/embeddedPythonTest/threadtest/pyworkqueue.cpp
URL: https://origsvn.digium.com/svn-view/hydra/techdemo/team/ken.hunt/embeddedPythonTest/threadtest/pyworkqueue.cpp?view=auto&rev=630
==============================================================================
--- techdemo/team/ken.hunt/embeddedPythonTest/threadtest/pyworkqueue.cpp (added)
+++ techdemo/team/ken.hunt/embeddedPythonTest/threadtest/pyworkqueue.cpp Thu May 20 14:31:30 2010
@@ -1,0 +1,242 @@
+/**
+ * A simple Work Queue implementation. On construction, starts an internal thread.
+ * Work can be enqueued via the thread-safe Enqueue method. All work must implement the IWork interface.
+ */
+#include <iostream>
+#include <boost/shared_ptr.hpp>
+#include <boost/bind.hpp>
+#include <Python.h>
+#include <pystate.h>
+
+#include "pyworkqueue.h"
+
+using namespace hydra;
+using namespace boost;
+
+namespace hydra
+{
+class PyWorkQueuePriv
+{
+public:
+ PyWorkQueuePriv(std::string id, bool paused)
+ : mQid(id),
+ mInitialized(false),
+ mPyInitialized(false),
+ mPaused(paused),
+ mFinished(false),
+ mThread(boost::bind(&PyWorkQueuePriv::Execute, this))
+ {
+ }
+
+ ~PyWorkQueuePriv()
+ {
+ // Clear my thread state
+ PyEval_AcquireLock();
+ PyThreadState_Swap(NULL);
+ PyThreadState_Clear(mMyThreadState);
+ PyThreadState_Delete(mMyThreadState);
+ PyEval_ReleaseLock();
+ }
+
+ IWorkPtr Dequeue();
+ IWorkPtr WaitAndDequeue();
+ void Execute();
+
+ PyThreadState *mMainThreadState;
+ PyThreadState * mMyThreadState;
+ std::string mQid;
+ bool mInitialized;
+ bool mPyInitialized;
+ bool mFinished;
+ bool mPaused;
+ std::list<IWorkPtr> mQueue;
+ boost::thread mThread;
+ boost::mutex mQueueMutex;
+ boost::condition mEmptyQueueCondition;
+ boost::mutex mPauseMutex;
+ boost::condition mPauseCondition;
+};
+}
+
+PyWorkQueue::PyWorkQueue(std::string qid, PyThreadState *mainThreadState, bool runByDefault) : mImpl(new PyWorkQueuePriv(qid, !runByDefault))
+{
+ mImpl->mInitialized = true;
+ mImpl->mMainThreadState = mainThreadState;
+}
+
+PyWorkQueue::~PyWorkQueue()
+{
+ Terminate();
+
+ // Wait for worker thread to shut down.
+ mImpl->mThread.join(); // If you don't do this, then the mImpl is trashed and Execute has bad "this" ptr on other thread.
+}
+
+bool PyWorkQueue::IsRunning()
+{
+ return (mImpl->mInitialized && !mImpl->mPaused && !mImpl->mFinished);
+}
+
+/**
+ * Pause the WorkQueue's thread.
+ */
+void PyWorkQueue::Pause()
+{
+ boost::mutex::scoped_lock lock(mImpl->mPauseMutex);
+ mImpl->mPaused = true;
+}
+
+
+/**
+ * Resume from a Paused state.
+ */
+void PyWorkQueue::Resume()
+{
+ boost::mutex::scoped_lock lock(mImpl->mPauseMutex);
+ mImpl->mPaused = false;
+ mImpl->mPauseCondition.notify_all();
+}
+
+/**
+ * Stops this thread from executing.
+ */
+void PyWorkQueue::Terminate()
+{
+ mImpl->mFinished = true;
+ mImpl->mPaused = false;
+ mImpl->mPauseCondition.notify_all(); // In case the thread was waiting on the PauseCondition.
+ mImpl->mEmptyQueueCondition.notify_all(); // In case the thread was waiting on an EmptyQueueCondition
+}
+
+/**
+ * A convenience method to determine if there is any pending work on the queue.
+ */
+bool PyWorkQueue::WorkPending()
+{
+ return !mImpl->mQueue.empty();
+}
+
+/**
+ * Allows other thread to join to this thread. The caller needs to
+ * call this object's Terminate method, or the join will block
+ * indefinitely.
+ */
+void PyWorkQueue::Join()
+{
+ mImpl->mThread.join();
+}
+
+/**
+ * Enqueue an item of work for processing on this queue's thread.
+ */
+void PyWorkQueue::Enqueue(IWorkPtr w)
+{
+ boost::mutex::scoped_lock lock(mImpl->mQueueMutex);
+ bool wasEmpty = mImpl->mQueue.empty();
+ mImpl->mQueue.push_back(w);
+ int size = mImpl->mQueue.size();
+ lock.unlock();
+
+ if (wasEmpty)
+ {
+ mImpl->mEmptyQueueCondition.notify_all();
+ }
+}
+
+/**
+ * This is a private no-op implementation of a work item. Returned from WaitAndDequeue
+ * if the program is Terminated while waiting on the EmptyQueueCondition.
+ */
+class NO_WORK_CLASS : public IWorkQueue::IWork
+{
+public:
+ NO_WORK_CLASS() {};
+ void DoWork() {} // Do nothing
+};
+static shared_ptr<IWorkQueue::IWork> NO_WORK_PTR(new NO_WORK_CLASS());
+
+/**
+ * This method returns the next work from the queue. If no work available,
+ * this method waits on the EmptyQueueCondition.
+ */
+IWorkPtr PyWorkQueuePriv::WaitAndDequeue()
+{
+ boost::mutex::scoped_lock lock(mQueueMutex);
+
+ int size = mQueue.size(); // debugging
+
+ while (mQueue.empty())
+ {
+ if (mFinished)
+ {
+ return NO_WORK_PTR;
+ }
+
+ mEmptyQueueCondition.wait(lock);
+ }
+
+ size = mQueue.size(); // debugging
+
+ shared_ptr<IWorkQueue::IWork> work = mQueue.front();
+ mQueue.pop_front();
+
+ return work;
+}
+
+/**
+ * This is the thread's event loop. The thread terminates when this method returns.
+ */
+void PyWorkQueuePriv::Execute()
+{
+ while (!mInitialized)
+ {
+ // The thread can start before the constructor has finished initializing the object.
+ // Can lead to strange behavior.
+ continue;
+ }
+
+ if (!mPyInitialized)
+ {
+ mPyInitialized = true;
+
+ // get the global lock
+ PyEval_AcquireLock();
+
+ // get a reference to the PyInterpreterState
+ PyInterpreterState * mainInterpreterState = mMainThreadState->interp;
+
+ // create a thread state object for this thread
+ mMyThreadState = PyThreadState_New(mainInterpreterState);
+
+ // free the lock
+ PyEval_ReleaseLock();
+ }
+
+ while (!mFinished)
+ {
+ { // scope the lock
+ boost::mutex::scoped_lock lock(mPauseMutex);
+ while(mPaused)
+ {
+ mPauseCondition.wait(lock);
+ }
+
+ if (mFinished) // In case Terminate was called while in PauseCondition
+ break;
+ }
+
+ shared_ptr<IWorkQueue::IWork> work = WaitAndDequeue();
+
+ // swap in my thread state
+ PyEval_AcquireLock();
+ PyThreadState_Swap(mMyThreadState);
+
+ work->DoWork();
+
+ // clear the thread state
+ PyThreadState_Swap(NULL);
+ PyEval_ReleaseLock();
+ }
+
+}
+
Propchange: techdemo/team/ken.hunt/embeddedPythonTest/threadtest/pyworkqueue.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: techdemo/team/ken.hunt/embeddedPythonTest/threadtest/pyworkqueue.cpp
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: techdemo/team/ken.hunt/embeddedPythonTest/threadtest/pyworkqueue.cpp
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: techdemo/team/ken.hunt/embeddedPythonTest/threadtest/pyworkqueue.h
URL: https://origsvn.digium.com/svn-view/hydra/techdemo/team/ken.hunt/embeddedPythonTest/threadtest/pyworkqueue.h?view=auto&rev=630
==============================================================================
--- techdemo/team/ken.hunt/embeddedPythonTest/threadtest/pyworkqueue.h (added)
+++ techdemo/team/ken.hunt/embeddedPythonTest/threadtest/pyworkqueue.h Thu May 20 14:31:30 2010
@@ -1,0 +1,40 @@
+#pragma once
+#ifndef _WORKQUEUE_H
+#define _WORKQUEUE_H
+
+#include <list>
+#include <boost/thread.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/shared_ptr.hpp>
+#include <Python.h>
+
+#include "iworkqueue.h"
+
+namespace hydra
+{
+class PyWorkQueuePriv;
+
+class PyWorkQueue : public IWorkQueue, boost::noncopyable
+{
+public:
+ PyWorkQueue(std::string id, PyThreadState *mainThreadState, bool runByDefault=false);
+ ~PyWorkQueue();
+
+ virtual void Enqueue(IWorkPtr w);
+ virtual void Terminate();
+ virtual void Join();
+
+ // This implementation adds the concept of Pausing to the generic IWorkQueue.
+ bool IsRunning();
+ bool WorkPending();
+ void Pause();
+ void Resume();
+
+private:
+ boost::shared_ptr<PyWorkQueuePriv> mImpl;
+};
+
+};
+
+#endif
+
Propchange: techdemo/team/ken.hunt/embeddedPythonTest/threadtest/pyworkqueue.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: techdemo/team/ken.hunt/embeddedPythonTest/threadtest/pyworkqueue.h
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: techdemo/team/ken.hunt/embeddedPythonTest/threadtest/pyworkqueue.h
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: techdemo/team/ken.hunt/embeddedPythonTest/threadtest/threadtest.cpp
URL: https://origsvn.digium.com/svn-view/hydra/techdemo/team/ken.hunt/embeddedPythonTest/threadtest/threadtest.cpp?view=auto&rev=630
==============================================================================
--- techdemo/team/ken.hunt/embeddedPythonTest/threadtest/threadtest.cpp (added)
+++ techdemo/team/ken.hunt/embeddedPythonTest/threadtest/threadtest.cpp Thu May 20 14:31:30 2010
@@ -1,0 +1,160 @@
+#include <iostream>
+#include <string>
+#include <boost/cast.hpp>
+#include <boost/shared_ptr.hpp>
+#include <stdio.h>
+#include "pyworkqueue.h"
+
+#ifndef __cplusplus
+#define __cplusplus 1
+#endif
+
+#include <Python.h>
+
+using namespace hydra;
+
+/**
+ * OS Portable sleep util function.
+ */
+void sleep(int secs)
+{
+ boost::posix_time::seconds workTime(secs);
+ boost::this_thread::sleep(workTime);
+}
+
+class TestWork : public hydra::IWorkQueue::IWork
+{
+public:
+ TestWork(std::string id, int val) : mTestVal(val), mId(id) {}
+ ~TestWork()
+ {
+ std::cout << "TestWork::~TestWork: Deleting " << mId << std::endl;
+ }
+
+ void DoWork()
+ {
+ std::cout << "Looking up " << mTestVal << std::endl;
+
+ PyObject *pName, *pModule;
+
+ // Make sure pythonScripts folder is in PYTHONPATH
+ pName = PyString_FromString("lookup");
+ pModule = PyImport_Import(pName);
+ Py_DECREF(pName);
+
+ if (pModule != 0)
+ {
+ PyObject *pFunc = PyObject_GetAttrString(pModule, "lookup");
+ if (pFunc != 0 && PyCallable_Check(pFunc))
+ {
+ PyObject *pArgs = PyTuple_New(1);
+ PyObject *pValue = PyInt_FromLong(mTestVal);
+ if (!pValue)
+ {
+ Py_DECREF(pArgs);
+ Py_DECREF(pFunc);
+ Py_DECREF(pModule);
+ std::cout << "NO VALUE FOUND. " << std::endl;
+ return ;
+ }
+ PyTuple_SetItem(pArgs, 0, pValue); // pValue ref given up here.
+
+ pValue = PyObject_CallObject(pFunc, pArgs);
+ Py_DECREF(pArgs);
+
+ if (pValue != 0)
+ {
+ std::cout << "Found: " << PyInt_AsLong(pValue) << std::endl;
+ Py_DECREF(pValue);
+ }
+ else
+ {
+ PyErr_Print();
+ }
+
+ Py_DECREF(pFunc);
+ Py_DECREF(pModule);
+ }
+ else if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ }
+ }
+ else
+ {
+ PyErr_Print();
+ }
+ }
+
+private:
+ int mTestVal;
+ std::string mId;
+};
+
+int main(int argc, char* argv[])
+{
+ // Init Python
+ Py_Initialize();
+
+ // init thread support.
+ PyEval_InitThreads();
+
+ PyThreadState * mainThreadState = NULL;
+ mainThreadState = PyThreadState_Get();
+ PyEval_ReleaseLock();
+
+ PyWorkQueue wqueue1("wq1", mainThreadState, true);
+ PyWorkQueue wqueue2("wq2", mainThreadState, true);
+
+ boost::shared_ptr<IWorkQueue::IWork> wq1_w1(new TestWork("WorkOnQueue1", 110));
+ boost::shared_ptr<IWorkQueue::IWork> wq1_w2(new TestWork("WorkOnQueue1", 120));
+ boost::shared_ptr<IWorkQueue::IWork> wq1_w3(new TestWork("WorkOnQueue1", 130));
+ boost::shared_ptr<IWorkQueue::IWork> wq1_w4(new TestWork("WorkOnQueue1", 140));
+ boost::shared_ptr<IWorkQueue::IWork> wq1_w5(new TestWork("WorkOnQueue1", 150));
+ boost::shared_ptr<IWorkQueue::IWork> wq1_w6(new TestWork("WorkOnQueue1", 160));
+ boost::shared_ptr<IWorkQueue::IWork> wq1_w7(new TestWork("WorkOnQueue1", 170));
+ boost::shared_ptr<IWorkQueue::IWork> wq1_w8(new TestWork("WorkOnQueue1", 180));
+
+ boost::shared_ptr<IWorkQueue::IWork> wq2_w1(new TestWork("WorkOnQueue2", 210));
+ boost::shared_ptr<IWorkQueue::IWork> wq2_w2(new TestWork("WorkOnQueue2", 220));
+ boost::shared_ptr<IWorkQueue::IWork> wq2_w3(new TestWork("WorkOnQueue2", 230));
+ boost::shared_ptr<IWorkQueue::IWork> wq2_w4(new TestWork("WorkOnQueue2", 240));
+ boost::shared_ptr<IWorkQueue::IWork> wq2_w5(new TestWork("WorkOnQueue2", 250));
+ boost::shared_ptr<IWorkQueue::IWork> wq2_w6(new TestWork("WorkOnQueue2", 260));
+ boost::shared_ptr<IWorkQueue::IWork> wq2_w7(new TestWork("WorkOnQueue2", 270));
+ boost::shared_ptr<IWorkQueue::IWork> wq2_w8(new TestWork("WorkOnQueue2", 280));
+
+ wqueue1.Enqueue(wq1_w1);
+ wqueue2.Enqueue(wq2_w1);
+
+ wqueue1.Enqueue(wq1_w2);
+ wqueue2.Enqueue(wq2_w2);
+
+ wqueue1.Enqueue(wq1_w3);
+ wqueue2.Enqueue(wq2_w3);
+
+ wqueue1.Enqueue(wq1_w4);
+ wqueue2.Enqueue(wq2_w4);
+
+ wqueue1.Enqueue(wq1_w5);
+ wqueue2.Enqueue(wq2_w5);
+
+ wqueue1.Enqueue(wq1_w6);
+ wqueue2.Enqueue(wq2_w6);
+
+ wqueue1.Enqueue(wq1_w7);
+ wqueue2.Enqueue(wq2_w7);
+
+ wqueue1.Enqueue(wq1_w8);
+ wqueue2.Enqueue(wq2_w8);
+
+ sleep(5);
+
+ wqueue1.Terminate();
+ wqueue2.Terminate();
+ wqueue1.Join();
+ wqueue2.Join();
+
+ PyEval_AcquireLock();
+ Py_Finalize();
+}
Propchange: techdemo/team/ken.hunt/embeddedPythonTest/threadtest/threadtest.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: techdemo/team/ken.hunt/embeddedPythonTest/threadtest/threadtest.cpp
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: techdemo/team/ken.hunt/embeddedPythonTest/threadtest/threadtest.cpp
------------------------------------------------------------------------------
svn:mime-type = text/plain
More information about the asterisk-scf-commits
mailing list