bool BadaFileStream::seek(int32 offs, int whence) { bool result = false; switch (whence) { case SEEK_SET: // set from start of file SetLastResult(file->Seek(FILESEEKPOSITION_BEGIN, offs)); result = (E_SUCCESS == GetLastResult()); break; case SEEK_CUR: // set relative to offs if (bufferIndex < bufferLength && bufferIndex > (uint32)-offs) { // re-position within the buffer SetLastResult(E_SUCCESS); bufferIndex += offs; return true; } else { offs -= (bufferLength - bufferIndex); if (offs < 0 && file->Tell() + offs < 0) { // avoid negative positioning offs = 0; } if (offs != 0) { SetLastResult(file->Seek(FILESEEKPOSITION_CURRENT, offs)); result = (E_SUCCESS == GetLastResult()); } else { result = true; } } break; case SEEK_END: // set relative to end - positive will increase the file size SetLastResult(file->Seek(FILESEEKPOSITION_END, offs)); result = (E_SUCCESS == GetLastResult()); break; default: AppLog("Invalid whence %d", whence); return false; } if (!result) { AppLog("seek failed"); } bufferIndex = bufferLength = 0; return result; }
int32 BadaFileStream::size() const { int32 oldPos = file->Tell(); file->Seek(FILESEEKPOSITION_END, 0); int32 length = file->Tell(); SetLastResult(file->Seek(FILESEEKPOSITION_BEGIN, oldPos)); return length; }
bool WaitObjectContainer::Wait(unsigned long milliseconds) { if (m_noWait || (m_handles.empty() && !m_firstEventTime)) { SetLastResult(LASTRESULT_NOWAIT); return true; } bool timeoutIsScheduledEvent = false; if (m_firstEventTime) { double timeToFirstEvent = SaturatingSubtract(m_firstEventTime, m_eventTimer.ElapsedTimeAsDouble()); if (timeToFirstEvent <= milliseconds) { milliseconds = (unsigned long)timeToFirstEvent; timeoutIsScheduledEvent = true; } if (m_handles.empty() || !milliseconds) { if (milliseconds) Sleep(milliseconds); SetLastResult(timeoutIsScheduledEvent ? LASTRESULT_SCHEDULED : LASTRESULT_TIMEOUT); return timeoutIsScheduledEvent; } } if (m_handles.size() > MAXIMUM_WAIT_OBJECTS) { // too many wait objects for a single WaitForMultipleObjects call, so use multiple threads static const unsigned int WAIT_OBJECTS_PER_THREAD = MAXIMUM_WAIT_OBJECTS-1; unsigned int nThreads = (unsigned int)((m_handles.size() + WAIT_OBJECTS_PER_THREAD - 1) / WAIT_OBJECTS_PER_THREAD); if (nThreads > MAXIMUM_WAIT_OBJECTS) // still too many wait objects, maybe implement recursive threading later? throw Err("WaitObjectContainer: number of wait objects exceeds limit"); CreateThreads(nThreads); DWORD error = S_OK; for (unsigned int i=0; i<m_threads.size(); i++) { WaitingThreadData &thread = *m_threads[i]; while (!thread.waitingToWait) // spin until thread is in the initial "waiting to wait" state Sleep(0); if (i<nThreads) { thread.waitHandles = &m_handles[i*WAIT_OBJECTS_PER_THREAD]; thread.count = UnsignedMin(WAIT_OBJECTS_PER_THREAD, m_handles.size() - i*WAIT_OBJECTS_PER_THREAD); thread.error = &error; } else thread.count = 0; } ResetEvent(m_stopWaiting); PulseEvent(m_startWaiting); DWORD result = ::WaitForSingleObject(m_stopWaiting, milliseconds); if (result == WAIT_OBJECT_0) { if (error == S_OK) return true; else throw Err("WaitObjectContainer: WaitForMultipleObjects in thread failed with error " + IntToString(error)); } SetEvent(m_stopWaiting); if (result == WAIT_TIMEOUT) { SetLastResult(timeoutIsScheduledEvent ? LASTRESULT_SCHEDULED : LASTRESULT_TIMEOUT); return timeoutIsScheduledEvent; } else throw Err("WaitObjectContainer: WaitForSingleObject failed with error " + IntToString(::GetLastError())); } else { #if TRACE_WAIT static Timer t(Timer::MICROSECONDS); static unsigned long lastTime = 0; unsigned long timeBeforeWait = t.ElapsedTime(); #endif DWORD result = ::WaitForMultipleObjects((DWORD)m_handles.size(), &m_handles[0], FALSE, milliseconds); #if TRACE_WAIT if (milliseconds > 0) { unsigned long timeAfterWait = t.ElapsedTime(); OutputDebugString(("Handles " + IntToString(m_handles.size()) + ", Woke up by " + IntToString(result-WAIT_OBJECT_0) + ", Busied for " + IntToString(timeBeforeWait-lastTime) + " us, Waited for " + IntToString(timeAfterWait-timeBeforeWait) + " us, max " + IntToString(milliseconds) + "ms\n").c_str()); lastTime = timeAfterWait; } #endif if (result >= WAIT_OBJECT_0 && result < WAIT_OBJECT_0 + m_handles.size()) { if (result == m_lastResult) m_sameResultCount++; else { m_lastResult = result; m_sameResultCount = 0; } return true; } else if (result == WAIT_TIMEOUT) { SetLastResult(timeoutIsScheduledEvent ? LASTRESULT_SCHEDULED : LASTRESULT_TIMEOUT); return timeoutIsScheduledEvent; } else throw Err("WaitObjectContainer: WaitForMultipleObjects failed with error " + IntToString(::GetLastError())); } }
void BadaFileStream::clearErr() { SetLastResult(E_SUCCESS); }
bool BadaFileStream::flush() { logEntered(); SetLastResult(file->Flush()); return (E_SUCCESS == GetLastResult()); }
uint32 BadaFileStream::write(const void *ptr, uint32 len) { result r = file->Write(ptr, len); SetLastResult(r); return (r == E_SUCCESS ? len : 0); }