bool V4L2Camera::enqueueRequestBuffers() { // Get a request from the queue (blocks this thread until one is available). std::shared_ptr<default_camera_hal::CaptureRequest> request = dequeueRequest(); // Assume request validated before being added to the queue // (For now, always exactly 1 output buffer, no inputs). // Setting and getting settings are best effort here, // since there's no way to know through V4L2 exactly what // settings are used for a buffer unless we were to enqueue them // one at a time, which would be too slow. // Set the requested settings int res = metadata_->SetRequestSettings(request->settings); if (res) { HAL_LOGE("Failed to set settings."); completeRequest(request, res); return true; } // Replace the requested settings with a snapshot of // the used settings/state immediately before enqueue. res = metadata_->FillResultMetadata(&request->settings); if (res) { // Note: since request is a shared pointer, this may happen if another // thread has already decided to complete the request (e.g. via flushing), // since that locks the metadata (in that case, this failing is fine, // and completeRequest will simply do nothing). HAL_LOGE("Failed to fill result metadata."); completeRequest(request, res); return true; } // Actually enqueue the buffer for capture. res = device_->EnqueueRequest(request); if (res) { HAL_LOGE("Device failed to enqueue buffer."); completeRequest(request, res); return true; } // Make sure the stream is on (no effect if already on). res = device_->StreamOn(); if (res) { HAL_LOGE("Device failed to turn on stream."); // Don't really want to send an error for only the request here, // since this is a full device error. // TODO: Should trigger full flush. return true; } std::unique_lock<std::mutex> lock(in_flight_lock_); in_flight_buffer_count_++; buffers_in_flight_.notify_one(); return true; }
//-------------------------------------------------------------- // load chunks from request list void ChunkWorld::chunkLoader() { while (!m_shutdown) { m_chunkEvent->wait(1000.0); // check shutdown every second // while there's work while (!m_shutdown) { ChunkObj* found = dequeueRequest(); // process the request if (found != NULL) processRequest(found); else break; // back to wait } } }
// This function must be called from the event loop. The only // exception is documented in QHttpNetworkConnectionPrivate::queueRequest // although it is called _q_startNextRequest, it will actually start multiple requests when possible void QHttpNetworkConnectionPrivate::_q_startNextRequest() { // If the QHttpNetworkConnection is currently paused then bail out immediately if (state == PausedState) return; //resend the necessary ones. for (int i = 0; i < channelCount; ++i) { if (channels[i].resendCurrent && (channels[i].state != QHttpNetworkConnectionChannel::ClosingState)) { channels[i].resendCurrent = false; channels[i].state = QHttpNetworkConnectionChannel::IdleState; // if this is not possible, error will be emitted and connection terminated if (!channels[i].resetUploadData()) continue; channels[i].sendRequest(); } } // dequeue new ones // return fast if there is nothing to do if (highPriorityQueue.isEmpty() && lowPriorityQueue.isEmpty()) return; // try to get a free AND connected socket for (int i = 0; i < channelCount; ++i) { if (!channels[i].reply && !channels[i].isSocketBusy() && channels[i].socket->state() == QAbstractSocket::ConnectedState) { if (dequeueRequest(channels[i].socket)) channels[i].sendRequest(); } } // try to push more into all sockets // ### FIXME we should move this to the beginning of the function // as soon as QtWebkit is properly using the pipelining // (e.g. not for XMLHttpRequest or the first page load) // ### FIXME we should also divide the requests more even // on the connected sockets //tryToFillPipeline(socket); // return fast if there is nothing to pipeline if (highPriorityQueue.isEmpty() && lowPriorityQueue.isEmpty()) return; for (int i = 0; i < channelCount; i++) if (channels[i].socket->state() == QAbstractSocket::ConnectedState) fillPipeline(channels[i].socket); // If there is not already any connected channels we need to connect a new one. // We do not pair the channel with the request until we know if it is // connected or not. This is to reuse connected channels before we connect new once. int queuedRequest = highPriorityQueue.count() + lowPriorityQueue.count(); for (int i = 0; i < channelCount; ++i) { if (channels[i].socket->state() == QAbstractSocket::ConnectingState) queuedRequest--; if ( queuedRequest <=0 ) break; if (!channels[i].reply && !channels[i].isSocketBusy() && (channels[i].socket->state() == QAbstractSocket::UnconnectedState)) { channels[i].ensureConnection(); queuedRequest--; } } }
//-------------------------------------------------------------- // update animation BOOL ChunkWorld::animate( double now, // current time (ms) double since) // milliseconds since last pass { BOOL viewChanged = false; m_chunkLock->lock(); // keep memory use under limits checkMemory(); resetRequestList(); // figure which chunk we are in int viewX = (int) floor(m_eyePt.x / CHUNK_SIZE); int viewZ = (int) floor(m_eyePt.z / CHUNK_SIZE); // for all coordinates in view list for (int i = m_viewListCount-1; i >= 0; i--) { ChunkOrigin* origin = &m_viewList[i]; int chunkX = CHUNK_SIZE*(viewX + origin->x); int chunkZ = CHUNK_SIZE*(viewZ + origin->z); // find/create chunk ChunkObj* chunk = createChunk(chunkX, chunkZ); // if chunk within view if (chunk->withinFrustum()) { switch (chunk->m_status) { case CHUNK_UNLOADED: // request the chunk (loads in memory) requestChunk(chunk); // request the neighbors loadNeighbors(chunk); break; case CHUNK_INMEMORY: // if all neighbors loaded, update chunk edges if (loadNeighbors(chunk)) { updateEdges(chunk); // request the chunk (loads in display) requestChunk(chunk); } break; case CHUNK_INDISPLAY: // if we have an update, use it if (!chunk->m_active && chunk->m_hasUpdate) { // mgDebug("use update on (%d, %d)", chunk->m_originX, chunk->m_originZ); int oldSize = chunk->getDisplayMemUsed(); chunk->useUpdate(); int size = chunk->getDisplayMemUsed(); m_displayMemUsed += size-oldSize; chunk->m_hasUpdate = false; } // if it needs an update, flag it if (!chunk->m_active && chunk->needsUpdate(m_eyePt)) { // mgDebug("wants update on (%d, %d)", chunk->m_originX, chunk->m_originZ); chunk->m_status = CHUNK_NEEDSUPDATE; chunk->m_eyePt = m_eyePt; m_requestList.addToTail(chunk); } // if still in display, animate it, since we will draw it if (chunk->m_status == CHUNK_INDISPLAY || chunk->m_status == CHUNK_NEEDSUPDATE) chunk->animate(now, since); break; case CHUNK_NEEDSUPDATE: // if needed update last pass, and not being processed, still needs update if (!chunk->m_active) { // mgDebug("still needs update on (%d, %d)", chunk->m_originX, chunk->m_originZ); m_requestList.addToTail(chunk); chunk->animate(now, since); } break; } // push to bottom of LRU list ChunkListNode* node = m_LRUList.find(chunk); if (node != NULL) m_LRUList.removeNode(node); m_LRUList.addToTail(chunk); } } if (m_chunksChanged) { viewChanged = true; m_chunksChanged = false; } m_chunkLock->unlock(); // if we requested chunks, activate worker threads if (!m_requestList.isEmpty()) { if (m_chunkThreads != NULL) { // signal the threads to look at requestList m_chunkEvent->signal(); } else { // process one request in this thread (no worker threads) ChunkObj* found = dequeueRequest(); if (found != NULL) processRequest(found); } } return viewChanged; }