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/socket/abstract_socket.h> // FIXME: Remove !!!
26 #include <dpl/log/wrt_log.h>
27 #include <dpl/assert.h>
31 namespace // anonymous
33 const size_t DEFAULT_READ_SIZE = 2048;
34 } // namespace anonymous
36 WaitableInputOutputExecutionContextSupport::
37 WaitableInputOutputExecutionContextSupport() :
39 m_waitableInputOutput(NULL),
40 m_hasReadWatch(false),
41 m_hasWriteWatch(false)
44 WaitableInputOutputExecutionContextSupport::~
45 WaitableInputOutputExecutionContextSupport()
47 // Ensure support is closed
51 void WaitableInputOutputExecutionContextSupport::Open(
52 AbstractWaitableInputOutput *inputOutput)
55 Throw(Exception::AlreadyOpened);
58 WrtLogD("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 WrtLogD("Waitable input-output execution context support opened");
75 void WaitableInputOutputExecutionContextSupport::Close()
81 WrtLogD("Closing waitable input-output execution context support...");
83 // Remove read and write watches
84 CheckedRemoveReadWriteWatch();
89 WrtLogD("Waitable input-output execution context support closed");
92 void WaitableInputOutputExecutionContextSupport::AddReadWatch()
94 WaitableHandleWatchSupport* ctx =
95 WaitableHandleWatchSupport::InheritedContext();
97 ctx->AddWaitableHandleWatch(
99 m_waitableInputOutput->WaitableReadHandle(),
103 void WaitableInputOutputExecutionContextSupport::RemoveReadWatch()
105 WaitableHandleWatchSupport* ctx =
106 WaitableHandleWatchSupport::InheritedContext();
108 ctx->RemoveWaitableHandleWatch(
110 m_waitableInputOutput->WaitableReadHandle(),
114 void WaitableInputOutputExecutionContextSupport::AddWriteWatch()
116 WaitableHandleWatchSupport* ctx =
117 WaitableHandleWatchSupport::InheritedContext();
119 ctx->AddWaitableHandleWatch(
121 m_waitableInputOutput->WaitableWriteHandle(),
125 void WaitableInputOutputExecutionContextSupport::RemoveWriteWatch()
127 WaitableHandleWatchSupport* ctx =
128 WaitableHandleWatchSupport::InheritedContext();
130 ctx->RemoveWaitableHandleWatch(
132 m_waitableInputOutput->WaitableWriteHandle(),
136 void WaitableInputOutputExecutionContextSupport::CheckedRemoveReadWatch()
138 if (!m_hasReadWatch) {
143 m_hasReadWatch = false;
146 void WaitableInputOutputExecutionContextSupport::CheckedRemoveWriteWatch()
148 if (!m_hasWriteWatch) {
153 m_hasWriteWatch = false;
156 void WaitableInputOutputExecutionContextSupport::CheckedRemoveReadWriteWatch()
158 // Remove read watch if any
159 CheckedRemoveReadWatch();
161 // Remove write watch if any
162 CheckedRemoveWriteWatch();
165 void WaitableInputOutputExecutionContextSupport::OnWaitableHandleEvent(
166 WaitableHandle waitableHandle,
169 (void)waitableHandle;
173 WrtLogD("Read event occurred");
175 // Read and parse bytes
181 case WaitMode::Write:
182 WrtLogD("Write event occurred");
184 // Push bytes and unregister from write event
187 // Unregister write watch only if no more data is available
188 if (m_outputStream.Empty()) {
189 Assert(m_hasWriteWatch == true);
190 CheckedRemoveWriteWatch();
202 void WaitableInputOutputExecutionContextSupport::ReadInput()
204 WrtLogD("Reading input bytes");
208 BinaryQueueAutoPtr inputBuffer = m_waitableInputOutput->Read(
211 if (inputBuffer.get() == NULL) {
212 // No data, should not occur
213 WrtLogD("WARNING: Spontaneous ReadSocket occurred");
217 if (inputBuffer->Empty()) {
218 // Connection was closed
219 OnInputStreamClosed();
221 // Unregister from further event insisting
222 Assert(m_hasReadWatch == true);
223 CheckedRemoveReadWriteWatch();
232 WrtLogD("Read %i input bytes", inputBuffer->Size());
234 // Append all read data
235 m_inputStream.AppendMoveFrom(*inputBuffer);
237 Catch(AbstractSocket::Exception::ConnectionBroken)
239 //FIXME: Inproper exception abstraction!!!
240 // Some errors occurred while feeding abstract IO
241 // Interpret connection broken errors, and pass futher other ones
242 WrtLogD("Abstract IO connection was broken during read");
244 // Signal broken connection
245 OnInputStreamBroken();
247 // Unregister from further event insisting
248 Assert(m_hasReadWatch == true);
249 CheckedRemoveReadWriteWatch();
262 void WaitableInputOutputExecutionContextSupport::FeedOutput()
265 Throw(Exception::NotOpened);
268 // Anything to feed ?
269 if (m_outputStream.Empty()) {
274 WrtLogD("Feeding output");
278 // Try to write some bytes
279 size_t bytes = m_waitableInputOutput->Write(m_outputStream,
280 m_outputStream.Size());
282 if (bytes < m_outputStream.Size()) {
283 // Start exhaustive output feeding if it is blocked and not already
285 if (!m_hasWriteWatch) {
287 m_hasWriteWatch = true;
289 WrtLogD("Started exhaustive output feeding");
293 // Some bytes were written, consume them
294 m_outputStream.Consume(bytes);
296 Catch(AbstractSocket::Exception::ConnectionBroken) // FIXME: Inproper
297 // exception abstraction
300 // Some errors occurred while feeding abstract IO
301 // Interpret connection broken errors, and pass futher other ones
302 WrtLogD("Abstract IO connection was broken during write");
304 // Signal broken connection
305 OnInputStreamBroken();
307 // Unregister from further event insisting
308 Assert(m_hasReadWatch == true);
309 CheckedRemoveReadWriteWatch();