lw-support/src/liblw-support/IO/Util/WriteTask.cpp

120 lines
2.8 KiB
C++
Raw Normal View History

2006-08-25 00:09:46 +01:00
/* 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;
}
}