blob: 2a238664864b965822f19a5d304c14df454daa4d [file] [log] [blame]
Tim Yao10e5d9b2020-12-30 17:38:10 -08001#include <algorithm> // for std::min
2#include <iostream>
3#include <cstring>
4
5#include <boost/interprocess/sync/scoped_lock.hpp>
6#include <boost/interprocess/managed_shared_memory.hpp>
7
8#include "audio_server_shmem.h"
9#include "IpcBuffer.h"
10#include "IpcBuffer_c.h"
11
12using namespace boost::interprocess;
13
14IpcBuffer::IpcBuffer(const char *name, size_t capacity)
15 : begin_index_(0)
16 , end_index_(0)
17 , size_(0)
18 , capacity_(capacity)
19 , name_(std::string(name))
20 , wr_position_(0)
21{
22 managed_shared_memory *segment = audio_server_shmem::getInstance();
23 void *shptr = segment->allocate(capacity);
24 handle_ = segment->get_handle_from_address(shptr);
25}
26
27IpcBuffer::~IpcBuffer()
28{
29 managed_shared_memory *segment = audio_server_shmem::getInstance();
30 uint8_t *base = static_cast<uint8_t *>(segment->get_address_from_handle(handle_));
31 segment->deallocate(base);
32}
33
34size_t IpcBuffer::write(const uint8_t *data, size_t bytes)
35{
36 if (bytes == 0) return 0;
37
38 uint8_t *ptr = static_cast<uint8_t *>(audio_server_shmem::getInstance()->get_address_from_handle(handle_));
39 size_t capacity = capacity_;
40 size_t bytes_to_write = std::min(bytes, capacity - size_);
41
42 if (bytes_to_write <= capacity - end_index_) {
43 memcpy(ptr + end_index_, data, bytes_to_write);
44 end_index_ += bytes_to_write;
45 if (end_index_ == capacity) end_index_ = 0;
46 } else {
47 size_t size_1 = capacity - end_index_;
48 memcpy(ptr + end_index_, data, size_1);
49 size_t size_2 = bytes_to_write - size_1;
50 memcpy(ptr, data + size_1, size_2);
51 end_index_ = size_2;
52 }
53
54 size_ += bytes_to_write;
55 return bytes_to_write;
56}
57
58size_t IpcBuffer::read(uint8_t *data, size_t bytes)
59{
60 if (bytes == 0) return 0;
61
62 uint8_t *ptr = static_cast<uint8_t *>(audio_server_shmem::getInstance()->get_address_from_handle(handle_));
63 size_t capacity = capacity_;
64 size_t bytes_to_read = std::min(bytes, size_);
65
66 if (bytes_to_read <= capacity - begin_index_) {
67 memcpy(data, ptr + begin_index_, bytes_to_read);
68 begin_index_ += bytes_to_read;
69 if (begin_index_ == capacity) begin_index_ = 0;
70 } else {
71 size_t size_1 = capacity - begin_index_;
72 memcpy(data, ptr + begin_index_, size_1);
73 size_t size_2 = bytes_to_read - size_1;
74 memcpy(data + size_1, ptr, size_2);
75 begin_index_ = size_2;
76 }
77
78 size_ -= bytes_to_read;
79 return bytes_to_read;
80}
81
82void IpcBuffer::write_nb(const uint8_t *data, size_t bytes)
83{
84 if (bytes == 0) return;
85
86 const uint8_t *ptr = data;
87 size_t len = bytes;
88 uint8_t *base = static_cast<uint8_t *>(audio_server_shmem::getInstance()->get_address_from_handle(handle_));
89
90 while (len > 0) {
91 size_t bytes_to_write = std::min(capacity_ - end_index_, len);
92 memcpy(base + end_index_, ptr, bytes_to_write);
93 ptr += bytes_to_write;
94 len -= bytes_to_write;
95 end_index_ += bytes_to_write;
96 if (end_index_ == capacity_) end_index_ = 0;
97 }
98
99 scoped_lock<interprocess_mutex> lock(wr_position_mutex_);
100
101 timespec ts;
102 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
103 wr_position_ += bytes;
104 wr_time_ = uint64_t(ts.tv_sec) * 1000000000 + uint64_t(ts.tv_nsec);
105}
106
107void IpcBuffer::get_write_position(uint64_t& time, uint64_t& position)
108{
109 scoped_lock<interprocess_mutex> lock(wr_position_mutex_);
110 time = wr_time_;
111 position = wr_position_;
112}
113
114uint8_t* IpcBuffer::start_ptr()
115{
116 return static_cast<uint8_t *>(audio_server_shmem::getInstance()->get_address_from_handle(handle_));
117}
118
119const char *IpcBuffer::name()
120{
121 return name_.c_str();
122}
123
124void IpcBuffer::reset()
125{
126 begin_index_ = end_index_ = size_ = wr_position_ = 0;
127}
128
129managed_shared_memory *audio_server_shmem::shm_;
130
131extern "C" {
132
133void *IpcBuffer_create(const char *name, size_t size)
134{
135 managed_shared_memory *shm = audio_server_shmem::getInstance();
136 IpcBuffer * cb = shm->find<IpcBuffer>(name).first;
137 if (cb) {
138 IpcBuffer_destroy(cb);
139 }
140 cb = shm->construct<IpcBuffer>(name)(name, size);
141 return cb;
142}
143
144void IpcBuffer_destroy(void *cb)
145{
146 managed_shared_memory *shm = audio_server_shmem::getInstance();
147 shm->destroy<IpcBuffer>(((IpcBuffer *)(cb))->name());
148}
149
150void IpcBuffer_write(void *cb, const unsigned char *buf, int size)
151{
152 ((IpcBuffer *)(cb))->write_nb(buf, size);
153}
154
155}
156