diff options
Diffstat (limited to 'raul')
-rw-r--r-- | raul/Atom.h | 127 | ||||
-rw-r--r-- | raul/AtomLiblo.h | 73 | ||||
-rw-r--r-- | raul/AtomRaptor.h | 93 | ||||
-rw-r--r-- | raul/Condition.h | 42 | ||||
-rw-r--r-- | raul/Makefile | 376 | ||||
-rw-r--r-- | raul/Makefile.am | 21 | ||||
-rw-r--r-- | raul/Mutex.h | 41 | ||||
-rw-r--r-- | raul/Path.h | 251 | ||||
-rw-r--r-- | raul/Queue.h | 160 | ||||
-rw-r--r-- | raul/Semaphore.h | 63 | ||||
-rw-r--r-- | raul/SharedPtr.h | 58 | ||||
-rw-r--r-- | raul/Slave.h | 66 | ||||
-rw-r--r-- | raul/Thread.h | 107 | ||||
-rw-r--r-- | raul/WeakPtr.h | 26 |
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 + |