inline unary ops: fix sc_floor for non-sse4.1
[supercollider.git] / common / server_shm.hpp
blob9073c25599a6299014129b5454f184ea86472ba3
1 // shared memory interface to the supercollider server
2 // Copyright (C) 2011 Tim Blechmann
3 // Copyright (C) 2011 Jakob Leben
4 //
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.
9 //
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/foreach.hpp>
26 #include <boost/ref.hpp>
27 #include <boost/lexical_cast.hpp>
28 #include <boost/interprocess/managed_shared_memory.hpp>
29 #include <boost/interprocess/containers/vector.hpp>
30 #include <boost/atomic.hpp>
32 namespace detail_server_shm {
34 using std::string; using std::pair;
36 using boost::ref;
38 namespace bi = boost::interprocess;
39 using bi::managed_shared_memory; using bi::shared_memory_object;
41 static inline string make_shmem_name(uint port_number)
43 return string("SuperColliderServer_") + boost::lexical_cast<string>(port_number);
46 struct server_shared_memory
48 typedef offset_ptr<float> sh_float_ptr;
49 typedef offset_ptr<scope_buffer> scope_buffer_ptr;
51 typedef bi::allocator<scope_buffer_ptr, managed_shared_memory::segment_manager> scope_buffer_ptr_allocator;
52 typedef bi::vector<scope_buffer_ptr, scope_buffer_ptr_allocator> scope_buffer_vector;
54 server_shared_memory(managed_shared_memory & segment, int control_busses, int num_scope_buffers = 128):
55 num_control_busses(control_busses),
57 scope_buffers(scope_buffer_ptr_allocator(segment.get_segment_manager()))
59 control_busses_ = (float*)segment.allocate(control_busses * sizeof(float));
60 std::fill(control_busses_.get(), control_busses_.get() + control_busses, 0);
62 for (int i = 0; i != num_scope_buffers; ++i) {
63 scope_buffer * raw_scope_ptr = (scope_buffer*)segment.allocate(sizeof(scope_buffer));
64 new(raw_scope_ptr) scope_buffer();
65 scope_buffer_ptr buf = raw_scope_ptr;
66 scope_buffers.push_back(buf);
70 void destroy(managed_shared_memory & segment)
72 segment.deallocate(control_busses_.get());
74 for (int i = 0; i != scope_buffers.size(); ++i)
75 segment.deallocate(scope_buffers[i].get());
78 void set_control_bus(int bus, float value)
80 // TODO: we need to set the control busses via a work queue
83 float * get_control_busses(void)
85 return control_busses_.get();
88 scope_buffer * get_scope_buffer(uint index)
90 if (index < scope_buffers.size())
91 return scope_buffers[index].get();
92 else
93 return 0;
96 private:
97 string shmem_name;
98 int num_control_busses;
99 sh_float_ptr control_busses_; // control busses
100 scope_buffer_vector scope_buffers;
103 class server_shared_memory_creator
105 public:
106 server_shared_memory_creator(uint port_number, uint control_busses):
107 shmem_name(detail_server_shm::make_shmem_name(port_number)),
108 segment(bi::open_or_create, shmem_name.c_str(), 8192 * 1024)
110 segment.flush();
112 const int num_scope_buffers = 128;
113 size_t scope_pool_size = num_scope_buffers * sizeof(float) * 8192; // pessimize, about 4 MB
114 void * memory_for_scope_pool = segment.allocate(scope_pool_size);
115 scope_pool.init(memory_for_scope_pool, scope_pool_size);
117 shm = segment.construct<server_shared_memory>(shmem_name.c_str())(ref(segment), control_busses,
118 num_scope_buffers);
121 static void cleanup(uint port_number)
123 shared_memory_object::remove(detail_server_shm::make_shmem_name(port_number).c_str());
126 ~server_shared_memory_creator(void)
128 shm->destroy(segment);
129 segment.destroy<server_shared_memory>(shmem_name.c_str());
130 shared_memory_object::remove(shmem_name.c_str());
133 float * get_control_busses(void)
135 return shm->get_control_busses();
138 scope_buffer_writer get_scope_buffer_writer(uint index, uint channels, uint size)
140 scope_buffer *buf = shm->get_scope_buffer(index);
141 if (buf)
142 return scope_buffer_writer(buf, scope_pool, channels, size);
143 else
144 return scope_buffer_writer();
147 void release_scope_buffer_writer( scope_buffer_writer & writer )
149 writer.release( scope_pool );
152 private:
153 string shmem_name;
154 managed_shared_memory segment;
155 scope_buffer_pool scope_pool;
157 protected:
158 server_shared_memory * shm;
162 class server_shared_memory_client
164 public:
165 server_shared_memory_client(uint port_number):
166 shmem_name(detail_server_shm::make_shmem_name(port_number)),
167 segment(bi::open_only, shmem_name.c_str())
169 pair<server_shared_memory*, size_t> res = segment.find<server_shared_memory> (shmem_name.c_str());
170 if (res.second != 1)
171 throw std::runtime_error("Cannot connect to shared memory");
172 shm = res.first;
175 float * get_control_busses(void)
177 return shm->get_control_busses();
180 scope_buffer_reader get_scope_buffer_reader(uint index)
182 scope_buffer *buf = shm->get_scope_buffer(index);
183 return scope_buffer_reader(buf);
186 private:
187 string shmem_name;
188 managed_shared_memory segment;
189 server_shared_memory * shm;
194 using detail_server_shm::server_shared_memory_client;
195 using detail_server_shm::server_shared_memory_creator;
196 using detail_server_shm::scope_buffer_writer;
197 using detail_server_shm::scope_buffer_reader;
198 using detail_server_shm::scope_buffer;
200 #endif /* SERVER_SHM_HPP */