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_input_output_execution_context_support.cpp
18 * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
20 * @brief This file is the implementation file of waitable input-output
21 * execution context support
24 #include <dpl/socket/waitable_input_output_execution_context_support.h>
25 #include <dpl/scoped_array.h>
26 #include <dpl/socket/abstract_socket.h> // FIXME: Remove !!!
27 #include <dpl/log/log.h>
28 #include <dpl/assert.h>
32 namespace // anonymous
34 const size_t DEFAULT_READ_SIZE = 2048;
35 } // namespace anonymous
37 WaitableInputOutputExecutionContextSupport::
38 WaitableInputOutputExecutionContextSupport() :
40 m_waitableInputOutput(NULL),
41 m_hasReadWatch(false),
42 m_hasWriteWatch(false)
45 WaitableInputOutputExecutionContextSupport::~
46 WaitableInputOutputExecutionContextSupport()
48 // Ensure support is closed
52 void WaitableInputOutputExecutionContextSupport::Open(
53 AbstractWaitableInputOutput *inputOutput)
56 Throw(Exception::AlreadyOpened);
59 LogPedantic("Opening waitable input-output execution context support...");
62 m_waitableInputOutput = inputOutput;
64 // Register read watch
65 Assert(m_hasReadWatch == false);
68 m_hasReadWatch = true;
73 LogPedantic("Waitable input-output execution context support opened");
76 void WaitableInputOutputExecutionContextSupport::Close()
82 LogPedantic("Closing waitable input-output execution context support...");
84 // Remove read and write watches
85 CheckedRemoveReadWriteWatch();
90 LogPedantic("Waitable input-output execution context support closed");
93 void WaitableInputOutputExecutionContextSupport::AddReadWatch()
95 WaitableHandleWatchSupport::InheritedContext()->AddWaitableHandleWatch(
98 ->WaitableReadHandle(),
103 void WaitableInputOutputExecutionContextSupport::RemoveReadWatch()
105 WaitableHandleWatchSupport::InheritedContext()->RemoveWaitableHandleWatch(
107 m_waitableInputOutput->WaitableReadHandle(),
111 void WaitableInputOutputExecutionContextSupport::AddWriteWatch()
113 WaitableHandleWatchSupport::InheritedContext()->AddWaitableHandleWatch(
115 m_waitableInputOutput
116 ->WaitableWriteHandle(),
121 void WaitableInputOutputExecutionContextSupport::RemoveWriteWatch()
123 WaitableHandleWatchSupport::InheritedContext()->RemoveWaitableHandleWatch(
125 m_waitableInputOutput->WaitableWriteHandle(),
129 void WaitableInputOutputExecutionContextSupport::CheckedRemoveReadWatch()
131 if (!m_hasReadWatch) {
136 m_hasReadWatch = false;
139 void WaitableInputOutputExecutionContextSupport::CheckedRemoveWriteWatch()
141 if (!m_hasWriteWatch) {
146 m_hasWriteWatch = false;
149 void WaitableInputOutputExecutionContextSupport::CheckedRemoveReadWriteWatch()
151 // Remove read watch if any
152 CheckedRemoveReadWatch();
154 // Remove write watch if any
155 CheckedRemoveWriteWatch();
158 void WaitableInputOutputExecutionContextSupport::OnWaitableHandleEvent(
159 WaitableHandle waitableHandle,
162 (void)waitableHandle;
166 LogPedantic("Read event occurred");
168 // Read and parse bytes
174 case WaitMode::Write:
175 LogPedantic("Write event occurred");
177 // Push bytes and unregister from write event
180 // Unregister write watch only if no more data is available
181 if (m_outputStream.Empty()) {
182 Assert(m_hasWriteWatch == true);
183 CheckedRemoveWriteWatch();
195 void WaitableInputOutputExecutionContextSupport::ReadInput()
197 LogPedantic("Reading input bytes");
201 BinaryQueueAutoPtr inputBuffer = m_waitableInputOutput->Read(
204 if (inputBuffer.get() == NULL) {
205 // No data, should not occur
206 LogPedantic("WARNING: Spontaneous ReadSocket occurred");
210 if (inputBuffer->Empty()) {
211 // Connection was closed
212 OnInputStreamClosed();
214 // Unregister from further event insisting
215 Assert(m_hasReadWatch == true);
216 CheckedRemoveReadWriteWatch();
225 LogPedantic("Read " << inputBuffer->Size() << " input bytes");
227 // Append all read data
228 m_inputStream.AppendMoveFrom(*inputBuffer);
230 Catch(AbstractSocket::Exception::ConnectionBroken)
232 //FIXME: Inproper exception abstraction!!!
233 // Some errors occurred while feeding abstract IO
234 // Interpret connection broken errors, and pass futher other ones
235 LogPedantic("Abstract IO connection was broken during read");
237 // Signal broken connection
238 OnInputStreamBroken();
240 // Unregister from further event insisting
241 Assert(m_hasReadWatch == true);
242 CheckedRemoveReadWriteWatch();
255 void WaitableInputOutputExecutionContextSupport::FeedOutput()
258 Throw(Exception::NotOpened);
261 // Anything to feed ?
262 if (m_outputStream.Empty()) {
267 LogPedantic("Feeding output");
271 // Try to write some bytes
272 size_t bytes = m_waitableInputOutput->Write(m_outputStream,
273 m_outputStream.Size());
275 if (bytes < m_outputStream.Size()) {
276 // Start exhaustive output feeding if it is blocked and not already
278 if (!m_hasWriteWatch) {
280 m_hasWriteWatch = true;
282 LogPedantic("Started exhaustive output feeding");
286 // Some bytes were written, consume them
287 m_outputStream.Consume(bytes);
289 Catch(AbstractSocket::Exception::ConnectionBroken) // FIXME: Inproper
290 // exception abstraction
293 // Some errors occurred while feeding abstract IO
294 // Interpret connection broken errors, and pass futher other ones
295 LogPedantic("Abstract IO connection was broken during write");
297 // Signal broken connection
298 OnInputStreamBroken();
300 // Unregister from further event insisting
301 Assert(m_hasReadWatch == true);
302 CheckedRemoveReadWriteWatch();