blob: d879cf21bd5520d416509c15b6c1280d0b801fbd [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)
zhaopeng.yan826c7772022-08-22 15:53:12 +080021 , blocking_(false)
22 , wr_time_(0)
Tim Yao10e5d9b2020-12-30 17:38:10 -080023{
24 managed_shared_memory *segment = audio_server_shmem::getInstance();
25 void *shptr = segment->allocate(capacity);
26 handle_ = segment->get_handle_from_address(shptr);
27}
28
29IpcBuffer::~IpcBuffer()
30{
31 managed_shared_memory *segment = audio_server_shmem::getInstance();
32 uint8_t *base = static_cast<uint8_t *>(segment->get_address_from_handle(handle_));
33 segment->deallocate(base);
34}
35
36size_t IpcBuffer::write(const uint8_t *data, size_t bytes)
37{
38 if (bytes == 0) return 0;
39
40 uint8_t *ptr = static_cast<uint8_t *>(audio_server_shmem::getInstance()->get_address_from_handle(handle_));
41 size_t capacity = capacity_;
42 size_t bytes_to_write = std::min(bytes, capacity - size_);
43
44 if (bytes_to_write <= capacity - end_index_) {
45 memcpy(ptr + end_index_, data, bytes_to_write);
46 end_index_ += bytes_to_write;
47 if (end_index_ == capacity) end_index_ = 0;
48 } else {
49 size_t size_1 = capacity - end_index_;
50 memcpy(ptr + end_index_, data, size_1);
51 size_t size_2 = bytes_to_write - size_1;
52 memcpy(ptr, data + size_1, size_2);
53 end_index_ = size_2;
54 }
55
56 size_ += bytes_to_write;
57 return bytes_to_write;
58}
59
60size_t IpcBuffer::read(uint8_t *data, size_t bytes)
61{
62 if (bytes == 0) return 0;
63
64 uint8_t *ptr = static_cast<uint8_t *>(audio_server_shmem::getInstance()->get_address_from_handle(handle_));
65 size_t capacity = capacity_;
66 size_t bytes_to_read = std::min(bytes, size_);
67
68 if (bytes_to_read <= capacity - begin_index_) {
69 memcpy(data, ptr + begin_index_, bytes_to_read);
70 begin_index_ += bytes_to_read;
71 if (begin_index_ == capacity) begin_index_ = 0;
72 } else {
73 size_t size_1 = capacity - begin_index_;
74 memcpy(data, ptr + begin_index_, size_1);
75 size_t size_2 = bytes_to_read - size_1;
76 memcpy(data + size_1, ptr, size_2);
77 begin_index_ = size_2;
78 }
79
80 size_ -= bytes_to_read;
81 return bytes_to_read;
82}
83
84void IpcBuffer::write_nb(const uint8_t *data, size_t bytes)
85{
86 if (bytes == 0) return;
87
88 const uint8_t *ptr = data;
89 size_t len = bytes;
90 uint8_t *base = static_cast<uint8_t *>(audio_server_shmem::getInstance()->get_address_from_handle(handle_));
91
92 while (len > 0) {
93 size_t bytes_to_write = std::min(capacity_ - end_index_, len);
94 memcpy(base + end_index_, ptr, bytes_to_write);
95 ptr += bytes_to_write;
96 len -= bytes_to_write;
97 end_index_ += bytes_to_write;
98 if (end_index_ == capacity_) end_index_ = 0;
99 }
100
101 scoped_lock<interprocess_mutex> lock(wr_position_mutex_);
102
103 timespec ts;
104 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
105 wr_position_ += bytes;
106 wr_time_ = uint64_t(ts.tv_sec) * 1000000000 + uint64_t(ts.tv_nsec);
107}
108
109void IpcBuffer::get_write_position(uint64_t& time, uint64_t& position)
110{
111 scoped_lock<interprocess_mutex> lock(wr_position_mutex_);
112 time = wr_time_;
113 position = wr_position_;
114}
115
116uint8_t* IpcBuffer::start_ptr()
117{
118 return static_cast<uint8_t *>(audio_server_shmem::getInstance()->get_address_from_handle(handle_));
119}
120
121const char *IpcBuffer::name()
122{
123 return name_.c_str();
124}
125
126void IpcBuffer::reset()
127{
128 begin_index_ = end_index_ = size_ = wr_position_ = 0;
129}
130
131managed_shared_memory *audio_server_shmem::shm_;
132
133extern "C" {
134
135void *IpcBuffer_create(const char *name, size_t size)
136{
137 managed_shared_memory *shm = audio_server_shmem::getInstance();
138 IpcBuffer * cb = shm->find<IpcBuffer>(name).first;
139 if (cb) {
140 IpcBuffer_destroy(cb);
141 }
142 cb = shm->construct<IpcBuffer>(name)(name, size);
143 return cb;
144}
145
146void IpcBuffer_destroy(void *cb)
147{
148 managed_shared_memory *shm = audio_server_shmem::getInstance();
149 shm->destroy<IpcBuffer>(((IpcBuffer *)(cb))->name());
150}
151
152void IpcBuffer_write(void *cb, const unsigned char *buf, int size)
153{
154 ((IpcBuffer *)(cb))->write_nb(buf, size);
155}
156
Tim Yaoa8aea182021-03-03 21:53:09 -0800157uint8_t *IpcBuffer_get_ptr(const char *name)
158{
159 managed_shared_memory *shm = audio_server_shmem::getInstance();
160 IpcBuffer * cb = shm->find<IpcBuffer>(name).first;
161 if (cb) {
162 return cb->start_ptr();
163 }
164 return NULL;
165}
166
167uint64_t IpcBuffer_get_wr_pos(const char *name)
168{
169 managed_shared_memory *shm = audio_server_shmem::getInstance();
170 IpcBuffer * cb = shm->find<IpcBuffer>(name).first;
171 if (cb) {
172 uint64_t time, position;
173 cb->get_write_position(time, position);
174 return position;
175 }
176 return 0;
177}
178
Tim Yao10e5d9b2020-12-30 17:38:10 -0800179}
180