Boost logo

Boost :

Subject: Re: [boost] [thread] Moving a `recursive_lock`
From: Daniel Trebbien (dtrebbien_at_[hidden])
Date: 2010-02-15 19:34:16


Andrey and Seth, thank you both for your responses.

After thinking about this more, I probably do not want to transfer the
lock. `pthread_mutex_unlock` failing if the calling thread does not
own the mutex makes sense to me now, and I am very glad, Andrey, that
you linked me to the pthreads reference. Looking at the Windows
equivalent, `ReleaseMutex`, the Microsoft documentation also says that
the function fails if the calling thread does not own the mutex.

The project that I am working on is a cross-platform template library
for spawning child processes
(http://code.google.com/p/libnstdcxx/source/browse/branches/experimental/nstd/process.hpp).
Incidentally, yes, I am aware of a number of other libraries that
provide similar functionality (libexecstream, pstreams, APL, dlib,
pexl, pclasses, Platinum, STLplus, and the Boost Process proposal),
but I have found aspects of these that I do not like, including lack
of wide character support, no Windows implementation, or an interface
that encourages non-portable programming.

The structure of the template that I am working on, which I am calling
`basic_process`, is header-only to support an arbitrary allocator.
There are platform data classes which contain platform-specific data
that is necessary to create child processes (handles, process
information structures, etc.), the cross-platform `basic_process`
definition, and a platform implementation header that fills in the
details of the `basic_process` member functions.

For the Windows port, which I am working on first, the platform data
class basically looks like:

class basic_process_data
{
  boost::mutex mutex;
  // handles and a `PROCESS_INFORMATION`
  bool running; // http://lists.boost.org/boost-users/2009/09/51813.php

  void start()
  {
    boost::mutex::scoped_lock lock(mutex);
    boost::thread(mem_fun5_t(&basic_process_data::runner), this,
boost::ref(lock), ...);
  }

  void runner(boost::mutex::scoped_lock& lock_, ...)
  {
    // setup, call `CreateProcess`, wait for the child process to finish
  }
};

Of course, I am going to remove the first parameter to the `runner`
function because I will no longer be trying to move the `scoped_lock`.

The idea for moving the lock to the new thread that is running
`runner` was to have an elegant solution to the problem of preventing
multiple "runner threads" from being created, which would all modify
the `basic_process_data` member variables in a very non-thread-safe
way. Perhaps what I will do now is just use the `running` variable,
which is `true` when the thread is running, to prevent multiple runner
threads as well as allow me to determine if the runner thread is
running (per the suggestion at
http://lists.boost.org/boost-users/2009/09/51813.php). Also, I
recently discovered a Windows function called
`RegisterWaitForSingleObject` which might obviate the creation of a
thread that justs waits for the child process to finish.

Daniel


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk