void * QA_PHYSICAL_CHANNEL_CLASS::WriterThread(void *argv) { void ** args = (void**) argv; QA_PHYSICAL_CHANNEL physicalChannel = (QA_PHYSICAL_CHANNEL) args[1]; tbb::concurrent_bounded_queue<UMF_MESSAGE> *incomingQ = &(physicalChannel->writeQ); QA_DEVICE_WRAPPER qaDevice = (QA_DEVICE_WRAPPER) args[0]; while (1) { UMF_MESSAGE message; incomingQ->pop(message); // Check to see if we're being torn down -- this is // done by passing a special message through the writeQ if (message == NULL) { if (!physicalChannel->uninitialized) { cerr << "QA_PHYSICAL_CHANNEL got an unexpected NULL value" << endl; } pthread_exit(0); } // The FPGA side detects NULLs inserted for alignment by looking at the // length field. Having a length of 0 would break the protocol. ASSERTX(message->GetLength() != 0); // construct header UMF_CHUNK header = 0; message->EncodeHeader((unsigned char *)&header); qaDevice->Write(&header, sizeof(header)); size_t n_bytes = message->ExtractBytesLeft(); // Round up to multiple of UMF_CHUNK size n_bytes = (n_bytes + sizeof(UMF_CHUNK) - 1) & ~(sizeof(UMF_CHUNK) - 1); qaDevice->Write(message->ExtractGetRawPtr(), n_bytes); message->ExtractUpdateRawPtr(n_bytes); // de-allocate message delete message; // Flush output channel if there isn't another message ready. if (incomingQ->empty()) { qaDevice->Flush(); } } }