Initialize Tizen 2.3
[framework/web/wrt-commons.git] / modules / 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
34 class Task :
35     private Noncopyable
36 {
37   public:
38     virtual ~Task() {}
39
40     virtual bool NextStep() = 0;
41     virtual bool Abort() = 0;
42     virtual size_t GetStepCount() const = 0;
43 };
44
45 template<typename Impl>
46 class TaskDecl :
47     public Task
48 {
49   protected:
50     typedef void (Impl::*Step)();
51
52   private:
53     typedef std::list<Step> StepList;
54
55     StepList m_steps;
56     StepList m_abortSteps;
57     typename StepList::iterator m_currentStep;
58     typename StepList::iterator m_nextStep;
59     bool m_switched;
60
61     Impl *m_impl;
62     bool m_running;
63
64   protected:
65     void AddStep(Step step)
66     {
67         Assert(!m_running && "AddStep is not allowed after calling NextStep!");
68         Assert(m_steps.end() == std::find(m_steps.begin(),
69                                           m_steps.end(),
70                                           step) &&
71                "The same step started twice is not supported");
72         m_steps.push_back(step);
73         m_nextStep = m_steps.begin();
74     }
75
76     void AddAbortStep(Step step)
77     {
78         Assert(
79             !m_running && "AddAbortStep is not allowed after calling NextStep!");
80         Assert(m_abortSteps.end() ==
81                std::find(m_abortSteps.begin(),
82                          m_abortSteps.end(),
83                          step) &&
84                "The same step started twice is not supported");
85         m_abortSteps.push_front(step);
86     }
87
88     void SwitchToStep(Step step)
89     {
90         /// @TODO There can be problem here if user sets the same method two
91         // times in task list.
92         typename StepList::iterator i = std::find(m_steps.begin(),
93                                                   m_steps.end(), step);
94         Assert(i != m_steps.end());
95         m_nextStep = i;
96         m_switched = true;
97     }
98
99     Step GetCurrentStep() const
100     {
101         if (m_currentStep == m_steps.end()) {
102             return NULL;
103         }
104
105         return *m_currentStep;
106     }
107
108   public:
109     TaskDecl(Impl *impl) :
110         m_switched(false),
111         m_impl(impl),
112         m_running(false)
113     {
114         Assert(this == m_impl);
115         m_currentStep = m_steps.end();
116         m_nextStep = m_steps.end();
117     }
118
119     bool NextStep()
120     {
121         m_running = true;
122
123         Assert(
124             m_nextStep != m_steps.end() &&
125             "Step list is empty or all steps done");
126
127         m_switched = false;
128
129         Step call = *m_nextStep;
130         (*m_impl.*call)();
131
132         m_currentStep = m_nextStep;
133
134         if (m_switched) {
135             return true;
136         } else {
137             return ++m_nextStep != m_steps.end();
138         }
139     }
140
141     bool Abort()
142     {
143         m_running = true;
144
145         m_steps.clear();
146
147         if (m_abortSteps.empty()) {
148             return false;
149         }
150
151         FOREACH(it, m_abortSteps)
152         m_steps.push_back(*it);
153
154         m_nextStep = m_steps.begin();
155
156         m_abortSteps.clear();
157
158         return true;
159     }
160
161     size_t GetStepCount() const
162     {
163         return static_cast<size_t>(m_steps.size());
164     }
165 };
166 } // namespace DPL
167
168 #endif // DPL_TASK_H