views:

1160

answers:

3

I'm developing a C++ program which has a "scan" method which will trigger a relatively long running scanning procedure. When the procedure is completed, the scan method will notify observers of results using the observer pattern.

I would like to create a separate thread for each scan. This way I can run multiple scans simultaneously. When each scanning process completes, I would like the scan method to notify the listeners.

According the boost thread library, it looks like I can maybe do something like this:

#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/bind.hpp>
#include <iostream>

boost::mutex io_mutex;

void scan(int scan_target, vector<Listener> listeners)  
{
  //...run scan 
  {
    boost::mutex::scoped_lock  
      lock(io_mutex);
    std::cout << "finished scan" << endl;
    // notify listeners by iterating through the vector
    // and calling "notify()

  }
}

int main(int argc, char* argv[])
{

  vector<Listener> listeners
  // create 
  boost::thread thrd1(
    boost::bind(&scan, 1, listeners));
  boost::thread thrd2(
    boost::bind(&scan, 2, listeners));
  //thrd1.join();
  //thrd2.join();
  return 0;
}

Does this look roughly correct? Do I need to mutex the call to listenrs? Is it ok to get rid of the joins?

A: 

I don't know the boost stuff, but conceptually it looks right. You have Observers that want to be notified of state changes. When a "qualifying event" happens, you have to run through a list (or vector, something like that) of Observers to notify. You also want to make sure somehow that concurrent notifications don't cause you trouble,

(Here's the Wikipedia article on the pattern.)

Charlie Martin
+1  A: 

Whether you need a lock or not depends on what you do with the notification. I think it would be more apt if you put the lock in notify function of only those listeners where you need a single threaded access.

Canopus
A: 

Your Listener::Notify() is being called from multiple threads, so unless Notify() has no side effects, you'll have to do one of the three:

  1. External lock (your example): acquiring a mutex before calling Listener::Notify()
  2. Internal lock: Listener::Notify() will acquire a lock internally
  3. Lock free: search for "lock free algorithm" in google

There are pros/cons for each option...

For what (i think) you need, option 1 will be good.

And, you'll have to keep the join statements otherwise your main() may exit before your threads can finish their job. Also consider using boost::thread_pool and joint_all.

Shing Yip