1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     os_BlockingQueue.h
4 
5   Copyright (C)2009 Nintendo Co., Ltd.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Rev: 30205 $
14  *---------------------------------------------------------------------------*/
15 
16 /*! @file
17     @brief      BlockingQueue に関する API の宣言
18 
19     :include nn/os.h
20 */
21 
22 #ifndef NN_OS_OS_BLOCKINGQUEUE_H_
23 #define NN_OS_OS_BLOCKINGQUEUE_H_
24 
25 #include <nn/os/os_LightSemaphore.h>
26 #include <nn/os/os_Mutex.h>
27 #include <nn/os/os_CriticalSection.h>
28 #include <nn/os/os_InterCoreCriticalSection.h>
29 #include <nn/fnd/fnd_Interlocked.h>
30 #include <nn/util/util_NonCopyable.h>
31 
32 #ifdef __cplusplus
33 
34 namespace nn { namespace os {
35 
36 namespace detail {
37 
38 /*!
39     :private
40 
41     @brief     ブロッキングキューの基底クラスです。
42 */
43 template <class Locker>
44 class BlockingQueueBase : private nn::util::NonCopyable<BlockingQueueBase<Locker> >
45 {
46 protected:
BlockingQueueBase()47     BlockingQueueBase() {}
BlockingQueueBase(uptr buffer[],size_t size)48     BlockingQueueBase(uptr buffer[], size_t size) { Initialize(buffer, size); }
49     ~BlockingQueueBase();
50     void Initialize(uptr buffer[], size_t size);
51     nn::Result TryInitialize(uptr buffer[], size_t size);
52     void Finalize();
53     void Enqueue(uptr data);
54     bool TryEnqueue(uptr data);
55     bool ForceEnqueue(uptr data, uptr* pOut);
56     void Jam(uptr data);
57     bool TryJam(uptr data);
58     uptr Dequeue();
59     bool TryDequeue(uptr* pOut);
60     uptr GetFront() const;
61     bool TryGetFront(uptr* pOut) const;
62 
63     // TODO: これらの関数の扱いを決める
64 
GetWaitingEnqueueCount(void)65     s32 GetWaitingEnqueueCount(void) const
66         { return m_WaitingEnqueueCount; }
67 
GetWaitingDequeueCount(void)68     s32 GetWaitingDequeueCount(void) const
69         { return m_WaitingDequeueCount; }
70 
71     // テスト用内部メンバアクセサ
GetSize()72     s32 GetSize() const
73         { return m_size; }
74 
GetUsedCount()75     s32 GetUsedCount() const
76         { return m_usedCount; }
77 
GetFirstIndex()78     s32 GetFirstIndex() const
79         { return m_firstIndex; }
80 
81 private:
82     typedef typename Locker::ScopedLock ScopedLock;
83 
84     uptr*                   m_ppBuffer;			//!< キュー用バッファ
85     mutable LightSemaphore  m_EnqueueSemaphore; //!< キューへの挿入待ち用同期オブジェクト
86     mutable LightSemaphore  m_DequeueSemaphore; //!< キューからの取り出し待ち用同期オブジェクト
87     mutable Locker          m_cs;				//!< キュー操作用同期オブジェクト
88     size_t                  m_size;             //!< キューのサイズ
89     s32                     m_firstIndex;       //!< キューの先頭へのインデックス
90     s32                     m_usedCount;        //!< キューに入っている要素数
91     mutable nn::fnd::InterlockedVariable<s32> m_WaitingEnqueueCount; //!< キューに挿入処理中のスレッド数
92     mutable nn::fnd::InterlockedVariable<s32> m_WaitingDequeueCount; //!< キューから取り出し処理中のスレッド数
93 
94 	//!< データ挿入待ちスレッドを起床します。
95     void NotifyEnqueue() const;
96 
97 	//!< キュー空き待ちスレッドを起床します。
98     void NotifyDequeue() const;
99 };
100 
101 }
102 
103 /*!
104     @brief ブロッキングキューを扱う為のクラスです。
105 
106     ブロッキングキューは安全にスレッド間の同期をとることの出来るメッセージ機構です。
107 
108     キューにおくことのできる要素の数は初期化時に与えるバッファのサイズによって制限されます。
109     これを超える数の要素がキューにある際にさらにキューに追加しようとすると、スレッドがブロックします。
110     同様に、キューの要素が空のときにキューから要素を取り出そうとすると、スレッドがブロックします。
111 
112     今までメッセージキューと呼ばれていた機能と同等の機能を有しています。
113 
114     内部でのスレッド同期に、@ref CriticalSection を用いているため、
115     優先度逆転を起こすような状況では、デッドロックする可能性があります。
116     そのような可能性がある場合には、@ref SafeBlockingQueue を使うようにしてください。
117 
118 */
119 class BlockingQueue : private os::detail::BlockingQueueBase<nn::os::CriticalSection>
120 {
121 private:
122     typedef os::detail::BlockingQueueBase<nn::os::CriticalSection> Base;
123 public:
124 
125     /*!
126       @brief        コンストラクタです。
127 
128                     ブロッキングキューを構築します。
129 
130                     初期化処理を行わないコンストラクタと、初期化処理を行うコンストラクタがあります。
131 
132                     コンストラクタで初期化しない場合、使用する前には別途 @ref Initialize を呼んで初期化する必要があります。
133     */
BlockingQueue()134     BlockingQueue() {}
135 
136     /*!
137       @brief        コンストラクタです。
138 
139                     ブロッキングキューを構築し、初期化します。
140 
141       @param[in]    buffer  キューに使用するバッファ。uptr 型の配列を指定します。
142       @param[in]    size    バッファのサイズ。配列の要素数を指定します。
143     */
BlockingQueue(uptr buffer[],size_t size)144     BlockingQueue(uptr buffer[], size_t size) : Base(buffer, size) {}
145 
146     /*!
147       @brief        デストラクタです。
148 
149                     内部で @ref Finalize を呼びます。
150     */
~BlockingQueue()151     ~BlockingQueue() { Finalize(); }
152 
153     /*!
154       @brief        ブロッキングキューを指定したバッファとサイズで初期化します。
155 
156       @param[in]    buffer  キューに使用するバッファ。uptr 型の配列を指定します。
157       @param[in]    size    バッファのサイズ。配列の要素数を指定します。
158 
159       @return       無し。
160     */
Initialize(uptr buffer[],size_t size)161     void Initialize(uptr buffer[], size_t size) { Base::Initialize(buffer, size); }
162 
163     /*!
164       @brief        ブロッキングキューを指定したバッファとサイズで初期化します。
165 
166                     初期化に失敗した際は、失敗に応じた Result 値を返します。
167 
168       @param[in]    buffer  キューに使用するバッファ。uptr 型の配列を指定します。
169       @param[in]    size    バッファのサイズ。配列の要素数を指定します。
170 
171       @return       関数の実行結果を返します。
172     */
TryInitialize(uptr buffer[],size_t size)173     nn::Result TryInitialize(uptr buffer[], size_t size) { return Base::TryInitialize(buffer, size); }
174 
175     /*!
176       @brief        ブロッキングキューを破棄します。
177 
178                     デストラクタから自動的に呼び出されますが、明示的に呼ぶこともできます。
179 
180       @return       無し。
181     */
Finalize()182     void Finalize() { Base::Finalize(); }
183 
184     /*!
185       @brief        キューの末尾に要素を挿入します。
186 
187                     キューの末尾にデータを挿入しますが、
188                     キューが一杯 (full) であれば、この関数を呼び出したスレッドはブロックされます。
189                     受信スレッドが動作して、キューからデータを取り出すとすぐに再開されます。
190 
191                     @ref Dequeue や @ref GetFront で待っているスレッドがあった場合、
192                     これらのスレッドが起こされます。
193 
194       @param[in]    data    挿入する要素
195 
196       @return       無し。
197     */
Enqueue(uptr data)198     void Enqueue(uptr data) { Base::Enqueue(data); }
199 
200     /*!
201       @brief        キューの末尾への要素の挿入を試行します。
202 
203                     キューに空きがあれば、末尾に要素を挿入し、true を返します。
204                     キューに空きが無いとき、何もせず、false を返します。
205 
206                     要素の挿入がされたときに @ref Dequeue や @ref GetFront で待っているスレッドがあった場合、
207                     これらのスレッドが起こされます。
208 
209       @param[in]    data    挿入する要素
210 
211       @return       挿入されたとき true を返し、挿入されなかったとき false を返します。
212     */
TryEnqueue(uptr data)213     bool TryEnqueue(uptr data) { return Base::TryEnqueue(data); }
214 
215     /*!
216       @brief        キューの先頭に要素を挿入します。
217 
218                     キューの先頭にデータを挿入しますが、
219                     キューが一杯 (full) であれば、この関数を呼び出したスレッドはブロックされます。
220                     受信スレッドが動作して、キューからデータを取り出すとすぐに再開されます。
221 
222                     @ref Dequeue や @ref GetFront で待っているスレッドがあった場合、
223                     これらのスレッドが起こされます。
224 
225       @param[in]    data    挿入する要素
226 
227       @return       無し。
228     */
Jam(uptr data)229     void Jam(uptr data) { Base::Jam(data); }
230 
231     /*!
232       @brief        キューの先頭への要素の挿入を試行します。
233 
234                     キューに空きがあれば、先頭に要素を挿入し、true を返します。
235                     キューに空きが無いとき、何もせず、false を返します。
236 
237                     要素の挿入がされたときに @ref Dequeue や @ref GetFront で待っているスレッドがあった場合、
238                     これらのスレッドが起こされます。
239 
240       @param[in]    data    挿入する要素
241 
242       @return       挿入されたとき true を返し、挿入されなかったとき false を返します。
243     */
TryJam(uptr data)244     bool TryJam(uptr data) { return Base::TryJam(data); }
245 
246     /*!
247       @brief        キューの先頭から要素を取り出します。
248 
249                     キューが空であるとき、キューが空でなくなるまでスレッドをブロックします。
250                     キューが空でなければ、キューの先頭から要素を取り出しすぐに処理を返します。
251 
252                     @ref Enqueue や @ref Jam で待っているスレッドがあった場合、
253                     これらのスレッドが起こされます。
254 
255       @return       キューから取り出した要素
256     */
Dequeue()257     uptr Dequeue() { return Base::Dequeue(); }
258 
259     /*!
260       @brief        キューの先頭から要素を取り出します。
261 
262                     キューが空でなれば、キューの先頭から要素を取り出し、true を返します。
263                     キューが空のとき、何もせず、false を返します。
264 
265                     要素の挿入がされたときに @ref Dequeue や @ref GetFront で待っているスレッドがあった場合、
266                     これらのスレッドが起こされます。
267 
268       @param[out]   pOut    取り出した要素を書き込むバッファ
269 
270       @return       要素を取り出したとき true を返し、取り出さなかったとき false を返します。
271     */
TryDequeue(uptr * pOut)272     bool TryDequeue(uptr* pOut) { return Base::TryDequeue(pOut); }
273 
274     /*!
275       @brief        キューの先頭から要素を取得します。
276 
277                     キューが空であるとき、キューが空でなくなるまでスレッドをブロックします。
278                     キューが空でなければ、キューの先頭の要素を取得します。キューの状態は変化しません。
279 
280       @return       キューの先頭の要素
281     */
GetFront()282     uptr GetFront() const { return Base::GetFront(); }
283 
284     /*!
285       @brief        キューの先頭から要素を取得します。
286 
287                     キューが空であるとき、何もせず false を返します。
288                     キューが空でなければ、キューの先頭の要素を *pOut に書き込み、true を返します。キューの状態は変化しません。
289 
290       @param[out]   pOut        取り出す値の格納先
291 
292       @return       要素を取得できたとき true を返し、取得できなかったとき false を返します。
293     */
TryGetFront(uptr * pOut)294     bool TryGetFront(uptr* pOut) const { return Base::TryGetFront(pOut); }
295 
296     // TODO: テスト用
297     using Base::GetSize;
298     using Base::GetUsedCount;
299     using Base::GetFirstIndex;
300 
301 };
302 
303 
304 /*! :private
305     @brief ブロッキングキューを扱う為のクラスです。
306 
307            基本的に @ref BlockingQueue と同じですが、スレッド同期に @ref InterCoreCriticalSection を
308            使っており、マルチコア間の同期に使用することを目的としています。
309 */
310 class InterCoreBlockingQueue : private os::detail::BlockingQueueBase<nn::os::InterCoreCriticalSection>
311 {
312 private:
313     typedef os::detail::BlockingQueueBase<nn::os::InterCoreCriticalSection> Base;
314 public:
315 
316     /*! :private
317       @brief        コンストラクタです。
318 
319                     ブロッキングキューを構築します。
320 
321                     初期化処理を行わないコンストラクタと、初期化処理を行うコンストラクタがあります。
322 
323                     コンストラクタで初期化しない場合、使用する前には別途 @ref Initialize を呼んで初期化する必要があります。
324     */
InterCoreBlockingQueue()325     InterCoreBlockingQueue() {}
326 
327     /*! :private
328       @brief        コンストラクタです。
329 
330                     ブロッキングキューを構築し、初期化します。
331 
332       @param[in]    buffer  キューに使用するバッファ。uptr 型の配列を指定します。
333       @param[in]    size    バッファのサイズ。配列の要素数を指定します。
334     */
InterCoreBlockingQueue(uptr buffer[],size_t size)335     InterCoreBlockingQueue(uptr buffer[], size_t size) : Base(buffer, size) {}
336 
337     /*! :private
338       @brief        デストラクタです。
339 
340                     内部で @ref Finalize を呼びます。
341     */
~InterCoreBlockingQueue()342     ~InterCoreBlockingQueue() { Finalize(); }
343 
344     /*! :private
345       @brief        ブロッキングキューを指定したバッファとサイズで初期化します。
346 
347       @param[in]    buffer  キューに使用するバッファ。uptr 型の配列を指定します。
348       @param[in]    size    バッファのサイズ。配列の要素数を指定します。
349 
350       @return       無し。
351     */
Initialize(uptr buffer[],size_t size)352     void Initialize(uptr buffer[], size_t size) { Base::Initialize(buffer, size); }
353 
354     /*! :private
355       @brief        ブロッキングキューを指定したバッファとサイズで初期化します。
356 
357                     初期化に失敗した際は、失敗に応じた Result 値を返します。
358 
359       @param[in]    buffer  キューに使用するバッファ。uptr 型の配列を指定します。
360       @param[in]    size    バッファのサイズ。配列の要素数を指定します。
361 
362       @return       関数の実行結果を返します。
363     */
TryInitialize(uptr buffer[],size_t size)364     nn::Result TryInitialize(uptr buffer[], size_t size) { return Base::TryInitialize(buffer, size); }
365 
366     /*! :private
367       @brief        ブロッキングキューを破棄します。
368 
369                     デストラクタから自動的に呼び出されますが、明示的に呼ぶこともできます。
370 
371       @return       無し。
372     */
Finalize()373     void Finalize() { Base::Finalize(); }
374 
375     /*! :private
376       @brief        キューの末尾に要素を挿入します。
377 
378                     キューの末尾にデータを挿入しますが、
379                     キューが一杯 (full) であれば、この関数を呼び出したスレッドはブロックされます。
380                     受信スレッドが動作して、キューからデータを取り出すとすぐに再開されます。
381 
382                     @ref Dequeue や @ref GetFront で待っているスレッドがあった場合、
383                     これらのスレッドが起こされます。
384 
385       @param[in]    data    挿入する要素
386 
387       @return       無し。
388     */
Enqueue(uptr data)389     void Enqueue(uptr data) { Base::Enqueue(data); }
390 
391     /*! :private
392       @brief        キューの末尾への要素の挿入を試行します。
393 
394                     キューに空きがあれば、末尾に要素を挿入し、true を返します。
395                     キューに空きが無いとき、何もせず、false を返します。
396 
397                     要素の挿入がされたときに @ref Dequeue や @ref GetFront で待っているスレッドがあった場合、
398                     これらのスレッドが起こされます。
399 
400       @param[in]    data    挿入する要素
401 
402       @return       挿入されたとき true を返し、挿入されなかったとき false を返します。
403     */
TryEnqueue(uptr data)404     bool TryEnqueue(uptr data) { return Base::TryEnqueue(data); }
405 
406     /*! :private
407       @brief        キューの先頭に要素を挿入します。
408 
409                     キューの先頭にデータを挿入しますが、
410                     キューが一杯 (full) であれば、この関数を呼び出したスレッドはブロックされます。
411                     受信スレッドが動作して、キューからデータを取り出すとすぐに再開されます。
412 
413                     @ref Dequeue や @ref GetFront で待っているスレッドがあった場合、
414                     これらのスレッドが起こされます。
415 
416       @param[in]    data    挿入する要素
417 
418       @return       無し。
419     */
Jam(uptr data)420     void Jam(uptr data) { Base::Jam(data); }
421 
422     /*! :private
423       @brief        キューの先頭への要素の挿入を試行します。
424 
425                     キューに空きがあれば、先頭に要素を挿入し、true を返します。
426                     キューに空きが無いとき、何もせず、false を返します。
427 
428                     要素の挿入がされたときに @ref Dequeue や @ref GetFront で待っているスレッドがあった場合、
429                     これらのスレッドが起こされます。
430 
431       @param[in]    data    挿入する要素
432 
433       @return       挿入されたとき true を返し、挿入されなかったとき false を返します。
434     */
TryJam(uptr data)435     bool TryJam(uptr data) { return Base::TryJam(data); }
436 
437     /*! :private
438       @brief        キューの先頭から要素を取り出します。
439 
440                     キューが空であるとき、キューが空でなくなるまでスレッドをブロックします。
441                     キューが空でなければ、キューの先頭から要素を取り出しすぐに処理を返します。
442 
443                     @ref Enqueue や @ref Jam で待っているスレッドがあった場合、
444                     これらのスレッドが起こされます。
445 
446       @return       キューから取り出した要素
447     */
Dequeue()448     uptr Dequeue() { return Base::Dequeue(); }
449 
450     /*! :private
451       @brief        キューの先頭から要素を取り出します。
452 
453                     キューが空でなれば、キューの先頭から要素を取り出し、true を返します。
454                     キューが空のとき、何もせず、false を返します。
455 
456                     要素の挿入がされたときに @ref Dequeue や @ref GetFront で待っているスレッドがあった場合、
457                     これらのスレッドが起こされます。
458 
459       @param[out]   pOut    取り出した要素を書き込むバッファ
460 
461       @return       要素を取り出したとき true を返し、取り出さなかったとき false を返します。
462     */
TryDequeue(uptr * pOut)463     bool TryDequeue(uptr* pOut) { return Base::TryDequeue(pOut); }
464 
465     /*! :private
466       @brief        キューの先頭から要素を取得します。
467 
468                     キューが空であるとき、キューが空でなくなるまでスレッドをブロックします。
469                     キューが空でなければ、キューの先頭の要素を取得します。キューの状態は変化しません。
470 
471       @return       キューの先頭の要素
472     */
GetFront()473     uptr GetFront() const { return Base::GetFront(); }
474 
475     /*! :private
476       @brief        キューの先頭から要素を取得します。
477 
478                     キューが空であるとき、何もせず false を返します。
479                     キューが空でなければ、キューの先頭の要素を *pOut に書き込み、true を返します。キューの状態は変化しません。
480 
481       @param[out]   pOut        取り出す値の格納先
482 
483       @return       要素を取得できたとき true を返し、取得できなかったとき false を返します。
484     */
TryGetFront(uptr * pOut)485     bool TryGetFront(uptr* pOut) const { return Base::TryGetFront(pOut); }
486 
487     // TODO: テスト用
488     using Base::GetSize;
489     using Base::GetUsedCount;
490     using Base::GetFirstIndex;
491 
492 };
493 
494 
495 
496 /*!
497     @brief ブロッキングキューを扱う為のクラスです。
498 
499            基本的に @ref BlockingQueue と同じですが、スレッド同期に @ref Mutex を使っているため、優先度逆転を起こすことがありません。
500            その代わり、若干パフォーマンスは落ちる可能性があります。
501 */
502 class SafeBlockingQueue : private os::detail::BlockingQueueBase<nn::os::Mutex>
503 {
504 private:
505     typedef os::detail::BlockingQueueBase<nn::os::Mutex> Base;
506 public:
507 
508     /*!
509       @brief        コンストラクタです。
510 
511                     ブロッキングキューを構築します。初期化はしません。使用する前には別途 @ref Initialize を呼んで初期化する必要があります。
512     */
SafeBlockingQueue()513     SafeBlockingQueue() {}
514 
515     /*!
516       @brief        コンストラクタです。
517 
518                     ブロッキングキューを構築し、初期化します。
519 
520       @param[in]    buffer  キューに使用するバッファ。uptr 型の配列を指定します。
521       @param[in]    size    バッファのサイズ。配列の要素数を指定します。
522     */
SafeBlockingQueue(uptr buffer[],size_t size)523     SafeBlockingQueue(uptr buffer[], size_t size) : Base(buffer, size) {}
524 
525     /*!
526       @brief        デストラクタです。
527 
528                     内部で @ref Finalize を呼びます。
529     */
~SafeBlockingQueue()530     ~SafeBlockingQueue() {}
531 
532     /*!
533       @brief        ブロッキングキューを指定したバッファとサイズで初期化します。
534 
535       @param[in]    buffer  キューに使用するバッファ。uptr 型の配列を指定します。
536       @param[in]    size    バッファのサイズ。配列の要素数を指定します。
537 
538       @return       無し。
539     */
Initialize(uptr buffer[],size_t size)540     void Initialize(uptr buffer[], size_t size) { Base::Initialize(buffer, size); }
541 
542     /*!
543       @brief        ブロッキングキューを指定したバッファとサイズで初期化します。
544 
545                     初期化に失敗した際は、失敗に応じた Result 値を返します。
546 
547       @param[in]    buffer  キューに使用するバッファ。uptr 型の配列を指定します。
548       @param[in]    size    バッファのサイズ。配列の要素数を指定します。
549 
550       @return       関数の実行結果を返します。
551     */
TryInitialize(uptr buffer[],size_t size)552     nn::Result TryInitialize(uptr buffer[], size_t size) { return Base::TryInitialize(buffer, size); }
553 
554     /*!
555       @brief        ブロッキングキューを破棄します。
556 
557                     デストラクタから自動的に呼び出されますが、明示的に呼ぶこともできます。
558 
559       @return       無し。
560     */
Finalize()561     void Finalize() { Base::Finalize(); }
562 
563     /*!
564       @brief        キューの末尾に要素を挿入します。
565 
566                     キューの末尾にデータを挿入しますが、
567                     キューが一杯 (full) であれば、この関数を呼び出したスレッドはブロックされます。
568                     受信スレッドが動作して、キューからデータを取り出すとすぐに再開されます。
569 
570                     @ref Dequeue や @ref GetFront で待っているスレッドがあった場合、
571                     これらのスレッドが起こされます。
572 
573       @param[in]    data    挿入する要素
574 
575       @return       無し。
576     */
Enqueue(uptr data)577     void Enqueue(uptr data) { Base::Enqueue(data); }
578 
579     /*!
580       @brief        キューの末尾への要素の挿入を試行します。
581 
582                     キューに空きがあれば、末尾に要素を挿入し、true を返します。
583                     キューに空きが無いとき、何もせず、false を返します。
584 
585                     要素の挿入がされたときに @ref Dequeue や @ref GetFront で待っているスレッドがあった場合、
586                     これらのスレッドが起こされます。
587 
588       @param[in]    data    挿入する要素
589 
590       @return       挿入されたとき true を返し、挿入されなかったとき false を返します。
591     */
TryEnqueue(uptr data)592     bool TryEnqueue(uptr data) { return Base::TryEnqueue(data); }
593 
594     /*!
595       @brief        キューの先頭に要素を挿入します。
596 
597                     キューの先頭にデータを挿入しますが、
598                     キューが一杯 (full) であれば、この関数を呼び出したスレッドはブロックされます。
599                     受信スレッドが動作して、キューからデータを取り出すとすぐに再開されます。
600 
601                     @ref Dequeue や @ref GetFront で待っているスレッドがあった場合、
602                     これらのスレッドが起こされます。
603 
604       @param[in]    data    挿入する要素
605 
606       @return       無し。
607     */
Jam(uptr data)608     void Jam(uptr data) { Base::Jam(data); }
609 
610     /*!
611       @brief        キューの先頭への要素の挿入を試行します。
612 
613                     キューに空きがあれば、先頭に要素を挿入し、true を返します。
614                     キューに空きが無いとき、何もせず、false を返します。
615 
616                     要素の挿入がされたときに @ref Dequeue や @ref GetFront で待っているスレッドがあった場合、
617                     これらのスレッドが起こされます。
618 
619       @param[in]    data    挿入する要素
620 
621       @return       挿入されたとき true を返し、挿入されなかったとき false を返します。
622     */
TryJam(uptr data)623     bool TryJam(uptr data) { return Base::TryJam(data); }
624 
625     /*!
626       @brief        キューの先頭から要素を取り出します。
627 
628                     キューが空であるとき、キューが空でなくなるまでスレッドをブロックします。
629                     キューが空でなければ、キューの先頭から要素を取り出しすぐに処理を返します。
630 
631                     @ref Enqueue や @ref Jam で待っているスレッドがあった場合、
632                     これらのスレッドが起こされます。
633 
634       @return       キューから取り出した要素
635     */
Dequeue()636     uptr Dequeue() { return Base::Dequeue(); }
637 
638     /*!
639       @brief        キューの先頭から要素を取り出します。
640 
641                     キューが空でなれば、キューの先頭から要素を取り出し、true を返します。
642                     キューが空のとき、何もせず、false を返します。
643 
644                     要素の挿入がされたときに @ref Dequeue や @ref GetFront で待っているスレッドがあった場合、
645                     これらのスレッドが起こされます。
646 
647       @param[out]   pOut    取り出した要素を書き込むバッファ
648 
649       @return       要素を取り出したとき true を返し、取り出さなかったとき false を返します。
650     */
TryDequeue(uptr * pOut)651     bool TryDequeue(uptr* pOut) { return Base::TryDequeue(pOut); }
652 
653     /*!
654       @brief        キューの先頭から要素を取得します。
655 
656                     キューが空であるとき、キューが空でなくなるまでスレッドをブロックします。
657                     キューが空でなければ、キューの先頭の要素を取得します。キューの状態は変化しません。
658 
659       @return       キューの先頭の要素
660     */
GetFront()661     uptr GetFront() const { return Base::GetFront(); }
662 
663     /*!
664       @brief        キューの先頭から要素を取得します。
665 
666                     キューが空であるとき、何もせず false を返します。
667                     キューが空でなければ、キューの先頭の要素を *pOut に書き込み、true を返します。キューの状態は変化しません。
668 
669       @param[out]   pOut        取り出す値の格納先
670 
671       @return       要素を取得できたとき true を返し、取得できなかったとき false を返します。
672     */
TryGetFront(uptr * pOut)673     bool TryGetFront(uptr* pOut) const { return Base::TryGetFront(pOut); }
674 
675     // TODO: テスト用
676     using Base::GetSize;
677     using Base::GetUsedCount;
678     using Base::GetFirstIndex;
679 
680 };
681 
682 }}
683 
684 #endif
685 
686 // 以下、C 用宣言
687 
688 #include <nn/util/detail/util_CLibImpl.h>
689 
690 /*!
691   @addtogroup   nn_os                   os
692   @{
693 
694   @defgroup     nn_os_BlockingQueue_c   BlockingQueue (C)
695 
696   @brief        @ref nn::os::BlockingQueue の C インタフェースモジュールです。
697 
698   @{
699 */
700 
701 
702 /*!
703   @struct       nnosBlockingQueue
704   @brief        ブロッキングキューを表す C の構造体です。
705 
706   @brief 対応するクラス @ref nn::os::BlockingQueue を参照してください。
707 */
708 NN_UTIL_DETAIL_CLIBIMPL_DEFINE_BUFFER_CLASS(nnosBlockingQueue, nn::os::BlockingQueue, 40 + NN_OS_CRITICALSECTION_SIZE, u32);
709 
710 /*!
711   @brief 対応する C++ 関数を参照してください。@ref nn::os::BlockingQueue::Initialize
712 */
713 NN_EXTERN_C void nnosBlockingQueueInitialize(nnosBlockingQueue* this_, uptr buffer[], size_t size);
714 
715 /*!
716   @brief 対応する C++ 関数を参照してください。@ref nn::os::BlockingQueue::TryInitialize
717 */
718 NN_EXTERN_C bool nnosBlockingQueueTryInitialize(nnosBlockingQueue* this_, uptr buffer[], size_t size);
719 
720 /*!
721   @brief 対応する C++ 関数を参照してください。@ref nn::os::BlockingQueue::Finalize
722 */
723 NN_EXTERN_C void nnosBlockingQueueFinalize(nnosBlockingQueue* this_);
724 
725 /*!
726   @brief 対応する C++ 関数を参照してください。@ref nn::os::BlockingQueue::TryEnqueue
727 */
728 NN_EXTERN_C bool nnosBlockingQueueTryEnqueue(nnosBlockingQueue* this_, uptr data);
729 
730 /*!
731   @brief 対応する C++ 関数を参照してください。@ref nn::os::BlockingQueue::Enqueue
732 */
733 NN_EXTERN_C void nnosBlockingQueueEnqueue(nnosBlockingQueue* this_, uptr data);
734 
735 /*!
736   @brief 対応する C++ 関数を参照してください。@ref nn::os::BlockingQueue::TryJam
737 */
738 NN_EXTERN_C bool nnosBlockingQueueTryJam(nnosBlockingQueue* this_, uptr data);
739 
740 /*!
741   @brief 対応する C++ 関数を参照してください。@ref nn::os::BlockingQueue::Jam
742 */
743 NN_EXTERN_C void nnosBlockingQueueJam(nnosBlockingQueue* this_, uptr data);
744 
745 /*!
746   @brief 対応する C++ 関数を参照してください。@ref nn::os::BlockingQueue::TryDequeue
747 */
748 NN_EXTERN_C bool nnosBlockingQueueTryDequeue(nnosBlockingQueue* this_, uptr* pOut);
749 
750 /*!
751   @brief 対応する C++ 関数を参照してください。@ref nn::os::BlockingQueue::Dequeue
752 */
753 NN_EXTERN_C uptr nnosBlockingQueueDequeue(nnosBlockingQueue* this_);
754 
755 /*!
756   @brief 対応する C++ 関数を参照してください。@ref nn::os::BlockingQueue::TryGetFront
757 */
758 NN_EXTERN_C bool nnosBlockingQueueTryGetFront(nnosBlockingQueue* this_, uptr* pOut);
759 
760 /*!
761   @brief 対応する C++ 関数を参照してください。@ref nn::os::BlockingQueue::GetFront
762 */
763 NN_EXTERN_C uptr nnosBlockingQueueGetFront(nnosBlockingQueue* this_);
764 
765 /*!
766   @}
767 
768   @}
769 */
770 
771 
772 /*!
773   @addtogroup   nn_os                   os
774   @{
775 
776   @defgroup     nn_os_SafeBlockingQueue_c   SafeBlockingQueue (C)
777 
778   @brief        @ref nn::os::SafeBlockingQueue の C インタフェースモジュールです。
779 
780   @{
781 */
782 
783 /*!
784   @struct       nnosSafeBlockingQueue
785   @brief        セーフブロッキングキューを表す C の構造体です。
786 
787   @brief 対応するクラス @ref nn::os::SafeBlockingQueue を参照してください。
788 */
789 NN_UTIL_DETAIL_CLIBIMPL_DEFINE_BUFFER_CLASS(nnosSafeBlockingQueue, nn::os::SafeBlockingQueue, 44, u32);
790 
791 /*!
792   @brief 対応する C++ 関数を参照してください。@ref nn::os::SafeBlockingQueue::Initialize
793 */
794 NN_EXTERN_C void nnosSafeBlockingQueueInitialize(nnosSafeBlockingQueue* this_, uptr buffer[], size_t size);
795 
796 /*!
797   @brief 対応する C++ 関数を参照してください。@ref nn::os::SafeBlockingQueue::TryInitialize
798 */
799 NN_EXTERN_C bool nnosSafeBlockingQueueTryInitialize(nnosSafeBlockingQueue* this_, uptr buffer[], size_t size);
800 
801 /*!
802   @brief 対応する C++ 関数を参照してください。@ref nn::os::SafeBlockingQueue::Finalize
803 */
804 NN_EXTERN_C void nnosSafeBlockingQueueFinalize(nnosSafeBlockingQueue* this_);
805 
806 /*!
807   @brief 対応する C++ 関数を参照してください。@ref nn::os::SafeBlockingQueue::TryEnqueue
808 */
809 NN_EXTERN_C bool nnosSafeBlockingQueueTryEnqueue(nnosSafeBlockingQueue* this_, uptr data);
810 
811 /*!
812   @brief 対応する C++ 関数を参照してください。@ref nn::os::SafeBlockingQueue::Enqueue
813 
814 */
815 NN_EXTERN_C void nnosSafeBlockingQueueEnqueue(nnosSafeBlockingQueue* this_, uptr data);
816 
817 /*!
818   @brief 対応する C++ 関数を参照してください。@ref nn::os::SafeBlockingQueue::TryJam
819 
820 */
821 NN_EXTERN_C bool nnosSafeBlockingQueueTryJam(nnosSafeBlockingQueue* this_, uptr data);
822 
823 /*!
824   @brief 対応する C++ 関数を参照してください。@ref nn::os::SafeBlockingQueue::Jam
825 
826 */
827 NN_EXTERN_C void nnosSafeBlockingQueueJam(nnosSafeBlockingQueue* this_, uptr data);
828 
829 /*!
830   @brief 対応する C++ 関数を参照してください。@ref nn::os::SafeBlockingQueue::TryDequeue
831 
832 */
833 NN_EXTERN_C bool nnosSafeBlockingQueueTryDequeue(nnosSafeBlockingQueue* this_, uptr* pOut);
834 
835 /*!
836   @brief 対応する C++ 関数を参照してください。@ref nn::os::SafeBlockingQueue::Dequeue
837 
838 */
839 NN_EXTERN_C uptr nnosSafeBlockingQueueDequeue(nnosSafeBlockingQueue* this_);
840 
841 /*!
842   @brief 対応する C++ 関数を参照してください。@ref nn::os::SafeBlockingQueue::TryGetFront
843 
844 */
845 NN_EXTERN_C bool nnosSafeBlockingQueueTryGetFront(nnosSafeBlockingQueue* this_, uptr* pOut);
846 
847 /*!
848   @brief 対応する C++ 関数を参照してください。@ref nn::os::SafeBlockingQueue::GetFront
849 
850 */
851 NN_EXTERN_C uptr nnosSafeBlockingQueueGetFront(nnosSafeBlockingQueue* this_);
852 
853 
854 /*!
855   @}
856 
857   @}
858 */
859 
860 #endif
861