aboutsummaryrefslogtreecommitdiff
path: root/shmem.c
diff options
context:
space:
mode:
Diffstat (limited to 'shmem.c')
-rw-r--r--shmem.c206
1 files changed, 158 insertions, 48 deletions
diff --git a/shmem.c b/shmem.c
index b6ac1d8..d609360 100644
--- a/shmem.c
+++ b/shmem.c
@@ -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);
}