summaryrefslogtreecommitdiffstats
path: root/raul
diff options
context:
space:
mode:
Diffstat (limited to 'raul')
-rw-r--r--raul/Atom.h127
-rw-r--r--raul/AtomLiblo.h73
-rw-r--r--raul/AtomRaptor.h93
-rw-r--r--raul/Condition.h42
-rw-r--r--raul/Makefile376
-rw-r--r--raul/Makefile.am21
-rw-r--r--raul/Mutex.h41
-rw-r--r--raul/Path.h251
-rw-r--r--raul/Queue.h160
-rw-r--r--raul/Semaphore.h63
-rw-r--r--raul/SharedPtr.h58
-rw-r--r--raul/Slave.h66
-rw-r--r--raul/Thread.h107
-rw-r--r--raul/WeakPtr.h26
14 files changed, 1504 insertions, 0 deletions
diff --git a/raul/Atom.h b/raul/Atom.h
new file mode 100644
index 0000000..4d85f7f
--- /dev/null
+++ b/raul/Atom.h
@@ -0,0 +1,127 @@
+/* This file is part of Ingen. Copyright (C) 2006 Dave Robillard.
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef RAUL_ATOM_H
+#define RAUL_ATOM_H
+
+#include <cstdlib>
+#include <cassert>
+#include <cstring>
+#include <string>
+
+using std::string;
+
+
+/** An OSC atom (fundamental data types OSC messages are composed of).
+ */
+class Atom {
+public:
+ enum Type {
+ NIL,
+ INT,
+ FLOAT,
+ STRING,
+ BLOB
+ };
+
+ Atom() : _type(NIL), _blob_val(0) {}
+ Atom(int32_t val) : _type(INT), _int_val(val) {}
+ Atom(float val) : _type(FLOAT), _float_val(val) {}
+ Atom(const char* val) : _type(STRING), _string_val(strdup(val)) {}
+ Atom(const string& val) : _type(STRING), _string_val(strdup(val.c_str())) {}
+
+ Atom(void* val) : _type(BLOB), _blob_size(sizeof(val)), _blob_val(malloc(_blob_size))
+ { memcpy(_blob_val, val, sizeof(_blob_size)); }
+
+ ~Atom()
+ {
+ if (_type == STRING)
+ free(_string_val);
+ else if (_type == BLOB)
+ free(_blob_val);
+ }
+
+ // Gotta love C++ boilerplate:
+
+ Atom(const Atom& copy)
+ : _type(copy._type)
+ , _blob_size(copy._blob_size)
+ {
+ switch (_type) {
+ case NIL: _blob_val = 0; break;
+ case INT: _int_val = copy._int_val; break;
+ case FLOAT: _float_val = copy._float_val; break;
+ case STRING: _string_val = strdup(copy._string_val); break;
+
+ case BLOB: _blob_val = malloc(_blob_size);
+ memcpy(_blob_val, copy._blob_val, _blob_size);
+ break;
+
+ default: break;
+ }
+ }
+
+ Atom& operator=(const Atom& other)
+ {
+ if (_type == BLOB)
+ free(_blob_val);
+ else if (_type == STRING)
+ free(_string_val);
+
+ _type = other._type;
+ _blob_size = other._blob_size;
+
+ switch (_type) {
+ case NIL: _blob_val = 0; break;
+ case INT: _int_val = other._int_val; break;
+ case FLOAT: _float_val = other._float_val; break;
+ case STRING: _string_val = strdup(other._string_val); break;
+
+ case BLOB: _blob_val = malloc(_blob_size);
+ memcpy(_blob_val, other._blob_val, _blob_size);
+ break;
+
+ default: break;
+ }
+ return *this;
+ }
+
+ /** Type of this atom. Always check this before attempting to get the
+ * value - attempting to get the incorrectly typed value is a fatal error.
+ */
+ Type type() const { return _type; }
+
+ inline int32_t get_int32() const { assert(_type == INT); return _int_val; }
+ inline float get_float() const { assert(_type == FLOAT); return _float_val; }
+ inline const char* get_string() const { assert(_type == STRING); return _string_val; }
+ inline const void* get_blob() const { assert(_type == BLOB); return _blob_val; }
+
+ inline operator bool() const { return (_type != NIL); }
+
+private:
+ Type _type;
+
+ size_t _blob_size; ///< always a multiple of 32
+
+ union {
+ int32_t _int_val;
+ float _float_val;
+ char* _string_val;
+ void* _blob_val;
+ };
+};
+
+#endif // RAUL_ATOM_H
diff --git a/raul/AtomLiblo.h b/raul/AtomLiblo.h
new file mode 100644
index 0000000..772a26e
--- /dev/null
+++ b/raul/AtomLiblo.h
@@ -0,0 +1,73 @@
+/* This file is part of Ingen. Copyright (C) 2006 Dave Robillard.
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef RAUL_ATOM_LIBLO_H
+#define RAUL_ATOM_LIBLO_H
+
+#include <lo/lo.h>
+#include "raul/Atom.h"
+
+
+/** Support for serializing an Atom to/from liblo messages.
+ *
+ * (Here to prevent a unnecessary liblo dependency for Atom).
+ */
+class AtomLiblo {
+public:
+ static void lo_message_add_atom(lo_message m, const Atom& atom) {
+ switch (atom.type()) {
+ //case NIL:
+ // (see below)
+ //break;
+ case Atom::INT:
+ lo_message_add_int32(m, atom.get_int32());
+ break;
+ case Atom::FLOAT:
+ lo_message_add_float(m, atom.get_float());
+ break;
+ case Atom::STRING:
+ lo_message_add_string(m, atom.get_string());
+ break;
+ case Atom::BLOB:
+ // FIXME: is this okay? what does liblo do?
+ lo_message_add_blob(m, const_cast<void*>(atom.get_blob()));
+ break;
+ default: // This catches Atom::Type::NIL too
+ lo_message_add_nil(m);
+ break;
+ }
+ }
+
+ static Atom lo_arg_to_atom(char type, lo_arg* arg) {
+ switch (type) {
+ case 'i':
+ return Atom(arg->i);
+ case 'f':
+ return Atom(arg->f);
+ case 's':
+ return Atom(&arg->s);
+ //case 'b'
+ // FIXME: How to get a blob from a lo_arg?
+ //return Atom(arg->b);
+ default:
+ return Atom();
+ }
+ }
+
+};
+
+
+#endif // RAUL_ATOM_LIBLO_H
diff --git a/raul/AtomRaptor.h b/raul/AtomRaptor.h
new file mode 100644
index 0000000..b06286d
--- /dev/null
+++ b/raul/AtomRaptor.h
@@ -0,0 +1,93 @@
+/* This file is part of Ingen. Copyright (C) 2006 Dave Robillard.
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef RAUL_ATOM_RAPTOR_H
+#define RAUL_ATOM_RAPTOR_H
+
+#include <sstream>
+#include <cstring>
+#include <raptor.h>
+#include "raul/Atom.h"
+
+#define U(x) ((const unsigned char*)(x))
+
+/** Support for serializing an Atom to/from RDF (via redland aka librdf).
+ *
+ * (Here to prevent a unnecessary redland dependency for Atom).
+ */
+class AtomRaptor {
+public:
+ /** Set this atom's value to the object (value) portion of an RDF triple.
+ *
+ * Caller is responsible for calling free(triple->object).
+ */
+ static void atom_to_triple_object(raptor_statement* triple, const Atom& atom) {
+ std::ostringstream os;
+
+ triple->object_literal_language = NULL;
+
+ switch (atom.type()) {
+ case Atom::INT:
+ os << atom.get_int32();
+ triple->object = (unsigned char*)strdup(os.str().c_str());
+ triple->object_type = RAPTOR_IDENTIFIER_TYPE_LITERAL;
+ triple->object_literal_datatype = raptor_new_uri(
+ U("http://www.w3.org/2001/XMLSchema#integer"));
+ break;
+ case Atom::FLOAT:
+ os << atom.get_float();
+ triple->object = (unsigned char*)strdup(os.str().c_str());
+ triple->object_type = RAPTOR_IDENTIFIER_TYPE_LITERAL;
+ triple->object_literal_datatype = raptor_new_uri(
+ U("http://www.w3.org/2001/XMLSchema#float"));
+ break;
+ case Atom::STRING:
+ triple->object = strdup(atom.get_string());
+ triple->object_type = RAPTOR_IDENTIFIER_TYPE_LITERAL;
+ break;
+ case Atom::BLOB:
+ case Atom::NIL:
+ default:
+ cerr << "WARNING: Unserializable Atom!" << endl;
+ triple->object = NULL;
+ triple->object_type = RAPTOR_IDENTIFIER_TYPE_UNKNOWN;
+ }
+ }
+
+#if 0
+ static Atom node_to_atom(librdf_node* node) {
+ /*switch (type) {
+ case 'i':
+ return Atom(arg->i);
+ case 'f':
+ return Atom(arg->f);
+ case 's':
+ return Atom(&arg->s);
+ //case 'b'
+ // FIXME: How to get a blob from a lo_arg?
+ //return Atom(arg->b);
+ default:
+ return Atom();
+ }*/
+ cerr << "FIXME: node_to_atom\n";
+ return Atom();
+ }
+#endif
+
+};
+
+
+#endif // RAUL_ATOM_RAPTOR_H
diff --git a/raul/Condition.h b/raul/Condition.h
new file mode 100644
index 0000000..29eaec8
--- /dev/null
+++ b/raul/Condition.h
@@ -0,0 +1,42 @@
+/* This file is part of Ingen. Copyright (C) 2006 Dave Robillard.
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef RAUL_CONDITION_H
+#define RAUL_CONDITION_H
+
+#include <pthread.h>
+
+
+/** Trivial (but pretty) wrapper around POSIX Conditions (zero overhead).
+ *
+ * A semaphore that isn't a counter, is slow, and not realtime safe. Yay.
+ */
+class Condition {
+public:
+ inline Condition() { pthread_cond_init(&_cond, NULL); }
+
+ inline ~Condition() { pthread_cond_destroy(&_cond); }
+
+ inline void signal() { pthread_cond_signal(&_cond); }
+ inline void wait(Mutex& mutex) { pthread_cond_wait(&_cond, &mutex._mutex); }
+
+private:
+ pthread_cond_t _cond;
+};
+
+
+#endif // RAUL_CONDITION_H
+
diff --git a/raul/Makefile b/raul/Makefile
new file mode 100644
index 0000000..6e7ba67
--- /dev/null
+++ b/raul/Makefile
@@ -0,0 +1,376 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# raul/Makefile. Generated from Makefile.in by configure.
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+
+srcdir = .
+top_srcdir = ..
+
+pkgdatadir = $(datadir)/raul
+pkglibdir = $(libdir)/raul
+pkgincludedir = $(includedir)/raul
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = /usr/bin/install -c
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+am__append_1 = AtomLiblo.h
+am__append_2 = AtomRaptor.h
+subdir = raul
+DIST_COMMON = $(am__raulinclude_HEADERS_DIST) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+am__raulinclude_HEADERS_DIST = SharedPtr.h WeakPtr.h Path.h Queue.h \
+ Semaphore.h Mutex.h Condition.h Thread.h Slave.h Atom.h \
+ AtomLiblo.h AtomRaptor.h
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(raulincludedir)"
+raulincludeHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(raulinclude_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = ${SHELL} /home/dave/code/codesonnet/raul/missing --run aclocal-1.9
+AMDEP_FALSE = #
+AMDEP_TRUE =
+AMTAR = ${SHELL} /home/dave/code/codesonnet/raul/missing --run tar
+AUTOCONF = ${SHELL} /home/dave/code/codesonnet/raul/missing --run autoconf
+AUTOHEADER = ${SHELL} /home/dave/code/codesonnet/raul/missing --run autoheader
+AUTOMAKE = ${SHELL} /home/dave/code/codesonnet/raul/missing --run automake-1.9
+AWK = gawk
+BOOST_CFLAGS =
+BOOST_LIBS =
+CPPFLAGS =
+CXX = g++
+CXXCPP = g++ -E
+CXXDEPMODE = depmode=none
+CXXFLAGS = -pipe -O2 -march=pentium4 -msse -msse2 -mfpmath=sse -ffast-math -ftree-vectorize -DNDEBUG -finline-functions -fomit-frame-pointer -fmessage-length=139 -fdiagnostics-show-location=every-line
+CYGPATH_W = echo
+DEFS = -DPACKAGE_NAME=\"raul\" -DPACKAGE_TARNAME=\"raul\" -DPACKAGE_VERSION=\"0.0.0\" -DPACKAGE_STRING=\"raul\ 0.0.0\" -DPACKAGE_BUGREPORT=\"drobilla@connect.carleton.ca\" -DPACKAGE=\"raul\" -DVERSION=\"0.0.0\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DSTDC_HEADERS=1 -DHAVE_STDLIB_H=1 -DHAVE_MALLOC=1 -DHAVE_STRDUP=1 -DHAVE_STRERROR=1
+DEPDIR = .deps
+ECHO_C =
+ECHO_N = -n
+ECHO_T =
+EGREP = /bin/grep -E
+EXEEXT =
+GREP = /bin/grep
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_STRIP_PROGRAM = ${SHELL} $(install_sh) -c -s
+LDFLAGS =
+LIBLO_CFLAGS = -I/usr/local/include
+LIBLO_LIBS = -L/usr/local/lib -llo -lpthread
+LIBOBJS =
+LIBS =
+LTLIBOBJS =
+MAKEINFO = ${SHELL} /home/dave/code/codesonnet/raul/missing --run makeinfo
+OBJEXT = o
+PACKAGE = raul
+PACKAGE_BUGREPORT = drobilla@connect.carleton.ca
+PACKAGE_NAME = raul
+PACKAGE_STRING = raul 0.0.0
+PACKAGE_TARNAME = raul
+PACKAGE_VERSION = 0.0.0
+PATH_SEPARATOR = :
+PKG_CONFIG = /usr/bin/pkg-config
+RAPTOR_CFLAGS =
+RAPTOR_LIBS = -lraptor -lcurl -lgssapi_krb5 -lkrb5 -lk5crypto -lkrb5support -lcom_err -lresolv -lidn -ldl -lssl -lcrypto -lz -lxslt -lxml2
+SET_MAKE =
+SHELL = /bin/bash
+STRIP =
+VERSION = 0.0.0
+WITH_BOOST_FALSE = #
+WITH_BOOST_TRUE =
+WITH_LIBLO_FALSE = #
+WITH_LIBLO_TRUE =
+WITH_RAPTOR_FALSE = #
+WITH_RAPTOR_TRUE =
+ac_ct_CXX = g++
+am__fastdepCXX_FALSE =
+am__fastdepCXX_TRUE = #
+am__include = include
+am__leading_dot = .
+am__quote =
+am__tar = ${AMTAR} chof - "$$tardir"
+am__untar = ${AMTAR} xf -
+bindir = ${exec_prefix}/bin
+build_alias =
+datadir = ${datarootdir}
+datarootdir = ${prefix}/share
+docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
+dvidir = ${docdir}
+exec_prefix = ${prefix}
+host_alias =
+htmldir = ${docdir}
+includedir = ${prefix}/include
+infodir = ${datarootdir}/info
+install_sh = /home/dave/code/codesonnet/raul/install-sh
+libdir = ${exec_prefix}/lib
+libexecdir = ${exec_prefix}/libexec
+localedir = ${datarootdir}/locale
+localstatedir = ${prefix}/var
+mandir = ${datarootdir}/man
+mkdir_p = mkdir -p --
+oldincludedir = /usr/include
+pdfdir = ${docdir}
+prefix = /usr/local
+program_transform_name = s,x,x,
+psdir = ${docdir}
+sbindir = ${exec_prefix}/sbin
+sharedstatedir = ${prefix}/com
+sysconfdir = ${prefix}/etc
+target_alias =
+raulincludedir = $(includedir)/raul
+raulinclude_HEADERS = SharedPtr.h WeakPtr.h Path.h Queue.h Semaphore.h \
+ Mutex.h Condition.h Thread.h Slave.h Atom.h $(am__append_1) \
+ $(am__append_2)
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu raul/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu raul/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+uninstall-info-am:
+install-raulincludeHEADERS: $(raulinclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(raulincludedir)" || $(mkdir_p) "$(DESTDIR)$(raulincludedir)"
+ @list='$(raulinclude_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(raulincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(raulincludedir)/$$f'"; \
+ $(raulincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(raulincludedir)/$$f"; \
+ done
+
+uninstall-raulincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(raulinclude_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(raulincludedir)/$$f'"; \
+ rm -f "$(DESTDIR)$(raulincludedir)/$$f"; \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(raulincludedir)"; do \
+ test -z "$$dir" || $(mkdir_p) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-raulincludeHEADERS
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am uninstall-raulincludeHEADERS
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ ctags distclean distclean-generic distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-exec install-exec-am \
+ install-info install-info-am install-man \
+ install-raulincludeHEADERS install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
+ pdf-am ps ps-am tags uninstall uninstall-am uninstall-info-am \
+ uninstall-raulincludeHEADERS
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/raul/Makefile.am b/raul/Makefile.am
new file mode 100644
index 0000000..7d5ac48
--- /dev/null
+++ b/raul/Makefile.am
@@ -0,0 +1,21 @@
+raulincludedir = $(includedir)/raul
+
+raulinclude_HEADERS = \
+ SharedPtr.h \
+ WeakPtr.h \
+ Path.h \
+ Queue.h \
+ Semaphore.h \
+ Mutex.h \
+ Condition.h \
+ Thread.h \
+ Slave.h \
+ Atom.h
+
+if WITH_LIBLO
+raulinclude_HEADERS += AtomLiblo.h
+endif
+
+if WITH_RAPTOR
+raulinclude_HEADERS += AtomRaptor.h
+endif
diff --git a/raul/Mutex.h b/raul/Mutex.h
new file mode 100644
index 0000000..8cff728
--- /dev/null
+++ b/raul/Mutex.h
@@ -0,0 +1,41 @@
+/* This file is part of Ingen. Copyright (C) 2006 Dave Robillard.
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef RAUL_MUTEX_H
+#define RAUL_MUTEX_H
+
+#include <pthread.h>
+
+
+/** Trivial (but pretty) wrapper around POSIX Mutexes (zero overhead).
+ */
+class Mutex {
+public:
+ inline Mutex() { pthread_mutex_init(&_mutex, NULL); }
+
+ inline ~Mutex() { pthread_mutex_destroy(&_mutex); }
+
+ inline bool try_lock() { return (pthread_mutex_trylock(&_mutex) == 0); }
+ inline void lock() { pthread_mutex_lock(&_mutex); }
+ inline void unlock() { pthread_mutex_unlock(&_mutex); }
+
+private:
+ friend class Condition;
+ pthread_mutex_t _mutex;
+};
+
+
+#endif // RAUL_MUTEX_H
diff --git a/raul/Path.h b/raul/Path.h
new file mode 100644
index 0000000..9412e3c
--- /dev/null
+++ b/raul/Path.h
@@ -0,0 +1,251 @@
+/* This file is part of Ingen. Copyright (C) 2006 Dave Robillard.
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef RAUL_PATH_H
+#define RAUL_PATH_H
+
+#include <cctype>
+#include <string>
+#include <cassert>
+using std::string;
+
+
+/** Simple wrapper around standard string with useful path-specific methods.
+ *
+ * This enforces that a Path is a valid OSC path (though it is used for
+ * GraphObject paths, which aren't directly OSC paths but a portion of one).
+ *
+ * A path is divided by slashes (/). The first character MUST be a slash, and
+ * the last character MUST NOT be a slash (except in the special case of the
+ * root path "/", which is the only valid single-character path).
+ *
+ * Valid characters are the 95 printable ASCII characters (32-126), excluding:
+ * space # * , ? [ ] { }
+ */
+class Path : public std::basic_string<char> {
+public:
+
+ /** Construct a Path from an std::string.
+ *
+ * It is a fatal error to construct a Path from an invalid string,
+ * use is_valid first to check.
+ */
+ Path(const std::basic_string<char>& path)
+ : std::basic_string<char>(path)
+ {
+ assert(is_valid(path));
+ }
+
+
+ /** Construct a Path from a C string.
+ *
+ * It is a fatal error to construct a Path from an invalid string,
+ * use is_valid first to check.
+ */
+ Path(const char* cpath)
+ : std::basic_string<char>(cpath)
+ {
+ assert(is_valid(cpath));
+ }
+
+
+ static bool is_valid(const std::basic_string<char>& path)
+ {
+ if (path.length() == 0)
+ return false;
+
+ // Must start with a /
+ if (path.at(0) != '/')
+ return false;
+
+ // Must not end with a slash unless "/"
+ if (path.length() > 1 && path.at(path.length()-1) == '/')
+ return false;
+
+ assert(path.find_last_of("/") != string::npos);
+
+ // Double slash not allowed
+ if (path.find("//") != string::npos)
+ return false;
+
+ // All characters must be printable ASCII
+ for (size_t i=0; i < path.length(); ++i)
+ if (path.at(i) < 32 || path.at(i) > 126)
+ return false;
+
+ // Disallowed characters
+ if ( path.find(" ") != string::npos
+ || path.find("#") != string::npos
+ || path.find("*") != string::npos
+ || path.find(",") != string::npos
+ || path.find("?") != string::npos
+ || path.find("[") != string::npos
+ || path.find("]") != string::npos
+ || path.find("{") != string::npos
+ || path.find("}") != string::npos)
+ return false;
+
+ return true;
+ }
+
+ static bool is_valid_name(const std::basic_string<char>& path)
+ {
+ return is_valid(string("/").append(path));
+ }
+
+
+ /** Convert a string to a valid full path.
+ *
+ * This will make a best effort at turning @a str into a complete, valid
+ * Path, and will always return one.
+ */
+ static string pathify(const std::basic_string<char>& str)
+ {
+ string path = str;
+
+ if (path.length() == 0)
+ return "/"; // this might not be wise
+
+ // Must start with a /
+ if (path.at(0) != '/')
+ path = string("/").append(path);
+
+ // Must not end with a slash unless "/"
+ if (path.length() > 1 && path.at(path.length()-1) == '/')
+ path = path.substr(0, path.length()-1); // chop trailing slash
+
+ assert(path.find_last_of("/") != string::npos);
+
+ replace_invalid_chars(path, false);
+
+ assert(is_valid(path));
+
+ return path;
+ }
+
+ /** Convert a string to a valid name (or "method" - tokens between slashes)
+ *
+ * This will strip all slashes, etc, and always return a valid name/method.
+ */
+ static string nameify(const std::basic_string<char>& str)
+ {
+ string name = str;
+
+ if (name.length() == 0)
+ return "."; // this might not be wise
+
+ replace_invalid_chars(name, true);
+
+ assert(is_valid(string("/") + name));
+
+ return name;
+ }
+
+
+ /** Replace any invalid characters in @a str with a suitable replacement.
+ *
+ * Makes a pretty name - underscores are a valid character, but this chops
+ * both spaces and underscores, uppercasing the next letter, to create
+ * uniform CamelCase names that look nice
+ */
+ static void replace_invalid_chars(string& str, bool replace_slash = false)
+ {
+ for (size_t i=0; i < str.length(); ++i) {
+ if (str[i] == ' ' || str[i] == '_') {
+ str[i+1] = std::toupper(str[i+1]); // capitalize next char
+ str = str.substr(0, i) + str.substr(i+1); // chop space/underscore
+ } else if (str[i] == '[' || str[i] == '{') {
+ str[i] = '(';
+ } else if (str[i] == ']' || str[i] == '}') {
+ str[i] = ')';
+ } else if (str[i] < 32 || str.at(i) > 126
+ || str[i] == '#'
+ || str[i] == '*'
+ || str[i] == ','
+ || str[i] == '?'
+ || (replace_slash && str[i] == '/')) {
+ str[i] = '.';
+ }
+ }
+
+ // Chop brackets
+ while (true) {
+
+ const string::size_type open = str.find("(");
+ const string::size_type close = str.find(")");
+
+ if (open != string::npos) {
+ if (close != string::npos)
+ str.erase(open, (close - open) + 1);
+ } else {
+ break;
+ }
+
+ }
+ }
+
+
+ /** Return the name of this object (everything after the last '/').
+ * This is the "method name" for OSC paths.
+ */
+ inline std::basic_string<char> name() const
+ {
+ if ((*this) == "/")
+ return "";
+ else
+ return substr(find_last_of("/")+1);
+ }
+
+
+ /** Return the parent's path.
+ *
+ * Calling this on the path "/" will return "/".
+ * This is the (deepest) "container path" for OSC paths.
+ */
+ inline Path parent() const
+ {
+ std::basic_string<char> parent = substr(0, find_last_of("/"));
+ return (parent == "") ? "/" : parent;
+ }
+
+ /** Parent path with a "/" appended.
+ *
+ * This exists to avoid needing to be careful about the special case of "/".
+ * To create a child of a path, use parent.base() + child_name.
+ * Returned value is always a valid path, with the single exception that
+ * the last character is "/".
+ */
+ inline string base() const
+ {
+ if ((*this) == "/")
+ return *this;
+ else
+ return (*this) + "/";
+ }
+
+ inline bool is_child_of(const Path& parent) const
+ {
+ return (length() > parent.length() && substr(0, parent.length()) == parent);
+ }
+
+ inline bool is_parent_of(const Path& child) const
+ {
+ return child.is_child_of(*this);
+ }
+};
+
+
+#endif // RAUL_PATH_H
diff --git a/raul/Queue.h b/raul/Queue.h
new file mode 100644
index 0000000..f400497
--- /dev/null
+++ b/raul/Queue.h
@@ -0,0 +1,160 @@
+/* This file is part of Ingen. Copyright (C) 2006 Dave Robillard.
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef RAUL_QUEUE_H
+#define RAUL_QUEUE_H
+
+#include <cassert>
+#include <cstdlib>
+
+
+/** Realtime-safe single-reader single-writer queue (aka lock-free ringbuffer)
+ *
+ * Implemented as a dequeue in a fixed array. This is read/write thread-safe,
+ * pushing and popping may occur simultaneously by seperate threads, but
+ * the push and pop operations themselves are not thread-safe.
+ *
+ * FIXME: Verify atomicity of everything here.
+ */
+template <typename T>
+class Queue
+{
+public:
+ Queue(size_t size);
+ ~Queue();
+
+ inline bool is_empty() const;
+ inline bool is_full() const;
+
+ inline size_t capacity() const { return m_size-1; }
+ inline size_t fill() const;
+
+ inline T& front() const;
+
+ inline bool push(T obj);
+ inline T& pop();
+
+private:
+ // Prevent copies (these are undefined)
+ Queue(const Queue& copy);
+ Queue& operator=(const Queue& copy);
+
+ volatile size_t m_front; ///< Index to front of queue (circular)
+ volatile size_t m_back; ///< Index to back of queue (one past last element) (circular)
+ const size_t m_size; ///< Size of @ref m_objects (you can store m_size-1 objects)
+ T* const m_objects; ///< Fixed array containing queued elements
+};
+
+
+template<typename T>
+Queue<T>::Queue(size_t size)
+: m_front(0),
+ m_back(0),
+ m_size(size+1),
+ m_objects((T*)calloc(m_size, sizeof(T)))
+{
+ assert(size > 1);
+}
+
+
+template <typename T>
+Queue<T>::~Queue()
+{
+ free(m_objects);
+}
+
+
+/** Return whether or not the queue is empty.
+ */
+template <typename T>
+inline bool
+Queue<T>::is_empty() const
+{
+ return (m_back == m_front);
+}
+
+
+/** Return whether or not the queue is full.
+ */
+template <typename T>
+inline bool
+Queue<T>::is_full() const
+{
+ // FIXME: This can probably be faster
+ return (fill() == capacity());
+}
+
+
+/** Returns how many elements are currently in the queue.
+ */
+template <typename T>
+inline size_t
+Queue<T>::fill() const
+{
+ return (m_back + m_size - m_front) % m_size;
+}
+
+
+/** Return the element at the front of the queue without removing it
+ */
+template <typename T>
+inline T&
+Queue<T>::front() const
+{
+ return m_objects[m_front];
+}
+
+
+/** Push an item onto the back of the Queue - realtime-safe, not thread-safe.
+ *
+ * @returns true if @a elem was successfully pushed onto the queue,
+ * false otherwise (queue is full).
+ */
+template <typename T>
+inline bool
+Queue<T>::push(T elem)
+{
+ if (is_full()) {
+ return false;
+ } else {
+ m_objects[m_back] = elem;
+ m_back = (m_back + 1) % (m_size);
+ return true;
+ }
+}
+
+
+/** Pop an item off the front of the queue - realtime-safe, not thread-safe.
+ *
+ * It is a fatal error to call pop() when the queue is empty.
+ *
+ * @returns the element popped.
+ */
+template <typename T>
+inline T&
+Queue<T>::pop()
+{
+ assert(!is_empty());
+ assert(m_size > 0);
+
+ T& r = m_objects[m_front];
+ m_front = (m_front + 1) % (m_size);
+
+ return r;
+}
+
+
+#endif // RAUL_QUEUE_H
diff --git a/raul/Semaphore.h b/raul/Semaphore.h
new file mode 100644
index 0000000..9a696f9
--- /dev/null
+++ b/raul/Semaphore.h
@@ -0,0 +1,63 @@
+/* This file is part of Ingen. Copyright (C) 2006 Dave Robillard.
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef RAUL_SEMAPHORE_H
+#define RAUL_SEMAPHORE_H
+
+#include <semaphore.h>
+
+
+/** Trivial wrapper around POSIX semaphores (zero memory overhead).
+ *
+ * This was created to provide an alternative debuggable implementation of
+ * semaphores based on a cond/mutex pair because semaphore's appeared not to
+ * work in GDB. Turns out sem_wait can fail when run in GDB, and Debian
+ * really needs to update it's man pages.
+ *
+ * This class remains as a trivial (yet pretty) wrapper/abstraction.
+ */
+class Semaphore {
+public:
+ inline Semaphore(unsigned int initial) { sem_init(&m_sem, 0, initial); }
+
+ inline ~Semaphore() { sem_destroy(&m_sem); }
+
+ /** Increment (and signal any waiters).
+ *
+ * Realtime safe.
+ */
+ inline void post() { sem_post(&m_sem); }
+
+ /** Wait until count is > 0, then decrement.
+ *
+ * Note that sem_wait always returns 0 in practise. It returns nonzero
+ * when run in GDB, so the while is necessary to allow debugging.
+ *
+ * Obviously not realtime safe.
+ */
+ inline void wait() { while (sem_wait(&m_sem) != 0) ; }
+
+ /** Non-blocking version of wait().
+ *
+ * Realtime safe?
+ */
+ inline int try_wait() { return sem_trywait(&m_sem); }
+private:
+ sem_t m_sem;
+};
+
+
+#endif // RAUL_SEMAPHORE_H
diff --git a/raul/SharedPtr.h b/raul/SharedPtr.h
new file mode 100644
index 0000000..c6e72a1
--- /dev/null
+++ b/raul/SharedPtr.h
@@ -0,0 +1,58 @@
+/* A Reference Counting Smart Pointer.
+ * Copyright (C) 2006 Dave Robillard.
+ *
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This file is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef RAUL_SHARED_PTR_H
+#define RAUL_SHARED_PTR_H
+
+#include <cassert>
+#include <cstddef>
+
+#ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
+#include <iostream>
+#include <list>
+#include <algorithm>
+
+static std::list<void*> shared_ptr_counters;
+
+// Use debug hooks to ensure 2 shared_ptrs never point to the same thing
+namespace boost {
+
+ inline void sp_scalar_constructor_hook(void* object, unsigned long cnt, void* ptr) {
+ assert(std::find(shared_ptr_counters.begin(), shared_ptr_counters.end(),
+ (void*)object) == shared_ptr_counters.end());
+ shared_ptr_counters.push_back(object);
+ //std::cerr << "Creating SharedPtr to "
+ // << object << ", count = " << cnt << std::endl;
+ }
+
+ inline void sp_scalar_destructor_hook(void* object, unsigned long cnt, void* ptr) {
+ shared_ptr_counters.remove(object);
+ //std::cerr << "Destroying SharedPtr to "
+ // << object << ", count = " << cnt << std::endl;
+ }
+
+}
+#endif // BOOST_SP_ENABLE_DEBUG_HOOKS
+
+
+#include <boost/shared_ptr.hpp>
+
+#define SharedPtr boost::shared_ptr
+#define PtrCast boost::dynamic_pointer_cast
+
+#endif // RAUL_SHARED_PTR_H
+
diff --git a/raul/Slave.h b/raul/Slave.h
new file mode 100644
index 0000000..c16818b
--- /dev/null
+++ b/raul/Slave.h
@@ -0,0 +1,66 @@
+/* This file is part of Ingen. Copyright (C) 2006 Dave Robillard.
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef RAUL_SLAVE_H
+#define RAUL_SLAVE_H
+
+#include <pthread.h>
+#include "raul/Semaphore.h"
+#include "raul/Thread.h"
+
+
+/** Thread driven by (realtime safe) signals.
+ *
+ * Use this to perform some task in a separate thread you want to 'drive'
+ * from a realtime (or otherwise) thread.
+ *
+ * \ingroup engine
+ */
+class Slave : public Thread
+{
+public:
+ Slave() : _whip(0) {}
+
+ /** Tell the slave to do whatever work it does. Realtime safe. */
+ inline void whip() { _whip.post(); }
+
+protected:
+ /** Worker method.
+ *
+ * This is called once from this thread every time whip() is called.
+ * Implementations likely want to put a single (non loop) chunk of code
+ * here, e.g. to process an event.
+ */
+ virtual void _whipped() = 0;
+
+ Semaphore _whip;
+
+private:
+ // Prevent copies (undefined)
+ Slave(const Slave&);
+ Slave& operator=(const Slave&);
+
+ inline void _run()
+ {
+ while (true) {
+ _whip.wait();
+ _whipped();
+ }
+ }
+};
+
+
+#endif // RAUL_SLAVE_H
diff --git a/raul/Thread.h b/raul/Thread.h
new file mode 100644
index 0000000..37dcacd
--- /dev/null
+++ b/raul/Thread.h
@@ -0,0 +1,107 @@
+/* This file is part of Ingen. Copyright (C) 2006 Dave Robillard.
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef RAUL_THREAD_H
+#define RAUL_THREAD_H
+
+#include <string>
+#include <iostream>
+#include <pthread.h>
+
+
+/** Abstract base class for a thread.
+ *
+ * Extend this and override the _run method to easily create a thread
+ * to perform some task.
+ *
+ * \ingroup engine
+ */
+class Thread
+{
+public:
+ Thread() : _pthread_exists(false) {}
+
+ virtual ~Thread() { stop(); }
+
+ void set_name(const std::string& name) { _name = name; }
+
+ /** Launch and start the thread. */
+ virtual void start() {
+ std::cout << "[" << _name << " Thread] Starting." << std::endl;
+
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setstacksize(&attr, 1500000);
+
+ pthread_create(&_pthread, &attr, _static_run, this);
+ _pthread_exists = true;
+ }
+
+ /** Stop and terminate the thread. */
+ virtual void stop() {
+ if (_pthread_exists) {
+ pthread_cancel(_pthread);
+ pthread_join(_pthread, NULL);
+ _pthread_exists = false;
+ }
+ }
+
+ void set_scheduling(int policy, unsigned int priority) {
+ sched_param sp;
+ sp.sched_priority = priority;
+ int result = pthread_setschedparam(_pthread, SCHED_FIFO, &sp);
+ if (!result) {
+ std::cout << "[" << _name << "] Set scheduling policy to ";
+ switch (policy) {
+ case SCHED_FIFO: std::cout << "SCHED_FIFO"; break;
+ case SCHED_RR: std::cout << "SCHED_RR"; break;
+ case SCHED_OTHER: std::cout << "SCHED_OTHER"; break;
+ default: std::cout << "UNKNOWN"; break;
+ }
+ std::cout << ", priority " << sp.sched_priority << std::endl;
+ } else {
+ std::cout << "[" << _name << "] Unable to set scheduling policy ("
+ << strerror(result) << ")" << std::endl;
+ }
+ }
+
+
+protected:
+ /** Thread function to execute.
+ *
+ * This is called once on start, and terminated on stop.
+ * Implementations likely want to put some infinite loop here.
+ */
+ virtual void _run() = 0;
+
+private:
+ // Prevent copies (undefined)
+ Thread(const Thread&);
+ Thread& operator=(const Thread&);
+
+ inline static void* _static_run(void* me) {
+ Thread* myself = (Thread*)me;
+ myself->_run();
+ return NULL; // and I
+ }
+
+ std::string _name;
+ bool _pthread_exists;
+ pthread_t _pthread;
+};
+
+
+#endif // RAUL_THREAD_H
diff --git a/raul/WeakPtr.h b/raul/WeakPtr.h
new file mode 100644
index 0000000..3523d25
--- /dev/null
+++ b/raul/WeakPtr.h
@@ -0,0 +1,26 @@
+/* A "weak" pointer to a resource owned by a shared pointer.
+ * Copyright (C) 2006 Dave Robillard.
+ *
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This file is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef RAUL_WEAK_PTR_H
+#define RAUL_WEAK_PTR_H
+
+#include <boost/weak_ptr.hpp>
+
+#define WeakPtr boost::weak_ptr
+
+#endif // RAUL_WEAK_PTR_H
+