Boost logo

Boost :

From: Roland Schwarz (roland.schwarz_at_[hidden])
Date: 2006-10-29 13:51:07


Sorry for answering to my own post, but ...

I have another small idea to throw in. ;-)

The real meaning of a mutex to me always was
to protect something by mere knowledge of its
identification. For interprocess this usually
means use of a named mutex.

I have always been under the wrong assumption
that this poses a problem for the construction,
in which thread comes first. I believed so
because named mutex in boost was used to solve
the reverse problem (constructing once function)
by letting the operating system take care for
the race.

Since I've seen now that the once problem can
be solved without need for a named mutex, I
discovered that named mutex is an orthogonal
concept. (Sorry if this sounds too trivial.)

Perhaps this idea is also too simply to be
useful, but I always were looking for a way to
be able to say:

class foo
{
  ...
} afoo;

lock lk(&afoo);

where &afoo is the process - unique equivalent
of a name for a mutex. Unfortunately a mutex
is an object that carries state, and foo isn't
prepared to store this state.

The problem is that this takes too much steps
at a time. Bringing the mutex again into play
to store the state one could say:

mutex& m1 = named_mutex::open(&afoo);

which will give back an unique mutex.
At another place, only knowing afoo's address
we could say:

mutex& m2 = named_mutex::open(&afoo);

and this will hand out an equivalent mutex.
Normally you would need to create a process wide
visible mutex to accomplish the same effect,
altough knowing an unique identifier, as is the
address, would be sufficient.

I have attached an example implementation that
stores the mutex objects in a global map. The
example works with my earlier posted POD mutex,
but can be easily modified to work with
boost::mutex as well.

Sorry if this idea sound too trivial, but I simply
did not see it before. If anyone knows a similar
implementation, I would be glad to hear about.

Roland


// Copyright (C) 2006 Roland Schwarz
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#ifndef NAMED_MUTEX_HPP__
#define NAMED_MUTEX_HPP__

#include "mutex.hpp"

namespace named_mutex {

    mutex& open(const void* addr);
    void close(const void* addr);
};

#endif

// Copyright (C) 2006 Roland Schwarz
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#include "named_mutex.hpp"
#include <map>
#include <exception>

namespace {
    
    mutex map_mtx;
    typedef std::map<const void*, std::pair<mutex*,int> > map_mutex_type;
    map_mutex_type map_mutex;

};

namespace named_mutex {

    mutex& open(const void* addr)
    {
        scoped_lock lk(map_mtx);
        map_mutex_type::iterator i = map_mutex.find(addr);
        mutex* pm;
        if (i == map_mutex.end()) {
            pm = new mutex(0);
            map_mutex.insert(std::make_pair(addr, std::make_pair(pm,1)));
        }
        else {
            pm = i->second.first;
            ++(i->second.second);
        }
        return *pm;
    }

    void close(const void* addr)
    {
        scoped_lock lk(map_mtx);
        map_mutex_type::iterator i = map_mutex.find(addr);
        if (i != map_mutex.end()) {
            if (0 == --(i->second.second)) {
                delete i->second.first;
                map_mutex.erase(addr);
            }
        }
    }

};


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