File: atomic_queue.hpp

package info (click to toggle)
python-visual 1%3A5.12-1.1
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 7,672 kB
  • ctags: 7,636
  • sloc: cpp: 15,593; sh: 9,615; ansic: 6,631; python: 4,737; makefile: 385
file content (82 lines) | stat: -rw-r--r-- 1,440 bytes parent folder | download | duplicates (3)
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
#ifndef VPYTHON_UTIL_ATOMIC_QUEUE_HPP
#define VPYTHON_UTIL_ATOMIC_QUEUE_HPP

#include "util/thread.hpp"
#include <queue>

namespace cvisual {
	
// This class exists to separate out code that is not templated (and therefore
// doesn't need to be in a header file) from code that is.  This prevents
// picking up the whole Python runtine throughout all of cvisual, thus making
// compilation faster.
class atomic_queue_impl
{
 protected:
	volatile bool waiting;
	volatile bool empty;
	condition ready;
	mutable mutex barrier;
	
	atomic_queue_impl()
		: waiting(false), empty(true)
	{}
	
	void push_notify();
	void py_pop_wait( lock& L);
};

template <typename T>
class atomic_queue : private atomic_queue_impl
{
 private:
	std::queue<T> data;
	
	/**
	 * Precondition - the buggar is locked, at least one item is in data
	 */
	T pop_impl()
	{
		T ret = data.front();
		data.pop();
		if (data.empty())
			empty = true;
		return ret;
	}

 public:
	atomic_queue() {}
	
	void push( const T& item)
	{
		lock L(barrier);
		data.push( item);
		push_notify();
	}

	// It's assumed that the caller of py_pop() holds the Python GIL
	T py_pop()
	{
		lock L(barrier);
		py_pop_wait( L);
		return pop_impl();
	}
	
	size_t size() const
	{
		lock L(barrier);
		return data.size();
	}
	
	void clear()
	{
		lock L(barrier);
		while (!data.empty())
			data.pop();
		empty = true;
	}
};

} // !namespace cvisual

#endif // !defined VPYTHON_UTIL_ATOMIC_QUEUE_HPP