diff options
Diffstat (limited to 'shmem.c')
-rw-r--r-- | shmem.c | 206 |
1 files changed, 158 insertions, 48 deletions
@@ -1,16 +1,30 @@ #include "m_pd.h" -#include <stdio.h> -#include <sys/shm.h> -#include <sys/stat.h> +#include <stdio.h> +#ifdef _WIN32
+ #define NOMINMAX // avoid interference between macro min and the function defined in this file... + #include <windows.h> + #include <stdio.h> + #include <conio.h> + #include <tchar.h> +#else + #include <sys/shm.h> + #include <sys/stat.h>
+#endif // _WIN32 typedef struct shmem { - t_object x_obj; - int segment_id; - t_float *share_memory; - int segment_size; + t_object x_obj;
+#ifdef _WIN32
+ HANDLE m_MapFile;
+ char m_fileMappingName[128];
+#else
+ int segment_id;
+#endif // _WIN32
+ t_outlet *m_info_out; + t_float *share_memory; + int segment_size; } t_shmem; - +
static inline t_float min(t_float x1,t_float x2) { if (x1 <= x2) { @@ -18,8 +32,13 @@ static inline t_float min(t_float x1,t_float x2) } else { return x2; } -} - +}
+
+/**
+ * \fn void shmem_set_tab(t_shmem *x, t_symbol *unused, int argc, t_atom *argv)
+ * \brief Set the table to bind to and copy its data to internal buffer.
+ *
+ */ int shmem_set_tab(t_shmem *x, t_symbol *table, int src_offset, int dest_offset, int size) { int npoints, i, index_max; @@ -41,9 +60,19 @@ int shmem_set_tab(t_shmem *x, t_symbol *table, int src_offset, int dest_offset, // post("copied=%d", i); return(i); } - +
+/**
+ * \fn void shmem_set(t_shmem *x, t_symbol *unused, int argc, t_atom *argv)
+ * \brief Handle the [memset ...( message
+ *
+ */ void shmem_set(t_shmem *x, t_symbol *unused, int argc, t_atom *argv) -{ +{
+ if ( !x->share_memory ){
+ error("Create a valid shared memory before setting data !");
+ return;
+ }
+ int i, j, index_max, shmem_offset, array_offset, size; if (argc < 1) { @@ -87,29 +116,39 @@ int shmem_dump_tab(t_shmem *x, t_symbol *table, int src_offset, int dest_offset, t_garray *a; t_word *vec; int i, index_max, vecsize; - + t_symbol *s = table; i=0; - + if (!(a = (t_garray *)pd_findbyclass(s, garray_class))) pd_error(x, "%s: no such array", s->s_name); - else if (!garray_getfloatwords(a, &vecsize, &vec)) + else if (!garray_getfloatwords(a, &vecsize, &vec)) pd_error(x, "%s: bad template for tabwrite", s->s_name); - else { - + else { + index_max = min(x->segment_size-src_offset, vecsize-dest_offset); index_max=min(index_max, size); for (i=0; i<index_max; i++) vec[i+dest_offset].w_float = x->share_memory[i+src_offset]; - } + } garray_redraw(a); // post("copied=%d", i); return(i); } - +
+/**
+ * void shmem_dump(t_shmem *x, t_symbol *unused, int argc, t_atom *argv)
+ * \brief Handle the [memdump ...( message
+ *
+ */ void shmem_dump(t_shmem *x, t_symbol *unused, int argc, t_atom *argv) -{ +{
+ if ( !x->share_memory ){
+ error("Create a valid shared memory before dumping data !");
+ return;
+ }
+ int i, j, shmem_offset, dest_offset, size; if (argc < 1) { @@ -141,57 +180,127 @@ void shmem_dump(t_shmem *x, t_symbol *unused, int argc, t_atom *argv) size = atom_getfloatarg(3,argc,argv); } shmem_dump_tab(x, s, shmem_offset, dest_offset, size); - } + } } void shmem_read(t_shmem *x, t_float index) -{ +{
+ if ( !x->share_memory ) return; int shmem_offset; - + shmem_offset = index; if (shmem_offset < 0) shmem_offset = 0; if (shmem_offset > x->segment_size-1) shmem_offset = x->segment_size-1; - // post("i=%d", offset); + // post("i=%d", offset); outlet_float(x->x_obj.ob_outlet, x->share_memory[shmem_offset]); } - -t_class *shmem_class; - -void *shmem_new( t_floatarg id, t_floatarg size) -{ - struct shmid_ds shmbuffer; - // post ("id, size: %f, %f", id, size); - t_shmem *x = (t_shmem *)pd_new(shmem_class); - - x->segment_size = (int)size; - x->segment_id = shmget ((int)id, sizeof(t_float)*x->segment_size, - IPC_CREAT | S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH); +
+/**
+ * \fn void shmem_allocate(t_shmem *x, int id, int size)
+ * \brief Allocate a new shared memory segment.
+ *
+ */
+
+void shmem_allocate(t_shmem *x, t_float fId, t_float fSize)
+{
+ int id = (int) fId;
+ x->segment_size = (int) fSize;
+#ifdef _WIN32
+ if ( x->share_memory ) UnmapViewOfFile( x->share_memory );
+ if ( x->m_MapFile ) CloseHandle( x->m_MapFile );
+
+ sprintf(x->m_fileMappingName, "puredata-FileMappingObject_%d", id);
+
+ x->m_MapFile = CreateFileMapping(
+ INVALID_HANDLE_VALUE, // use paging file
+ NULL, // default security
+ PAGE_READWRITE, // read/write access
+ (x->segment_size & 0xFFFFFFFF00000000) >> 32, // maximum object size (high-order DWORD)
+ x->segment_size & 0xFFFFFFFF, // maximum object size (low-order DWORD)
+ x->m_fileMappingName); // name of mapping object
+
+ if (x->m_MapFile == NULL)
+ {
+ error("Could not create file mapping object %s - error %ld.",x->m_fileMappingName, GetLastError());
+ outlet_float(x->m_info_out, -1);
+ return;
+ }
+
+ x->share_memory = (t_float*) MapViewOfFile(x->m_MapFile, // handle to map object
+ FILE_MAP_ALL_ACCESS, // read/write permission
+ 0,
+ 0,
+ x->segment_size);
+
+ if ( !x->share_memory ){
+ error("Could not get a view of file %s - error %ld",x->m_fileMappingName, GetLastError());
+ outlet_float(x->m_info_out, -1);
+ return;
+ } else {
+ verbose(0,"File mapping object %s successfully created.",x->m_fileMappingName);
+ }
+
+#else
+
+ struct shmid_ds shmbuffer; +
+ x->segment_id = shmget (id, sizeof(t_float)*x->segment_size, + IPC_CREAT | S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH); if(x->segment_id>0) { - x->share_memory = (t_float*) shmat (x->segment_id, 0, 0); - // post("shmem memory attached at address %p\n", x->share_memory); + x->share_memory = (t_float*) shmat (x->segment_id, 0, 0); + // post("shmem memory attached at address %p\n", x->share_memory); - shmctl (x->segment_id, IPC_STAT, &shmbuffer); - // post ("segment size: %d\n", shmbuffer.shm_segsz); + shmctl (x->segment_id, IPC_STAT, &shmbuffer); + // post ("segment size: %d\n", shmbuffer.shm_segsz); if ((int)shmbuffer.shm_segsz < (int)sizeof(t_float)*x->segment_size) { // there was a problem, set object meme size to 0 error("could not allocate shmem memory Id : %d, size %d", (int)id, x->segment_size ); - x->segment_size = 0; + x->segment_size = 0;
+ outlet_float(x->m_info_out, -1); } } else { error("could not allocate shmem memory Id : %d, size %d", (int)id, x->segment_size ); - x->segment_size = 0; - } + x->segment_size = 0;
+ outlet_float(x->m_info_out, -1); + }
+#endif // _WIN32
+ outlet_float(x->m_info_out, id);
+}
- outlet_new(&x->x_obj, 0); +t_class *shmem_class; +
+/**
+ * \fn void shmem_new(t_floatarg id, t_floatarg size)
+ * \brief Create a new instance of object.
+ *
+ * \param t_floatarg id : a unique id defining the shared memory segment
+ * \param t_floatarg size : size of the memory segment
+ *
+ */ +void *shmem_new( t_floatarg id, t_floatarg size) +{ + // post ("id, size: %f, %f", id, size); + t_shmem *x = (t_shmem *)pd_new(shmem_class);
+
+ x->share_memory = NULL;
+
+ outlet_new(&x->x_obj, 0);
+ x->m_info_out = outlet_new(&x->x_obj, 0);
+ shmem_allocate(x, id, size); return (void *)x; -} +}
void shmem_free(t_shmem *x) -{ +{
+#ifdef _WIN32
+ if ( x->share_memory ) UnmapViewOfFile( x->share_memory );
+ if ( x->m_MapFile ) CloseHandle( x->m_MapFile );
+#else shmdt (x->share_memory); - shmctl (x->segment_id, IPC_RMID, 0); + shmctl (x->segment_id, IPC_RMID, 0);
+#endif // _WIN32 } void shmem_clear(t_shmem *x) @@ -208,6 +317,7 @@ void shmem_setup(void) class_addmethod(shmem_class, (t_method)shmem_set, gensym("memset"), A_GIMME, 0); class_addmethod(shmem_class, (t_method)shmem_dump, gensym("memdump"), A_GIMME, 0); class_addmethod(shmem_class, (t_method)shmem_clear, gensym("memclear"), 0); - class_addmethod(shmem_class, (t_method)shmem_read, gensym("memread"),A_DEFFLOAT, 0); + class_addmethod(shmem_class, (t_method)shmem_read, gensym("memread"),A_DEFFLOAT, 0);
+ class_addmethod(shmem_class, (t_method)shmem_allocate, gensym("allocate"),A_FLOAT, A_FLOAT, 0); } |