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
22 #include <dpl/waitable_event.h>
23 #include <dpl/workaround.h>
24 #include <dpl/log/log.h>
25 #include <sys/select.h>
29 #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 Assert(0 && "CheckWaitableHandle: Invalid WaitableHandle! (EBADF)");
44 Assert(result != -1 && "CheckWaitableHandle: Invalid WaitableHandle!");
45 #endif // DPL_ENABLE_WAITABLE_HANDLE_BADF_CHECK
47 } // namespace anonymous
49 WaitableHandleIndexList WaitForSingleHandle(WaitableHandle handle, unsigned long miliseconds)
51 WaitableHandleList waitHandles;
52 waitHandles.push_back(handle);
53 return WaitForMultipleHandles(waitHandles, miliseconds);
56 WaitableHandleIndexList WaitForSingleHandle(WaitableHandle handle, WaitMode::Type mode, unsigned long miliseconds)
58 WaitableHandleListEx waitHandles;
59 waitHandles.push_back(std::make_pair(handle, mode));
60 return WaitForMultipleHandles(waitHandles, miliseconds);
63 WaitableHandleIndexList WaitForMultipleHandles(const WaitableHandleList &waitableHandleList, unsigned long miliseconds)
65 WaitableHandleListEx handleList;
67 for (WaitableHandleList::const_iterator iterator = waitableHandleList.begin();
68 iterator != waitableHandleList.end();
71 // Wait for multiple objects
72 handleList.push_back(std::make_pair(*iterator, WaitMode::Read));
76 return WaitForMultipleHandles(handleList, miliseconds);
79 WaitableHandleIndexList WaitForMultipleHandles(const WaitableHandleListEx &waitableHandleListEx, unsigned long miliseconds)
81 fd_set readFds, writeFds, errorFds;
90 // Add read wait handles
91 for (WaitableHandleListEx::const_iterator iterator = waitableHandleListEx.begin();
92 iterator != waitableHandleListEx.end();
95 if (iterator->first > maxFd)
96 maxFd = iterator->first;
98 CheckWaitableHandle(iterator->first);
100 // Handle errors along with read and write events
101 FD_SET(iterator->first, &errorFds);
103 if (iterator->second == WaitMode::Read)
105 FD_SET(iterator->first, &readFds);
107 else if (iterator->second == WaitMode::Write)
109 FD_SET(iterator->first, &writeFds);
115 timeval *effectiveTimeout = NULL;
116 if (miliseconds != 0xFFFFFFFF) {
117 timeout.tv_sec = miliseconds / 1000;
118 timeout.tv_usec = (miliseconds % 1000) * 1000;
119 effectiveTimeout = &timeout;
122 if (TEMP_FAILURE_RETRY(select(maxFd + 1, &readFds, &writeFds, &errorFds, effectiveTimeout)) == -1)
126 WaitableHandleIndexList indexes;
129 for (WaitableHandleListEx::const_iterator iterator = waitableHandleListEx.begin();
130 iterator != waitableHandleListEx.end();
133 // Always return errors, no matter what type of listening is set
134 if (FD_ISSET(iterator->first, &errorFds)) {
135 indexes.push_back(index);
137 else if (iterator->second == WaitMode::Read)
139 if (FD_ISSET(iterator->first, &readFds))
140 indexes.push_back(index);
142 else if (iterator->second == WaitMode::Write)
144 if (FD_ISSET(iterator->first, &writeFds))
145 indexes.push_back(index);
150 // Successfuly awaited some events or timeout occurred