/* 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; } }