1 /***************************************************************************
2  *  foxxll/io/request_operations.hpp
3  *
4  *  Part of FOXXLL. See http://foxxll.org
5  *
6  *  Copyright (C) 2002 Roman Dementiev <dementiev@mpi-sb.mpg.de>
7  *  Copyright (C) 2008, 2009 Andreas Beckmann <beckmann@cs.uni-frankfurt.de>
8  *  Copyright (C) 2009 Johannes Singler <singler@ira.uka.de>
9  *
10  *  Distributed under the Boost Software License, Version 1.0.
11  *  (See accompanying file LICENSE_1_0.txt or copy at
12  *  http://www.boost.org/LICENSE_1_0.txt)
13  **************************************************************************/
14 
15 #ifndef FOXXLL_IO_REQUEST_OPERATIONS_HEADER
16 #define FOXXLL_IO_REQUEST_OPERATIONS_HEADER
17 
18 #include <foxxll/common/onoff_switch.hpp>
19 #include <foxxll/io/iostats.hpp>
20 #include <foxxll/io/request.hpp>
21 
22 namespace foxxll {
23 
24 //! \addtogroup foxxll_reqlayer
25 //! \{
26 
27 //! Collection of functions to track statuses of a number of requests.
28 
29 //! Suspends calling thread until \b all given requests are completed.
30 //! \param reqs_begin begin of request sequence to wait for
31 //! \param reqs_end end of request sequence to wait for
32 template <class RequestIterator>
wait_all(RequestIterator reqs_begin,RequestIterator reqs_end)33 void wait_all(RequestIterator reqs_begin, RequestIterator reqs_end)
34 {
35     for ( ; reqs_begin != reqs_end; ++reqs_begin)
36         (request_ptr(*reqs_begin))->wait();
37 }
38 
39 //! Suspends calling thread until \b all given requests are completed.
40 //! \param req_array array of request_ptr objects
41 //! \param count size of req_array
wait_all(request_ptr req_array[],size_t count)42 static inline void wait_all(request_ptr req_array[], size_t count)
43 {
44     wait_all(req_array, req_array + count);
45 }
46 
47 //! Cancel requests.
48 //! The specified requests are canceled unless already being processed.
49 //! However, cancelation cannot be guaranteed.
50 //! Cancelled requests must still be waited for in order to ensure correct
51 //! operation.
52 //! \param reqs_begin begin of request sequence
53 //! \param reqs_end end of request sequence
54 //! \return number of request canceled
55 template <class RequestIterator>
56 typename std::iterator_traits<RequestIterator>::difference_type
cancel_all(RequestIterator reqs_begin,RequestIterator reqs_end)57 cancel_all(RequestIterator reqs_begin, RequestIterator reqs_end)
58 {
59     typename std::iterator_traits<RequestIterator>::difference_type num_canceled = 0;
60     while (reqs_begin != reqs_end)
61     {
62         if ((request_ptr(*reqs_begin))->cancel())
63             ++num_canceled;
64         ++reqs_begin;
65     }
66     return num_canceled;
67 }
68 
69 //! Polls requests.
70 //! \param reqs_begin begin of request sequence to poll
71 //! \param reqs_end end of request sequence to poll
72 //! \return \c true if any of requests is completed, then index contains valid value, otherwise \c false
73 template <class RequestIterator>
poll_any(RequestIterator reqs_begin,RequestIterator reqs_end)74 RequestIterator poll_any(RequestIterator reqs_begin, RequestIterator reqs_end)
75 {
76     while (reqs_begin != reqs_end)
77     {
78         if ((request_ptr(*reqs_begin))->poll())
79             return reqs_begin;
80 
81         ++reqs_begin;
82     }
83     return reqs_end;
84 }
85 
86 //! Polls requests.
87 //! \param req_array array of request_ptr objects
88 //! \param count size of req_array
89 //! \param index contains index of the \b first completed request if any
90 //! \return \c true if any of requests is completed, then index contains valid value, otherwise \c false
91 static inline
poll_any(request_ptr req_array[],size_t count,size_t & index)92 bool poll_any(request_ptr req_array[], size_t count, size_t& index)
93 {
94     request_ptr* res = poll_any(req_array, req_array + count);
95     index = static_cast<size_t>(res - req_array);
96     return res != (req_array + count);
97 }
98 
99 //! Suspends calling thread until \b any of requests is completed.
100 //! \param reqs_begin begin of request sequence to wait for
101 //! \param reqs_end end of request sequence to wait for
102 //! \return index in req_array pointing to the \b first completed request
103 template <class RequestIterator>
wait_any(RequestIterator reqs_begin,RequestIterator reqs_end)104 RequestIterator wait_any(RequestIterator reqs_begin, RequestIterator reqs_end)
105 {
106     stats::scoped_wait_timer wait_timer(stats::WAIT_OP_ANY);
107 
108     onoff_switch sw;
109 
110     RequestIterator cur = reqs_begin, result = reqs_end;
111 
112     for ( ; cur != reqs_end; cur++)
113     {
114         if ((request_ptr(*cur))->add_waiter(&sw))
115         {
116             // request is already done, no waiter was added to the request
117             result = cur;
118 
119             if (cur != reqs_begin)
120             {
121                 while (--cur != reqs_begin)
122                     (request_ptr(*cur))->delete_waiter(&sw);
123 
124                 (request_ptr(*cur))->delete_waiter(&sw);
125             }
126 
127             (request_ptr(*result))->check_errors();
128 
129             return result;
130         }
131     }
132 
133     sw.wait_for_on();
134 
135     for (cur = reqs_begin; cur != reqs_end; cur++)
136     {
137         (request_ptr(*cur))->delete_waiter(&sw);
138         if (result == reqs_end && (request_ptr(*cur))->poll())
139             result = cur;
140     }
141 
142     return result;
143 }
144 
145 //! Suspends calling thread until \b any of requests is completed.
146 //! \param req_array array of \c request_ptr objects
147 //! \param count size of req_array
148 //! \return index in req_array pointing to the \b first completed request
149 static inline
wait_any(request_ptr req_array[],size_t count)150 size_t wait_any(request_ptr req_array[], size_t count)
151 {
152     return static_cast<size_t>(wait_any(req_array, req_array + count) - req_array);
153 }
154 
155 //! \}
156 
157 } // namespace foxxll
158 
159 #endif // !FOXXLL_IO_REQUEST_OPERATIONS_HEADER
160 
161 /**************************************************************************/
162