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
22 #include <dpl/socket/waitable_input_output_execution_context_support.h>
23 #include <dpl/scoped_array.h>
24 #include <dpl/socket/abstract_socket.h> // FIXME: Remove !!!
25 #include <dpl/log/log.h>
26 #include <dpl/assert.h>
33 namespace // anonymous
35 const size_t DEFAULT_READ_SIZE = 2048;
36 } // namespace anonymous
38 WaitableInputOutputExecutionContextSupport::WaitableInputOutputExecutionContextSupport()
40 m_waitableInputOutput(NULL),
41 m_hasReadWatch(false),
42 m_hasWriteWatch(false)
46 WaitableInputOutputExecutionContextSupport::~WaitableInputOutputExecutionContextSupport()
48 // Ensure support is closed
52 void WaitableInputOutputExecutionContextSupport::Open(AbstractWaitableInputOutput *inputOutput)
55 Throw(Exception::AlreadyOpened);
57 LogPedantic("Opening waitable input-output execution context support...");
60 m_waitableInputOutput = inputOutput;
62 // Register read watch
63 Assert(m_hasReadWatch == false);
66 m_hasReadWatch = true;
71 LogPedantic("Waitable input-output execution context support opened");
74 void WaitableInputOutputExecutionContextSupport::Close()
79 LogPedantic("Closing waitable input-output execution context support...");
81 // Remove read and write watches
82 CheckedRemoveReadWriteWatch();
87 LogPedantic("Waitable input-output execution context support closed");
90 void WaitableInputOutputExecutionContextSupport::AddReadWatch()
92 WaitableHandleWatchSupport::InheritedContext()->AddWaitableHandleWatch(this, m_waitableInputOutput->WaitableReadHandle(), WaitMode::Read);
95 void WaitableInputOutputExecutionContextSupport::RemoveReadWatch()
97 WaitableHandleWatchSupport::InheritedContext()->RemoveWaitableHandleWatch(this, m_waitableInputOutput->WaitableReadHandle(), WaitMode::Read);
100 void WaitableInputOutputExecutionContextSupport::AddWriteWatch()
102 WaitableHandleWatchSupport::InheritedContext()->AddWaitableHandleWatch(this, m_waitableInputOutput->WaitableWriteHandle(), WaitMode::Write);
105 void WaitableInputOutputExecutionContextSupport::RemoveWriteWatch()
107 WaitableHandleWatchSupport::InheritedContext()->RemoveWaitableHandleWatch(this, m_waitableInputOutput->WaitableWriteHandle(), WaitMode::Write);
110 void WaitableInputOutputExecutionContextSupport::CheckedRemoveReadWatch()
116 m_hasReadWatch = false;
119 void WaitableInputOutputExecutionContextSupport::CheckedRemoveWriteWatch()
121 if (!m_hasWriteWatch)
125 m_hasWriteWatch = false;
128 void WaitableInputOutputExecutionContextSupport::CheckedRemoveReadWriteWatch()
130 // Remove read watch if any
131 CheckedRemoveReadWatch();
133 // Remove write watch if any
134 CheckedRemoveWriteWatch();
137 void WaitableInputOutputExecutionContextSupport::OnWaitableHandleEvent(WaitableHandle waitableHandle, WaitMode::Type mode)
139 (void)waitableHandle;
144 LogPedantic("Read event occurred");
146 // Read and parse bytes
152 case WaitMode::Write:
153 LogPedantic("Write event occurred");
155 // Push bytes and unregister from write event
158 // Unregister write watch only if no more data is available
159 if (m_outputStream.Empty())
161 Assert(m_hasWriteWatch == true);
162 CheckedRemoveWriteWatch();
174 void WaitableInputOutputExecutionContextSupport::ReadInput()
176 LogPedantic("Reading input bytes");
180 BinaryQueueAutoPtr inputBuffer = m_waitableInputOutput->Read(DEFAULT_READ_SIZE);
182 if (inputBuffer.get() == NULL)
184 // No data, should not occur
185 LogPedantic("WARNING: Spontaneous ReadSocket occurred");
189 if (inputBuffer->Empty())
191 // Connection was closed
192 OnInputStreamClosed();
194 // Unregister from further event insisting
195 Assert(m_hasReadWatch == true);
196 CheckedRemoveReadWriteWatch();
205 LogPedantic("Read " << inputBuffer->Size() << " input bytes");
207 // Append all read data
208 m_inputStream.AppendMoveFrom(*inputBuffer);
210 Catch (AbstractSocket::Exception::ConnectionBroken) // FIXME: Inproper exception abstraction !!!
212 // Some errors occurred while feeding abstract IO
213 // Interpret connection broken errors, and pass futher other ones
214 LogPedantic("Abstract IO connection was broken during read");
216 // Signal broken connection
217 OnInputStreamBroken();
219 // Unregister from further event insisting
220 Assert(m_hasReadWatch == true);
221 CheckedRemoveReadWriteWatch();
234 void WaitableInputOutputExecutionContextSupport::FeedOutput()
237 Throw(Exception::NotOpened);
239 // Anything to feed ?
240 if (m_outputStream.Empty())
244 LogPedantic("Feeding output");
248 // Try to write some bytes
249 size_t bytes = m_waitableInputOutput->Write(m_outputStream, m_outputStream.Size());
251 if (bytes < m_outputStream.Size())
253 // Start exhaustive output feeding if it is blocked and not already started
254 if (!m_hasWriteWatch)
257 m_hasWriteWatch = true;
259 LogPedantic("Started exhaustive output feeding");
263 // Some bytes were written, consume them
264 m_outputStream.Consume(bytes);
266 Catch (AbstractSocket::Exception::ConnectionBroken) // FIXME: Inproper exception abstraction !!!
268 // Some errors occurred while feeding abstract IO
269 // Interpret connection broken errors, and pass futher other ones
270 LogPedantic("Abstract IO connection was broken during write");
272 // Signal broken connection
273 OnInputStreamBroken();
275 // Unregister from further event insisting
276 Assert(m_hasReadWatch == true);
277 CheckedRemoveReadWriteWatch();