libt3widget
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups
keybuffer.h
1 /* Copyright (C) 2011-2012 G.P. Halkes
2  This program is free software: you can redistribute it and/or modify
3  it under the terms of the GNU General Public License version 3, as
4  published by the Free Software Foundation.
5 
6  This program is distributed in the hope that it will be useful,
7  but WITHOUT ANY WARRANTY; without even the implied warranty of
8  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9  GNU General Public License for more details.
10 
11  You should have received a copy of the GNU General Public License
12  along with this program. If not, see <http://www.gnu.org/licenses/>.
13 */
14 #ifndef T3_WIDGET_KEYBUFFER_H
15 #define T3_WIDGET_KEYBUFFER_H
16 
17 #ifndef _T3_WIDGET_INTERNAL
18 #error This header file is for internal use _only_!!
19 #endif
20 
21 /* Buffer for storing keys that ensures thread-safe operation by means of a
22  mutex. It is implemented by means of a double ended queue. */
23 
24 #include <pthread.h>
25 #include <algorithm>
26 #include <deque>
27 
28 #include <t3widget/key.h>
29 namespace t3_widget {
30 
32 template <class T>
33 class T3_WIDGET_LOCAL item_buffer_t {
34  protected:
36  std::deque<T> items;
38  pthread_mutex_t lock;
40  pthread_cond_t cond;
41 
42  public:
44  item_buffer_t(void) {
45  pthread_mutex_init(&lock, NULL);
46  pthread_cond_init(&cond, NULL);
47  }
48 
50  void push_back(T item) {
51  pthread_mutex_lock(&lock);
52  /* Catch all exceptions, to enusre that unlocking of the mutex is
53  performed. The only real exception that can occur here is bad_alloc,
54  and there is not much we can do about that anyway. */
55  try {
56  items.push_back(item);
57  } catch (...) {
58  }
59  pthread_cond_signal(&cond);
60  pthread_mutex_unlock(&lock);
61  }
62 
64  T pop_front(void) {
65  T result;
66  pthread_mutex_lock(&lock);
67  while (items.empty())
68  pthread_cond_wait(&cond, &lock);
69  result = items.front();
70  items.pop_front();
71  pthread_mutex_unlock(&lock);
72  return result;
73  }
74 
77  pthread_mutex_destroy(&lock);
78  pthread_cond_destroy(&cond);
79  }
80 };
81 
83 class T3_WIDGET_LOCAL key_buffer_t : public item_buffer_t<key_t> {
84  public:
86  void push_back_unique(key_t key) {
87  pthread_mutex_lock(&lock);
88 
89  // Return without adding if the key is already queued
90  if (find(items.begin(), items.end(), key) != items.end()) {
91  pthread_mutex_unlock(&lock);
92  return;
93  }
94 
95  /* Catch all exceptions, to enusre that unlocking of the mutex is
96  performed. The only real exception that can occur here is bad_alloc,
97  and there is not much we can do about that anyway. */
98  try {
99  items.push_back(key);
100  } catch (...) {
101  }
102  pthread_cond_signal(&cond);
103  pthread_mutex_unlock(&lock);
104  }
105 };
106 
107 typedef item_buffer_t<mouse_event_t> mouse_event_buffer_t;
108 
109 }; // namespace
110 #endif