OLD | NEW |
| (Empty) |
1 // Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE.md file. | |
4 | |
5 #include "platforms/stm/disco_fletch/src/circular_buffer.h" | |
6 | |
7 #include <stdlib.h> | |
8 #include <string.h> | |
9 | |
10 CircularBuffer::CircularBuffer(size_t capacity) { | |
11 monitor_ = fletch::Platform::CreateMonitor(); | |
12 // One additional byte needed to distinguish between empty and full. | |
13 capacity_ = capacity + 1; | |
14 buffer_ = new uint8_t[capacity_]; | |
15 head_ = tail_ = 0; | |
16 } | |
17 | |
18 CircularBuffer::~CircularBuffer() { | |
19 delete[] buffer_; | |
20 } | |
21 | |
22 bool CircularBuffer::IsEmpty() { | |
23 fletch::ScopedMonitorLock locker(monitor_); | |
24 return head_ == tail_; | |
25 } | |
26 | |
27 bool CircularBuffer::IsFull() { | |
28 fletch::ScopedMonitorLock locker(monitor_); | |
29 return ((head_ + 1) % capacity_) == tail_; | |
30 } | |
31 | |
32 size_t CircularBuffer::Read(uint8_t* data, size_t count, Blocking block) { | |
33 fletch::ScopedMonitorLock locker(monitor_); | |
34 | |
35 // If buffer is empty wait for data. | |
36 if (block == kBlock) { | |
37 if (head_ == tail_) { | |
38 monitor_->Wait(); | |
39 } | |
40 } | |
41 | |
42 int bytes; | |
43 int read = 0; | |
44 | |
45 if (tail_ > head_) { | |
46 bytes = MIN(capacity_ - tail_, count); | |
47 memcpy(data, buffer_ + tail_, bytes); | |
48 read = bytes; | |
49 tail_ = (tail_ + bytes) % capacity_; | |
50 } | |
51 | |
52 if (tail_ < head_) { | |
53 bytes = MIN(head_ - tail_, count - read); | |
54 memcpy(data + read, buffer_ + tail_, bytes); | |
55 read += bytes; | |
56 tail_ = (tail_ + bytes) % capacity_; | |
57 } | |
58 | |
59 monitor_->Notify(); | |
60 | |
61 return read; | |
62 } | |
63 | |
64 size_t CircularBuffer::Write( | |
65 const uint8_t* data, size_t count, Blocking block) { | |
66 fletch::ScopedMonitorLock locker(monitor_); | |
67 | |
68 // If buffer is full wait for room. | |
69 if (block == kBlock) { | |
70 if (((head_ + 1) % capacity_) == tail_) { | |
71 monitor_->Wait(); | |
72 } | |
73 } | |
74 | |
75 int bytes; | |
76 int written = 0; | |
77 | |
78 if (head_ >= tail_) { | |
79 bytes = (capacity_ - head_) - (tail_ == 0 ? 1 : 0); | |
80 bytes = MIN(bytes, count); | |
81 memcpy(buffer_ + head_, data, bytes); | |
82 written = bytes; | |
83 head_ = (head_ + bytes) % capacity_; | |
84 } | |
85 | |
86 if (head_ < tail_) { | |
87 bytes = MIN(tail_ - head_ - 1, count - written); | |
88 memcpy(buffer_ + head_, data + written, bytes); | |
89 written += bytes; | |
90 head_ = (head_ + bytes) % capacity_; | |
91 } | |
92 | |
93 monitor_->Notify(); | |
94 | |
95 return written; | |
96 } | |
OLD | NEW |