private void RecordDatum(bool immediate)
    {
        // If recording is stopped (which is it by default), loop back around next frame.
        if (recordingStopped)
        {
            return;
        }

        if (!immediate)         // we run in the same thread as unity we can update the transformations in a synchronized way
        {
            UpdateFoveInterfaceMatrices(false);
        }

        Matrix4x4 transformMat;

        lock (foveInterfaceTransfo)
        {
            switch (raysCoordinateSpace)
            {
            case CoordinateSpace.World:
                transformMat = foveInterfaceTransfo.HMDToWorld;
                break;

            case CoordinateSpace.Local:
                transformMat = foveInterfaceTransfo.HMDToLocal;
                break;

            default:
                transformMat = Matrix4x4.identity;
                break;
            }
        }

        var leftEyeOffset  = FoveManager.GetLeftEyeOffset(immediate);
        var rightEyeOffset = FoveManager.GetRightEyeOffset(immediate);
        var leftEyeVector  = FoveManager.GetLeftEyeVector(immediate);
        var rightEyeVector = FoveManager.GetRightEyeVector(immediate);

        Ray leftRay, rightRay;

        Utils.CalculateGazeRays(ref transformMat, ref leftEyeVector, ref rightEyeVector, ref leftEyeOffset, ref rightEyeOffset, out leftRay, out rightRay);

        // If you add new fields, be sure to write them here.
        var datum = new RecordingDatum
        {
            frameTime = stopwatch.Elapsed.TotalSeconds,
            leftGaze  = leftRay,
            rightGaze = rightRay,
        };

        dataSlice.Add(datum);

        if (dataSlice.Count >= writeAtDataCount)
        {
            // Make sure we have exclusive access by locking the mutex, but only wait for up to 30 milliseconds.
            if (!writingDataMutex.WaitOne(30))
            {
                // If we got here, it means that we couldn't acquire exclusive access within the specified time
                // limit. Likely this means an error happened, but it could also mean that more data was being
                // written than it took to gather another set of data -- in which case you may need to extend the
                // timeout duration, though that will cause a noticeable frame skip in your application.

                // For now, the best thing we can do is continue the loop and try writing data again next frame.
                long excess = dataSlice.Count - writeAtDataCount;
                if (excess > 1)
                {
                    Debug.LogError("Data slice is " + excess + " entries over where it should be; this is" +
                                   "indicative of a major performance concern in the data recording and writing" +
                                   "process.");
                }
                return;
            }

            CheckForNullDataToWrite();

            // Move our current slice over to dataToWrite, and then create a new slice.
            dataToWrite = dataSlice;
            dataSlice   = new List <RecordingDatum>((int)(writeAtDataCount + 1));

            // Release our claim on the mutex.
            writingDataMutex.ReleaseMutex();

            if (!threadWaitHandle.Set())
            {
                Debug.LogError("Error setting the event to wake up the file writer thread");
            }
        }
    }