blob: 94546c8a061f1bd25f40060e9aa753aeda66e00a [file] [log] [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.h"
#include <utility>
#include "base/memory/ptr_util.h"
#include "device/base/synchronization/shared_memory_seqlock_buffer.h"
#include "services/device/public/cpp/generic_sensor/sensor_reading.h"
#include "services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer.h"
namespace {
constexpr int kMaxReadAttemptsCount = 10;
} // namespace
namespace device {
SensorReadingSharedBufferReader::SensorReadingSharedBufferReader(
base::ReadOnlySharedMemoryMapping mapping)
: mapping_(std::move(mapping)) {}
SensorReadingSharedBufferReader::~SensorReadingSharedBufferReader() = default;
// static
std::unique_ptr<SensorReadingSharedBufferReader>
SensorReadingSharedBufferReader::Create(base::ReadOnlySharedMemoryRegion region,
uint64_t reading_buffer_offset) {
constexpr size_t kReadBufferSize = sizeof(SensorReadingSharedBuffer);
DCHECK_EQ(0u, reading_buffer_offset % kReadBufferSize);
base::ReadOnlySharedMemoryMapping mapping =
region.MapAt(reading_buffer_offset, kReadBufferSize);
if (!mapping.IsValid())
return nullptr;
return base::WrapUnique(
new SensorReadingSharedBufferReader(std::move(mapping)));
}
bool SensorReadingSharedBufferReader::GetReading(SensorReading* result) {
DCHECK(mapping_.IsValid());
// TODO(someone): This *should* use GetMemoryAs, but SensorReadingSharedBuffer
// is not considered trivially copyable. Maybe there's a better trait to
// use...
const auto* buffer =
static_cast<const device::SensorReadingSharedBuffer*>(mapping_.memory());
return GetReading(buffer, result);
}
// static
bool SensorReadingSharedBufferReader::GetReading(
const SensorReadingSharedBuffer* buffer,
SensorReading* result) {
DCHECK(buffer);
uint32_t retries = 0;
int32_t version;
do {
version = buffer->seqlock.value().ReadBegin();
device::OneWriterSeqLock::AtomicReaderMemcpy(result, &buffer->reading,
sizeof(SensorReading));
} while (buffer->seqlock.value().ReadRetry(version) &&
++retries < kMaxReadAttemptsCount);
// Consider the number of retries less than kMaxRetries as success.
return retries < kMaxReadAttemptsCount;
}
} // namespace device