1 // shared memory interface to the supercollider server
2 // Copyright (C) 2011 Tim Blechmann
3 // Copyright (C) 2011 Jakob Leben
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; see the file COPYING. If not, write to
17 // the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 // Boston, MA 02111-1307, USA.
20 #ifndef SERVER_SHM_HPP
21 #define SERVER_SHM_HPP
23 #include "scope_buffer.hpp"
25 #include <boost/version.hpp>
26 #include <boost/foreach.hpp>
27 #include <boost/ref.hpp>
28 #include <boost/lexical_cast.hpp>
29 #include <boost/interprocess/managed_shared_memory.hpp>
30 #include <boost/interprocess/containers/vector.hpp>
31 #include <boost/atomic.hpp>
33 namespace detail_server_shm
{
35 using std::string
; using std::pair
;
39 namespace bi
= boost::interprocess
;
40 using bi::managed_shared_memory
; using bi::shared_memory_object
;
42 static inline string
make_shmem_name(unsigned int port_number
)
44 return string("SuperColliderServer_") + boost::lexical_cast
<string
>(port_number
);
47 class server_shared_memory
50 typedef offset_ptr
<float> sh_float_ptr
;
51 typedef offset_ptr
<scope_buffer
> scope_buffer_ptr
;
53 typedef bi::allocator
<scope_buffer_ptr
, managed_shared_memory::segment_manager
> scope_buffer_ptr_allocator
;
54 typedef bi::vector
<scope_buffer_ptr
, scope_buffer_ptr_allocator
> scope_buffer_vector
;
56 server_shared_memory(managed_shared_memory
& segment
, int control_busses
, int num_scope_buffers
= 128):
57 num_control_busses(control_busses
),
59 scope_buffers(scope_buffer_ptr_allocator(segment
.get_segment_manager()))
61 control_busses_
= (float*)segment
.allocate(control_busses
* sizeof(float));
62 std::fill(control_busses_
.get(), control_busses_
.get() + control_busses
, 0);
64 for (int i
= 0; i
!= num_scope_buffers
; ++i
) {
65 scope_buffer
* raw_scope_ptr
= (scope_buffer
*)segment
.allocate(sizeof(scope_buffer
));
66 new(raw_scope_ptr
) scope_buffer();
67 scope_buffer_ptr buf
= raw_scope_ptr
;
68 scope_buffers
.push_back(buf
);
72 void destroy(managed_shared_memory
& segment
)
74 segment
.deallocate(control_busses_
.get());
76 for (int i
= 0; i
!= scope_buffers
.size(); ++i
)
77 segment
.deallocate(scope_buffers
[i
].get());
80 void set_control_bus(int bus
, float value
)
82 // TODO: we need to set the control busses via a work queue
85 float * get_control_busses(void)
87 return control_busses_
.get();
90 scope_buffer
* get_scope_buffer(unsigned int index
)
92 if (index
< scope_buffers
.size())
93 return scope_buffers
[index
].get();
100 int num_control_busses
;
101 sh_float_ptr control_busses_
; // control busses
102 scope_buffer_vector scope_buffers
;
105 class server_shared_memory_creator
108 server_shared_memory_creator(unsigned int port_number
, unsigned int control_busses
):
109 shmem_name(detail_server_shm::make_shmem_name(port_number
)),
110 segment(bi::open_or_create
, shmem_name
.c_str(), 8192 * 1024)
112 #if (BOOST_VERSION < 105100)
116 const int num_scope_buffers
= 128;
117 size_t scope_pool_size
= num_scope_buffers
* sizeof(float) * 8192; // pessimize, about 4 MB
118 void * memory_for_scope_pool
= segment
.allocate(scope_pool_size
);
119 scope_pool
.init(memory_for_scope_pool
, scope_pool_size
);
121 shm
= segment
.construct
<server_shared_memory
>(shmem_name
.c_str())(ref(segment
), control_busses
,
125 static void cleanup(unsigned int port_number
)
127 shared_memory_object::remove(detail_server_shm::make_shmem_name(port_number
).c_str());
130 ~server_shared_memory_creator(void)
138 shm
->destroy(segment
);
139 segment
.destroy
<server_shared_memory
>(shmem_name
.c_str());
140 shared_memory_object::remove(shmem_name
.c_str());
144 float * get_control_busses(void)
146 return shm
->get_control_busses();
149 scope_buffer_writer
get_scope_buffer_writer(unsigned int index
, unsigned int channels
, unsigned int size
)
151 scope_buffer
*buf
= shm
->get_scope_buffer(index
);
153 return scope_buffer_writer(buf
, scope_pool
, channels
, size
);
155 return scope_buffer_writer();
158 void release_scope_buffer_writer( scope_buffer_writer
& writer
)
160 writer
.release( scope_pool
);
165 managed_shared_memory segment
;
166 scope_buffer_pool scope_pool
;
169 server_shared_memory
* shm
;
173 class server_shared_memory_client
176 server_shared_memory_client(unsigned int port_number
):
177 shmem_name(detail_server_shm::make_shmem_name(port_number
)),
178 segment(bi::open_only
, shmem_name
.c_str())
180 pair
<server_shared_memory
*, size_t> res
= segment
.find
<server_shared_memory
> (shmem_name
.c_str());
182 throw std::runtime_error("Cannot connect to shared memory");
186 float * get_control_busses(void)
188 return shm
->get_control_busses();
191 scope_buffer_reader
get_scope_buffer_reader(unsigned int index
)
193 scope_buffer
*buf
= shm
->get_scope_buffer(index
);
194 return scope_buffer_reader(buf
);
199 managed_shared_memory segment
;
200 server_shared_memory
* shm
;
205 using detail_server_shm::server_shared_memory_client
;
206 using detail_server_shm::server_shared_memory_creator
;
207 using detail_server_shm::scope_buffer_writer
;
208 using detail_server_shm::scope_buffer_reader
;
209 using detail_server_shm::scope_buffer
;
211 #endif /* SERVER_SHM_HPP */