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