1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     snd_TaskManager.cpp
4 
5   Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc.  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   $Revision: 29467 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "precompiled.h"
17 
18 #include <nw/snd/snd_TaskManager.h>
19 
20 namespace nw {
21 namespace snd {
22 namespace internal {
23 
24 /*---------------------------------------------------------------------------*
25   Name:         GetInstance
26 
27   Description:  シングルトンのインスタンスを取得する
28 
29   Arguments:    なし
30 
31   Returns:      インスタンス
32  *---------------------------------------------------------------------------*/
GetInstance()33 TaskManager& TaskManager::GetInstance()
34 {
35     static TaskManager instance;
36     return instance;
37 }
38 
39 /*---------------------------------------------------------------------------*
40   Name:         TaskManager
41 
42   Description:  コンストラクタ
43 
44   Arguments:    None.
45 
46   Returns:      None.
47  *---------------------------------------------------------------------------*/
TaskManager()48 TaskManager::TaskManager()
49 : m_pCurrentTask( NULL ),
50   m_IsWaitTaskCancel( false )
51 {
52 }
53 
Initialize()54 void TaskManager::Initialize()
55 {
56     m_CriticalSection.Initialize();
57     m_BlockingQueue.Initialize( m_MsgBuffer, THREAD_MESSAGE_BUFSIZE );
58 }
59 
Finalize()60 void TaskManager::Finalize()
61 {
62     m_CriticalSection.Finalize();
63     m_BlockingQueue.Finalize();
64 }
65 
66 /*---------------------------------------------------------------------------*
67   Name:         AppendTask
68 
69   Description:  タスクリストにタスクを登録
70 
71   Arguments:    task - 登録するタスク
72                 priority - タスクを登録するリストのプライオリティ
73 
74   Returns:      None.
75  *---------------------------------------------------------------------------*/
AppendTask(Task * task,TaskPriority priority)76 void TaskManager::AppendTask( Task* task, TaskPriority priority )
77 {
78     NW_MINMAXLT_ASSERT( priority, 0, PRIORITY_NUM );
79 
80     nn::os::CriticalSection::ScopedLock scopeLock(m_CriticalSection);
81 
82     task->m_Event.ClearSignal();
83     task->m_Status = Task::STATUS_APPEND;
84     m_TaskList[ priority ].PushBack( task );
85     m_BlockingQueue.TryEnqueue( static_cast<uptr>( MESSAGE_APPEND ) );
86 }
87 
88 /*---------------------------------------------------------------------------*
89   Name:         GetNextTask
90 
91   Description:  次のタスクを取得する
92 
93   Arguments:    priority - タスクを抜き出すリストのプライオリティ
94                 doRemove - リストから削除するかどうか
95 
96   Returns:      取得したタスク
97  *---------------------------------------------------------------------------*/
GetNextTask(TaskPriority priority,bool doRemove)98 Task* TaskManager::GetNextTask( TaskPriority priority, bool doRemove )
99 {
100     NW_MINMAXLT_ASSERT( priority, 0, PRIORITY_NUM );
101 
102     nn::os::CriticalSection::ScopedLock scopeLock(m_CriticalSection);
103 
104     if ( m_TaskList[ priority ].IsEmpty() ) return NULL;
105 
106     Task* task = &m_TaskList[ priority ].GetFront();
107     if ( doRemove ) {
108         m_TaskList[ priority ].PopFront();
109     }
110     return task;
111 }
112 
113 /*---------------------------------------------------------------------------*
114   Name:         PopTask
115 
116   Description:  最優先のタスクを取り出す
117 
118   Arguments:    なし
119 
120   Returns:      取り出したタスク
121  *---------------------------------------------------------------------------*/
PopTask()122 Task* TaskManager::PopTask()
123 {
124     nn::os::CriticalSection::ScopedLock scopeLock(m_CriticalSection);
125 
126     Task* task = GetNextTask( PRIORITY_HIGH, true );
127     if ( task != NULL ) return task;
128 
129     task = GetNextTask( PRIORITY_MIDDLE, true );
130     if ( task != NULL ) return task;
131 
132     task = GetNextTask( PRIORITY_LOW, true );
133     if ( task != NULL ) return task;
134 
135     return NULL;
136 }
137 
138 /*---------------------------------------------------------------------------*
139   Name:         PopTask
140 
141   Description:  最優先のタスクを取得する(リストから削除しない)
142 
143   Arguments:    なし
144 
145   Returns:      取得したタスク
146  *---------------------------------------------------------------------------*/
GetNextTask()147 Task* TaskManager::GetNextTask()
148 {
149     Task* task = GetNextTask( PRIORITY_HIGH, false );
150     if ( task != NULL ) return task;
151 
152     task = GetNextTask( PRIORITY_MIDDLE, false );
153     if ( task != NULL ) return task;
154 
155     task = GetNextTask( PRIORITY_LOW, false );
156     if ( task != NULL ) return task;
157 
158     return NULL;
159 }
160 
161 /*---------------------------------------------------------------------------*
162   Name:         ExecuteTask
163 
164   Description:  全てのタスクを実行する
165 
166   Arguments:    None.
167 
168   Returns:      None.
169  *---------------------------------------------------------------------------*/
ExecuteTask()170 void TaskManager::ExecuteTask()
171 {
172     while ( 1 )
173     {
174         Task* task = PopTask();
175         if ( task == NULL ) break;
176 
177         m_pCurrentTask = task;
178 
179         task->Execute();
180         task->m_Status = Task::STATUS_DONE;
181         task->m_Event.Signal();
182         m_pCurrentTask = NULL;
183     }
184 }
185 
186 /*---------------------------------------------------------------------------*
187   Name:         CancelTask
188 
189   Description:  タスクをキャンセルする
190 
191   Arguments:    task - キャンセルするタスク
192 
193   Returns:      None.
194  *---------------------------------------------------------------------------*/
CancelTask(Task * task)195 void TaskManager::CancelTask( Task* task )
196 {
197     if ( RemoveTask(task) ) {
198         return;
199     }
200 
201     task->m_Event.Wait();
202 }
203 
204 /*---------------------------------------------------------------------------*
205   Name:         CancelTaskById
206 
207   Description:  ID指定で、タスクをキャンセルする
208 
209   Arguments:    id - キャンセルするタスクのID
210 
211   Returns:      None.
212  *---------------------------------------------------------------------------*/
CancelTaskById(u32 id)213 void TaskManager::CancelTaskById( u32 id )
214 {
215     RemoveTaskById(id);
216 }
217 
218 /*---------------------------------------------------------------------------*
219   Name:         CancelAllTask
220 
221   Description:  全タスクをキャンセルする
222 
223   Arguments:    None.
224 
225   Returns:      None.
226  *---------------------------------------------------------------------------*/
CancelAllTask()227 void TaskManager::CancelAllTask()
228 {
229     // TODO
230 }
231 
232 /*---------------------------------------------------------------------------*
233   Name:         RemoveTask
234 
235   Description:  タスクを削除する
236 
237   Arguments:    task - 削除するタスク
238 
239   Returns:      削除できたかどうか
240  *---------------------------------------------------------------------------*/
RemoveTask(Task * task)241 bool TaskManager::RemoveTask( Task* task )
242 {
243     nn::os::CriticalSection::ScopedLock scopeLock(m_CriticalSection);
244 
245     for ( int i=0; i<PRIORITY_NUM; i++ )
246     {
247         TaskPriority priority = static_cast<TaskPriority>( i );
248         TaskList::Iterator itr = m_TaskList[ priority ].GetBeginIter();
249         while ( itr != m_TaskList[ priority ].GetEndIter() )
250         {
251             TaskList::Iterator curItr = itr++;
252             if ( &*curItr == task ) {
253                 m_TaskList[ priority ].Erase( curItr );
254                 curItr->m_Status = Task::STATUS_CANCEL;
255                 curItr->m_Event.Signal();
256                 return true;
257             }
258         }
259     }
260 
261     return false;
262 }
263 
264 
265 /*---------------------------------------------------------------------------*
266   Name:         RemoveTaskById
267 
268   Description:  タスクを削除する
269 
270   Arguments:    id - 削除するタスクのID
271 
272   Returns:      None.
273  *---------------------------------------------------------------------------*/
RemoveTaskById(u32 id)274 void TaskManager::RemoveTaskById( u32 id )
275 {
276     nn::os::CriticalSection::ScopedLock scopeLock(m_CriticalSection);
277 
278     for ( int i=0; i<PRIORITY_NUM; i++ )
279     {
280         TaskPriority priority = static_cast<TaskPriority>( i );
281         TaskList::Iterator itr = m_TaskList[ priority ].GetBeginIter();
282         while ( itr != m_TaskList[ priority ].GetEndIter() )
283         {
284             TaskList::Iterator curItr = itr++;
285             if ( curItr->m_Id == id ) {
286                 m_TaskList[ priority ].Erase( curItr );
287                 curItr->m_Status = Task::STATUS_CANCEL;
288                 curItr->m_Event.Signal();
289             }
290         }
291     }
292 }
293 
294 
295 /*---------------------------------------------------------------------------*
296   Name:         WaitTask
297 
298   Description:  タスクが登録されるまで待つ
299 
300   Arguments:    None.
301 
302   Returns:      None.
303  *---------------------------------------------------------------------------*/
WaitTask()304 void TaskManager::WaitTask()
305 {
306     m_IsWaitTaskCancel = false;
307 
308     while( GetNextTask() == NULL && ! m_IsWaitTaskCancel )
309     {
310         if ( m_BlockingQueue.Dequeue() == MESSAGE_APPEND )
311         {
312             break;
313         }
314     }
315 }
316 
317 /*---------------------------------------------------------------------------*
318   Name:         CancelWaitTask
319 
320   Description:  WaitTaskの処理をキャンセルする
321 
322   Arguments:    None.
323 
324   Returns:      None.
325  *---------------------------------------------------------------------------*/
CancelWaitTask()326 void TaskManager::CancelWaitTask()
327 {
328     m_IsWaitTaskCancel = true;
329 
330     m_BlockingQueue.Enqueue( static_cast<uptr>( MESSAGE_APPEND ) );
331 }
332 
333 } // namespace nw::snd::internal
334 } // namespace nw::snd
335 } // namespace nw
336 
337