Reply to comment

Headers

I know that this is a very old thread. However, this was a great help. I just wish it was more easy to follow. I'm a beginner from the Windows side of the world. So put up this simple guide for those who are beginners like me. For Visual Studio users, here's a more complete example (But not the safest I think). Make sure you add the Boost Lib, and the Includes Folder.

Using Visual Studio 2010:

  1. Go to File -> New -> Project. Choose a name for you project.
  2. On the left side at the Installed Templates Choose Visual C++, then Win32. Then click on the Win32 Console Application. Click Next.
  3. The Win32 Console App Wizard will open. Click next on the Welcome Page.
  4. Choose Console Application as the Application Type.
  5. Choose Empty Project for Additional Options.
  6. Uncheck Precompiled Header, ATL and MFC.
  7. Click Finish.
  8. At the Solutions Explorer, right click on the project, and then Click Properties.
  9. In the Configuration Properties, go to VC++ Directories.
  10. In the Configuration Drop Down choose All Configurations.
  11. In the Include Directories, add the Root of your Boost.
  12. In the Library Directories, add the lib folder of your Boost. Then confirm the changes.
  13. Press Ok to Confirm.
  14. Right Click on the Project Again and Add Class.
  15. Choose the C++ Class File. And press Ok to Confirm.
  16. Name the Class CThreadedFib. The .h File and .cpp file will be populated as you type.
  17. Make sure you make its Access in to Public, and Virtual Destructor and Inline are Unchecked.
  18. Copy the code below to the corresponding auto generated files on your project.
  19. Right Click again on your project from the solutions explorer, and Add New Item.
  20. Choose C++ File (.cpp) and name it main.cpp.
  21. Copy from the main.cpp code listing below to the newly created file.
  22. Build.
  23. The program should try to get the Fib(60). It will sleep if the worker thread isn't done yet.

There is a part of the code from the main.cpp that you can uncomment which will allow the program to stop the worker thread before it completes its task. It then stops gracefully.

ThreadedFib.h - The Class Header file

#pragma once
 
#include <boost/bind.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/shared_ptr.hpp>
#include <vector>
 
#include "boost/date_time/posix_time/posix_time.hpp"
 
class CThreadedFib
{
public:
	// constructor
	CThreadedFib(void);
 
	// destructor
	~CThreadedFib(void);
 
	// Create the thread and start work
	void Go();
 
	// Stops the thread
	void stop();
 
	// returns that value of the vector at the nth element - element
	unsigned long get_FibonacciAt(int element);
 
	// returns the current vector size
	int get_VectorSize();
 
	// returns if the current worker is busy
	bool get_isBusy();
 
	// sets the maximum value to check
	void set_FibSteps(int fibSteps);
 
	boost::posix_time::time_duration CThreadedFib::get_Duration();
 
private:
	boost::posix_time::ptime m_TimeStart;
	boost::posix_time::ptime m_TimeStop;
 
 
	// is the worker busy? stores this variable.
	bool m_Busy;
 
	// private field for the maximum value to check
	int m_FibSteps;
 
	// true if a stop was requested, false otherwise
	volatile bool m_stoprequested;
 
	// thread pointer
	boost::shared_ptr<boost::thread> m_thread;
 
	// mutex - locks following variables to current thread
	boost::mutex m_mutex;
 
	// the vector which stores the fib sequence
	std::vector<unsigned long> m_fibonacci_values;
 
	// the basic fibonacci function - using unsigned long for max efficiency
	unsigned long fibonacci_number(unsigned long num);
 
	// Compute and save fibonacci numbers as fast as possible
	void do_work();
};

ThreadedFib.cpp - The Class Header file

#include "ThreadedFib.h"
 
#include <boost/bind.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/shared_ptr.hpp>
#include <vector>
 
// constructor implementation
CThreadedFib::CThreadedFib(void)
{
	this->m_Busy = false;
	this->m_FibSteps = 95;
	this->m_stoprequested = false;
}
 
// destructor implementation
CThreadedFib::~CThreadedFib(void)
{
	boost::mutex::scoped_lock l(this->m_mutex);
	if (this->m_Busy == true) 
	{
		this->stop();
	}
}
 
bool CThreadedFib::get_isBusy()
{
	return this->m_Busy;
}
 
// starts the worker thread.
void CThreadedFib::Go() 
{
	if (!this->m_Busy) 
	{
		this->m_TimeStart = boost::posix_time::second_clock::local_time();
		this->m_Busy = true;
		this->m_stoprequested = false;
		assert(!this->m_thread);
		this->m_thread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&CThreadedFib::do_work, this)));
	}
}
 
// returns the current size of the vector
int CThreadedFib::get_VectorSize() 
{
	boost::mutex::scoped_lock l(this->m_mutex);
	return this->m_fibonacci_values.size();
}
 
// stops the thread worker if it's running
void CThreadedFib::stop() // Note 1
{
	if (this->m_Busy == true) 
	{
		assert(this->m_thread);
		this->m_stoprequested = true;
		this->m_thread->join();
		this->m_Busy = false;
	}
}
 
// returns the current value of the 
unsigned long CThreadedFib::get_FibonacciAt(int element)
{
	boost::mutex::scoped_lock l(this->m_mutex); //Note 2
	return this->m_fibonacci_values.at(element);
}
 
unsigned long CThreadedFib::fibonacci_number(unsigned long num)
{
	switch(num)
	{
		case 0:
			return 0;
		case 1:
			return 1;
		default:
			return this->fibonacci_number(num-2) + this->fibonacci_number(num - 1);
	};
}  
 
// Compute and save fibonacci numbers as fast as possible
void CThreadedFib::do_work()
{
	int iteration = 0;
	while (!this->m_stoprequested &&  iteration < this->m_FibSteps)
	{
		int value = this->fibonacci_number(++iteration);
		boost::mutex::scoped_lock l(this->m_mutex);
		this->m_fibonacci_values.push_back(value);
	}
 
	boost::mutex::scoped_lock l(this->m_mutex);
	this->m_Busy = false;
	this->m_stoprequested = false;
	this->m_TimeStop = boost::posix_time::second_clock::local_time();	
}
 
void CThreadedFib::set_FibSteps(int fibSteps)
{
	boost::mutex::scoped_lock l(this->m_mutex);
	this->m_FibSteps = fibSteps;
}
 
boost::posix_time::time_duration CThreadedFib::get_Duration() 
{
	return this->m_TimeStop - this->m_TimeStart;
}

main.cpp - The Class Header file

#include <iostream>
#include <stdio.h>
#include <boost/algorithm/string.hpp>
#include <Windows.h>
 
#include "ThreadedFib.h"
 
#include "boost/date_time/posix_time/posix_time.hpp"
 
using namespace boost::posix_time;
using namespace std;
using namespace boost;
 
string printTime() 
{
	ptime now = second_clock::local_time();
	return to_simple_string(now);
}
 
int main() 
{
 
	// maximum fibonacci number to get
	int max = 60;
 
	// the current size of the vector element holds the fib sequence
	int size;
 
	// the value of the nth element of the vector
	unsigned long i;
 
	// creates the fib worker
	cout << printTime() << ": Creating the fib worker." << std::endl;
	CThreadedFib fib;
 
	// initiallizes the new max value (default to 10 - check constructor)
	fib.set_FibSteps(max);
 
	// Starts the fib worker
	cout << printTime() << ": Starting the fib worker." << std::endl;
	fib.Go();
 
	// to give the worker a jump start.
	cout << printTime() << ": Sleeping for 2 seconds." << std::endl;
	Sleep(2000);
 
	// Loops and checks if we have reached the max value to get the fib num.
	while (fib.get_VectorSize() <= max && fib.get_isBusy()) 
	{
		// make sure that the vector size > 0, else there'd be no content
		if (fib.get_VectorSize() > 0)
		{
			// This part you can turn on if you want to stop before 
			// the completion of the entire loop to the fib of max.
			//if (fib.get_VectorSize() > 35) {
			//	fib.stop();
			//}
 
			// get the size of the vector
			size = fib.get_VectorSize();
 
			// set i as the last value calculated
			i = fib.get_FibonacciAt(size-1);
 
			// show resluts
			cout << printTime() << ": The value of fib @ " << size << " is " << i << std::endl;
 
			// sleep again.
			cout << printTime() << ": Sleeping for another 2 seconds." << std::endl;
			Sleep(2000);
		}
	}
 
	cout << printTime() << ": Stopping fib worker." << std::endl;
	fib.stop();
 
	cout << printTime() << ": Sleeping for 2 seconds to stop." << std::endl;
	Sleep(2000);
 
	cout << printTime() << ": Geting the number of iterations." << std::endl;
	size = fib.get_VectorSize();
	i = fib.get_FibonacciAt(size-1);
	cout << printTime() << ": The value of fib(" << size << ") is " << i << std::endl;
	cout << printTime() << ": Real solving time duration was " << to_simple_string(fib.get_Duration()) << std::endl;
 
	cout << "Press any key to continue!" << std::endl;
	getchar();
 
	return 0;
}

Reply

The content of this field is kept private and will not be shown publicly.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <blockquote>
  • Lines and paragraphs break automatically.
  • You may post PHP code. You should include <?php ?> tags.
  • Web page addresses and e-mail addresses turn into links automatically.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <cpp>. The supported tag styles are: <foo>, [foo]. PHP source code can also be enclosed in <?php ... ?> or <% ... %>.
  • Images can be added to this post.

More information about formatting options

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
5 + 2 =
Solve this simple math problem and enter the result. E.g. for 1+3, enter 4.