2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * @file waitable_handle.cpp
18 * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
20 * @brief This file is the implementation file of waitable handle
23 #include <dpl/waitable_event.h>
24 #include <dpl/workaround.h>
25 #include <sys/select.h>
29 #include <dpl/assert.h>
32 namespace // anonymous
34 void CheckWaitableHandle(WaitableHandle handle)
36 #ifdef DPL_ENABLE_WAITABLE_HANDLE_BADF_CHECK
37 // Try to get descriptor flags
38 int result = fcntl(handle, F_GETFL);
40 if (result == -1 && errno == EBADF) {
41 AssertMsg(0, "CheckWaitableHandle: Invalid WaitableHandle! (EBADF)");
44 AssertMsg(result != -1, "CheckWaitableHandle: Invalid WaitableHandle!");
45 #endif // DPL_ENABLE_WAITABLE_HANDLE_BADF_CHECK
47 } // namespace anonymous
49 WaitableHandleIndexList WaitForSingleHandle(WaitableHandle handle,
50 unsigned long miliseconds)
52 WaitableHandleList waitHandles;
53 waitHandles.push_back(handle);
54 return WaitForMultipleHandles(waitHandles, miliseconds);
57 WaitableHandleIndexList WaitForSingleHandle(WaitableHandle handle,
59 unsigned long miliseconds)
61 WaitableHandleListEx waitHandles;
62 waitHandles.push_back(std::make_pair(handle, mode));
63 return WaitForMultipleHandles(waitHandles, miliseconds);
66 WaitableHandleIndexList WaitForMultipleHandles(
67 const WaitableHandleList &waitableHandleList,
68 unsigned long miliseconds)
70 WaitableHandleListEx handleList;
72 for (WaitableHandleList::const_iterator iterator = waitableHandleList.begin();
73 iterator != waitableHandleList.end();
76 // Wait for multiple objects
77 handleList.push_back(std::make_pair(*iterator, WaitMode::Read));
81 return WaitForMultipleHandles(handleList, miliseconds);
84 WaitableHandleIndexList WaitForMultipleHandles(
85 const WaitableHandleListEx &waitableHandleListEx,
86 unsigned long miliseconds)
88 fd_set readFds, writeFds, errorFds;
97 // Add read wait handles
98 for (WaitableHandleListEx::const_iterator iterator =
99 waitableHandleListEx.begin();
100 iterator != waitableHandleListEx.end();
103 if (iterator->first > maxFd) {
104 maxFd = iterator->first;
107 CheckWaitableHandle(iterator->first);
109 // Handle errors along with read and write events
110 FD_SET(iterator->first, &errorFds);
112 if (iterator->second == WaitMode::Read) {
113 FD_SET(iterator->first, &readFds);
114 } else if (iterator->second == WaitMode::Write) {
115 FD_SET(iterator->first, &writeFds);
121 timeval *effectiveTimeout = NULL;
122 if (miliseconds != 0xFFFFFFFF) {
123 timeout.tv_sec = miliseconds / 1000;
124 timeout.tv_usec = (miliseconds % 1000) * 1000;
125 effectiveTimeout = &timeout;
128 if (TEMP_FAILURE_RETRY(select(maxFd + 1, &readFds, &writeFds, &errorFds,
129 effectiveTimeout)) == -1)
135 WaitableHandleIndexList indexes;
138 for (WaitableHandleListEx::const_iterator iterator =
139 waitableHandleListEx.begin();
140 iterator != waitableHandleListEx.end();
143 // Always return errors, no matter what type of listening is set
144 if (FD_ISSET(iterator->first, &errorFds)) {
145 indexes.push_back(index);
146 } else if (iterator->second == WaitMode::Read) {
147 if (FD_ISSET(iterator->first, &readFds)) {
148 indexes.push_back(index);
150 } else if (iterator->second == WaitMode::Write) {
151 if (FD_ISSET(iterator->first, &writeFds)) {
152 indexes.push_back(index);
158 // Successfuly awaited some events or timeout occurred