summaryrefslogtreecommitdiff
path: root/shared/loki/LockingPtr.h
blob: 5482f0751e072f748a55af74c6dca65ef2f8bfb8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
////////////////////////////////////////////////////////////////////////////////
// The Loki Library
// Copyright (c) 2001 by Andrei Alexandrescu
// This code is from the article:
//     "Generic<Programming>: volatile — Multithreaded Programmer’s Best Friend
//     Volatile-Correctness or How to Have Your Compiler Detect Race Conditions
//     for You" by Alexandrescu, Andrei.
//     Published in the February 2001 issue of the C/C++ Users Journal.
//     http://www.cuj.com/documents/s=7998/cujcexp1902alexandr/
// Permission to use, copy, modify, distribute and sell this software for any
//     purpose is hereby granted without fee, provided that the above copyright
//     notice appear in all copies and that both that copyright notice and this
//     permission notice appear in supporting documentation.
// The author makes no representations about the
//     suitability of this software for any purpose. It is provided "as is"
//     without express or implied warranty.
// Prepared for Loki library by Richard Sposato
////////////////////////////////////////////////////////////////////////////////
#ifndef LOKI_LOCKING_PTR_INC_
#define LOKI_LOCKING_PTR_INC_

// $Id: LockingPtr.h 840 2008-03-19 19:44:38Z rich_sposato $


#include <loki/ConstPolicy.h>
#include <loki/Threads.h>


namespace Loki
{
/** @class LockingPtr
 Locks a volatile object and casts away volatility so that the object
 can be safely used in a single-threaded region of code.
 Original version of LockingPtr had only one template - for the shared
 object, but not the mutex type.  This version allows users to specify a
 the mutex type as a LockingPolicy class.  The only requirements for a
 LockingPolicy class are to provide Lock and Unlock methods.
 */
template < typename SharedObject, typename LockingPolicy = LOKI_DEFAULT_MUTEX,
         template<class> class ConstPolicy = LOKI_DEFAULT_CONSTNESS >
class LockingPtr
{
public:

    typedef typename ConstPolicy<SharedObject>::Type ConstOrNotType;

    /** Constructor locks mutex associated with an object.
     @param object Reference to object.
     @param mutex Mutex used to control thread access to object.
     */
    LockingPtr( volatile ConstOrNotType& object, LockingPolicy& mutex )
        : pObject_( const_cast< SharedObject* >( &object ) ),
          pMutex_( &mutex )
    {
        mutex.Lock();
    }

    typedef typename std::pair<volatile ConstOrNotType*, LockingPolicy*> Pair;

    /** Constructor locks mutex associated with an object.
     @param lockpair a std::pair of pointers to the object and the mutex
     */
    LockingPtr( Pair lockpair )
        : pObject_( const_cast< SharedObject* >( lockpair.first ) ),
          pMutex_( lockpair.second )
    {
        lockpair.second->Lock();
    }

    /// Destructor unlocks the mutex.
    ~LockingPtr()
    {
        pMutex_->Unlock();
    }

    /// Star-operator dereferences pointer.
    ConstOrNotType& operator * ()
    {
        return *pObject_;
    }

    /// Point-operator returns pointer to object.
    ConstOrNotType* operator -> ()
    {
        return pObject_;
    }

private:

    /// Default constructor is not implemented.
    LockingPtr();

    /// Copy-constructor is not implemented.
    LockingPtr( const LockingPtr& );

    /// Copy-assignment-operator is not implemented.
    LockingPtr& operator = ( const LockingPtr& );

    /// Pointer to the shared object.
    ConstOrNotType* pObject_;

    /// Pointer to the mutex.
    LockingPolicy* pMutex_;

}; // end class LockingPtr

} // namespace Loki

#endif // end file guardian

bgstack15