1 /******************************************************************************
2 
3     An interface for a FIFO queue with items of a specific type.
4 
5     This interface is deliberately designed to be as minimal as possible,
6     only covering the core functionality shared by the wide variety of possible
7     queue implementations. For example, even a basic pop function which returns
8     an item is not generic -- certain implementations may need to relinquish the
9     item after popping it, making a simple pop-then-return implementation
10     impossible. For this reason, some additional helper functions are provided,
11     which may be useful with some queue implementations.
12 
13     Copyright:
14         Copyright (c) 2009-2016 dunnhumby Germany GmbH.
15         All rights reserved.
16 
17     License:
18         Boost Software License Version 1.0. See LICENSE_BOOST.txt for details.
19         Alternatively, this file may be distributed under the terms of the Tango
20         3-Clause BSD License (see LICENSE_BSD.txt for details).
21 
22 *******************************************************************************/
23 
24 module ocean.util.container.queue.model.ITypedQueue;
25 import ocean.core.Test;
26 
27 
28 /******************************************************************************
29 
30     An interface for a FIFO queue with items of a specific type.
31 
32     Params:
33         T = Type of items to be stored in the queue
34 
35 *******************************************************************************/
36 
37 public interface ITypedQueue ( T )
38 {
39     /**************************************************************************
40 
41         Returns:
42             true if queue is empty, false otherwise
43 
44     ***************************************************************************/
45 
46     bool empty ( );
47 
48 
49     /**************************************************************************
50 
51         Returns:
52             number of items in the queue
53 
54     ***************************************************************************/
55 
56     size_t length ( );
57 
58 
59     /**************************************************************************
60 
61         Removes all items from the queue
62 
63     ***************************************************************************/
64 
65     void clear ( );
66 
67 
68     /**************************************************************************
69 
70         Pushes an item to the queue. The caller should set the returned item as
71         desired
72 
73         Returns:
74             Pointer to the newly pushed item, null if the item could not be pushed
75             (see documentation of implementing class for possible failure reasons)
76 
77     ***************************************************************************/
78 
79     T* push ( );
80 
81 
82     /**************************************************************************
83 
84         Discards the item at the top of the queue.
85 
86     ***************************************************************************/
87 
88     void discardTop ( );
89 
90 
91     /**************************************************************************
92 
93         Returns:
94             A pointer to the item at the top of the queue, null if the queue is
95             empty
96 
97     ***************************************************************************/
98 
99     T* top ( );
100 }
101 
102 
103 /******************************************************************************
104 
105     A helper function to push an item into ITypedQueue.
106 
107     Note: this function performs a shallow copy of t into the queue.
108     If this is not desired, the caller class is to call `push()` method of
109     `ITypedQueue` and apply desired logic on returned pointer.
110 
111     Params:
112         T = type of items stored in queue
113         q = A queue to push into
114         t = An item to push into q
115 
116     Returns:
117         true if t pushed into q, false otherwise
118 
119 *******************************************************************************/
120 
121 public bool push ( T ) ( ITypedQueue!(T) q, T t )
122 {
123     auto p = q.push();
124     if ( p is null ) return false;
125     *p = t;
126     return true;
127 }
128 
129 
130 /******************************************************************************
131 
132     A helper function to pop an item from ITypedQueue.
133 
134     Note: this function performs a shallow copy of the popped item into t.
135     if this is not desired, the caller class is to call `top()` method of
136     `ITypedQueue` and apply desired logic on returned pointer and then call
137     `discardTop()`.
138 
139     Params:
140         T = type of items stored in queue
141         q = A queue to pop from
142         t = if pop succeeds, will hold item popped from q, when function ends
143 
144     Returns:
145         true if top item was popped and copied to t, false otherwise
146 
147 *******************************************************************************/
148 
149 public bool pop ( T ) ( ITypedQueue!(T) q, ref T t )
150 {
151     auto p = q.top();
152     if ( p is null )
153     {
154         return false;
155     }
156     t = *p;
157     q.discardTop();
158     return true;
159 }
160 
161 
162 version (unittest)
163 {
164     /**************************************************************************
165 
166         Test the methods defined in the ITypedQueue interface
167 
168         params:
169             queue = queue to run tests on
170             items = an array of items to test the queue with
171 
172     ***************************************************************************/
173 
174     void testInterfaceMethods ( T ) ( ITypedQueue!( T ) queue, T[] items )
175     {
176         // test 'push' and 'top'
177         foreach ( i, item; items)
178         {
179             test(push(queue, items[i]), "push should have been successfull");
180 
181             test!("==")(queue.length(), i + 1, "push method should have added an item!");
182             test(queue.top() != null, "queue isn't empty. Should have topped something!");
183         }
184 
185         // test 'pop' (which calls 'top' and 'discardTop')
186         foreach ( i, item; items)
187         {
188             T popped;
189             pop(queue, popped);
190 
191             test!("==")(popped, items[i], "First element in queue should change after we pop!");
192             test!("==")(queue.length(), items.length - i - 1, "pop method should have removed a single item from queue!");
193         }
194 
195         // test 'clear'
196         foreach ( i, item; items)
197         {
198             test(push(queue, items[i]), "push should have been successfull");
199         }
200 
201         queue.clear();
202         test(queue.empty(), "clear method should have removed all items from queue!");
203         test(!queue.length(), "clear method should have removed all items from queue. Length should be 0!");
204     }
205 }