summaryrefslogtreecommitdiff
path: root/ACE/ace/Reverse_Lock_T.h
blob: 9f0d2ae659f3bb954aff1c99ca01e0ad65e60f0f (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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// -*- C++ -*-

//==========================================================================
/**
 *  @file    Reverse_Lock_T.h
 *
 *  @author Douglas C. Schmidt <d.schmidt@vanderbilt.edu>
 */
//==========================================================================

#ifndef ACE_REVERSE_LOCK_T_H
#define ACE_REVERSE_LOCK_T_H
#include /**/ "ace/pre.h"

#include "ace/Lock.h"

#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */

ACE_BEGIN_VERSIONED_NAMESPACE_DECL

/**
 * @namespace ACE_Acquire_Method
 *
 * @brief An enum namespace.
 *
 * These enums should have been inside the reverse lock class, but
 * some lame compilers cannot handle enums inside template classes.
 *
 * The METHOD_TYPE is used to indicate which acquire() method will be
 * called on the real lock when the release() method is called on the
 * reverse lock. REGULAR indicated the acquire() method, READ
 * indicates the acquire_read() method, and WRITE indicates the
 * acquire_write() method.  Note that the try_*() methods are not
 * represented here because we have to make sure that the release()
 * method on the reverse lock acquires a lock on the real lock.
 **/
namespace ACE_Acquire_Method
{
  enum METHOD_TYPE
  {
    ACE_REGULAR,
    ACE_READ,
    ACE_WRITE
  };
}

/**
 * @class ACE_Reverse_Lock
 *
 * @brief A reverse (or anti) lock.
 *
 * This is an interesting adapter class that changes a lock into
 * a reverse lock, i.e., <acquire> on this class calls <release>
 * on the lock, and <release> on this class calls <acquire> on
 * the lock.
 * One motivation for this class is when we temporarily want to
 * release a lock (which we have already acquired) but then
 * reacquire it soon after.  An alternative design would be to
 * add a Anti_Guard or Reverse_Guard class which would <release>
 * on construction and <acquire> destruction.  However, there
 * are *many* varieties of the Guard class and this design
 * choice would lead to at least 6 new classes.  One new
 * ACE_Reverse_Lock class seemed more reasonable.
 */
template <class ACE_LOCKING_MECHANISM>
class ACE_Reverse_Lock : public ACE_Lock
{
public:
  typedef ACE_LOCKING_MECHANISM ACE_LOCK;

  // = Initialization/Finalization methods.

  /// Constructor. All locking requests will be forwarded to @a lock.
  ACE_Reverse_Lock (ACE_LOCKING_MECHANISM &lock,
                    ACE_Acquire_Method::METHOD_TYPE acquire_method = ACE_Acquire_Method::ACE_REGULAR);

  /// Destructor. If <lock_> was not passed in by the user, it will be
  /// deleted.
  virtual ~ACE_Reverse_Lock () = default;

  // = Lock accessors.
  /// Release the lock.
  virtual int acquire ();

  /// Release the lock.
  virtual int tryacquire ();

  /// Acquire the lock.
  virtual int release ();

  /// Release the lock.
  virtual int acquire_read ();

  /// Release the lock.
  virtual int acquire_write ();

  /// Release the lock.
  virtual int tryacquire_read ();

  /// Release the lock.
  virtual int tryacquire_write ();

  /// Release the lock.
  virtual int tryacquire_write_upgrade ();

  /// Explicitly destroy the lock.
  virtual int remove ();

private:
  /// The concrete locking mechanism that all the methods delegate to.
  ACE_LOCKING_MECHANISM &lock_;

  /// This indicates what kind of acquire method will be called.
  ACE_Acquire_Method::METHOD_TYPE acquire_method_;
};

ACE_END_VERSIONED_NAMESPACE_DECL

#if defined (__ACE_INLINE__)
#include "ace/Reverse_Lock_T.inl"
#endif /* __ACE_INLINE__ */

#include "ace/Reverse_Lock_T.cpp"

#include /**/ "ace/post.h"
#endif /* ACE_REVERSE_LOCK_T_H */