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: 17972 $
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_Event.Signal();
181         task->m_Status = Task::STATUS_DONE;
182 
183         m_pCurrentTask = NULL;
184     }
185 }
186 
187 /*---------------------------------------------------------------------------*
188   Name:         CancelTask
189 
190   Description:  タスクをキャンセルする
191 
192   Arguments:    task - キャンセルするタスク
193 
194   Returns:      None.
195  *---------------------------------------------------------------------------*/
CancelTask(Task * task)196 void TaskManager::CancelTask( Task* task )
197 {
198     if ( RemoveTask(task) ) {
199         return;
200     }
201 
202     task->m_Event.Wait();
203 }
204 
205 /*---------------------------------------------------------------------------*
206   Name:         CancelTaskById
207 
208   Description:  ID指定で、タスクをキャンセルする
209 
210   Arguments:    id - キャンセルするタスクのID
211 
212   Returns:      None.
213  *---------------------------------------------------------------------------*/
CancelTaskById(u32 id)214 void TaskManager::CancelTaskById( u32 id )
215 {
216     RemoveTaskById(id);
217 }
218 
219 /*---------------------------------------------------------------------------*
220   Name:         CancelAllTask
221 
222   Description:  全タスクをキャンセルする
223 
224   Arguments:    None.
225 
226   Returns:      None.
227  *---------------------------------------------------------------------------*/
CancelAllTask()228 void TaskManager::CancelAllTask()
229 {
230     // TODO
231 }
232 
233 /*---------------------------------------------------------------------------*
234   Name:         RemoveTask
235 
236   Description:  タスクを削除する
237 
238   Arguments:    task - 削除するタスク
239 
240   Returns:      削除できたかどうか
241  *---------------------------------------------------------------------------*/
RemoveTask(Task * task)242 bool TaskManager::RemoveTask( Task* task )
243 {
244     nn::os::CriticalSection::ScopedLock scopeLock(m_CriticalSection);
245 
246     for ( int i=0; i<PRIORITY_NUM; i++ )
247     {
248         TaskPriority priority = static_cast<TaskPriority>( i );
249         TaskList::Iterator itr = m_TaskList[ priority ].GetBeginIter();
250         while ( itr != m_TaskList[ priority ].GetEndIter() )
251         {
252             TaskList::Iterator curItr = itr++;
253             if ( &*curItr == task ) {
254                 m_TaskList[ priority ].Erase( curItr );
255                 curItr->m_Event.Signal();
256                 curItr->m_Status = Task::STATUS_CANCEL;
257                 return true;
258             }
259         }
260     }
261 
262     return false;
263 }
264 
265 
266 /*---------------------------------------------------------------------------*
267   Name:         RemoveTaskById
268 
269   Description:  タスクを削除する
270 
271   Arguments:    id - 削除するタスクのID
272 
273   Returns:      None.
274  *---------------------------------------------------------------------------*/
RemoveTaskById(u32 id)275 void TaskManager::RemoveTaskById( u32 id )
276 {
277     nn::os::CriticalSection::ScopedLock scopeLock(m_CriticalSection);
278 
279     for ( int i=0; i<PRIORITY_NUM; i++ )
280     {
281         TaskPriority priority = static_cast<TaskPriority>( i );
282         TaskList::Iterator itr = m_TaskList[ priority ].GetBeginIter();
283         while ( itr != m_TaskList[ priority ].GetEndIter() )
284         {
285             TaskList::Iterator curItr = itr++;
286             if ( curItr->m_Id == id ) {
287                 m_TaskList[ priority ].Erase( curItr );
288                 curItr->m_Event.Signal();
289                 curItr->m_Status = Task::STATUS_CANCEL;
290             }
291         }
292     }
293 }
294 
295 
296 /*---------------------------------------------------------------------------*
297   Name:         WaitTask
298 
299   Description:  タスクが登録されるまで待つ
300 
301   Arguments:    None.
302 
303   Returns:      None.
304  *---------------------------------------------------------------------------*/
WaitTask()305 void TaskManager::WaitTask()
306 {
307     m_IsWaitTaskCancel = false;
308 
309     while( GetNextTask() == NULL && ! m_IsWaitTaskCancel )
310     {
311         if ( m_BlockingQueue.Dequeue() == MESSAGE_APPEND )
312         {
313             break;
314         }
315     }
316 }
317 
318 /*---------------------------------------------------------------------------*
319   Name:         CancelWaitTask
320 
321   Description:  WaitTaskの処理をキャンセルする
322 
323   Arguments:    None.
324 
325   Returns:      None.
326  *---------------------------------------------------------------------------*/
CancelWaitTask()327 void TaskManager::CancelWaitTask()
328 {
329     m_IsWaitTaskCancel = true;
330 
331     m_BlockingQueue.Enqueue( static_cast<uptr>( MESSAGE_APPEND ) );
332 }
333 
334 } // namespace nw::snd::internal
335 } // namespace nw::snd
336 } // namespace nw
337 
338