Initialize Tizen 2.3
[framework/web/wrt-commons.git] / modules_mobile / core / include / dpl / task.h
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @file    task.h
18  * @author  Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
19  * @author  Radoslaw Wicik (r.wicik@samsung.com)
20  * @version 1.0
21  * @brief   Header file for abstaract task definition
22  */
23 #ifndef DPL_TASK_H
24 #define DPL_TASK_H
25
26 #include <dpl/noncopyable.h>
27 #include <dpl/foreach.h>
28 #include <dpl/assert.h>
29 #include <algorithm>
30 #include <list>
31
32 namespace DPL {
33 class TaskList;
34
35 class Task :
36     private Noncopyable
37 {
38   public:
39     virtual ~Task() {}
40
41     virtual bool NextStep() = 0;
42     virtual bool Abort() = 0;
43     virtual size_t GetStepCount() const = 0;
44 };
45
46 template<typename Impl>
47 class TaskDecl :
48     public Task
49 {
50   protected:
51     typedef void (Impl::*Step)();
52
53   private:
54     typedef std::list<Step> StepList;
55
56     StepList m_steps;
57     StepList m_abortSteps;
58     typename StepList::iterator m_currentStep;
59     typename StepList::iterator m_nextStep;
60     bool m_switched;
61
62     Impl *m_impl;
63     bool m_running;
64
65   protected:
66     void AddStep(Step step)
67     {
68         Assert(!m_running && "AddStep is not allowed after calling NextStep!");
69         Assert(m_steps.end() == std::find(m_steps.begin(),
70                                           m_steps.end(),
71                                           step) &&
72                "The same step started twice is not supported");
73         m_steps.push_back(step);
74         m_nextStep = m_steps.begin();
75     }
76
77     void AddAbortStep(Step step)
78     {
79         Assert(
80             !m_running && "AddAbortStep is not allowed after calling NextStep!");
81         Assert(m_abortSteps.end() ==
82                std::find(m_abortSteps.begin(),
83                          m_abortSteps.end(),
84                          step) &&
85                "The same step started twice is not supported");
86         m_abortSteps.push_front(step);
87     }
88
89     void SwitchToStep(Step step)
90     {
91         /// @TODO There can be problem here if user sets the same method two
92         // times in task list.
93         typename StepList::iterator i = std::find(m_steps.begin(),
94                                                   m_steps.end(), step);
95         Assert(i != m_steps.end());
96         m_nextStep = i;
97         m_switched = true;
98     }
99
100     Step GetCurrentStep() const
101     {
102         if (m_currentStep == m_steps.end()) {
103             return NULL;
104         }
105
106         return *m_currentStep;
107     }
108
109   public:
110     TaskDecl(Impl *impl) :
111         m_switched(false),
112         m_impl(impl),
113         m_running(false)
114     {
115         Assert(this == m_impl);
116         m_currentStep = m_steps.end();
117         m_nextStep = m_steps.end();
118     }
119
120     bool NextStep()
121     {
122         m_running = true;
123
124         Assert(
125             m_nextStep != m_steps.end() &&
126             "Step list is empty or all steps done");
127
128         m_switched = false;
129
130         Step call = *m_nextStep;
131         (*m_impl.*call)();
132
133         m_currentStep = m_nextStep;
134
135         if (m_switched) {
136             return true;
137         } else {
138             return ++m_nextStep != m_steps.end();
139         }
140     }
141
142     bool Abort()
143     {
144         m_running = true;
145
146         m_steps.clear();
147
148         if (m_abortSteps.empty()) {
149             return false;
150         }
151
152         FOREACH(it, m_abortSteps)
153         m_steps.push_back(*it);
154
155         m_nextStep = m_steps.begin();
156
157         m_abortSteps.clear();
158
159         return true;
160     }
161
162     size_t GetStepCount() const
163     {
164         return static_cast<size_t>(m_steps.size());
165     }
166 };
167 } // namespace DPL
168
169 #endif // DPL_TASK_H