1 /*
2  * Copyright 2003-2021 The Music Player Daemon Project
3  * http://www.musicpd.org
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 #ifndef MPD_PIPE_H
21 #define MPD_PIPE_H
22 
23 #include "MusicChunkPtr.hxx"
24 #include "thread/Mutex.hxx"
25 
26 #ifndef NDEBUG
27 #include "pcm/AudioFormat.hxx"
28 #endif
29 
30 /**
31  * A queue of #MusicChunk objects.  One party appends chunks at the
32  * tail, and the other consumes them from the head.
33  */
34 class MusicPipe {
35 	/** the first chunk */
36 	MusicChunkPtr head;
37 
38 	/** a pointer to the tail of the chunk */
39 	MusicChunkPtr *tail_r = &head;
40 
41 	/** the current number of chunks */
42 	unsigned size = 0;
43 
44 	/** a mutex which protects #head and #tail_r */
45 	mutable Mutex mutex;
46 
47 #ifndef NDEBUG
48 	AudioFormat audio_format = AudioFormat::Undefined();
49 #endif
50 
51 public:
~MusicPipe()52 	~MusicPipe() noexcept {
53 		Clear();
54 	}
55 
56 #ifndef NDEBUG
57 	/**
58 	 * Checks if the audio format if the chunk is equal to the specified
59 	 * audio_format.
60 	 */
61 	[[gnu::pure]]
CheckFormat(AudioFormat other) const62 	bool CheckFormat(AudioFormat other) const noexcept {
63 		return !audio_format.IsDefined() ||
64 			audio_format == other;
65 	}
66 
67 	/**
68 	 * Checks if the specified chunk is enqueued in the music pipe.
69 	 */
70 	[[gnu::pure]]
71 	bool Contains(const MusicChunk *chunk) const noexcept;
72 #endif
73 
74 	/**
75 	 * Returns the first #MusicChunk from the pipe.  Returns
76 	 * nullptr if the pipe is empty.
77 	 */
78 	[[gnu::pure]]
Peek() const79 	const MusicChunk *Peek() const noexcept {
80 		const std::scoped_lock<Mutex> protect(mutex);
81 		return head.get();
82 	}
83 
84 	/**
85 	 * Removes the first chunk from the head, and returns it.
86 	 */
87 	MusicChunkPtr Shift() noexcept;
88 
89 	/**
90 	 * Clears the whole pipe and returns the chunks to the buffer.
91 	 */
92 	void Clear() noexcept;
93 
94 	/**
95 	 * Pushes a chunk to the tail of the pipe.
96 	 */
97 	void Push(MusicChunkPtr chunk) noexcept;
98 
99 	/**
100 	 * Returns the number of chunks currently in this pipe.
101 	 */
102 	[[gnu::pure]]
GetSize() const103 	unsigned GetSize() const noexcept {
104 		const std::scoped_lock<Mutex> protect(mutex);
105 		return size;
106 	}
107 
108 	[[gnu::pure]]
IsEmpty() const109 	bool IsEmpty() const noexcept {
110 		return GetSize() == 0;
111 	}
112 };
113 
114 #endif
115