tizen 2.3.1 release
[framework/web/wearable/wrt-security.git] / commons / modules / core / src / waitable_handle.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  * @file        waitable_handle.cpp
18  * @author      Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
19  * @version     1.0
20  * @brief       This file is the implementation file of waitable handle
21  */
22 #include <stddef.h>
23 #include <dpl/waitable_event.h>
24 #include <dpl/workaround.h>
25 #include <dpl/log/log.h>
26 #include <sys/select.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <errno.h>
30 #include <dpl/assert.h>
31
32 namespace DPL {
33 namespace // anonymous
34 {
35 void CheckWaitableHandle(WaitableHandle handle)
36 {
37 #ifdef DPL_ENABLE_WAITABLE_HANDLE_BADF_CHECK
38     // Try to get descriptor flags
39     int result = fcntl(handle, F_GETFL);
40
41     if (result == -1 && errno == EBADF) {
42         AssertMsg(0, "CheckWaitableHandle: Invalid WaitableHandle! (EBADF)");
43     }
44
45     AssertMsg(result != -1, "CheckWaitableHandle: Invalid WaitableHandle!");
46 #endif // DPL_ENABLE_WAITABLE_HANDLE_BADF_CHECK
47 }
48 } // namespace anonymous
49
50 WaitableHandleIndexList WaitForSingleHandle(WaitableHandle handle,
51                                             unsigned long miliseconds)
52 {
53     WaitableHandleList waitHandles;
54     waitHandles.push_back(handle);
55     return WaitForMultipleHandles(waitHandles, miliseconds);
56 }
57
58 WaitableHandleIndexList WaitForSingleHandle(WaitableHandle handle,
59                                             WaitMode::Type mode,
60                                             unsigned long miliseconds)
61 {
62     WaitableHandleListEx waitHandles;
63     waitHandles.push_back(std::make_pair(handle, mode));
64     return WaitForMultipleHandles(waitHandles, miliseconds);
65 }
66
67 WaitableHandleIndexList WaitForMultipleHandles(
68     const WaitableHandleList &waitableHandleList,
69     unsigned long miliseconds)
70 {
71     WaitableHandleListEx handleList;
72
73     for (WaitableHandleList::const_iterator iterator = waitableHandleList.begin();
74          iterator != waitableHandleList.end();
75          ++iterator)
76     {
77         // Wait for multiple objects
78         handleList.push_back(std::make_pair(*iterator, WaitMode::Read));
79     }
80
81     // Do waiting
82     return WaitForMultipleHandles(handleList, miliseconds);
83 }
84
85 WaitableHandleIndexList WaitForMultipleHandles(
86     const WaitableHandleListEx &waitableHandleListEx,
87     unsigned long miliseconds)
88 {
89     fd_set readFds, writeFds, errorFds;
90
91     // Fill sets
92     int maxFd = -1;
93
94     FD_ZERO(&readFds);
95     FD_ZERO(&writeFds);
96     FD_ZERO(&errorFds);
97
98     // Add read wait handles
99     for (WaitableHandleListEx::const_iterator iterator =
100              waitableHandleListEx.begin();
101          iterator != waitableHandleListEx.end();
102          ++iterator)
103     {
104         if (iterator->first > maxFd) {
105             maxFd = iterator->first;
106         }
107
108         CheckWaitableHandle(iterator->first);
109
110         // Handle errors along with read and write events
111         FD_SET(iterator->first, &errorFds);
112
113         if (iterator->second == WaitMode::Read) {
114             FD_SET(iterator->first, &readFds);
115         } else if (iterator->second == WaitMode::Write) {
116             FD_SET(iterator->first, &writeFds);
117         }
118     }
119
120     // Do select
121     timeval timeout;
122     timeval *effectiveTimeout = NULL;
123     if (miliseconds != 0xFFFFFFFF) {
124         timeout.tv_sec = miliseconds / 1000;
125         timeout.tv_usec = (miliseconds % 1000) * 1000;
126         effectiveTimeout = &timeout;
127     }
128
129     if (TEMP_FAILURE_RETRY(select(maxFd + 1, &readFds, &writeFds, &errorFds,
130                                   effectiveTimeout)) == -1)
131     {
132         Throw(WaitFailed);
133     }
134
135     // Check results
136     WaitableHandleIndexList indexes;
137     size_t index = 0;
138
139     for (WaitableHandleListEx::const_iterator iterator =
140              waitableHandleListEx.begin();
141          iterator != waitableHandleListEx.end();
142          ++iterator)
143     {
144         // Always return errors, no matter what type of listening is set
145         if (FD_ISSET(iterator->first, &errorFds)) {
146             indexes.push_back(index);
147         } else if (iterator->second == WaitMode::Read) {
148             if (FD_ISSET(iterator->first, &readFds)) {
149                 indexes.push_back(index);
150             }
151         } else if (iterator->second == WaitMode::Write) {
152             if (FD_ISSET(iterator->first, &writeFds)) {
153                 indexes.push_back(index);
154             }
155         }
156         ++index;
157     }
158
159     // Successfuly awaited some events or timeout occurred
160     return indexes;
161 }
162 } // namespace DPL