1 // Copyright 2021 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 #include "pw_multisink/multisink.h"
15
16 #include <cstring>
17
18 #include "pw_assert/light.h"
19 #include "pw_multisink/drain.h"
20 #include "pw_status/try.h"
21 #include "pw_varint/varint.h"
22
23 namespace pw {
24 namespace multisink {
25
GetEntry(Drain & drain,ByteSpan buffer,uint32_t & sequence_id_out)26 Result<ConstByteSpan> MultiSink::GetEntry(Drain& drain,
27 ByteSpan buffer,
28 uint32_t& sequence_id_out) {
29 size_t bytes_read = 0;
30
31 // Exit immediately if there's no multisink attached to this drain.
32 if (drain.multisink_ == nullptr) {
33 return Status::FailedPrecondition();
34 }
35
36 const Status status =
37 drain.reader_.PeekFrontWithPreamble(buffer, sequence_id_out, bytes_read);
38 if (status.IsOutOfRange()) {
39 // If the drain has caught up, report the last handled sequence ID so that
40 // it can still process any dropped entries.
41 sequence_id_out = drain.multisink_->sequence_id_ - 1;
42 return status;
43 }
44 PW_CHECK(drain.reader_.PopFront().ok());
45 return std::as_bytes(buffer.first(bytes_read));
46 }
47
AttachDrain(Drain & drain)48 Status MultiSink::AttachDrain(Drain& drain) {
49 PW_DCHECK(drain.multisink_ == nullptr);
50 drain.multisink_ = this;
51 drain.last_handled_sequence_id_ = sequence_id_ - 1;
52 return ring_buffer_.AttachReader(drain.reader_);
53 }
54
DetachDrain(Drain & drain)55 Status MultiSink::DetachDrain(Drain& drain) {
56 PW_DCHECK(drain.multisink_ == this);
57 drain.multisink_ = nullptr;
58 return ring_buffer_.DetachReader(drain.reader_);
59 }
60
61 } // namespace multisink
62 } // namespace pw
63