120 lines
2.8 KiB
C++
120 lines
2.8 KiB
C++
![]() |
/* lw-support/src/lib/IO/Util/WriteTask.cpp
|
||
|
*
|
||
|
* (c)2005, Laurence Withers. Released under the GNU GPL. See file
|
||
|
* COPYING for more information / terms of license.
|
||
|
*/
|
||
|
|
||
|
namespace lw {
|
||
|
|
||
|
|
||
|
|
||
|
IOWriteTask::IOWriteTask(lw::EventManager& eventManager, IODevice* ioDev, int timeoutInactive,
|
||
|
int timeoutOverall, CompletionCallback* completion,
|
||
|
const char* data, size_t amt, bool copy)
|
||
|
: CompletionTask(completion), eventManager(eventManager), ioDev(ioDev),
|
||
|
timeoutInactive(timeoutInactive), timeoutOverall(timeoutOverall), data(0), wr(0), amt(amt),
|
||
|
copy(copy)
|
||
|
{
|
||
|
try {
|
||
|
NullPointer::check(data, L"data");
|
||
|
NullPointer::check(ioDev, L"ioDev");
|
||
|
|
||
|
eventManager.registerDevice(ioDev, this, lw::IOEventHUP | lw::IOEventWrite
|
||
|
| lw::IOEventError);
|
||
|
#if 0
|
||
|
timerKey2 = eventManager.registerTimer(this, lw::ElapsedTime(0));
|
||
|
#endif
|
||
|
|
||
|
// copy data if necessary
|
||
|
if(copy) {
|
||
|
this->data = new char[amt];
|
||
|
memcpy(this->data, data, amt);
|
||
|
} else {
|
||
|
this->data = (char*)data;
|
||
|
}
|
||
|
wr = this->data;
|
||
|
|
||
|
// set timeouts if necessary
|
||
|
if(timeoutInactive >= 0)
|
||
|
timerKey0 = eventManager.registerTimer(this, lw::ElapsedTime::from_ms(timeoutInactive));
|
||
|
if(timeoutOverall >= 0)
|
||
|
timerKey1 = eventManager.registerTimer(this, lw::ElapsedTime::from_ms(timeoutOverall));
|
||
|
}
|
||
|
catch(lw::Exception& e) {
|
||
|
if(copy) delete [] this->data;
|
||
|
e.chain(L"IOWriteTask::IOWriteTask()");
|
||
|
throw;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
IOWriteTask::~IOWriteTask()
|
||
|
{
|
||
|
if(this->timeoutInactive >= 0) eventManager.ignoreTimer(timerKey0);
|
||
|
if(this->timeoutOverall >= 0) eventManager.ignoreTimer(timerKey1);
|
||
|
delete ioDev;
|
||
|
// if(copy) delete [] data;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void IOWriteTask::taskAbort(const lw::Exception& e)
|
||
|
{
|
||
|
taskAborted(e);
|
||
|
delete this;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
bool IOWriteTask::ioReady(uint32_t flags)
|
||
|
{
|
||
|
try {
|
||
|
if(flags & lw::IOEventError) ioDev->checkErrors();
|
||
|
if(flags & lw::IOEventHUP) throw lw::Exception(L"Remote device closed connection.");
|
||
|
if(flags & lw::IOEventWrite) tryWrite();
|
||
|
}
|
||
|
catch(lw::Exception& e) {
|
||
|
taskAbort(e);
|
||
|
delete this;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void IOWriteTask::tryWrite()
|
||
|
{
|
||
|
while(amt) {
|
||
|
size_t w = ioDev->write(wr, amt);
|
||
|
if(!w) return;
|
||
|
|
||
|
wr += w;
|
||
|
amt -= w;
|
||
|
|
||
|
if(timeoutInactive >= 0) {
|
||
|
eventManager.ignoreTimer(timerKey0);
|
||
|
timerKey0 = eventManager.registerTimer(this, lw::ElapsedTime::from_ms(timeoutInactive), 0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// done!
|
||
|
taskCompleted();
|
||
|
delete this;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
bool IOWriteTask::timer(Key)
|
||
|
{
|
||
|
// must be a timeout
|
||
|
taskAbort(lw::Exception(L"WriteTask timeout."));
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
}
|