Quantitative Analysis
Parallel Processing
Numerical Analysis
C++ Multithreading
Python for Excel
Python Utilities
Services
Author

I. Installation.
II. Threading primitives.
III. NonBlockingQueue.
IV. ThreadPool.
V. ThreadMaster.
1. ThreadMaster prototypes.
2. Acceptance test for the ThreadMaster.
VI. OTS Scheduler.
VII. Bibliography
Downloads. Index. Contents.

Acceptance test for the ThreadMaster.


e are going to export ThreadMaster to Python and supply classes for Job and Condition parameters. Consider the following boost::python declarations.

Lines 3-7. TestJob is a C++ class with void operator()() that supplies idle stage calculation and occasionally throws an exception.

Lines 8-12. ExitCondition is exactly that. It has bool operator()() that returns "true" several times and afterwards returns "false".

Lines 13-18. These declarations export boost::function0<void> and boost::function0<bool> to Python under names "Job" and "Condition".

Line 19. The "makeJob" is a function that transforms a python object into a C++ boost::function0<void> object.

Lines 20-24. These declare ThreadMaster as a Python class and export its interface.

1\ void pythonThreadMaster()

2\ {

3\ class_<TestJob>("TestJob",init<std::string,int,int,int,double>())

4\ .def("__call__",&TestJob::operator())

5\ .def("job",&TestJob::job)

6\ .def("__str__",&TestJob::toString)

7\ ;

8\ class_<ExitCondition>("ExitCondition",init<int>())

9\ .def("__call__",&ExitCondition::operator())

10\ .def("condition",&ExitCondition::condition)

11\ .def("__str__",&ExitCondition::toString)

12\ ;

13\ class_<boost::function0<void> >("Job")

14\ .def("__call__",&boost::function0<void>::operator())

15\ ;

16\ class_<boost::function0<bool> >("Condition")

17\ .def("__call__",&boost::function0<bool>::operator())

18\ ;

19\ def("makeJob",&makeJob);

20\ class_<ThreadMaster,boost::noncopyable>("ThreadMaster",init<int>())

21\ .def("add",&ThreadMaster::add)

22\ .def("run",&ThreadMaster::run)

23\ .def("isRunning",&ThreadMaster::isRunning)

24\ ;

25\ }

The code for TestJob and ExitCondition consist of functional part that we are about to consider and a standard boost::shared_ptr-based copy-by-value semantics (also called "Bridge Pattern").

The lines 30-50 contain the functional part of the Job. We put some debugging information to std::cout in lines 33-36, 41, 47-49. In the line 37-43 we throw an exception with probability given by the parameter theProb. It eventually comes from the user via constructor arguments. If the exception is not thrown then the lines 44-45 do some idle cycling an waiting. Then the code returns.

We supply the parameter "theName" to include it in the std::cout outputs. This way we can have distinct test stages based on the same code.

The line 77 is included because Python will not convert TestJob into boost::function0<void> automatically the way C++ would.

1\ class TestJob

2\ {

3\ private:

4\ class Impl : boost::noncopyable

5\ {

6\ public:

7\ typedef ots::config::ExclusiveMutex::type Mutex;

8\ typedef ots::config::WriterLock<Mutex>::type Lock;

9\ private:

10\ Mutex theMutex;

11\ std::string theName;

12\ int theStartingDelay;

13\ int thePeriodicDelay;

14\ int theSteps;

15\ double theProb;

16\ public:

17\ Impl(

18\ const std::string& name,

19\ int startingDelay,

20\ int periodicDelay,

21\ int steps,

22\ double prob

23\ );

30\ void operator()()

31\ {

32\ ots::threading::Sleep s(theStartingDelay); //give time to Python to print the next prompt

33\ {

34\ Lock guard(theMutex);

35\ std::cout<<"Starting "<<theName<<std::endl;

36\ }

37\ double u=ots::random::uniform();

38\ if( 0<u && u<theProb )

39\ {

40\ Lock guard(theMutex);

41\ std::cout<<"Job "<<theName<<" throwing boost::thread_resource_error"<<std::endl;

42\ throw boost::thread_resource_error();

43\ }

44\ for( int i=0; i<theSteps; ++i )

45\ ots::threading::Sleep s(thePeriodicDelay);

46\ {

47\ Lock guard(theMutex);

48\ std::cout<<"Finishing "<<theName<<std::endl;

49\ }

50\ }

...

61\ };

62\ boost::shared_ptr<Impl> theImpl;

63\ public:

64\ TestJob(

65\ const std::string& name,

66\ int startingDelay,

67\ int periodicDelay,

68\ int steps,

69\ double prob

70\ );

76\ void operator()() { (*theImpl)(); }

77\ boost::function0<void> job() const { return *this; }

...

79\ };

The ExitCondition is also Bridge Pattern based but has much simpler functional code.

1\ class ExitCondition

2\ {

3\ private:

4\ class Impl : boost::noncopyable

5\ {

6\ private:

7\ int theTimes;

8\ public:

9\ explicit Impl( int times )

10\ : theTimes(times)

11\ {}

12\ bool operator()() { return --theTimes>0; }

13\ std::string toString() const { return "ExitCondition("+boost::lexical_cast<std::string>(theTimes)+")"; }

14\ };

15\ boost::shared_ptr<Impl> theImpl;

16\ public:

17\ explicit ExitCondition( int times )

18\ : theImpl(new Impl(times))

19\ {}

20\ ExitCondition( const ExitCondition& e ) : theImpl(e.theImpl) {}

21\ ExitCondition& operator=( const ExitCondition& e ) { theImpl=e.theImpl; return *this; }

22\ bool operator()() { return (*theImpl)(); }

23\ boost::function0<bool> condition() const { return *this; }

24\ std::string toString() const { return theImpl->toString(); }

25\ };

The line 12 is the functional code. The "theTimes" parameter is set in the constructor, lines 17,9. At every call to bool operator()() this parameter is decreased. While theTimes is positive the ExitCondition returns "true". Otherwise it returns "false".

We place the following Python code into a file 'test.py':

1\ import test

2\ tm=test.ThreadMaster(4)

3\ tj1=test.TestJob("job1",100000,10000,100,0.1)

4\ tj2=test.TestJob("job2",100000,10000,100,0.1)

5\ tj3=test.TestJob("job3",100000,10000,100,0.1)

6\ tc=test.ExitCondition(6)

7\ tm.add(tj1.job(),tc.condition())

8\ tm.add(tj2.job(),tc.condition())

9\ tm.add(tj3.job(),tc.condition())

and activate the C++ code with the following Python session. We assume that the current directory is ThreadMasterTest/ThreadMasterTest_msvc_ide/release of the ots installation.

In [1]: execfile('../../test.py')

In [2]: tm.run()

In [3]: Starting job1

Starting job1

Starting job1

Starting job1

Finishing job1

Finishing job1

Finishing job1

Finishing job1

Starting job2

Starting job2

Starting job2

Starting job2

Job job2 throwing boost::thread_resource_error

Starting job2

Finishing job2

Finishing job2

Finishing job2

Finishing job2

Starting job3

Starting job3

Starting job3

Starting job3

Finishing job3

Finishing job3

Finishing job3

Finishing job3

Starting job1

Starting job1

Starting job1

Starting job1

Finishing job1

Finishing job1

Finishing job1

Finishing job1

Starting job2

Starting job2

Starting job2

Starting job2

Finishing job2

Finishing job2

Finishing job2

Finishing job2

Starting job3

Starting job3

Starting job3

Starting job3

Job job3 throwing boost::thread_resource_error

Job job3 throwing boost::thread_resource_error

Starting job3

Starting job3

Finishing job3

Finishing job3

Finishing job3

Finishing job3





Downloads. Index. Contents.


















Copyright 2007