Commit dc1c71de authored by Thomas Feuvrier's avatar Thomas Feuvrier

ENH: ADD OpenThreads library in OTB/Utilities directory (add two testing)

OTB search if the OpenThreads library exist on the platform. If NO, we compile the OpenThreads library
parent 390d0dfb
......@@ -127,6 +127,26 @@ IF(OTB_COMPILE_JPEG2000)
ENDIF(NOT BUILD_SHARED_LIBS)
ENDIF(OTB_COMPILE_JPEG2000)
#-----------------------------------------------------------------------------
# Option for OpenThreads (necessary because used by the new version of OSSIM library
# Find OpenThread library
IF(EXISTS "${CMAKE_ROOT}/Modules/FindOpenThreads.cmake")
FIND_PACKAGE(OpenThreads)
ELSE(EXISTS "${CMAKE_ROOT}/Modules/FindOpenThreads.cmake")
INCLUDE(${OTB_SOURCE_DIR}/FindOpenThreads.cmake)
ENDIF(EXISTS "${CMAKE_ROOT}/Modules/FindOpenThreads.cmake")
SET(OTB_USE_EXTERNAL_OPENTHREADS 1)
IF(OPENTHREADS_FOUND)
INCLUDE_DIRECTORIES(${OPENTHREADS_INCLUDE_DIR})
LINK_DIRECTORIES( ${OPENTHREADS_LIBRARY} )
ELSE(OPENTHREADS_FOUND)
ADD_DEFINITIONS(-DOTB_USE_INTERNAL_OPENTHREADS)
SET(OTB_USE_EXTERNAL_OPENTHREADS 0)
SET(OPENTHREADS_INCLUDE_DIR "${OTB_SOURCE_DIR}/Utilities/otbopenthreads/OpenThreads/include")
SET(OPENTHREADS_LIBRARY "OpenThreads" )
INCLUDE_DIRECTORIES(${OPENTHREADS_INCLUDE_DIR})
ENDIF(OPENTHREADS_FOUND)
#-----------------------------------------------------------------------------
......
......@@ -334,6 +334,19 @@ ADD_TEST(utOpenJpegDecoder ${UTILITIES_TESTS}
ENDIF(OTB_COMPILE_JPEG2000)
# ------- lib OpenThreads ------------------------------
IF(NOT OTB_USE_EXTERNAL_OPENTHREADS)
ADD_TEST(utOpenthreadsSimpleThreader ${UTILITIES_TESTS}
openthreadsSimpleThreader
2 # [NUM_ELTS]
1 # [NUM_THREADS]
)
ADD_TEST(utOpenthreadsWorkCrew ${UTILITIES_TESTS}
openthreadsWorkCrew
1 # [NUM_THREADS]
)
ENDIF(NOT OTB_USE_EXTERNAL_OPENTHREADS)
# ------- SIFT -------------------------------------
ADD_TEST(ut2DSiftImageSquareSyntheticRotate10 ${UTILITIES_TESTS}
itk2DScaleInvariantFeatureImageFilterTest
......@@ -422,6 +435,16 @@ IF(OTB_COMPILE_JPEG2000)
SET(UtilitiesTests_SRCS ${UtilitiesTests_SRCS} openJpegEncoder.cxx openJpegDecoder.cxx)
ENDIF(OTB_COMPILE_JPEG2000)
IF(NOT OTB_USE_EXTERNAL_OPENTHREADS)
SET(UtilitiesTests_SRCS ${UtilitiesTests_SRCS}
openthreadsThreadObserver.cpp
openthreadsThreadReporter.cpp
openthreadsWorkCrew.cpp
openthreadsSimpleThreader.cpp )
ENDIF(NOT OTB_USE_EXTERNAL_OPENTHREADS)
INCLUDE_DIRECTORIES("${OTBTesting_BINARY_DIR}")
INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}")
......@@ -438,6 +461,10 @@ IF(OTB_COMPILE_JPEG2000)
TARGET_LINK_LIBRARIES(otbUtilitiesTests otbopenjpeg)
ENDIF(OTB_COMPILE_JPEG2000)
IF(NOT OTB_USE_EXTERNAL_OPENTHREADS)
TARGET_LINK_LIBRARIES(otbUtilitiesTests OpenThreads)
ENDIF(NOT OTB_USE_EXTERNAL_OPENTHREADS)
IF(UNIX)
TARGET_LINK_LIBRARIES (otbUtilitiesTests m)
ENDIF(UNIX)
......@@ -487,5 +514,4 @@ ENDIF(UNIX)
# TARGET_LINK_LIBRARIES (otb6SMainWithCallFunction m)
# ENDIF(UNIX)
ENDIF( NOT OTB_DISABLE_CXX_TESTING AND BUILD_TESTING )
//
// OpenThread library, Copyright (C) 2002 - 2003 The Open Thread Group
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// 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 GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
#include <sys/types.h>
#include <cassert>
#include <cstdio>
#include <iostream>
#include <vector>
#include <OpenThreads/Thread>
#include <OpenThreads/Mutex>
#include <OpenThreads/Barrier>
#include "openthreadsThreadObserver.h"
#include "openthreadsThreadReporter.h"
#ifdef _WIN32
#include <process.h>
#define getpid() _getpid()
#else
#include <unistd.h>
#endif
OpenThreads::Barrier bar;
int GLOBAL_NUM_THREADS;
//-----------------------------------------------------------------------------
// Custom Thread Observer (w/finished count)
//
class MyThreadObserver : public ThreadObserver {
public:
MyThreadObserver() : ThreadObserver(), _finishedCount(0) {};
virtual ~MyThreadObserver() {};
void threadFinished(const int threadId) {
ThreadObserver::threadFinished(threadId);
++_finishedCount;
}
int getFinishedCount() {return _finishedCount;};
private:
volatile int _finishedCount;
};
// check the working of OpenThreads::Thread::CurrentThread()
static OpenThreads::Thread* CurrentChecker(){
return OpenThreads::Thread::CurrentThread();
};
//-----------------------------------------------------------------------------
// Custom thread class - with reporting
//
class MyThread : public OpenThreads::Thread, public ThreadReporter {
public:
MyThread(int *dataPtr, int numElts) : OpenThreads::Thread(),
ThreadReporter(),
_dataPtr(dataPtr), _numElts(numElts), _quitflag(false) {};
virtual ~MyThread() {};
virtual void run() {
if( CurrentChecker()!=this)
notifyObserversMessage(getThreadId(), "Thread::CurrentThread is NOT working");
else
notifyObserversMessage(getThreadId(), "Thread::CurrentThread is working");
bar.block(GLOBAL_NUM_THREADS); // Sync the threads.
char tmp[80];
sprintf(tmp, "StackSize: %d\n", static_cast<int>(getStackSize()));
notifyObserversStarted(getThreadId());
notifyObserversMessage(getThreadId(), "This is a thread message.");
notifyObserversMessage(getThreadId(), tmp);
register int i;
for (i=0; i<_numElts; ++i) {
_dataPtr[i] = getThreadId();
}
notifyObserversMessage(getThreadId(), "Finished my work");
bar.block(GLOBAL_NUM_THREADS); // Sync the threads.
//---------------------------------------------------------------------
// Now that we've done our work, wait for a sign that we should quit.
//
while (true) {
_quitmutex.lock();
if(_quitflag == true) break;
_quitmutex.unlock();
OpenThreads::Thread::YieldCurrentThread();
}
notifyObserversFinished(getThreadId());
}
void quit() {
_quitmutex.lock();
_quitflag = true;
_quitmutex.unlock();
}
private:
int *_dataPtr;
int _numElts;
volatile bool _quitflag;
OpenThreads::Mutex _quitmutex;
};
int openthreadsSimpleThreader(int argc, char *argv []) {
if(argc != 3) {
std::cout << "Usage: simpleThreader [NUM_ELTS] [NUM_THREADS] "
<< std::endl;
return 0;
};
std::cout << "Root Thread ID: " << getpid() << std::endl;
int NUM_ELTS = atoi(argv[1]);
int NUM_THREADS = atoi(argv[2]);
GLOBAL_NUM_THREADS = NUM_THREADS + 1;
MyThreadObserver observer;
register int i;
int *dataArray = new int[NUM_ELTS];
std::vector<MyThread *> threads;
for(i=0; i<NUM_ELTS; ++i) {
dataArray[i] = -1;
}
OpenThreads::Thread::SetConcurrency(NUM_THREADS);
OpenThreads::Thread::Init();
for(i=0; i<NUM_THREADS; ++i) {
int status;
MyThread *thread = new MyThread(dataArray + (i*(NUM_ELTS/NUM_THREADS)),
NUM_ELTS/NUM_THREADS);
threads.push_back(thread);
thread->addObserver(&observer);
thread->setStackSize(1024*256);
status = thread->start();
assert(status == 0);
}
bar.block(GLOBAL_NUM_THREADS); // Block 'till ready
bar.block(GLOBAL_NUM_THREADS); // Block 'till finished
// char val;
// std::cout << "Press any key + return to quit." << std::endl;
// std::cin >> val;
// Notify the threads to quit, wait for this to happen.
for(i=0;i<static_cast<int>(threads.size());++i) {
MyThread *thread = threads[i];
thread->quit();
}
while(observer.getFinishedCount() != NUM_THREADS) {
// Spin our wheels.
}
std::cout << "Data Array: " << std::endl;
for(i=0; i < NUM_THREADS; ++i) {
register int j;
for (j=0; j<NUM_ELTS/NUM_THREADS; ++j) {
std::cout << dataArray[(i*NUM_ELTS/NUM_THREADS)+j] << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
// Delete all the threads.
for(i=0;i<static_cast<int>(threads.size());++i) {
MyThread *thread = threads[i];
delete thread;
}
threads.clear();
delete [] dataArray;
return EXIT_SUCCESS;
}
//
// OpenThread library, Copyright (C) 2002 - 2003 The Open Thread Group
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// 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 GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
#include <cstdio>
#include "openthreadsThreadObserver.h"
void ThreadObserver::threadStarted(const int threadId) {
printf("Thread %d started.\n", threadId);
}
void ThreadObserver::threadFinished(const int threadId) {
printf("Thread %d finished.\n", threadId);
}
void ThreadObserver::threadMessage(const int threadId, const char *message) {
printf("Thread Message (%d) : %s\n", threadId, message);
}
void ThreadObserver::threadError(const int threadId,
const char *errorMessage) {
printf("Thread Message (%d) : %s\n", threadId, errorMessage);
}
//
// OpenThread library, Copyright (C) 2002 - 2003 The Open Thread Group
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// 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 GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
//
// ThreadObserver.h - provide a basic thread observer class
// ~~~~~~~~~~~~~~~~
//
#ifndef _THREADOBSERVER_H_
#define _THREADOBSERVER_H_
class ThreadObserver {
public:
ThreadObserver() {};
virtual ~ThreadObserver() {};
virtual void threadStarted (const int threadId);
virtual void threadFinished(const int threadId);
virtual void threadMessage(const int threadId, const char *message);
virtual void threadError(const int threadId, const char *errorMessage);
};
#endif
//
// OpenThread library, Copyright (C) 2002 - 2003 The Open Thread Group
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// 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 GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
//
// ThreadReporter - Basic Thread Reporter class.
// ~~~~~~~~~~~~~~~
//
#include "openthreadsThreadReporter.h"
//-----------------------------------------------------------------------------
//
// Description: Constructor
//
// Use: public
//
ThreadReporter::ThreadReporter() {
_observers.clear();
}
//-----------------------------------------------------------------------------
//
// Description: Destructor
//
// Use: public
//
ThreadReporter::~ThreadReporter() {
_observers.clear();
}
//-----------------------------------------------------------------------------
//
// Description: Add an observer to the list
//
// Use: public
//
void ThreadReporter::addObserver(ThreadObserver *observer) {
_observers.push_back(observer);
}
//-----------------------------------------------------------------------------
//
// Description: Remove an observer from the list
//
// Use: public
//
void ThreadReporter::removeObserver(ThreadObserver *observer) {
std::list<ThreadObserver *>::iterator iter;
for(iter=_observers.begin(); iter != _observers.end(); ++iter) {
if(*iter == observer) {
_observers.erase(iter);
return;
}
}
}
//-----------------------------------------------------------------------------
//
// Description: Notify the observers the thread has started
//
// Use: protected
//
void ThreadReporter::notifyObserversStarted(const int threadId) {
std::list<ThreadObserver *>::iterator iter;
for(iter=_observers.begin(); iter != _observers.end(); ++iter) {
ThreadObserver *observer = static_cast<ThreadObserver *>(*iter);
observer->threadStarted(threadId);
}
}
//-----------------------------------------------------------------------------
//
// Description: Notify the observers the thread has finished
//
// Use: protected
//
void ThreadReporter::notifyObserversFinished(const int threadId) {
std::list<ThreadObserver *>::iterator iter;
for(iter=_observers.begin(); iter != _observers.end(); ++iter) {
ThreadObserver *observer = static_cast<ThreadObserver *>(*iter);
observer->threadFinished(threadId);
}
}
//-----------------------------------------------------------------------------
//
// Description: Notify the observers of a thread message
//
// Use: protected
//
void ThreadReporter::notifyObserversMessage(const int threadId,
const char *message) {
std::list<ThreadObserver *>::iterator iter;
for(iter=_observers.begin(); iter != _observers.end(); ++iter) {
ThreadObserver *observer = static_cast<ThreadObserver *>(*iter);
observer->threadMessage(threadId, message);
}
}
//-----------------------------------------------------------------------------
//
// Description: Notify the observers of a thread error
//
// Use: protected
//
void ThreadReporter::notifyObserversError(const int threadId,
const char *errorMessage) {
std::list<ThreadObserver *>::iterator iter;
for(iter=_observers.begin(); iter != _observers.end(); ++iter) {
ThreadObserver *observer = static_cast<ThreadObserver *>(*iter);
observer->threadError(threadId, errorMessage);
}
}
//
// OpenThread library, Copyright (C) 2002 - 2003 The Open Thread Group
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// 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 GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
//
// ThreadReporter - Basic thread reporter class.
// ~~~~~~~~~~~~~~~
//
#ifndef _THREADREPORTER_H_
#define _THREADREPORTER_H_
#include <list>
#include "openthreadsThreadObserver.h"
class ThreadReporter {
public:
ThreadReporter();
virtual ~ThreadReporter();
void addObserver(ThreadObserver *observer);
void removeObserver(ThreadObserver *observer);
protected:
void notifyObserversStarted(const int threadId);
void notifyObserversFinished(const int threadId);
void notifyObserversMessage(const int threadId, const char *message);
void notifyObserversError(const int threadId, const char *errorMessage);
private:
std::list<ThreadObserver *> _observers;
};
#endif
This diff is collapsed.
......@@ -44,5 +44,10 @@ REGISTER_TEST(itk2DScaleInvariantFeatureImageFilterTest);
REGISTER_TEST(openJpegEncoder);
REGISTER_TEST(openJpegDecoder);
#endif
// register OPENTHREADS testing
#ifdef OTB_USE_INTERNAL_OPENTHREADS
REGISTER_TEST(openthreadsSimpleThreader);
REGISTER_TEST(openthreadsWorkCrew);
#endif
}
......@@ -5,8 +5,13 @@ IF(NOT OTB_USE_EXTERNAL_ITK)
SUBDIRS(ITK)
ENDIF(NOT OTB_USE_EXTERNAL_ITK)
IF(NOT OTB_USE_EXTERNAL_OPENTHREADS)
SUBDIRS( otbopenthreads )
ENDIF(NOT OTB_USE_EXTERNAL_OPENTHREADS)
IF(OTB_COMPILE_JPEG2000)
SUBDIRS( otbopenjpeg)
SUBDIRS( otbopenjpeg )
ENDIF(OTB_COMPILE_JPEG2000)
IF(OTB_USE_VISU_GUI)
......
SUBDIRS(OpenThreads)
#INCLUDE_DIRECTORIES("${OTB_SOURCE_DIR}/Utilities/otbopenthreads/OpenThreads/include")
#INCLUDE_DIRECTORIES("${OTB_SOURCE_DIR}/Utilities/otbopenthreads/OpenThreads/include/OpenThreads")
The Open Thread Group consists of:
Sean Spicer......Original project author (posix threads) and maintainer.
Jack Lees........Friendly neighborhood API tester/contributer/developer
e.g. (Jack-of-all-trades)
Don Burns........Master of multi-threaded windowing and scene-graphs
Robert Osfield...The Open Scene Graph Yoda
Boris Bralo......Developed the Win32 implementation
The numerous developers who contribute on a daily basis to the design,
testing, and general discussion surrounding OpenThreads.
\ No newline at end of file
IF(WIN32)
CMAKE_MINIMUM_REQUIRED(VERSION 2.4.6 FATAL_ERROR)
ELSE(WIN32)
IF(APPLE)
CMAKE_MINIMUM_REQUIRED(VERSION 2.4.6 FATAL_ERROR)
ELSE(APPLE)
CMAKE_MINIMUM_REQUIRED(VERSION 2.4.0 FATAL_ERROR)
ENDIF(APPLE)
ENDIF(WIN32)
PROJECT(OpenThreads)
# We have some custom .cmake scripts not in the official distribution.
# Maybe this can be used override existing behavior if needed?
SET(CMAKE_MODULE_PATH "${OpenThreads_SOURCE_DIR}/CMakeModules;${CMAKE_MODULE_PATH}")