summaryrefslogtreecommitdiff
path: root/ACE/ace/Notification_Queue.h
blob: dc7801e1630c80b6448d1aecb21e8e8841a4ae5d (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
157
/**
 *  @file Notification_Queue.h
 *
 *  @author Carlos O'Ryan <coryan@atdesk.com>
 */

#ifndef ACE_NOTIFICATION_QUEUE_H
#define ACE_NOTIFICATION_QUEUE_H

#include /**/ "ace/pre.h"

#include "ace/Copy_Disabled.h"
#include "ace/Event_Handler.h"
#include "ace/Intrusive_List.h"
#include "ace/Intrusive_List_Node.h"
#include "ace/Unbounded_Queue.h"

ACE_BEGIN_VERSIONED_NAMESPACE_DECL

/**
 * @class ACE_Notification_Queue_Node
 *
 * @brief Helper class
 */
class ACE_Export ACE_Notification_Queue_Node
  : public ACE_Intrusive_List_Node<ACE_Notification_Queue_Node>
{
public:
  /**
   * @brief Constructor
   */
  ACE_Notification_Queue_Node();

  /**
   * @brief Modifier change the contained buffer
   */
  void set(ACE_Notification_Buffer const & rhs);

  /**
   * @brief Accessor, fetch the contained buffer
   */
  ACE_Notification_Buffer const & get() const;

  /**
   * @brief Checks if the event handler matches the purge condition
   */
  bool matches_for_purging(ACE_Event_Handler * eh) const;

  /**
   * @brief Return true if clearing the mask would leave no
   * notifications to deliver.
   */
  bool mask_disables_all_notifications(ACE_Reactor_Mask mask);

  /**
   * @brief Clear the notifications specified by @c mask
   */
  void clear_mask(ACE_Reactor_Mask mask);

  ACE_ALLOC_HOOK_DECLARE;

private:
  ACE_Notification_Buffer contents_;
};

/**
 * @class ACE_Notification_Queue
 *
 * @brief Implements a user-space queue to send Reactor notifications.
 *
 * The ACE_Reactor uses a pipe to send wake up the thread running the
 * event loop from other threads.  This pipe can be limited in size
 * under some operating systems.  For some applications, this limit
 * presents a problem.  A user-space notification queue is used to
 * overcome those limitations.  The queue tries to use as few
 * resources on the pipe as possible, while keeping all the data in
 * user space.
 *
 * This code was refactored from Select_Reactor_Base.
 */
class ACE_Export ACE_Notification_Queue : private ACE_Copy_Disabled
{
public:
  ACE_Notification_Queue();
  ~ACE_Notification_Queue();

  /**
   * @brief Pre-allocate resources in the queue
   */
  int open();

  /**
   * @brief Release all resources in the queue
   */
  void reset();

  /**
   * @brief Remove all elements in the queue matching @c eh and @c mask
   *
   * I suggest reading the documentation in ACE_Reactor to find a more
   * detailed description.  This is just a helper function.
   */
  int purge_pending_notifications(ACE_Event_Handler * eh,
                                  ACE_Reactor_Mask mask);

  /**
   * @brief Add a new notification to the queue
   *
   * @return -1 on failure, 1 if a new message should be sent through
   * the pipe and 0 otherwise.
   */
  int push_new_notification(ACE_Notification_Buffer const & buffer);

  /**
   * @brief Extract the next notification from the queue
   *
   * @return -1 on failure, 1 if a message was popped, 0 otherwise
   */
  int pop_next_notification(
      ACE_Notification_Buffer & current,
      bool & more_messages_queued,
      ACE_Notification_Buffer & next);

private:
  /**
   * @brief Allocate more memory for the queue
   */
  int allocate_more_buffers();

private:
  /// Keeps track of allocated arrays of type
  /// ACE_Notification_Buffer.  The idea is to amortize allocation
  /// costs by allocating multiple ACE_Notification_Buffer objects at
  /// a time.
  ACE_Unbounded_Queue <ACE_Notification_Queue_Node*> alloc_queue_;

  typedef ACE_Intrusive_List<ACE_Notification_Queue_Node> Buffer_List;

  /// Keeps track of all pending notifications.
  Buffer_List notify_queue_;

  /// Keeps track of all free buffers.
  Buffer_List free_queue_;

  /// Synchronization for handling of queues.
  ACE_SYNCH_MUTEX notify_queue_lock_;
};

ACE_END_VERSIONED_NAMESPACE_DECL

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

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

#endif /* ACE_NOTIFICATION_QUEUE_H */