summaryrefslogtreecommitdiff
path: root/ACE/ace/SV_Semaphore_Complex.h
blob: b94932ac66b8903c534c3134dc4d5046b8f4efdb (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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// -*- C++ -*-

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

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

#include "ace/SV_Semaphore_Simple.h"

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

ACE_BEGIN_VERSIONED_NAMESPACE_DECL

/**
 * @class ACE_SV_Semaphore_Complex
 *
 * @brief This is a more complex semaphore wrapper that handles race
 * conditions for initialization correctly...
 *
 * This code is a port to C++, inspired by: W. Richard Stevens
 * from his book: UNIX Network Programming (Prentice Hall, ISBN
 * 0-13-949876-1 - 1990).  We provide a simpler and easier to
 * understand interface to the System V Semaphore system calls.
 * We create and use a 2 + n-member set for the requested
 * ACE_SV_Semaphore_Complex. The first member, [0], is a
 * counter used to know when all processes have finished with
 * the ACE_SV_Semaphore_Complex.  The counter is initialized
 * to a large number, decremented on every create or open and
 * incremented on every close. This way we can use the "adjust"
 * feature provided by System V so that any process that exit's
 * without calling <close> is accounted for. It doesn't help us
 * if the last process does this (as we have no way of getting
 * control to remove the ACE_SV_Semaphore_Complex) but it
 * will work if any process other than the last does an exit
 * (intentional or unintentional).
 * The second member, [1], of the semaphore is used as a lock
 * variable to avoid any race conditions in the create() and
 * close() functions.
 * The members beyond [1] are actual semaphore values in the
 * array of semaphores, which may be sized by the user in the
 * constructor.
 */
class ACE_Export ACE_SV_Semaphore_Complex : private ACE_SV_Semaphore_Simple
{
public:
  enum
  {
    ACE_CREATE = IPC_CREAT,
    ACE_OPEN   = 0
  };

  ACE_SV_Semaphore_Complex (void);
  ACE_SV_Semaphore_Complex (key_t key,
                            short create = ACE_SV_Semaphore_Complex::ACE_CREATE,
                            int initial_value = 1,
                            u_short nsems = 1,
                            mode_t perms = ACE_DEFAULT_FILE_PERMS);
  ACE_SV_Semaphore_Complex (const char *name,
                            short create = ACE_SV_Semaphore_Complex::ACE_CREATE,
                            int initial_value = 1,
                            u_short nsems = 1,
                            mode_t perms = ACE_DEFAULT_FILE_PERMS);
  ~ACE_SV_Semaphore_Complex (void);

  /// Open or create an array of SV_Semaphores.  We return 0 if all is
  /// OK, else -1.
  int open (const char *name,
            short flags = ACE_SV_Semaphore_Simple::ACE_CREATE,
            int initial_value = 1,
            u_short nsems = 1,
            mode_t perms = ACE_DEFAULT_FILE_PERMS);

  /// Open or create an array of SV_Semaphores.  We return 0 if all is
  /// OK, else -1.
  int open (key_t key,
            short flags = ACE_SV_Semaphore_Simple::ACE_CREATE,
            int initial_value = 1,
            u_short nsems = 1,
            mode_t perms = ACE_DEFAULT_FILE_PERMS);

  /**
   * Close an ACE_SV_Semaphore. Unlike the remove() method, this
   * method is for a process to call before it exits, when it is done
   * with the ACE_SV_Semaphore. We "decrement" the counter of
   * processes using the ACE_SV_Semaphore, and if this was the last
   * one, we can remove the ACE_SV_Semaphore.
   */
  int close (void);

  // = Semaphore acquire and release methods.

  /// Acquire the semaphore.
  int acquire (u_short n = 0, short flags = 0) const;

  /// Acquire a semaphore for reading.
  int acquire_read (u_short n = 0, short flags = 0) const;

  /// Acquire a semaphore for writing
  int acquire_write (u_short n = 0, short flags = 0) const;

  /// Try to acquire the semaphore.
  int tryacquire (u_short n = 0, short flags = 0) const;

  /// Try to acquire the semaphore for reading.
  int tryacquire_read (u_short n = 0, short flags = 0) const;

  /// Try to acquire the semaphore for writing.
  int tryacquire_write (u_short n = 0, short flags = 0) const;

  /// Release the semaphore.
  int release (u_short n = 0, short flags = 0) const;

  // = Semaphore operation methods.
  int op (short val, u_short n = 0, short flags = 0) const;
  int op (sembuf op_vec[], u_short n) const;

  // = Semaphore control methods.
  int control (int cmd, semun arg, u_short n = 0) const;
  int control (int cmd, int value = 0, u_short n = 0) const;

  // = Upgrade access control...
  using ACE_SV_Semaphore_Simple::get_id;
  using ACE_SV_Semaphore_Simple::remove;

  /// Dump the state of an object.
  void dump () const;

  /// Declare the dynamic allocation hooks.
  ACE_ALLOC_HOOK_DECLARE;

private:
  static const int BIGCOUNT_;
  static sembuf op_lock_[2];
  static sembuf op_endcreate_[2];
  static sembuf op_open_[1];
  static sembuf op_close_[3];
  static sembuf op_unlock_[1];
};

ACE_END_VERSIONED_NAMESPACE_DECL

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

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