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 execution context support
23 #include <dpl/socket/waitable_input_output_execution_context_support.h>
24 #include <dpl/scoped_array.h>
25 #include <dpl/socket/abstract_socket.h> // FIXME: Remove !!!
26 #include <dpl/log/log.h>
27 #include <dpl/assert.h>
34 namespace // anonymous
36 const size_t DEFAULT_READ_SIZE = 2048;
37 } // namespace anonymous
39 WaitableInputOutputExecutionContextSupport::WaitableInputOutputExecutionContextSupport()
41 m_waitableInputOutput(NULL),
42 m_hasReadWatch(false),
43 m_hasWriteWatch(false)
47 WaitableInputOutputExecutionContextSupport::~WaitableInputOutputExecutionContextSupport()
49 // Ensure support is closed
53 void WaitableInputOutputExecutionContextSupport::Open(AbstractWaitableInputOutput *inputOutput)
56 Throw(Exception::AlreadyOpened);
58 LogPedantic("Opening waitable input-output execution context support...");
61 m_waitableInputOutput = inputOutput;
63 // Register read watch
64 Assert(m_hasReadWatch == false);
67 m_hasReadWatch = true;
72 LogPedantic("Waitable input-output execution context support opened");
75 void WaitableInputOutputExecutionContextSupport::Close()
80 LogPedantic("Closing waitable input-output execution context support...");
82 // Remove read and write watches
83 CheckedRemoveReadWriteWatch();
88 LogPedantic("Waitable input-output execution context support closed");
91 void WaitableInputOutputExecutionContextSupport::AddReadWatch()
93 WaitableHandleWatchSupport::InheritedContext()->AddWaitableHandleWatch(this, m_waitableInputOutput->WaitableReadHandle(), WaitMode::Read);
96 void WaitableInputOutputExecutionContextSupport::RemoveReadWatch()
98 WaitableHandleWatchSupport::InheritedContext()->RemoveWaitableHandleWatch(this, m_waitableInputOutput->WaitableReadHandle(), WaitMode::Read);
101 void WaitableInputOutputExecutionContextSupport::AddWriteWatch()
103 WaitableHandleWatchSupport::InheritedContext()->AddWaitableHandleWatch(this, m_waitableInputOutput->WaitableWriteHandle(), WaitMode::Write);
106 void WaitableInputOutputExecutionContextSupport::RemoveWriteWatch()
108 WaitableHandleWatchSupport::InheritedContext()->RemoveWaitableHandleWatch(this, m_waitableInputOutput->WaitableWriteHandle(), WaitMode::Write);
111 void WaitableInputOutputExecutionContextSupport::CheckedRemoveReadWatch()
117 m_hasReadWatch = false;
120 void WaitableInputOutputExecutionContextSupport::CheckedRemoveWriteWatch()
122 if (!m_hasWriteWatch)
126 m_hasWriteWatch = false;
129 void WaitableInputOutputExecutionContextSupport::CheckedRemoveReadWriteWatch()
131 // Remove read watch if any
132 CheckedRemoveReadWatch();
134 // Remove write watch if any
135 CheckedRemoveWriteWatch();
138 void WaitableInputOutputExecutionContextSupport::OnWaitableHandleEvent(WaitableHandle waitableHandle, WaitMode::Type mode)
140 (void)waitableHandle;
145 LogPedantic("Read event occurred");
147 // Read and parse bytes
153 case WaitMode::Write:
154 LogPedantic("Write event occurred");
156 // Push bytes and unregister from write event
159 // Unregister write watch only if no more data is available
160 if (m_outputStream.Empty())
162 Assert(m_hasWriteWatch == true);
163 CheckedRemoveWriteWatch();
175 void WaitableInputOutputExecutionContextSupport::ReadInput()
177 LogPedantic("Reading input bytes");
181 BinaryQueueAutoPtr inputBuffer = m_waitableInputOutput->Read(DEFAULT_READ_SIZE);
183 if (inputBuffer.get() == NULL)
185 // No data, should not occur
186 LogPedantic("WARNING: Spontaneous ReadSocket occurred");
190 if (inputBuffer->Empty())
192 // Connection was closed
193 OnInputStreamClosed();
195 // Unregister from further event insisting
196 Assert(m_hasReadWatch == true);
197 CheckedRemoveReadWriteWatch();
206 LogPedantic("Read " << inputBuffer->Size() << " input bytes");
208 // Append all read data
209 m_inputStream.AppendMoveFrom(*inputBuffer);
211 Catch (AbstractSocket::Exception::ConnectionBroken) // FIXME: Inproper exception abstraction !!!
213 // Some errors occurred while feeding abstract IO
214 // Interpret connection broken errors, and pass futher other ones
215 LogPedantic("Abstract IO connection was broken during read");
217 // Signal broken connection
218 OnInputStreamBroken();
220 // Unregister from further event insisting
221 Assert(m_hasReadWatch == true);
222 CheckedRemoveReadWriteWatch();
235 void WaitableInputOutputExecutionContextSupport::FeedOutput()
238 Throw(Exception::NotOpened);
240 // Anything to feed ?
241 if (m_outputStream.Empty())
245 LogPedantic("Feeding output");
249 // Try to write some bytes
250 size_t bytes = m_waitableInputOutput->Write(m_outputStream, m_outputStream.Size());
252 if (bytes < m_outputStream.Size())
254 // Start exhaustive output feeding if it is blocked and not already started
255 if (!m_hasWriteWatch)
258 m_hasWriteWatch = true;
260 LogPedantic("Started exhaustive output feeding");
264 // Some bytes were written, consume them
265 m_outputStream.Consume(bytes);
267 Catch (AbstractSocket::Exception::ConnectionBroken) // FIXME: Inproper exception abstraction !!!
269 // Some errors occurred while feeding abstract IO
270 // Interpret connection broken errors, and pass futher other ones
271 LogPedantic("Abstract IO connection was broken during write");
273 // Signal broken connection
274 OnInputStreamBroken();
276 // Unregister from further event insisting
277 Assert(m_hasReadWatch == true);
278 CheckedRemoveReadWriteWatch();