Sunday, October 20, 2013

A lesson in philosophy

It has been a while since there has been any forward progress made, mostly due to class eating up all of my time.  In order to not feel like the time has been completely wasted, I thought I'd make a post about a recent assignment I completed.

The assignment was to implement a solution to the famous dining philosopher's problem.  The problem generally requires students to use various tools such as semaphores and threads that, historically, have not been available in a simple cross platform way unless certain specialized libraries have been added.  Enter the C++11 standard, and you have the opportunity to finally write a cross platform solution with nothing but the STL.

The dining philosophers problem turns out to be one of the problems where it is beneficial to think of each thread as a class - after all, each thread represents a philosopher.  This solution called for a classic runnable class model which I implemented entirely in a header file out of a combination of laziness and ease of use (the latter reason is debatable).

The runnable class
A few points about the runnable class: first - visual studio hasn't yet implemented the delete operator so we still have to work to make runnable noncopyable the old way.  I expect this will change in the near future, so the preprocessor guards will come out eventually.  Everything else about this class is fairly straightforward - implementors are encouraged to use the m_stop variable or the stopped method inside their loops in order to respect the stop command, and I'm not sure if more can (or even should) be done on this front, though I am wary of relying on the people using the class to ensure most of the methods the base class itself defines are useful.

The magic of the solution occurs in the philosopher class.  C++11 provides a lock function that guarantees it is deadlock free.  A simple solution (modified Dijkstra's solution) is then presented using this mechanism for philosophers to request their chopsticks.

A simplified view of the philosopher class

C++11 provides a couple of interesting locking mechanics for a mutex, but the appropriate mechanism for a philosopher is a unique lock, since only one philosopher may hold a chopstick at any given time and the lock must hold even after the method that locks the resource (get_resource) has completed. The second argument to the unique_lock constructor tells it not to immediately grab the lock, since that will be done in the thread's run loop.

And that is really all there is to it.  Unfortunately, the current solution does nothing to address possible thread starvation.  In order to truly do that, a conductor would be needed (or in this case, a waiter).  The solution to that problem, however, will have to wait for another day.  Until then, you can click here to view the git repo for this project.

No comments:

Post a Comment