Tizen 2.0 Release
[framework/web/wrt-commons.git] / modules / event / src / nested_loop.cpp
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  * This file contains the definition of the NestedLoopManager class.
18  *
19  * @file    nested_loop.cpp
20  * @author  Lukasz Marek (l.marek@samsung.com)
21  * @version 0.1
22  * @brief   This file contains the definition of the NestedLoopManager class.
23  */
24
25 #include <dpl/event/nested_loop.h>
26 #include <algorithm>
27 #include <Ecore.h>
28 #include <dpl/log/log.h>
29 #include <dpl/assert.h>
30 #include <dpl/singleton_impl.h>
31
32 IMPLEMENT_SINGLETON(DPL::Event::NestedLoopManager)
33
34 namespace DPL
35 {
36 namespace Event
37 {
38
39 NestedLoopManager::NestedLoopManager() : m_eventGuard(false),
40     m_handle(0)
41 {
42     Touch();
43 }
44
45 NestedLoopManager::~NestedLoopManager()
46 {
47 }
48
49 void* NestedLoopManager::begin(LoopHandle loopHandle)
50 {
51     LoopInformation info(loopHandle);
52     m_runningLoops.push_back(info);
53     LogPedantic("Nested loop begin. Nested loop level: " << getLevel());
54
55     ecore_main_loop_begin();
56
57     Assert(m_runningLoops.size() && "No loop on the stack");
58
59     info = m_runningLoops.back();
60     m_runningLoops.pop_back();
61
62     Assert(info.loopHandle == loopHandle && "You exit from wrong loop");
63     Assert(info.exitFlag == true && "Exit flag not set");
64
65     LogPedantic("Nested loop quit. Nested loop level: " << getLevel());
66
67     if (!m_runningLoops.empty() && m_runningLoops.back().exitFlag &&
68         !m_eventGuard) {
69         m_eventGuard = true;
70         LoopExitEvent event;
71         PostEvent(event);
72     }
73     return info.userParam;
74 }
75
76 void NestedLoopManager::exit(LoopHandle loopHandle,
77         void *userParam)
78 {
79     RunningLoopsListIterator iterator = std::find_if(
80             m_runningLoops.begin(),
81             m_runningLoops.end(),
82             RunningLoopsHandlePredicate(loopHandle));
83
84     Assert(iterator != m_runningLoops.end() && "Unknown loopHandle");
85     Assert(iterator->exitFlag == false && "You cannot close a loop twice.");
86
87     iterator->exitFlag = true;
88     iterator->userParam = userParam;
89
90     if (m_runningLoops.back().exitFlag && !m_eventGuard) {
91         m_eventGuard = true;
92         LoopExitEvent event;
93         PostEvent(event);
94     }
95 }
96
97 size_t NestedLoopManager::getLevel() const
98 {
99     return m_runningLoops.size();
100 }
101
102 LoopHandle NestedLoopManager::getNewHandle()
103 {
104     return m_handle++;
105 }
106
107 void NestedLoopManager::OnEventReceived(const LoopExitEvent& event)
108 {
109     (void)event;
110     Assert(!m_runningLoops.empty());
111     m_eventGuard = false; // no event in queue
112     if (m_runningLoops.back().exitFlag) {
113         //exit loop when last started one is readu to finish
114         //this will post event if next loop is ready to exit
115         ecore_main_loop_quit();
116     }
117 }
118
119 }
120 }