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>
34 namespace // anonymous
36 void CheckWaitableHandle(WaitableHandle handle)
38 #ifdef DPL_ENABLE_WAITABLE_HANDLE_BADF_CHECK
39 // Try to get descriptor flags
40 int result = fcntl(handle, F_GETFL);
42 if (result == -1 && errno == EBADF)
43 Assert(0 && "CheckWaitableHandle: Invalid WaitableHandle! (EBADF)");
45 Assert(result != -1 && "CheckWaitableHandle: Invalid WaitableHandle!");
46 #endif // DPL_ENABLE_WAITABLE_HANDLE_BADF_CHECK
48 } // namespace anonymous
50 WaitableHandleIndexList WaitForSingleHandle(WaitableHandle handle, unsigned long miliseconds)
52 WaitableHandleList waitHandles;
53 waitHandles.push_back(handle);
54 return WaitForMultipleHandles(waitHandles, miliseconds);
57 WaitableHandleIndexList WaitForSingleHandle(WaitableHandle handle, WaitMode::Type mode, unsigned long miliseconds)
59 WaitableHandleListEx waitHandles;
60 waitHandles.push_back(std::make_pair(handle, mode));
61 return WaitForMultipleHandles(waitHandles, miliseconds);
64 WaitableHandleIndexList WaitForMultipleHandles(const WaitableHandleList &waitableHandleList, unsigned long miliseconds)
66 WaitableHandleListEx handleList;
68 for (WaitableHandleList::const_iterator iterator = waitableHandleList.begin();
69 iterator != waitableHandleList.end();
72 // Wait for multiple objects
73 handleList.push_back(std::make_pair(*iterator, WaitMode::Read));
77 return WaitForMultipleHandles(handleList, miliseconds);
80 WaitableHandleIndexList WaitForMultipleHandles(const WaitableHandleListEx &waitableHandleListEx, unsigned long miliseconds)
82 fd_set readFds, writeFds, errorFds;
91 // Add read wait handles
92 for (WaitableHandleListEx::const_iterator iterator = waitableHandleListEx.begin();
93 iterator != waitableHandleListEx.end();
96 if (iterator->first > maxFd)
97 maxFd = iterator->first;
99 CheckWaitableHandle(iterator->first);
101 // Handle errors along with read and write events
102 FD_SET(iterator->first, &errorFds);
104 if (iterator->second == WaitMode::Read)
106 FD_SET(iterator->first, &readFds);
108 else if (iterator->second == WaitMode::Write)
110 FD_SET(iterator->first, &writeFds);
116 timeval *effectiveTimeout = NULL;
117 if (miliseconds != 0xFFFFFFFF) {
118 timeout.tv_sec = miliseconds / 1000;
119 timeout.tv_usec = (miliseconds % 1000) * 1000;
120 effectiveTimeout = &timeout;
123 if (TEMP_FAILURE_RETRY(select(maxFd + 1, &readFds, &writeFds, &errorFds, effectiveTimeout)) == -1)
127 WaitableHandleIndexList indexes;
130 for (WaitableHandleListEx::const_iterator iterator = waitableHandleListEx.begin();
131 iterator != waitableHandleListEx.end();
134 // Always return errors, no matter what type of listening is set
135 if (FD_ISSET(iterator->first, &errorFds)) {
136 indexes.push_back(index);
138 else if (iterator->second == WaitMode::Read)
140 if (FD_ISSET(iterator->first, &readFds))
141 indexes.push_back(index);
143 else if (iterator->second == WaitMode::Write)
145 if (FD_ISSET(iterator->first, &writeFds))
146 indexes.push_back(index);
151 // Successfuly awaited some events or timeout occurred