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 <dpl/log/log.h>
26 #include <sys/select.h>
30 #include <dpl/assert.h>
33 namespace // anonymous
35 void CheckWaitableHandle(WaitableHandle handle)
37 #ifdef DPL_ENABLE_WAITABLE_HANDLE_BADF_CHECK
38 // Try to get descriptor flags
39 int result = fcntl(handle, F_GETFL);
41 if (result == -1 && errno == EBADF) {
42 AssertMsg(0, "CheckWaitableHandle: Invalid WaitableHandle! (EBADF)");
45 AssertMsg(result != -1, "CheckWaitableHandle: Invalid WaitableHandle!");
46 #endif // DPL_ENABLE_WAITABLE_HANDLE_BADF_CHECK
48 } // namespace anonymous
50 WaitableHandleIndexList WaitForSingleHandle(WaitableHandle handle,
51 unsigned long miliseconds)
53 WaitableHandleList waitHandles;
54 waitHandles.push_back(handle);
55 return WaitForMultipleHandles(waitHandles, miliseconds);
58 WaitableHandleIndexList WaitForSingleHandle(WaitableHandle handle,
60 unsigned long miliseconds)
62 WaitableHandleListEx waitHandles;
63 waitHandles.push_back(std::make_pair(handle, mode));
64 return WaitForMultipleHandles(waitHandles, miliseconds);
67 WaitableHandleIndexList WaitForMultipleHandles(
68 const WaitableHandleList &waitableHandleList,
69 unsigned long miliseconds)
71 WaitableHandleListEx handleList;
73 for (WaitableHandleList::const_iterator iterator = waitableHandleList.begin();
74 iterator != waitableHandleList.end();
77 // Wait for multiple objects
78 handleList.push_back(std::make_pair(*iterator, WaitMode::Read));
82 return WaitForMultipleHandles(handleList, miliseconds);
85 WaitableHandleIndexList WaitForMultipleHandles(
86 const WaitableHandleListEx &waitableHandleListEx,
87 unsigned long miliseconds)
89 fd_set readFds, writeFds, errorFds;
98 // Add read wait handles
99 for (WaitableHandleListEx::const_iterator iterator =
100 waitableHandleListEx.begin();
101 iterator != waitableHandleListEx.end();
104 if (iterator->first > maxFd) {
105 maxFd = iterator->first;
108 CheckWaitableHandle(iterator->first);
110 // Handle errors along with read and write events
111 FD_SET(iterator->first, &errorFds);
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);
122 timeval *effectiveTimeout = NULL;
123 if (miliseconds != 0xFFFFFFFF) {
124 timeout.tv_sec = miliseconds / 1000;
125 timeout.tv_usec = (miliseconds % 1000) * 1000;
126 effectiveTimeout = &timeout;
129 if (TEMP_FAILURE_RETRY(select(maxFd + 1, &readFds, &writeFds, &errorFds,
130 effectiveTimeout)) == -1)
136 WaitableHandleIndexList indexes;
139 for (WaitableHandleListEx::const_iterator iterator =
140 waitableHandleListEx.begin();
141 iterator != waitableHandleListEx.end();
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);
151 } else if (iterator->second == WaitMode::Write) {
152 if (FD_ISSET(iterator->first, &writeFds)) {
153 indexes.push_back(index);
159 // Successfuly awaited some events or timeout occurred