--- /dev/null
+
+SUBDIRS = src
--- /dev/null
+IMPROVEMENTS :
+
+- OutGate::isAlreadyInList : use std::find
+- Bloc::checkNoCyclePassingThrough : first loop iter1=currentNodesToTest.erase(iter1) as last argument
--- /dev/null
+dnl @synopsis AC_PROG_SWIG([major.minor.micro])
+dnl
+dnl This macro searches for a SWIG installation on your system. If found you
+dnl should) SWIG via $(SWIG). You can use the optional first argument to check
+dnl if the version of the available SWIG is greater than or equal to the
+dnl value of the argument. It should have the format: N[.N[.N]] (N is a
+dnl number between 0 and 999. Only the first N is mandatory.)
+dnl
+dnl If the version argument is given (e.g. 1.3.17), AC_PROG_SWIG checks that the
+dnl swig package is this version number or higher.
+dnl
+dnl In configure.in, use as:
+dnl
+dnl AC_PROG_SWIG(1.3.17)
+dnl SWIG_ENABLE_CXX
+dnl SWIG_MULTI_MODULE_SUPPORT
+dnl SWIG_PYTHON
+dnl
+dnl @authors Sebastian Huber <address@hidden>, Alan W. Irwin
+dnl <address@hidden>, Rafael Laboissiere <address@hidden> and
+dnl Andrew Collier <address@hidden>.
+dnl
+dnl
+AC_DEFUN([AC_PROG_SWIG],[
+ AC_PATH_PROG([SWIG],[swig])
+ if test -z "$SWIG" ; then
+ AC_MSG_WARN([cannot find 'swig' program. You should look at http://www.swig.org])
+ SWIG='echo "Error: SWIG is not installed. You should look at http://www.swig.org" ; false'
+ elif test -n "$1" ; then
+ AC_MSG_CHECKING([for SWIG version])
+ [swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`]
+ AC_MSG_RESULT([$swig_version])
+ if test -n "$swig_version" ; then
+ # Calculate the required version number components
+ [required=$1]
+ [required_major=`echo $required | sed 's/[^0-9].*//'`]
+ if test -z "$required_major" ; then
+ [required_major=0]
+ fi
+ [required=`echo $required | sed 's/[0-9]*[^0-9]//'`]
+ [required_minor=`echo $required | sed 's/[^0-9].*//'`]
+ if test -z "$required_minor" ; then
+ [required_minor=0]
+ fi
+ [required=`echo $required | sed 's/[0-9]*[^0-9]//'`]
+ [required_patch=`echo $required | sed 's/[^0-9].*//'`]
+ if test -z "$required_patch" ; then
+ [required_patch=0]
+ fi
+ # Calculate the available version number components
+ [available=$swig_version]
+ [available_major=`echo $available | sed 's/[^0-9].*//'`]
+ if test -z "$available_major" ; then
+ [available_major=0]
+ fi
+ [available=`echo $available | sed 's/[0-9]*[^0-9]//'`]
+ [available_minor=`echo $available | sed 's/[^0-9].*//'`]
+ if test -z "$available_minor" ; then
+ [available_minor=0]
+ fi
+ [available=`echo $available | sed 's/[0-9]*[^0-9]//'`]
+ [available_patch=`echo $available | sed 's/[^0-9].*//'`]
+ if test -z "$available_patch" ; then
+ [available_patch=0]
+ fi
+ if test $available_major -ne $required_major \
+ -o $available_minor -ne $required_minor \
+ -o $available_patch -lt $required_patch ; then
+ AC_MSG_WARN([SWIG version >= $1 is required. You have $swig_version. You should look at http://www.swig.org])
+ SWIG='echo "Error: SWIG version >= $1 is required. You have '"$swig_version"'. You should look at http://www.swig.org" ; false'
+ else
+ AC_MSG_NOTICE([SWIG executable is '$SWIG'])
+ SWIG_LIB=`$SWIG -swiglib`
+ AC_MSG_NOTICE([SWIG runtime library directory is '$SWIG_LIB'])
+ fi
+ else
+ AC_MSG_WARN([cannot determine SWIG version])
+ SWIG='echo "Error: Cannot determine SWIG version. You should look at http://www.swig.org" ; false'
+ fi
+ fi
+ AC_SUBST([SWIG_LIB])
+])
+
+# SWIG_ENABLE_CXX()
+#
+# Enable SWIG C++ support. This affects all invocations of $(SWIG).
+AC_DEFUN([SWIG_ENABLE_CXX],[
+ AC_REQUIRE([AC_PROG_SWIG])
+ AC_REQUIRE([AC_PROG_CXX])
+ SWIG="$SWIG -c++"
+])
+
+# SWIG_MULTI_MODULE_SUPPORT()
+#
+# Enable support for multiple modules. This effects all invocations
+# of $(SWIG). You have to link all generated modules against the
+# appropriate SWIG runtime library. If you want to build Python
+# modules for example, use the SWIG_PYTHON() macro and link the
+# modules against $(SWIG_PYTHON_LIBS).
+AC_DEFUN([SWIG_MULTI_MODULE_SUPPORT],[
+ AC_REQUIRE([AC_PROG_SWIG])
+ SWIG="$SWIG -c"
+])
+
+# SWIG_PYTHON([use-shadow-classes = {no, yes}])
+#
+# Checks for Python and provides the $(SWIG_PYTHON_CPPFLAGS),
+# $(SWIG_PYTHON_LIBS) and $(SWIG_PYTHON_OPT) output variables.
+# $(SWIG_PYTHON_OPT) contains all necessary SWIG options to generate
+# code for Python. Shadow classes are enabled unless the value of the
+# optional first argument is exactly 'no'. If you need multi module
+# support (provided by the SWIG_MULTI_MODULE_SUPPORT() macro) use
+# $(SWIG_PYTHON_LIBS) to link against the appropriate library. It
+# contains the SWIG Python runtime library that is needed by the type
+# check system for example.
+AC_DEFUN([SWIG_PYTHON],[
+ AC_REQUIRE([AC_PROG_SWIG])
+ AC_REQUIRE([AC_PYTHON_DEVEL])
+ test "x$1" != "xno" || swig_shadow=" -noproxy"
+ AC_SUBST([SWIG_PYTHON_OPT],[-python$swig_shadow])
+ AC_SUBST([SWIG_PYTHON_CPPFLAGS],[$PYTHON_CPPFLAGS])
+ AC_SUBST([SWIG_PYTHON_LIBS],["-L$SWIG_LIB -lswigpy"])
+])
+
+
+dnl @synopsis AC_LIB_WAD
+dnl
+dnl This macro searches for installed WAD library.
+dnl
+AC_DEFUN([AC_LIB_WAD],
+[
+ AC_REQUIRE([AC_PYTHON_DEVEL])
+ AC_ARG_ENABLE(wad,
+ AC_HELP_STRING([--enable-wad], [enable wad module]),
+ [
+ case "${enableval}" in
+ no) ;;
+ *) if test "x${enableval}" = xyes;
+ then
+ check_wad="yes"
+ fi ;;
+ esac
+ ], [])
+
+ if test -n "$check_wad";
+ then
+ AC_CHECK_LIB(wadpy, _init, [WADPY=-lwadpy], [], $PYTHON_LDFLAGS $PYTHON_EXTRA_LIBS)
+ AC_SUBST(WADPY)
+ fi
+])
--- /dev/null
+# Check availability of Med binary distribution
+#
+# Author : Anthony GEAY (CEA, 2005)
+#
+
+AC_DEFUN([AC_PROG_ESOPE],[
+CHECK_MED
+
+AC_CHECKING(for Esope)
+
+srcdirea=`( cd $srcdir && pwd )`
+
+esope_ok=yes
+
+AC_ARG_WITH(esope,
+ [ --with-esope=EXEC esope executable ],
+ [ESOPE="$withval"
+ AC_MSG_RESULT("select $withval as esope executable")
+ ], [
+ AC_PATH_PROG(ESOPE, esopv10_0)
+ ])
+if test "x$ESOPE" = "x" ;
+then
+ ESOPE=$srcdirea/bin/esopv10_0
+ AC_MSG_RESULT(use esope furnished in sources at location : $ESOPE)
+fi
+AC_SUBST(ESOPE)
+
+dnl --- To improve UNIX 32
+EFLAGS="ESOPE=2000000,NORME=TRADUCTEUR,FORT=UNIX32"
+AC_SUBST(EFLAGS)
+
+AC_PATH_PROG(CPPFORESOPE, cpp)
+if test "x$CPPFORESOPE" = "x" ;
+then
+ esope_ok=no
+ AC_MSG_RESULT(cpp not found in PATH !!! - used by esope to generate Fortran files)
+fi
+AC_SUBST(CPPFORESOPE)
+
+CPPFORESOPEFLAGS="-Dunix32 -Dlinux ${MED_INCLUDES}"
+AC_SUBST(CPPFORESOPEFLAGS)
+dnl --- Segment directory
+SEGMENTS_DIR="-I"$srcdirea/bin/SEGMENTS
+AC_SUBST(SEGMENTS_DIR)
+
+AC_MSG_RESULT(for Esope: $esope_ok)
+
+])dnl
+
--- /dev/null
+dnl @synopsis AC_PYTHON_DEVEL()
+dnl
+dnl Checks for Python and tries to get the include path to 'Python.h'.
+dnl It provides the $(PYTHON_CPPFLAGS) and $(PYTHON_LDFLAGS) output variable.
+dnl
+dnl @authors Sebastian Huber <address@hidden>, Alan W. Irwin
+dnl <address@hidden>, Rafael Laboissiere <address@hidden> and
+dnl Andrew Collier <address@hidden>.
+dnl
+dnl
+AC_DEFUN([AC_PYTHON_DEVEL],[
+ #
+ # should allow for checking of python version here...
+ #
+ AC_REQUIRE([AM_PATH_PYTHON])
+
+ # Check for Python include path
+ AC_MSG_CHECKING([for Python include path])
+ python_path=`echo $PYTHON | sed "s,/bin.*$,,"`
+ for i in "$python_path/include/python$PYTHON_VERSION/" "$python_path/include/python/" "$python_path/" ; do
+ python_path=`find $i -type f -name Python.h -print | sed "1q"`
+ if test -n "$python_path" ; then
+ break
+ fi
+ done
+ python_path=`echo $python_path | sed "s,/Python.h$,,"`
+ AC_MSG_RESULT([$python_path])
+ if test -z "$python_path" ; then
+ AC_MSG_ERROR([cannot find Python include path])
+ fi
+ AC_SUBST([PYTHON_CPPFLAGS],[-I$python_path])
+
+ # Check for Python library path
+ AC_MSG_CHECKING([for Python library path])
+ python_path=`echo $PYTHON | sed "s,/bin.*$,,"`
+ for i in "$python_path/lib/python$PYTHON_VERSION/config/" "$python_path/lib/python$PYTHON_VERSION/" "$python_path/lib/python/config/" "$python_path/lib/python/" "$python_path/" ; do
+ python_path=`find $i -type f -name libpython$PYTHON_VERSION.* -print | sed "1q"`
+ if test -n "$python_path" ; then
+ break
+ fi
+ done
+ python_path=`echo $python_path | sed "s,/libpython.*$,,"`
+ AC_MSG_RESULT([$python_path])
+ if test -z "$python_path" ; then
+ AC_MSG_ERROR([cannot find Python library path])
+ fi
+ AC_SUBST([PYTHON_LDFLAGS],["-L$python_path -lpython$PYTHON_VERSION"])
+ #
+ python_site=`echo $python_path | sed "s/config/site-packages/"`
+ AC_SUBST([PYTHON_SITE_PKG],[$python_site])
+ #
+ # libraries which must be linked in when embedding
+ #
+ AC_MSG_CHECKING(python extra libraries)
+ PYTHON_EXTRA_LIBS=`$PYTHON -c "import distutils.sysconfig; \
+ conf = distutils.sysconfig.get_config_var; \
+ print conf('LOCALMODLIBS')+' '+conf('LIBS')"
+ AC_MSG_RESULT($PYTHON_EXTRA_LIBS)`
+ AC_SUBST(PYTHON_EXTRA_LIBS)
+])
--- /dev/null
+# Check presence of "CPPUNIT" product presence
+#
+# Author : Anthony GEAY (CEA, 2006)
+#
+
+AC_DEFUN([CHECK_CPPUNIT],[
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_CPP])dnl
+
+AC_CHECKING(for CPPUNIT)
+AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+cppunit_ok=no
+AC_ARG_WITH(cppunit,
+ [AC_HELP_STRING([--with-cppunit=DIR],[cppunit directory path where cppunit is installed])],
+ [CPPUNITINSTDIR="$withval"
+ AC_MSG_RESULT("select $withval as path to cppunit")
+ ])
+
+AC_SUBST(CPPUNIT_INCLUDES)
+AC_SUBST(CPPUNIT_LIBS)
+AC_SUBST(CPPUNIT_LIBS_DIR)
+AC_SUBST(CPPUNITINSTDIR)
+
+CPPUNIT_INCLUDES=""
+CPPUNIT_LIBS=""
+
+LOCAL_INCLUDES=""
+LOCAL_LIBS=""
+
+if test "x$CPPUNITINSTDIR" = "x"
+then
+ LOCAL_INCLUDES=""
+ LOCAL_LIBS_DIR=""
+else
+ LOCAL_INCLUDES="-I$CPPUNITINSTDIR/include"
+ LOCAL_LIBS_DIR="$CPPUNITINSTDIR/lib"
+fi
+
+dnl cppunit headers
+
+CPPFLAGS_old="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS $LOCAL_INCLUDES"
+AC_LANG_CPLUSPLUS
+AC_CHECK_HEADER(cppunit/ui/text/TestRunner.h,cppunit_ok=yes ,cppunit_ok=no)
+CPPFLAGS="$CPPFLAGS_old"
+
+if test "x$cppunit_ok" = "xyes"
+then
+ if test "x$LOCAL_INCLUDES" = "x"
+ then
+ CPPUNIT_INCLUDES=""
+ CPPUNIT_LIBS="-lcppunit"
+ CPPUNIT_LIBS_DIR=""
+ else
+ CPPUNIT_INCLUDES="$LOCAL_INCLUDES"
+ CPPUNIT_LIBS="-L$LOCAL_LIBS_DIR -lcppunit"
+ CPPUNIT_LIBS_DIR="$LOCAL_LIBS_DIR"
+ fi
+fi
+AC_LANG_RESTORE
+AC_MSG_RESULT(for cppunit: $cppunit_ok)
+
+])dnl
--- /dev/null
+dnl Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+dnl CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+dnl
+dnl This library is free software; you can redistribute it and/or
+dnl modify it under the terms of the GNU Lesser General Public
+dnl License as published by the Free Software Foundation; either
+dnl version 2.1 of the License.
+dnl
+dnl This library is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+dnl Lesser General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU Lesser General Public
+dnl License along with this library; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+dnl
+dnl See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
+dnl
+dnl
+dnl
+
+AC_DEFUN([CHECK_QT],[
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_CXX])dnl
+AC_REQUIRE([AC_PROG_CPP])dnl
+AC_REQUIRE([AC_PROG_CXXCPP])dnl
+
+AC_CHECKING(for QT)
+qt_ok=yes
+
+AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+
+if test "x$QTDIR" = "x"
+then
+ AC_MSG_RESULT(please define QTDIR variable)
+ qt_ok=no
+fi
+
+if test "x$qt_ok" = "xyes"
+then
+ if test -f ${QTDIR}/bin/moc
+ then
+ MOC=${QTDIR}/bin/moc
+ else
+ AC_PATH_PROG(MOC, moc)
+ fi
+ if test "x$MOC" = "x"
+ then
+ qt_ok=no
+ AC_MSG_RESULT(moc qt-compiler not in PATH variable)
+ else
+ qt_ok=yes
+ AC_MSG_RESULT(moc found)
+ fi
+fi
+
+if test "x$qt_ok" = "xyes"
+then
+ if test -f ${QTDIR}/bin/uic
+ then
+ UIC=${QTDIR}/bin/uic
+ else
+ AC_PATH_PROG(UIC, uic)
+ fi
+ if test "x$UIC" = "x"
+ then
+ qt_ok=no
+ AC_MSG_RESULT(uic qt-interface compiler not in PATH variable)
+ else
+ qt_ok=yes
+ AC_MSG_RESULT(uic found)
+ fi
+fi
+
+AC_SUBST(QTDIR)
+QT_ROOT=$QTDIR
+
+if test "x$qt_ok" = "xyes"
+then
+ AC_MSG_CHECKING(include of qt headers)
+
+ CPPFLAGS_old=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS -I$QTDIR/include"
+
+ AC_LANG_CPLUSPLUS
+ AC_CHECK_HEADER(qaction.h,qt_ok=yes ,qt_ok=no)
+
+ CPPFLAGS=$CPPFLAGS_old
+
+ if test "x$qt_ok" = "xno"
+ then
+ AC_MSG_RESULT(qt headers not found, or too old qt version, in $QTDIR/include)
+ AC_MSG_RESULT(QTDIR environment variable may be wrong)
+ else
+ AC_MSG_RESULT(yes)
+ QT_INCLUDES="-I${QT_ROOT}/include -DQT_THREAD_SUPPORT"
+ QT_MT_INCLUDES="-I${QT_ROOT}/include -DQT_THREAD_SUPPORT"
+ fi
+fi
+
+if test "x$qt_ok" = "xyes"
+then
+ AC_MSG_CHECKING(linking qt library)
+ LIBS_old=$LIBS
+ LIBS="$LIBS -L$QTDIR/lib -lqt-mt $OGL_LIBS"
+
+ CXXFLAGS_old=$CXXFLAGS
+ CXXFLAGS="$CXXFLAGS -I$QTDIR/include"
+
+ AC_CACHE_VAL(salome_cv_lib_qt,[
+ AC_TRY_LINK(
+#include <qapplication.h>
+, int n;
+ char **s;
+ QApplication a(n, s);
+ a.exec();,
+ eval "salome_cv_lib_qt=yes",eval "salome_cv_lib_qt=no")
+ ])
+ qt_ok="$salome_cv_lib_qt"
+
+ if test "x$qt_ok" = "xno"
+ then
+ AC_MSG_RESULT(unable to link with qt library)
+ AC_MSG_RESULT(QTDIR environment variable may be wrong)
+ else
+ AC_MSG_RESULT(yes)
+ QT_LIBS="-L$QTDIR/lib -lqt-mt"
+ QT_MT_LIBS="-L$QTDIR/lib -lqt-mt"
+ fi
+
+ LIBS=$LIBS_old
+ CXXFLAGS=$CXXFLAGS_old
+
+fi
+
+AC_SUBST(MOC)
+AC_SUBST(UIC)
+
+AC_SUBST(QT_ROOT)
+AC_SUBST(QT_INCLUDES)
+AC_SUBST(QT_LIBS)
+AC_SUBST(QT_MT_LIBS)
+
+AC_LANG_RESTORE
+
+AC_MSG_RESULT(for qt: $qt_ok)
+
+# Save cache
+AC_CACHE_SAVE
+
+])dnl
+dnl
--- /dev/null
+dnl Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+dnl CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+dnl
+dnl This library is free software; you can redistribute it and/or
+dnl modify it under the terms of the GNU Lesser General Public
+dnl License as published by the Free Software Foundation; either
+dnl version 2.1 of the License.
+dnl
+dnl This library is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+dnl Lesser General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU Lesser General Public
+dnl License along with this library; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+dnl
+dnl See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
+dnl
+dnl
+dnl
+dnl define macros :
+dnl AC_ENABLE_PRODUCTION AC_DISABLE_PRODUCTION
+dnl and
+dnl AC_ENABLE_DEBUG AC_DISABLE_DEBUG
+dnl
+dnl version $Id$
+dnl author Patrick GOLDBRONN
+dnl
+
+# AC_ENABLE_PRODUCTION
+AC_DEFUN(AC_ENABLE_PRODUCTION, [dnl
+define([AC_ENABLE_PRODUCTION_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(production,
+changequote(<<, >>)dnl
+<< --enable-production[=PKGS] build without debug information [default=>>AC_ENABLE_PRODUCTION_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_production=yes ;;
+no) enable_production=no ;;
+*)
+ enable_production=no
+ # Look at the argument we got. We use all the common list separators.
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+ for pkg in $enableval; do
+ if test "X$pkg" = "X$p"; then
+ enable_production=yes
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac],
+enable_production=AC_ENABLE_PRODUCTION_DEFAULT)dnl
+if test "X$enable_production" = "Xyes"; then
+ FFLAGS="$FFLAGS -O3 "
+ CFLAGS="$CFLAGS -O3 "
+ CXXFLAGS="$CXXFLAGS -O3 "
+else
+ FFLAGS="$FFLAGS"
+ CFLAGS="$CFLAGS"
+ CXXFLAGS="$CXXFLAGS"
+fi
+])
+
+# AC_DISABLE_PRODUCTION - set the default flag to --disable-production
+AC_DEFUN(AC_DISABLE_PRODUCTION, [AC_ENABLE_PRODUCTION(no)])
+
+# AC_ENABLE_DEBUG
+AC_DEFUN(AC_ENABLE_DEBUG, [dnl
+define([AC_ENABLE_DEBUG_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(debug,
+changequote(<<, >>)dnl
+<< --enable-debug[=PKGS] build without debug information [default=>>AC_ENABLE_DEBUG_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_debug=yes ;;
+no) enable_debug=no ;;
+*)
+ enable_debug=no
+ # Look at the argument we got. We use all the common list separators.
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+ for pkg in $enableval; do
+ if test "X$pkg" = "X$p"; then
+ enable_debug=yes
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac],
+enable_debug=AC_ENABLE_DEBUG_DEFAULT)dnl
+
+if test "X$enable_debug" = "Xyes"; then
+ FFLAGS="$FFLAGS -g "
+ CFLAGS="$CFLAGS -g "
+ CXXFLAGS="$CXXFLAGS -g "
+else
+ FFLAGS="$FFLAGS"
+ CFLAGS="$CFLAGS"
+ CXXFLAGS="$CXXFLAGS"
+fi
+])
+
+# AC_DISABLE_DEBUG - set the default flag to --disable-debug
+AC_DEFUN(AC_DISABLE_DEBUG, [AC_ENABLE_DEBUG(no)])
+
--- /dev/null
+# Check presence of "CPPUNIT" product presence
+#
+# Author : Anthony GEAY (CEA, 2006)
+#
+
+AC_DEFUN([CHECK_THREAD],[
+
+AC_CHECKING(for THREADs)
+AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+thread_ok=no
+
+AC_SUBST(THREAD_DEF)
+if test `uname` = "Linux"
+then
+ THREAD_DEF="-DYACS_PTHREAD"
+ AC_CHECK_HEADER(pthread.h,thread_ok=yes ,thread_ok=no)
+ thread_ok="yes"
+fi
+
+AC_LANG_RESTORE
+AC_MSG_RESULT(for THREADs: $thread_ok)
+
+])dnl
--- /dev/null
+
+EXTRA_DIST = $(wildcard $(srcdir)/*.hxx) $(wildcard $(srcdir)/*.h)
--- /dev/null
+
+SUFFIXES =
+
+# --------------------------------------------
+# *.i --> *wrap.cxx
+# --------------------------------------------
+
+SUFFIXES += .i WRAP.cxx
+
+.iWRAP.cxx :
+ $(SWIG) $(SWIG_PYTHON_OPT) $(SWIG_PYTHON_INCLUDES) -o $@ $<
--- /dev/null
+#! /bin/sh
+
+# --
+#
+PROJECT="YACS"
+
+# --
+# set VERSION from CVS_TAG_NAME
+
+CVS_TAG_NAME='$Name$'
+VERSION=${CVS_TAG_NAME}
+VERSION=`echo ${VERSION/'$Name:'/}`
+VERSION=`echo ${VERSION/'$'/}`
+if test X$VERSION = X ; then
+ VERSION=`date +"%F"` # -%H-%M
+else
+ VERSION=`echo $VERSION | sed -e "s/V_//g"`
+ VERSION=`echo $VERSION | sed -e "s/_/./g"`
+fi
+
+# --
+ORIG_DIR=`pwd`
+run() {
+ local logfile=$ORIG_DIR/build_configure.log
+ printf "%-50s" "$1 ... "
+ eval $1 > $logfile 2>&1
+ if test $? != 0 ; then
+ echo "[FAILED]"
+ echo "see file build_configure.log ..."
+ exit 1
+ fi
+ echo "[ OK ]"
+}
+
+# --
+# -- goto build_configure dir
+CONF_DIR=`echo $0 | sed -e "s,[^/]*$,,;s,/$,,;s,^$,.,"`
+cd ${CONF_DIR}
+
+# --
+# -- list all Makefile.am in Makefile.am.list
+./rfind . Makefile.am > Makefile.am.list
+
+# --
+# -- configure.in construction
+rm -f configure.in
+touch configure.in
+echo "AC_INIT(src)" >> configure.in
+echo "RELEASE=$VERSION" >> configure.in
+echo "PROJECT=$PROJECT" >> configure.in
+cat configure.in.base >> configure.in
+echo "AC_OUTPUT([ \\" >> configure.in
+# echo " src/XDATA/xversion.py \\" >> configure.in
+# echo " doc/xversion.tex \\" >> configure.in
+sed -e 's,\.am, \\,' -e 's,\.\/,,' Makefile.am.list >> configure.in
+echo "])" >> configure.in
+
+# --
+run "libtoolize"
+run "aclocal -I adm/unix/config_files"
+run "autoconf"
+run "automake --add-missing --copy"
--- /dev/null
+# --
+# Copyright (C) CEA, EDF
+# Author : Anthony Geay (CEA)
+# --
+
+AC_ENABLE_DEBUG(no)
+AC_DISABLE_PRODUCTION
+AC_SUBST(RELEASE)
+AM_INIT_AUTOMAKE($PROJECT, $RELEASE)
+AC_PROG_CXX
+AM_PROG_LIBTOOL
+CHECK_CPPUNIT
+AC_PROG_SWIG(1.3.17)
+SWIG_ENABLE_CXX
+SWIG_PYTHON
+CHECK_THREAD
--- /dev/null
+<!ENTITY % date-time "(#PCDATA)*" > <!-- conforming to the Date and Time Specification of RFC 822.-->\r
+<!ENTITY % number "(#PCDATA)*" >\r
+<!ENTITY % string "(#PCDATA)*" >\r
+\r
+\r
+\r
+<!ELEMENT opml (head, body) >\r
+<!ATTLIST opml\r
+version CDATA #IMPLIED> <!-- a version string, of the form, x.y, where x and y are both numeric strings.-->\r
+\r
+<!ELEMENT head ( title?, dateCreated?, dateModified?,\r
+ownerName?, ownerEmail?, expansionState?, vertScrollState?,\r
+windowTop?, windowLeft?, windowBottom?, windowRight? ) >\r
+\r
+<!ELEMENT title (#PCDATA)* > <!--the title of the document.-->\r
+<!ELEMENT dateCreated %date-time; > <!--a date-time, indicating when the document was created.-->\r
+<!ELEMENT dateModified %date-time;> <!--a date-time, indicating when the document was last modified.-->\r
+<!ELEMENT ownerName %string; > <!--a string, the owner of the document. -->\r
+<!ELEMENT ownerEmail %string; > <!--a string, the email address of the owner of the document.-->\r
+\r
+<!ELEMENT expansionState (#PCDATA)* >\r
+<!--\r
+a comma-separated list of line numbers that are expanded.\r
+The line numbers in the list tell you which headlines to expand.\r
+The order is important.\r
+For each element in the list, X, starting at the first summit, navigate \r
+flatdown X times and expand.\r
+Repeat for each element in the list.\r
+-->\r
+\r
+<!ELEMENT vertScrollState %number; >\r
+<!--\r
+a number, saying which line of the outline is displayed on the top line of \r
+the window.\r
+This number is calculated with the expansion state already applied.\r
+-->\r
+\r
+<!ELEMENT windowTop %number; > <!-- a number, the pixel location of the top edge of the window.-->\r
+<!ELEMENT windowLeft %number; > <!-- a number, the pixel location of the left edge of the window.-->\r
+<!ELEMENT windowBottom %number; > <!-- a number, the pixel location of the bottom edge of the window.-->\r
+<!ELEMENT windowRight %number; > <!-- a number, the pixel location of the right edge of the window.-->\r
+\r
+\r
+<!ELEMENT body (outline)+ >\r
+<!ELEMENT outline (outline)* >\r
+\r
+<!ENTITY % OtherAttributes " " >\r
+<!ATTLIST outline text CDATA #IMPLIED\r
+ type CDATA #IMPLIED\r
+ isComment ( true | false ) false\r
+isBreakpoint (true|false) false >\r
+<!--\r
+text is the string of characters that's displayed when the outline is being browsed or edited. \r
+type is a string, it says how the other attributes of the <outline> are interpreted.\r
+isComment indicates whether the outline is commented or not.\r
+By convention if an outline is commented, all subordinate outlines are considered to be commented as well.\r
+isBreakpoint indicates whether a breakpoint is set on this outline.This attribute is mainly necessary for outlines used to edit scripts that execute.\r
+\r
+You can add whatever other attributes on the outline element you want.\r
+-->\r
+\r
+\r
+\r
--- /dev/null
+<?xml version="1.0" encoding="ISO-8859-1"?>\r
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">\r
+<xsl:output method = "html" version = "4.0" encoding="ISO-8859-1" indent = "no" />\r
+<xsl:strip-space elements = "*" />\r
+\r
+<xsl:variable name="markerNormal">►</xsl:variable>\r
+<xsl:variable name="markerComment">≪</xsl:variable>\r
+<xsl:variable name="markerLink">☼</xsl:variable>\r
+\r
+<xsl:template match = "/opml" >\r
+<html>\r
+ <script language="JavaScript" src="http://www.netcrucible.com/xslt/opml.js" />\r
+ <link rel="stylesheet" href="http://www.netcrucible.com/xslt/opml.css" />\r
+ <head><title><xsl:value-of select="head/title" /></title></head>\r
+ <body>\r
+ <div id="outlineRoot" class="outlineRoot">\r
+ <xsl:for-each select="head/*" >\r
+ <span class="outlineAttribute" title="{name()}"><xsl:value-of select="." /></span>\r
+ </xsl:for-each>\r
+ <xsl:apply-templates select="body"/>\r
+ </div>\r
+ <span id="markerNormal" style="display:none"><xsl:value-of select="$markerNormal" /></span>\r
+ <span id="markerComment" style="display:none"><xsl:value-of select="$markerComment" /></span>\r
+ <span id="markerLink" style="display:none"><xsl:value-of select="$markerLink" /></span>\r
+ </body>\r
+</html>\r
+</xsl:template>\r
+\r
+<xsl:template match = "outline" >\r
+ <div class="outline">\r
+ <xsl:attribute name="style">\r
+ <xsl:if test="parent::outline">display:none</xsl:if> \r
+ </xsl:attribute>\r
+ <xsl:for-each select="@*[name() !='text']" >\r
+ <span class="outlineAttribute" title="{name()}"><xsl:value-of select="." /></span>\r
+ </xsl:for-each>\r
+ <span>\r
+ <xsl:attribute name="class">\r
+ <xsl:choose>\r
+ <xsl:when test="./*">markerClosed</xsl:when>\r
+ <xsl:when test="contains(@url,'.opml') or contains(@url,'.OPML')">markerClosed</xsl:when>\r
+ <xsl:otherwise>markerOpen</xsl:otherwise>\r
+ </xsl:choose>\r
+ </xsl:attribute>\r
+ <xsl:choose>\r
+ <xsl:when test="@isComment = 'true'"><xsl:value-of select="$markerComment" /></xsl:when>\r
+ <xsl:when test="@type = 'link' and not(contains(@url,'.opml') or contains(@url,'.OPML'))"><xsl:value-of select="$markerLink" /></xsl:when>\r
+ <xsl:otherwise><xsl:value-of select="$markerNormal" /></xsl:otherwise>\r
+ </xsl:choose>\r
+ </span>\r
+ <span class="outlineText">\r
+ <xsl:value-of select = "@text" disable-output-escaping = "yes" /></span>\r
+ <xsl:apply-templates />\r
+ </div>\r
+</xsl:template>\r
+\r
+</xsl:stylesheet>\r
--- /dev/null
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+errstatus=0
+dirmode=""
+
+usage="\
+Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..."
+
+# process command line arguments
+while test $# -gt 0 ; do
+ case "${1}" in
+ -h | --help | --h* ) # -h for help
+ echo "${usage}" 1>&2; exit 0 ;;
+ -m ) # -m PERM arg
+ shift
+ test $# -eq 0 && { echo "${usage}" 1>&2; exit 1; }
+ dirmode="${1}"
+ shift ;;
+ -- ) shift; break ;; # stop option processing
+ -* ) echo "${usage}" 1>&2; exit 1 ;; # unknown option
+ * ) break ;; # first non-opt arg
+ esac
+done
+
+for file
+do
+ if test -d "$file"; then
+ shift
+ else
+ break
+ fi
+done
+
+case $# in
+0) exit 0 ;;
+esac
+
+case $dirmode in
+'')
+ if mkdir -p -- . 2>/dev/null; then
+ echo "mkdir -p -- $*"
+ exec mkdir -p -- "$@"
+ fi ;;
+*)
+ if mkdir -m "$dirmode" -p -- . 2>/dev/null; then
+ echo "mkdir -m $dirmode -p -- $*"
+ exec mkdir -m "$dirmode" -p -- "$@"
+ fi ;;
+esac
+
+for file
+do
+ set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+ shift
+
+ pathcomp=
+ for d
+ do
+ pathcomp="$pathcomp$d"
+ case "$pathcomp" in
+ -* ) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp"
+
+ mkdir "$pathcomp" || lasterr=$?
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ else
+ if test ! -z "$dirmode"; then
+ echo "chmod $dirmode $pathcomp"
+
+ lasterr=""
+ chmod "$dirmode" "$pathcomp" || lasterr=$?
+
+ if test ! -z "$lasterr"; then
+ errstatus=$lasterr
+ fi
+ fi
+ fi
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 3
+# End:
+# mkinstalldirs ends here
--- /dev/null
+#!/bin/sh
+
+# py-compile - Compile a Python program
+# Copyright 2000, 2001 Free Software Foundation, Inc.
+
+# This program 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, or (at your option)
+# any later version.
+
+# This program 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 more 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., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# called as "py-compile [--basedir DIR] PY_FILES ...
+
+if [ -z "$PYTHON" ]; then
+ PYTHON=python
+fi
+
+basedir=
+
+case "$1" in
+ --basedir)
+ basedir=$2
+ shift 2
+ ;;
+ --help)
+ echo "Usage: py-compile [--basedir DIR] PY_FILES ..."
+ echo "Byte compile some python scripts. This should be performed"
+ echo "after they have been moved to the final installation location"
+ exit 0
+ ;;
+ --version)
+ echo "py-compile version 0.0"
+ exit 0
+ ;;
+esac
+
+if [ $# = 0 ]; then
+ echo "No files given to $0" 1>&2
+ exit 1
+fi
+
+# if basedir was given, then it should be prepended to filenames before
+# byte compilation.
+if [ -z "$basedir" ]; then
+ trans="path = file"
+else
+ trans="path = os.path.join('$basedir', file)"
+fi
+
+$PYTHON -c "
+import sys, os, string, py_compile
+
+files = '''$*'''
+print 'Byte-compiling python modules...'
+for file in string.split(files):
+ $trans
+ if not os.path.exists(path) or not (len(path) >= 3 and path[-3:] == '.py'):
+ continue
+ print file,
+ sys.stdout.flush()
+ py_compile.compile(path)
+print" || exit $?
+
+# this will fail for python < 1.5, but that doesn't matter ...
+$PYTHON -O -c "
+import sys, os, string, py_compile
+
+files = '''$*'''
+print 'Byte-compiling python modules (optimised versions) ...'
+for file in string.split(files):
+ $trans
+ if not os.path.exists(path) or not (len(path) >= 3 and path[-3:] == '.py'):
+ continue
+ print file,
+ sys.stdout.flush()
+ py_compile.compile(path)
+print" 2>/dev/null || :
+
--- /dev/null
+#! /bin/sh
+# --
+# Copyright (C) CEA, EDF
+# Author : Erwan ADAM (CEA)
+# --
+
+#
+# Usage : rfind dir suffix ...
+#
+# find all files *suffix in dir in a recursive way
+# different of the usual command find ...
+#
+
+if test $# != 2 ; then
+ echo "Usage : $0 dir suffix"
+ exit
+fi
+
+local_find() {
+ # if the first argument is not a directory, returns
+ if test ! -d $1 ; then
+ # echo "$1 is not a directory"
+ return
+ fi
+ # dont look in the CVS directories
+ # dont look in the autom4te* directories
+ case "$1" in
+ */CVS) return ;;
+ */autom4te*) return ;;
+ */*_ROOT) return ;;
+ */*_SRC) return ;;
+ *) ;;
+ esac
+ # for each regular file contained in the directory
+ # test if it's a *"$2" file
+ for i in $1/*
+ do
+ if test -f $i ; then
+ case `basename $i` in
+ *$2) echo " "$i ;;
+ *) ;;
+ esac
+ fi
+ done
+ # for each subdirectory of the first argument, proceeds recursively
+ for i in $1/*
+ do
+ local_find $i $2
+ done
+}
+
+local_find $1 $2
--- /dev/null
+#!/bin/sh
+
+CONF_DIR=`echo $0 | sed -e "s,[^/]*$,,;s,/$,,;s,^$,.,"`
+cd ${CONF_DIR}
+
+TO_CLEAN=
+TO_CLEAN=${TO_CLEAN}' build_configure.log'
+TO_CLEAN=${TO_CLEAN}' Makefile.am.list'
+TO_CLEAN=${TO_CLEAN}' aclocal.m4'
+TO_CLEAN=${TO_CLEAN}' autom4te*'
+TO_CLEAN=${TO_CLEAN}' configure'
+TO_CLEAN=${TO_CLEAN}' configure.in'
+TO_CLEAN=${TO_CLEAN}' COPYING INSTALL'
+TO_CLEAN=${TO_CLEAN}' missing'
+TO_CLEAN=${TO_CLEAN}' install-sh'
+TO_CLEAN=${TO_CLEAN}' config.guess'
+TO_CLEAN=${TO_CLEAN}' config.sub'
+TO_CLEAN=${TO_CLEAN}' depcomp'
+
+rm -rf $TO_CLEAN > /dev/null
+
+l=`find . -name "Makefile.in" -or -name "*~"`
+
+if test X"$l" != X ; then
+ rm -f $l
+fi
--- /dev/null
+
+SUBDIRS = bases basicData engine
--- /dev/null
+#include "Exception.hxx"
+
+using namespace YACS;
+
+Exception::Exception(const std::string& what):_what(what)
+{
+}
+
+const char *Exception::what( void ) const throw ()
+{
+ return _what.c_str();
+}
+
+Exception::~Exception() throw ()
+{
+}
--- /dev/null
+#ifndef __EXCEPTION_HXX__
+#define __EXCEPTION_HXX__
+
+#include <string>
+#include <exception>
+
+namespace YACS
+{
+ class Exception : public std::exception
+ {
+ protected:
+ std::string _what;
+ public:
+ Exception(const std::string& what);
+ const char *what( void ) const throw ();
+ ~Exception() throw ();
+ };
+}
+
+#endif
--- /dev/null
+
+include $(top_srcdir)/adm/unix/make_begin.am
+
+SUBDIRS = Test
+
+noinst_LTLIBRARIES = libYACSBases.la
+
+libYACSBases_la_SOURCES = Exception.cxx Thread.cxx Mutex.cxx Semaphore.cxx \
+ $(__dummy__)
+
+EXTRA_libYACSBases_la_SOURCES =
+ Thread.hxx ThreadPT.hxx ThreadPT.cxx \
+ Mutex.hxx MutexPT.cxx MutexPT.hxx \
+ Semaphore.hxx SemaphorePT.cxx SemaphorePT.hxx \
+ Exception.hxx \
+ $(__dummy__)
+
+AM_CXXFLAGS = $(THREAD_DEF)
+
+include $(top_srcdir)/adm/unix/make_end.am
--- /dev/null
+#include "Mutex.hxx"
+
+#if defined(YACS_PTHREAD)
+#include "MutexPT.cxx"
+#else
+#error
+#endif
--- /dev/null
+#ifndef __MUTEX_HXX__
+#define __MUTEX_HXX__
+
+/* Interface is :
+ class Mutex
+ {
+ public:
+ Mutex();
+ void lock();
+ void unlock();
+ };
+ */
+
+#if defined(YACS_PTHREAD)
+#include "MutexPT.hxx"
+
+namespace YACS
+{
+ namespace BASES
+ {
+ typedef MutexPT Mutex;
+ }
+}
+#else
+#error
+#endif
+
+#endif
--- /dev/null
+#include "MutexPT.hxx"
+
+using namespace YACS::BASES;
+
+MutexPT::MutexPT()
+{
+ pthread_mutexattr_settype(&_options, PTHREAD_MUTEX_FAST_NP);
+ pthread_mutex_init(&_mutexDesc, &_options);
+}
+
+MutexPT::~MutexPT()
+{
+ pthread_mutex_destroy(&_mutexDesc);
+}
+
+void MutexPT::lock()
+{
+ pthread_mutex_lock(&_mutexDesc);
+}
+
+void MutexPT::unlock()
+{
+ pthread_mutex_unlock(&_mutexDesc);
+}
--- /dev/null
+#ifndef __MUTEXPT_HXX__
+#define __MUTEXPT_HXX__
+
+#include <pthread.h>
+
+namespace YACS
+{
+ namespace BASES
+ {
+ class MutexPT
+ {
+ public:
+ MutexPT();
+ ~MutexPT();
+ void lock();
+ void unlock();
+ private:
+ pthread_mutex_t _mutexDesc;
+ pthread_mutexattr_t _options;
+
+ };
+ }
+}
+
+#endif
--- /dev/null
+#include "Semaphore.hxx"
+
+#if defined(YACS_PTHREAD)
+#include "SemaphorePT.cxx"
+#else
+#error
+#endif
--- /dev/null
+#ifndef __SEMAPHORE_HXX__
+#define __SEMAPHORE_HXX__
+
+/* Interface is :
+ class Semaphore
+ {
+ public:
+ Semaphore(int initValue=0);
+ ~Semaphore();
+ void post();
+ void wait();
+ int getvalue();
+ };
+ */
+
+#if defined(YACS_PTHREAD)
+#include "SemaphorePT.hxx"
+
+namespace YACS
+{
+ namespace BASES
+ {
+ typedef SemaphorePT Semaphore;
+ }
+}
+#else
+#error
+#endif
+
+#endif
--- /dev/null
+#include "SemaphorePT.hxx"
+
+using namespace YACS::BASES;
+
+SemaphorePT::SemaphorePT(int initValue)
+{
+ sem_init(&_semDesc, 0, initValue);
+}
+
+SemaphorePT::~SemaphorePT()
+{
+ sem_destroy(&_semDesc);
+}
+
+void SemaphorePT::post()
+{
+ sem_post(&_semDesc);
+}
+
+void SemaphorePT::wait()
+{
+ sem_wait(&_semDesc);
+}
+
+int SemaphorePT::getValue()
+{
+ int val;
+ sem_getvalue(&_semDesc,&val);
+ return val;
+}
--- /dev/null
+#ifndef __SEMAPHOREPT_HXX__
+#define __SEMAPHOREPT_HXX__
+
+#include <semaphore.h>
+
+namespace YACS
+{
+ namespace BASES
+ {
+ class SemaphorePT
+ {
+ public:
+ SemaphorePT(int initValue=0);
+ ~SemaphorePT();
+ void post();
+ void wait();
+ int getValue();
+ private:
+ sem_t _semDesc;
+ };
+ }
+}
+
+#endif
--- /dev/null
+
+include $(top_srcdir)/adm/unix/make_begin.am
+
+AM_CXXFLAGS = $(THREAD_DEF) -I$(srcdir)/..
+
+check_PROGRAMS = test1
+
+test1_SOURCES = test1.cxx
+
+test1_LDADD = ../libYACSBases.la
+
+test1_LDFLAGS = $(CPPUNIT_LIBS) -pthread -ldl
+
+test1_CXXFLAGS = $(THREAD_DEF) $(CPPUNIT_INCLUDES) -I$(srcdir)/..
+
+TESTS = test1
+
+include $(top_srcdir)/adm/unix/make_end.am
--- /dev/null
+#include "Mutex.hxx"
+#include "Thread.hxx"
+#include "Semaphore.hxx"
+//
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/ui/text/TestRunner.h>
+#include <sstream>
+//
+
+using namespace YACS::BASES;
+
+class ThreadMechanismTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE( ThreadMechanismTest );
+ CPPUNIT_TEST( test1 );
+ CPPUNIT_TEST( test2 );
+ CPPUNIT_TEST_SUITE_END();
+public:
+ void setUp();
+ void tearDown();
+ void test1();
+ void test2();
+private:
+ static void *th1_1(void *);
+ static void *th1_2(void *);
+ static void *th1_3(void *);
+ static void *th2_1(void *);
+private:
+ static int _var;
+ static std::ostringstream _glob;
+ static Mutex _m;
+ static Semaphore _s1;
+ static Semaphore _s2;
+ //
+ static const int THREAD_NUM;
+ static const int LOOPS;
+ static int _value;
+};
+
+Mutex ThreadMechanismTest::_m;
+
+Semaphore ThreadMechanismTest::_s1;
+
+Semaphore ThreadMechanismTest::_s2;
+
+std::ostringstream ThreadMechanismTest::_glob;
+
+int ThreadMechanismTest::_var=7;
+
+const int ThreadMechanismTest::THREAD_NUM=5;
+
+const int ThreadMechanismTest::LOOPS=4;
+
+int ThreadMechanismTest::_value=0;
+
+void ThreadMechanismTest::setUp()
+{
+}
+
+void ThreadMechanismTest::tearDown()
+{
+}
+
+void ThreadMechanismTest::test1()
+{
+ char t1Name='A'; char t2Name='B'; char t3Name='C';
+ Thread t1(th1_1,&t1Name);
+ Thread t2(th1_2,&t2Name);
+ Thread t3(th1_3,&t3Name);
+ t1.join();
+ t2.join();
+ t3.join();
+ CPPUNIT_ASSERT( _glob.str() == "C7A8B10" );
+}
+
+void ThreadMechanismTest::test2()
+{
+ int i;
+ Thread **ths=new Thread *[THREAD_NUM];
+ for (i=0; i<THREAD_NUM; ++i)
+ ths[i]=new Thread(th2_1,0);
+
+ for (i=0; i<THREAD_NUM; ++i)
+ {
+ ths[i]->join();
+ delete ths[i];
+ }
+ delete [] ths;
+ CPPUNIT_ASSERT( _value == THREAD_NUM*LOOPS );
+}
+
+void *ThreadMechanismTest::th1_1(void *st)
+{
+ char myName=*((char *) st);
+ _s1.wait();
+ _glob<< myName << _var;
+ _var+=2;
+ _s1.post();
+ _s2.post();
+}
+
+void *ThreadMechanismTest::th1_2(void *st)
+{
+ char myName=*((char *) st);
+ _s2.wait();
+ _glob<< myName << _var;
+ _s2.post();
+}
+
+void *ThreadMechanismTest::th1_3(void *st)
+{
+ char myName=*((char *) st);
+ _glob<< myName << _var++;
+ _s1.post();
+}
+
+void *ThreadMechanismTest::th2_1(void *)
+{
+ int i, tmp;
+ int rc = 0;
+ for (i=0; i<LOOPS; ++i)
+ {
+ _m.lock();
+ tmp = _value;
+ tmp = tmp+1;
+ Thread::sleep(1000);
+ _value = tmp;
+ _m.unlock();
+ Thread::sleep(100000);
+ }
+}
+
+int main()
+{
+ CppUnit::TextUi::TestRunner runner;
+ runner.addTest( ThreadMechanismTest::suite() );
+ runner.run();
+ return 0;
+}
--- /dev/null
+#include "Thread.hxx"
+
+#if defined(YACS_PTHREAD)
+
+#include "ThreadPT.cxx"
+
+#else
+#error
+#endif
--- /dev/null
+#ifndef __THREAD_HXX__
+#define __THREAD_HXX__
+
+/* Interface is :
+ class Thread
+ {
+ public:
+ typedef void *(*ThreadJob)(void*);
+ public:
+ Thread(ThreadJob funcPtr, void *stack);
+ bool operator==(const Thread& other);
+ void join();
+ static void sleep(unsigned long usec);
+ };
+ */
+
+#if defined(YACS_PTHREAD)
+#include "ThreadPT.hxx"
+
+namespace YACS
+{
+ namespace BASES
+ {
+ typedef ThreadPT Thread;
+ }
+}
+#else
+#error
+#endif
+
+#endif
--- /dev/null
+#include "ThreadPT.hxx"
+#include <unistd.h>
+
+using namespace YACS::BASES;
+
+ThreadPT::ThreadPT(ThreadJob funcPtr, void *stack)
+{
+ void **stackT=(void **) stack;
+ pthread_create(&_threadId,0,funcPtr,stackT);
+}
+
+bool ThreadPT::operator==(const ThreadPT& other)
+{
+ return pthread_equal(_threadId, other._threadId) != 0;
+}
+
+void ThreadPT::join()
+{
+ void *ret;
+ pthread_join(_threadId, &ret);
+}
+
+void ThreadPT::sleep(unsigned long usec)
+{
+ usleep(usec);
+}
--- /dev/null
+#ifndef __THREADPT_HXX__
+#define __THREADPT_HXX__
+
+#include <pthread.h>
+
+namespace YACS
+{
+ namespace BASES
+ {
+ class ThreadPT
+ {
+ public:
+ typedef void *(*ThreadJob)(void*);
+ public:
+ ThreadPT(ThreadJob funcPtr, void *stack);
+ bool operator==(const ThreadPT& other);
+ void join();
+ static void sleep(unsigned long usec);
+ private:
+ pthread_t _threadId;
+ };
+ }
+}
+
+#endif
--- /dev/null
+#ifndef __DEFINE_HXX__
+#define __DEFINE_HXX__
+
+namespace YACS
+{
+ //for algs of graphs and trees
+ typedef enum
+ {
+ White = 10,
+ Grey = 11,
+ Black = 12
+ } Colour;
+
+ typedef enum
+ {
+ Double = 41,
+ Int = 42,
+ String = 44,
+ Bool = 45,
+ //CorbaRef = 46,
+ None = 49
+ } DynType;
+
+ typedef enum
+ {
+ SDouble = 71
+ } StreamType;
+
+ typedef enum
+ {
+ INITED = 100,
+ TOLOAD = 101,
+ LOADED = 102,
+ TOACTIVATE = 103,
+ ACTIVATED = 104,
+ DESACTIVATED = 105,
+ DONE = 106,
+ SUSPENDED = 107,
+ LOADFAILED = 108,
+ EXECFAILED = 109,
+ PAUSE = 110
+ } StatesForNode;
+
+ typedef enum
+ {
+ NOEVENT = 200,
+ START = 201,
+ FINISH = 202,
+ ABORT = 203
+ } Event;
+}
+
+#endif
--- /dev/null
+#include "ContentOfDataFlow.hxx"
+
+using namespace YACS::ENGINE;
+
+const char ContentOfDataFlow::STRFORNULLREPR[]="NULL";
+
+template< YACS::DynType type >
+class TreatmentForNewContentDataFlow
+{
+public:
+ static void perform(const std::string& input, ContentOfDataFlow::Type& ret)
+ {
+ ret=ContentOfDataFlow::createNewContent<type>(input);
+ }
+};
+
+template< YACS::DynType fromType, YACS::DynType toType >
+class TreatmentForConvertContentDataFlow
+{
+ public:
+ static void perform(ContentOfDataFlow::Type input, ContentOfDataFlow::Type& ret)
+ {
+ ret=StaticAndDynamicTypeConverter<ContentOfDataFlow,fromType,toType>::convert(input);
+ }
+};
+
+template< YACS::DynType fromType, YACS::DynType toType >
+class TreatmentToCheckStaticallyTypes
+{
+ public:
+ static void perform(ContentOfDataFlow::Type input, bool& ret)
+ {
+ ret=StaticTypeConverter<fromType,toType>::_staticallyCompatible;
+ }
+};
+
+void ContentOfDataFlow::duplicate(ContentOfDataFlow::Type content)
+{
+ if(content!=neuter())
+ {
+ int *contentC=(int *)content;
+ (*contentC)=(*contentC)+1;
+ }
+}
+
+void ContentOfDataFlow::release(ContentOfDataFlow::Type& content)
+{
+ if(content!=neuter())
+ {
+ int *contentC=(int *)content;
+ (*contentC)=(*contentC)-1;
+ if((*contentC)==0)
+ {
+ free(content);
+ content=neuter();
+ }
+ }
+}
+
+ContentOfDataFlow::Type ContentOfDataFlow::createNewContent(const std::string& content, DynType typeOfContent) throw(Exception)
+{
+ ContentOfDataFlow::Type ret;
+ DynToStaticTypeDispatcher1<TreatmentForNewContentDataFlow>::perform(typeOfContent, content, ret);
+ return ret;
+}
+
+ContentOfDataFlow::Type ContentOfDataFlow::convertContent(ContentOfDataFlow::Type content, DynType fromType, DynType toType) throw(ConversionException)
+{
+ if(fromType==toType)
+ return content;
+ else
+ {
+ ContentOfDataFlow::Type ret;
+ DynToStaticTypeDispatcher2<TreatmentForConvertContentDataFlow>::perform(fromType, toType, content, ret);
+ return ret;
+ }
+}
+
+bool ContentOfDataFlow::isStaticallyCompatibleWith(DynType fromType, DynType toType) throw(Exception)
+{
+ bool ret;
+ DynToStaticTypeDispatcher2<TreatmentToCheckStaticallyTypes>::perform(fromType, toType, ContentOfDataFlow::neuter(), ret);
+ return ret;
+}
+
+std::string ContentOfDataFlow::getRepresentation(ContentOfDataFlow::Type content)
+{
+ if(content!=ContentOfDataFlow::neuter())
+ {
+ char *contentC=(char *)content;
+ contentC+=sizeof(int);
+ return std::string(contentC);
+ }
+ else
+ return ContentOfDataFlow::STRFORNULLREPR;
+}
+
+ContentOfDataFlow::Type ContentOfDataFlow::allocate(int lgth)
+{
+ ContentOfDataFlow::Type ret=malloc(lgth+1+sizeof(int));
+ int *ret2=(int *)ret;
+ *ret2=1;
+ return ret;
+}
--- /dev/null
+#ifndef __CONTENTOFDATAFLOW_HXX__
+#define __CONTENTOFDATAFLOW_HXX__
+
+#include "define.hxx"
+#include "TypeCheckerDataFlow.hxx"
+#include "ConversionException.hxx"
+
+#include <string>
+#include <cstring>
+#include <sstream>
+#include <stdlib.h>
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ class ContentOfDataFlow
+ {
+ public:
+ typedef void * Type;
+
+ static void duplicate(Type content);
+ static void release(Type& content);
+ static Type createNewContent(const std::string& content, DynType typeOfContent) throw(Exception);
+ static Type convertContent(Type content, DynType fromType, DynType toType) throw(ConversionException);
+ static bool isStaticallyCompatibleWith(DynType fromType, DynType toType) throw(Exception);
+ template<class T>
+ static Type createNewContent(T value);
+ template<YACS::DynType typ>
+ static Type createNewContent(const std::string& content) throw(Exception);
+ template<class T>
+ static void readContent(Type content, T& value) throw(Exception);
+ static Type neuter() { return 0; }
+ static std::string getRepresentation(Type content);
+ private:
+ static Type allocate(int lgth);
+ private:
+ static const char STRFORNULLREPR[];
+ };
+
+ template<class T>
+ ContentOfDataFlow::Type ContentOfDataFlow::createNewContent(T value)
+ {
+ std::ostringstream stream;
+ stream << value;
+ int length=stream.str().length();
+ ContentOfDataFlow::Type ret=allocate(length);
+ int *retC=(int *)ret;
+ memcpy(retC+1,stream.str().c_str(),length+1);
+ return ret;
+ }
+
+ template<class T>
+ void ContentOfDataFlow::readContent(ContentOfDataFlow::Type content, T& value) throw(Exception)
+ {
+ if(content==ContentOfDataFlow::neuter())
+ throw Exception("no content to read");
+ char *contentC=(char *)content;
+ contentC+=sizeof(int);
+ const DynType typ=TypeDescriptorTraitsInv<T>::_typeEnum;
+ std::istringstream stream(contentC);
+ stream >> value;
+ if(stream.fail() || !stream.eof())
+ {
+ std::string what="Content not recognized as "; what+=TypeDescriptorTraits<TypeDescriptorTraitsInv<T>::_typeEnum>::_name;
+ throw Exception(what);
+ }
+ }
+
+ template<YACS::DynType typ>
+ ContentOfDataFlow::Type ContentOfDataFlow::createNewContent(const std::string& content) throw(Exception)
+ {
+ std::istringstream stream(content);
+ typename TypeDescriptorTraits<typ>::ConcreteType value;
+ stream >> value;
+ if(!stream.fail() && stream.eof())
+ return createNewContent(value);
+ else
+ {
+ std::string what(content);
+ what+=" is not recognized as "; what+=TypeDescriptorTraits<typ>::_name;
+ throw Exception(what);
+ }
+ }
+ }
+}
+
+#endif
--- /dev/null
+#include "ConversionException.hxx"
+
+using namespace YACS::ENGINE;
+
+const char ConversionException::TYPEOFEXCEPTION[]="Conversion between types failed : ";
+
+
+ConversionException::ConversionException(const std::string& content, const std::string& expectedType):Exception(TYPEOFEXCEPTION)
+{
+ _what=TYPEOFEXCEPTION;
+ _what+=content;
+ _what+=" -> Expecting type ";
+ _what+=expectedType;
+}
--- /dev/null
+#ifndef __CONVERSIONEXCEPTION_HXX__
+#define __CONVERSIONEXCEPTION_HXX__
+
+#include "Exception.hxx"
+
+#include <string>
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ class ConversionException : public Exception
+ {
+ public:
+ ConversionException(const std::string& content, const std::string& expectedType);
+ private:
+ static const char TYPEOFEXCEPTION[];
+ };
+ }
+}
+
+#endif
--- /dev/null
+#include "Data.hxx"
+
+using namespace YACS::ENGINE;
+
+const char Data::UNRECOGNIZEDTYPENAME[]="Unrecognized type";
+
+Data::Data(DynType typeOfContent):_edType(typeOfContent),_exContent(ContentOfDataFlow::neuter())
+{
+}
+
+Data::Data(const std::string& content, DynType typeOfContent) throw(Exception):_edType(typeOfContent)
+{
+ _exContent=ContentOfDataFlow::createNewContent(content,typeOfContent);
+}
+
+Data::Data(const Data& other):_edType(other._edType)
+{
+ ContentOfDataFlow::duplicate(other._exContent);
+ _exContent=other._exContent;
+}
+
+Data::~Data()
+{
+ ContentOfDataFlow::release(_exContent);
+}
+
+Data &Data::operator =(const Data& other) throw(ConversionException)
+{
+ if(&other!=this)
+ {
+ if(other._exContent==ContentOfDataFlow::neuter())
+ {
+ ContentOfDataFlow::release(_exContent);
+ _exContent=ContentOfDataFlow::neuter();
+ return *this;
+ }
+ if(other._edType==_edType)
+ {
+ ContentOfDataFlow::duplicate(other._exContent);
+ ContentOfDataFlow::release(_exContent);
+ _exContent=other._exContent;
+ }
+ else
+ {
+ ContentOfDataFlow::release(_exContent);
+ _exContent=ContentOfDataFlow::convertContent(other._exContent,other._edType,_edType);
+ }
+ }
+ return *this;
+}
+
+std::string Data::edGetRepresentation() const
+{
+ std::ostringstream stream;
+ stream << _edType << "_" << ContentOfDataFlow::getRepresentation(_exContent);
+ return stream.str();
+}
+
+void Data::edSetNewType(DynType newTypeOfContent) throw(ConversionException)
+{
+ if(_edType==newTypeOfContent)
+ return;
+ ContentOfDataFlow::Type newContent=ContentOfDataFlow::convertContent(_exContent,_edType,newTypeOfContent);
+ ContentOfDataFlow::release(_exContent);
+ _exContent=newContent;
+ _edType=newTypeOfContent;
+}
+
+void Data::exSetContent(const std::string& content) throw(ConversionException)
+{
+ ContentOfDataFlow::release(_exContent);
+ _exContent=ContentOfDataFlow::createNewContent(content,_edType);
+}
+
+void Data::edInitToType(DynType typeOfContent)
+{
+ ContentOfDataFlow::release(_exContent);
+ _exContent=ContentOfDataFlow::neuter();
+ _edType=typeOfContent;
+}
+
+void Data::exInit()
+{
+ ContentOfDataFlow::release(_exContent);
+ _exContent=ContentOfDataFlow::neuter();
+}
+
+// Part of Data::edGetType implementation
+template< YACS::DynType type >
+class TreatmentForNameOfType
+{
+public:
+ static void perform(int input, std::string& ret)
+ {
+ ret=TypeDescriptorTraits<type>::_name;
+ }
+};
+
+std::string Data::edGetTypeInPrintableForm(DynType type)
+{
+ try
+ {
+ int fake1;
+ std::string ret;
+ DynToStaticTypeDispatcher1<TreatmentForNameOfType>::perform(type, fake1, ret);
+ return ret;
+ }
+ catch(Exception& e)
+ {
+ return UNRECOGNIZEDTYPENAME;
+ }
+}
+
+bool Data::isStaticallyCompatibleWith(const Data& other) const throw(Exception)
+{
+ return areStaticallyCompatible(_edType, other._edType);
+}
+
+bool Data::areStaticallyCompatible(DynType type1, DynType type2) throw(Exception)
+{
+ return ContentOfDataFlow::isStaticallyCompatibleWith(type1, type2);
+}
+
+bool Data::empty() const
+{
+ return _exContent==ContentOfDataFlow::neuter();
+}
--- /dev/null
+#ifndef __DATA_HXX__
+#define __DATA_HXX__
+
+#include "define.hxx"
+#include "ContentOfDataFlow.hxx"
+#include "ConversionException.hxx"
+#include <string>
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ /**
+ *
+ * Manage Data exchanged through dataflow pipe between 2 nodes. This class minimizes duplications of data.
+ * WARNING : Data has a type defined on constructor or after having called edSetNewType method.
+ * All the methods that change the content of data check the validity regarding _edType attribute.
+ *
+ */
+ class Data
+ {
+ private:
+ DynType _edType;
+ ContentOfDataFlow::Type _exContent;
+ static const char Data::UNRECOGNIZEDTYPENAME[];
+ public:
+ Data(DynType typeOfContent);
+ Data(const std::string& content, DynType typeOfContent) throw(Exception);
+ template<class T>
+ Data(T val);
+ Data(const Data& other);
+ ~Data();
+ Data &operator =(const Data& other) throw(ConversionException);
+ template<class T>
+ Data &operator =(T val) throw(ConversionException);
+ std::string edGetRepresentation() const;
+ void edSetNewType(DynType newTypeOfContent) throw(ConversionException);
+ void exSetContent(const std::string& content) throw(ConversionException);
+ template<class T>
+ T exGet() const throw(ConversionException);
+ void edInitToType(DynType typeOfContent);
+ void exInit();
+ DynType edGetType() const { return _edType; }
+ static std::string edGetTypeInPrintableForm(DynType type);
+ bool isStaticallyCompatibleWith(const Data& other) const throw(Exception);
+ static bool areStaticallyCompatible(DynType type1, DynType type2) throw(Exception);
+ bool empty() const;
+ };
+
+ template<class T>
+ Data::Data(T val)
+ {
+ _edType=TypeDescriptorTraitsInv<T>::_typeEnum;
+ _exContent=ContentOfDataFlow::createNewContent(val);
+ }
+
+ template<class T>
+ Data &Data::operator =(T val) throw(ConversionException)
+ {
+ ContentOfDataFlow::release(_exContent);
+ typename ContentOfDataFlow::Type content=ContentOfDataFlow::createNewContent(val);
+ if(_edType==TypeDescriptorTraitsInv<T>::_typeEnum)
+ {
+ _exContent=content;
+ }
+ else
+ {
+ _exContent=ContentOfDataFlow::convertContent(content,TypeDescriptorTraitsInv<T>::_typeEnum,_edType);
+ ContentOfDataFlow::release(content);
+ }
+ return *this;
+ }
+
+ template<class T>
+ T Data::exGet() const throw(ConversionException)
+ {
+ T ret;
+ ContentOfDataFlow::readContent(_exContent,ret);
+ return ret;
+ }
+ }
+}
+
+#endif
--- /dev/null
+
+include $(top_srcdir)/adm/unix/make_begin.am
+
+SUBDIRS = Test
+
+lib_LTLIBRARIES = libYACSBasicData.la
+
+libYACSBasicData_la_SOURCES = \
+ Data.cxx \
+ ContentOfDataFlow.cxx \
+ ConversionException.cxx \
+ TypeCheckerDataFlow.cxx \
+ TypeCheckerDataStream.cxx \
+ $(__dummy__)
+
+EXTRA_libYACSBasicData_la_SOURCES = \
+ Data.hxx \
+ $(__dummy__)
+
+libYACSBasicData_la_LIBADD = ../bases/libYACSBases.la
+
+AM_CXXFLAGS = $(THREAD_DEF) \
+ -I$(srcdir)/../bases \
+ -D__OLD_GCC__
+
+include $(top_srcdir)/adm/unix/make_end.am
--- /dev/null
+
+include $(top_srcdir)/adm/unix/make_begin.am
+
+ $(__dummy__)
+
+check_PROGRAMS = testData
+
+testData_SOURCES = testData.cxx
+
+testData_LDADD = ../libYACSBasicData.la \
+ ../../bases/libYACSBases.la
+
+testData_LDFLAGS = $(CPPUNIT_LIBS) -pthread -ldl
+
+testData_CXXFLAGS = $(CPPUNIT_INCLUDES) \
+ -I$(srcdir)/.. \
+ -I$(srcdir)/../../bases
+
+TESTS = testData
+
+include $(top_srcdir)/adm/unix/make_end.am
--- /dev/null
+#include "Data.hxx"
+//
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/ui/text/TestRunner.h>
+#include <sstream>
+//
+
+using namespace YACS::ENGINE;
+
+class DataTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE( DataTest );
+ CPPUNIT_TEST( test1 );
+ CPPUNIT_TEST( test2 );
+ CPPUNIT_TEST( test3 );
+ CPPUNIT_TEST( test4 );
+ CPPUNIT_TEST_EXCEPTION( test5, YACS::ENGINE::ConversionException);
+ CPPUNIT_TEST( test6 );
+ CPPUNIT_TEST( testStaticCheckType );
+ CPPUNIT_TEST_SUITE_END();
+public:
+ void tearDown();
+ void test1();
+ void test2();
+ void test3();
+ void test4();
+ void test5();
+ void test6();
+ void testStaticCheckType();
+};
+
+void DataTest::tearDown()
+{
+}
+
+void DataTest::test1()
+{
+ Data d1(YACS::Double),d2(YACS::Int),d3(YACS::Bool);
+ d1=3.14; d3=d2=d1;
+ CPPUNIT_ASSERT( d1.edGetRepresentation() == "41_3.14" );
+ CPPUNIT_ASSERT( d2.edGetRepresentation() == "42_3" );
+ CPPUNIT_ASSERT( d3.edGetRepresentation() == "45_1" );
+}
+
+void DataTest::test2()
+{
+ Data d1("2.78",YACS::Double);
+ d1.edSetNewType(YACS::Int);
+ CPPUNIT_ASSERT( d1.edGetRepresentation() == "42_2" );
+ d1.edSetNewType(YACS::Bool);
+ CPPUNIT_ASSERT( d1.edGetRepresentation() == "45_1" );
+ d1.edInitToType(YACS::String);
+ CPPUNIT_ASSERT( d1.edGetRepresentation() == "44_NULL" );
+}
+
+void DataTest::test3()
+{
+ Data d1("2.78",YACS::Double);
+ CPPUNIT_ASSERT( d1.edGetRepresentation() == "41_2.78" );
+ d1.exSetContent("4.14e3");
+ CPPUNIT_ASSERT( d1.edGetRepresentation() == "41_4140" );
+ d1.exSetContent("-4.9995");
+ CPPUNIT_ASSERT( d1.edGetRepresentation() == "41_-4.9995" );
+}
+
+void DataTest::test4()
+{
+ Data d1(6.279),d2(67), d3(false), d4(std::string("coucou"));
+ CPPUNIT_ASSERT( d1.edGetRepresentation() == "41_6.279" );
+ CPPUNIT_ASSERT( d2.edGetRepresentation() == "42_67" );
+ CPPUNIT_ASSERT( Data::edGetTypeInPrintableForm(d1.edGetType()) == "Double" );
+ CPPUNIT_ASSERT( d3.edGetRepresentation() == "45_0" );
+ CPPUNIT_ASSERT( Data::edGetTypeInPrintableForm(d3.edGetType()) == "Bool" );
+ CPPUNIT_ASSERT( d4.edGetRepresentation() == "44_coucou" );
+ CPPUNIT_ASSERT( Data::edGetTypeInPrintableForm(d4.edGetType()) == "String" );
+}
+
+void DataTest::test5()
+{
+ Data d1("2.78",YACS::Double);
+ d1=std::string("coucou");
+}
+
+void DataTest::test6()
+{
+ Data d1("2.78",YACS::Double);
+ Data d2("3.14",YACS::Double);
+ CPPUNIT_ASSERT( d1.edGetRepresentation() == "41_2.78" );
+ CPPUNIT_ASSERT( d2.edGetRepresentation() == "41_3.14" );
+ d1=d2;
+ Data d3(d1);
+ Data d4=d1;
+ CPPUNIT_ASSERT( d1.edGetRepresentation() == "41_3.14" );
+ CPPUNIT_ASSERT( d3.edGetRepresentation() == "41_3.14" );
+ CPPUNIT_ASSERT( d4.edGetRepresentation() == "41_3.14" );
+ d3.edInitToType(YACS::Int);
+ CPPUNIT_ASSERT( d3.empty() );
+ CPPUNIT_ASSERT( Data::edGetTypeInPrintableForm(d3.edGetType()) == "Int" );
+}
+
+void DataTest::testStaticCheckType()
+{
+ Data d1("2.78",YACS::Double);
+ Data d2("3.14",YACS::Double);
+ CPPUNIT_ASSERT( d1.isStaticallyCompatibleWith(d2) );
+ d1.edInitToType(YACS::Int);
+ CPPUNIT_ASSERT( d1.isStaticallyCompatibleWith(d2) );
+ d1.edInitToType(YACS::Bool);
+ CPPUNIT_ASSERT( !d1.isStaticallyCompatibleWith(d2) );
+}
+
+int main()
+{
+ CppUnit::TextUi::TestRunner runner;
+ runner.addTest( DataTest::suite() );
+ runner.run();
+ return 0;
+}
--- /dev/null
+#include "TypeCheckerDataFlow.hxx"
+
+using namespace YACS::ENGINE;
+
+const char TypeDescriptorTraits<YACS::Double>::_name[]="Double";
+
+const char TypeDescriptorTraits<YACS::Int>::_name[]="Int";
+
+const char TypeDescriptorTraits<YACS::Bool>::_name[]="Bool";
+
+const char TypeDescriptorTraits<YACS::String>::_name[]="String";
--- /dev/null
+#ifndef __TYPECHECKERDATAFLOW_HXX__
+#define __TYPECHECKERDATAFLOW_HXX__
+
+#include "define.hxx"
+#include "ConversionException.hxx"
+
+#include <string>
+#include <sstream>
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ /**
+ *
+ * @ note : container in all this file is a concept that stores any data of any data into container::Type type.
+ * container concept must at least implement
+ * - createNewContent method
+ * - readContent method
+ * and container must define Type class that stores data independently of type.
+ * ContentOfDataFlow is one class fulfilling this concept !
+ *
+ */
+ template< template< DynType type> class TREATMENTPERTYPE >
+ class DynToStaticTypeDispatcher1
+ {
+ public:
+ template<class T, class U>
+ static void perform(YACS::DynType myTypeDyn, T input, U& output) throw(Exception)
+ {
+ switch(myTypeDyn)
+ {
+ case Double:
+ TREATMENTPERTYPE<Double>::perform(input, output);
+ break;
+ case Int:
+ TREATMENTPERTYPE<Int>::perform(input, output);
+ break;
+ case String:
+ TREATMENTPERTYPE<String>::perform(input, output);
+ break;
+ case Bool:
+ TREATMENTPERTYPE<Bool>::perform(input, output);
+ break;
+ default:
+ throw Exception("Unknow type enum");
+ }
+ }
+ };
+
+ template< template< DynType fromType, DynType toType> class TREATMENTPERTYPE >
+ class DynToStaticTypeDispatcher2
+ {
+ template<DynType toType> class TREATMENTPERTYPEDOUBLE : public TREATMENTPERTYPE<Double,toType> { };
+ template<DynType toType> class TREATMENTPERTYPEINT : public TREATMENTPERTYPE<Int,toType> { };
+ template<DynType toType> class TREATMENTPERTYPEBOOL : public TREATMENTPERTYPE<Bool,toType> { };
+ template<DynType toType> class TREATMENTPERTYPESTRING : public TREATMENTPERTYPE<String,toType> { };
+ public:
+ template<class T, class U>
+ static void perform(YACS::DynType myTypeDynFrom, YACS::DynType myTypeDynTo, T input, U& output) throw(Exception)
+ {
+ switch(myTypeDynFrom)
+ {
+ case Double:
+#ifndef __OLD_GCC__
+ DynToStaticTypeDispatcher1<TREATMENTPERTYPEDOUBLE>::perform(myTypeDynTo, input, output);
+#else
+ switch(myTypeDynTo)
+ {
+ case Double:
+ TREATMENTPERTYPE<Double,Double>::perform(input, output);
+ break;
+ case Int:
+ TREATMENTPERTYPE<Double,Int>::perform(input, output);
+ break;
+ case String:
+ TREATMENTPERTYPE<Double,String>::perform(input, output);
+ break;
+ case Bool:
+ TREATMENTPERTYPE<Double,Bool>::perform(input, output);
+ break;
+ default:
+ throw Exception("Unknow type enum");
+ }
+#endif
+ break;
+ case Int:
+#ifndef __OLD_GCC__
+ DynToStaticTypeDispatcher1<TREATMENTPERTYPEINT>::perform(myTypeDynTo, input, output);
+#else
+ switch(myTypeDynTo)
+ {
+ case Double:
+ TREATMENTPERTYPE<Int,Double>::perform(input, output);
+ break;
+ case Int:
+ TREATMENTPERTYPE<Int,Int>::perform(input, output);
+ break;
+ case String:
+ TREATMENTPERTYPE<Int,String>::perform(input, output);
+ break;
+ case Bool:
+ TREATMENTPERTYPE<Int,Bool>::perform(input, output);
+ break;
+ default:
+ throw Exception("Unknow type enum");
+ }
+#endif
+ break;
+ case String:
+#ifndef __OLD_GCC__
+ DynToStaticTypeDispatcher1<TREATMENTPERTYPESTRING>::perform(myTypeDynTo, input, output);
+#else
+ switch(myTypeDynTo)
+ {
+ case Double:
+ TREATMENTPERTYPE<String,Double>::perform(input, output);
+ break;
+ case Int:
+ TREATMENTPERTYPE<String,Int>::perform(input, output);
+ break;
+ case String:
+ TREATMENTPERTYPE<String,String>::perform(input, output);
+ break;
+ case Bool:
+ TREATMENTPERTYPE<String,Bool>::perform(input, output);
+ break;
+ default:
+ throw Exception("Unknow type enum");
+ }
+#endif
+ break;
+ case Bool:
+#ifndef __OLD_GCC__
+ DynToStaticTypeDispatcher1<TREATMENTPERTYPESTRING>::perform(myTypeDynTo, input, output);
+#else
+ switch(myTypeDynTo)
+ {
+ case Double:
+ TREATMENTPERTYPE<Bool,Double>::perform(input, output);
+ break;
+ case Int:
+ TREATMENTPERTYPE<Bool,Int>::perform(input, output);
+ break;
+ case String:
+ TREATMENTPERTYPE<Bool,String>::perform(input, output);
+ break;
+ case Bool:
+ TREATMENTPERTYPE<Bool,Bool>::perform(input, output);
+ break;
+ default:
+ throw Exception("Unknow type enum");
+ }
+#endif
+ break;
+ default:
+ throw Exception("Unknow type enum");
+ }
+ }
+ };
+
+ template<YACS::DynType baseTyp>
+ class TypeDescriptorTraits
+ {
+ };
+
+ template<class T>
+ class TypeDescriptorTraitsInv
+ {
+ };
+
+ template<>
+ class TypeDescriptorTraits<YACS::Double>
+ {
+ public:
+ typedef double ConcreteType;
+ static const char _name[];
+ };
+
+ template<>
+ class TypeDescriptorTraitsInv<double>
+ {
+ public:
+ static const YACS::DynType _typeEnum=Double;
+ };
+
+ template<>
+ class TypeDescriptorTraits<YACS::Int>
+ {
+ public:
+ typedef int ConcreteType;
+ static const char _name[];
+ };
+
+ template<>
+ class TypeDescriptorTraitsInv<int>
+ {
+ public:
+ static const YACS::DynType _typeEnum=Int;
+ };
+
+ template<>
+ class TypeDescriptorTraits<YACS::Bool>
+ {
+ public:
+ typedef bool ConcreteType;
+ static const char _name[];
+ };
+
+ template<>
+ class TypeDescriptorTraitsInv<bool>
+ {
+ public:
+ static const YACS::DynType _typeEnum=Bool;
+ };
+
+ template<>
+ class TypeDescriptorTraits<YACS::String>
+ {
+ public:
+ typedef std::string ConcreteType;
+ static const char _name[];
+ };
+
+ template<>
+ class TypeDescriptorTraitsInv<std::string>
+ {
+ public:
+ static const YACS::DynType _typeEnum=String;
+ };
+
+ /**
+ *
+ * This class has the responsability of the validity of the content of data regarding only statically its types from and to.
+ *
+ */
+ template<DynType fromType, DynType toType >
+ class StaticTypeConverter
+ {
+ public:
+ enum { _staticallyCompatible=0 };
+ static typename TypeDescriptorTraits<toType>::ConcreteType traduce(typename TypeDescriptorTraits<fromType>::ConcreteType input) throw(ConversionException)
+ {
+ throw ConversionException(TypeDescriptorTraits<fromType>::_name, TypeDescriptorTraits<toType>::_name);
+ }
+ };
+
+ //Specialisation of the previously declared StaticTypeConverter class when 'fromType' and 'toType' are equal.
+ template<DynType aType>
+ class StaticTypeConverter<aType, aType>
+ {
+ public:
+ enum { _staticallyCompatible=1 };
+ static typename TypeDescriptorTraits<aType>::ConcreteType traduce(typename TypeDescriptorTraits<aType>::ConcreteType input) throw(ConversionException)
+ {
+ return input;
+ }
+ };
+
+ template<>
+ class StaticTypeConverter<YACS::Double, YACS::Int>
+ {
+ public:
+ enum { _staticallyCompatible=1 };
+ static TypeDescriptorTraits<YACS::Int>::ConcreteType traduce(TypeDescriptorTraits<YACS::Double>::ConcreteType input) throw(ConversionException)
+ {
+ return (TypeDescriptorTraits<YACS::Int>::ConcreteType) input;
+ }
+ };
+
+ template<>
+ class StaticTypeConverter<YACS::Int, YACS::Double>
+ {
+ public:
+ enum { _staticallyCompatible=1 };
+ static TypeDescriptorTraits<YACS::Double>::ConcreteType traduce(TypeDescriptorTraits<YACS::Int>::ConcreteType input) throw(ConversionException)
+ {
+ return (TypeDescriptorTraits<YACS::Double>::ConcreteType) input;
+ }
+ };
+
+ template<>
+ class StaticTypeConverter<YACS::Int, YACS::Bool>
+ {
+ public:
+ enum { _staticallyCompatible=1 };
+ static TypeDescriptorTraits<YACS::Bool>::ConcreteType traduce(TypeDescriptorTraits<YACS::Int>::ConcreteType input) throw(ConversionException)
+ {
+ if(input!=0)
+ return true;
+ else
+ return false;
+ }
+ };
+
+ template<>
+ class StaticTypeConverter<YACS::Bool, YACS::Int>
+ {
+ public:
+ enum { _staticallyCompatible=1 };
+ static TypeDescriptorTraits<YACS::Int>::ConcreteType traduce(TypeDescriptorTraits<YACS::Bool>::ConcreteType input) throw(ConversionException)
+ {
+ if(input)
+ return 1;
+ else
+ return 0;
+ }
+ };
+
+ /**
+ *
+ * This class has the responsability of the validity of the content of data regarding statically and dynamically its types from and to.
+ *
+ */
+ template<class container, DynType fromType, DynType toType >
+ class StaticAndDynamicTypeConverter
+ {
+ public:
+ static typename container::Type convert(typename container::Type source) throw(ConversionException)
+ {
+ if(!StaticTypeConverter<fromType, toType>::_staticallyCompatible)
+ throw ConversionException(TypeDescriptorTraits<fromType>::_name, TypeDescriptorTraits<toType>::_name);
+ typename TypeDescriptorTraits<fromType>::ConcreteType sourceValue;
+ container::readContent(source,sourceValue);
+ typename TypeDescriptorTraits<toType>::ConcreteType targetValue=StaticTypeConverter<fromType, toType>::traduce(sourceValue);
+ return container::createNewContent(targetValue);
+ }
+ };
+ }
+}
+
+#endif
--- /dev/null
+#include "TypeCheckerDataStream.hxx"
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ template< template< StreamType type> class TREATMENTPERTYPE >
+ class DynToStaticStreamTypeDispatcher1
+ {
+ public:
+ template<class T, class U>
+ static void perform(YACS::StreamType myTypeDyn, T input, U& output) throw(Exception)
+ {
+ switch(myTypeDyn)
+ {
+ case SDouble:
+ TREATMENTPERTYPE<SDouble>::perform(input, output);
+ break;
+ default:
+ throw Exception("Unknow stream type enum");
+ }
+ }
+ };
+
+ template< template< StreamType fromType, StreamType toType> class TREATMENTPERTYPE >
+ class DynToStaticStreamTypeDispatcher2
+ {
+ template<StreamType toType> class TREATMENTPERTYPESDOUBLE : public TREATMENTPERTYPE<SDouble,toType> { };
+ public:
+ template<class T, class U>
+ static void perform(YACS::StreamType myTypeDynFrom, YACS::StreamType myTypeDynTo, T input, U& output) throw(Exception)
+ {
+ switch(myTypeDynFrom)
+ {
+ case SDouble:
+ DynToStaticStreamTypeDispatcher1<TREATMENTPERTYPESDOUBLE>::perform(myTypeDynTo, input, output);
+ break;
+ default:
+ throw Exception("Unknow stream type enum");
+ }
+ }
+ };
+
+ template<YACS::StreamType baseTyp>
+ class StreamTypeDescriptorTraits
+ {
+ };
+
+ template<>
+ class StreamTypeDescriptorTraits<YACS::SDouble>
+ {
+ public:
+ static const char _name[];
+ };
+
+ /**
+ *
+ * This class has the responsability of the validity of the content of stream data regarding only statically its types from and to.
+ *
+ */
+ template< StreamType fromType, StreamType toType >
+ class StaticStreamTypeConverter
+ {
+ public:
+ enum { _staticallyCompatible=0 };
+ };
+
+ template<StreamType type>
+ class StaticStreamTypeConverter<type,type>
+ {
+ public:
+ enum { _staticallyCompatible=1 };
+ };
+ }
+}
+
+using namespace YACS::ENGINE;
+
+const char StreamTypeDescriptorTraits<YACS::SDouble>::_name[]="SDouble";
+
+const char TypeCheckerDataStream::UNRECOGNIZEDTYPENAME[]="Unrecognized type";
+
+//Part of TypeCheckerDataStream::areStaticallyCompatible implementation
+template< YACS::StreamType fromType, YACS::StreamType toType >
+class TreatmentToCheckStaticallyTypes
+{
+public:
+ static void perform(int input, bool& ret)
+ {
+ ret=StaticStreamTypeConverter<fromType,toType>::_staticallyCompatible;
+ }
+};
+
+bool TypeCheckerDataStream::areStaticallyCompatible(YACS::StreamType type1, YACS::StreamType type2) throw(Exception)
+{
+ bool ret;
+ int fake;
+ //DynToStaticStreamTypeDispatcher2<TreatmentToCheckStaticallyTypes>::perform(type1, type2, fake, ret);
+ return ret;
+}
+
+// Part of TypeCheckerDataStream::edGetTypeInPrintableForm implementation
+
+template< YACS::StreamType type >
+class TreatmentForNameOfStreamType
+{
+public:
+ static void perform(int input, std::string& ret)
+ {
+ ret=StreamTypeDescriptorTraits<type>::_name;
+ }
+};
+
+std::string TypeCheckerDataStream::edGetTypeInPrintableForm(YACS::StreamType type)
+{
+ try
+ {
+ int fake1;
+ std::string ret;
+ DynToStaticStreamTypeDispatcher1< TreatmentForNameOfStreamType >::perform(type, fake1, ret);
+ return ret;
+ }
+ catch(Exception& e)
+ {
+ return UNRECOGNIZEDTYPENAME;
+ }
+}
--- /dev/null
+#ifndef __TYPECHECKERDATASTREAM_HXX__
+#define __TYPECHECKERDATASTREAM_HXX__
+
+#include "define.hxx"
+#include "Exception.hxx"
+
+#include <string>
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ class TypeCheckerDataStream
+ {
+ public:
+ static bool areStaticallyCompatible(YACS::StreamType type1, YACS::StreamType type2) throw(Exception);
+ static std::string edGetTypeInPrintableForm(YACS::StreamType type);
+ private:
+ static const char UNRECOGNIZEDTYPENAME[];
+ };
+ }
+}
+
+#endif
--- /dev/null
+#include "Bloc.hxx"
+#include "ElementaryNode.hxx"
+
+using namespace YACS::ENGINE;
+
+Bloc::Bloc(const std::string& name):ComposedNode(name)
+{
+}
+
+Bloc::~Bloc()
+{
+ for(std::list<Node *>::iterator iter=_listOfNode.begin();iter!=_listOfNode.end();iter++)
+ delete *iter;
+}
+
+void Bloc::init()
+{
+ for(std::list<Node *>::iterator iter=_listOfNode.begin();iter!=_listOfNode.end();iter++)
+ (*iter)->init();
+ if(_inGate.exIsReady())
+ _state=YACS::TOACTIVATE;
+ else
+ _state=YACS::INITED;
+}
+
+bool Bloc::isFinished()
+{
+ return _state==YACS::DONE;
+}
+
+int Bloc::getNumberOfCFLinks() const
+{
+ int ret=0;
+ for(std::list<Node *>::const_iterator iter=_listOfNode.begin();iter!=_listOfNode.end();iter++)
+ {
+ ret+=(*iter)->getOutGate()->getNbOfInGatesConnected();
+ }
+ return ret;
+}
+
+std::vector<Task *> Bloc::getNextTasks(bool& isMore)
+{
+ std::vector<Task *> ret;
+ isMore=false;
+ if(_state==YACS::DONE || _state==YACS::INITED)
+ return ret;
+ for(std::list<Node *>::iterator iter=_listOfNode.begin();iter!=_listOfNode.end();iter++)
+ (*iter)->getReadyTasks(ret);
+ isMore=!ret.empty();
+ return ret;
+}
+
+void Bloc::getReadyTasks(std::vector<Task *>& tasks)
+{
+ if(_state==YACS::TOACTIVATE || _state==YACS::ACTIVATED)
+ for(std::list<Node *>::iterator iter=_listOfNode.begin();iter!=_listOfNode.end();iter++)
+ (*iter)->getReadyTasks(tasks);
+}
+
+std::list<ElementaryNode *> Bloc::getRecursiveConstituents()
+{
+ std::list<ElementaryNode *> ret;
+ for(std::list<Node *>::iterator iter=_listOfNode.begin();iter!=_listOfNode.end();iter++)
+ {
+ std::list<ElementaryNode *> myCurrentList=(*iter)->getRecursiveConstituents();
+ ret.insert(ret.begin(),myCurrentList.begin(),myCurrentList.end());
+ }
+ return ret;
+}
+
+/**
+ * @ note : Update the '_state' attribute.
+ * Typically called by 'this->_inGate' when 'this->_inGate' is ready. Contrary to Node::exUpdateState no check done on inputs
+ * because internal linked DF inputports are not valid yet.
+ */
+void Bloc::exUpdateState()
+{
+ if(_inGate.exIsReady())
+ _state=YACS::TOACTIVATE;
+}
+
+bool Bloc::edAddChild(Node *node) throw(Exception)
+{
+ if(isNodeAlreadyAggregated(node))
+ {
+ if(node->_father==this)
+ return false;
+ else
+ throw Exception("Bloc::edAddChild : Internal error occured");
+ }
+ if(node->_father)
+ throw Exception("Bloc::edAddChild : node is not orphan");
+ if(isNameAlreadyUsed(node->getName()))
+ {
+ std::string what("Bloc::edAddChild : name "); what+=node->getName(); what+=" already exists in the scope of "; what+=_name;
+ throw Exception(what);
+ }
+ node->_father=this;
+ _listOfNode.push_back(node);
+ return true;
+}
+
+/**
+ * @ note : Remove 'node' from the list of direct children.
+ * WARNING 1 : node is destroyed after invocation of this method because Bloc class has ownership of its child nodes.
+ * WARNING 2 : all links to 'node' are automatically desactivated. As consequence this method is quite heavy for big graphs due to
+ * unilateral storing policy of links.
+ * @ exception : If 'node' is NOT the direct son of 'this'.
+ *
+ */
+void Bloc::edRemoveChild(Node *node) throw(Exception)
+{
+ if(node->_father!=this)
+ throw Exception("Bloc::edRemoveChild : node is NOT managed by this");
+ if(!isNodeAlreadyAggregated(node))
+ throw Exception("Bloc::edRemoveChild : Internal error occured");
+ ComposedNode *myRootNode=getRootNode();
+ myRootNode->disconnectAllLinksConnectedTo(node);
+ _listOfNode.remove(node);
+ delete node;
+}
+
+void Bloc::selectRunnableTasks(std::vector<Task *>& tasks)
+{
+}
+
+bool Bloc::areAllSubNodesFinished() const
+{
+ bool ret=true;
+ for(std::list<Node *>::const_iterator iter=_listOfNode.begin();iter!=_listOfNode.end() && ret;iter++)
+ if((*iter)->_state!=YACS::DONE)
+ ret=false;
+ return ret;
+}
+
+bool Bloc::isNodeAlreadyAggregated(Node *node) const
+{
+ for(std::list<Node *>::const_iterator iter=_listOfNode.begin();iter!=_listOfNode.end();iter++)
+ {
+ if((*iter)==node)
+ return true;
+ }
+ return false;
+}
+
+bool Bloc::isNameAlreadyUsed(const std::string& name) const
+{
+ for(std::list<Node *>::const_iterator iter=_listOfNode.begin();iter!=_listOfNode.end();iter++)
+ if((*iter)->getName()==name)
+ return true;
+ return false;
+}
+
+/**
+ * @ note : Checks that in the forest from 'node' there are NO back-edges.
+ * WARNING : When using this method 'node' has to be checked in order to be part of direct children of 'this'.
+ *
+ */
+void Bloc::checkNoCyclePassingThrough(Node *node) throw(Exception)
+{
+ initChildrenForDFS();
+ node->_colour=YACS::Grey;
+ bool verdict=true;
+ std::list<Node *> currentNodesToTest;
+ currentNodesToTest.push_back(node);
+ for(std::list<Node *>::iterator iter1=currentNodesToTest.begin();iter1!=currentNodesToTest.end() && verdict;)
+ {
+ std::list<Node *> outNodes=(*iter1)->getOutNodes();
+ for(std::list<Node *>::iterator iter2=outNodes.begin();iter2!=outNodes.end() && verdict;iter2++)
+ if((*iter2)->_colour==YACS::White)
+ {
+ currentNodesToTest.push_back(*iter2);
+ (*iter2)->_colour=YACS::Grey;
+ }
+ else
+ verdict=false;
+ iter1=currentNodesToTest.erase(iter1);
+ }
+ if(!verdict)
+ throw Exception("Cycle has been detected");
+}
+
+void Bloc::initChildrenForDFS() const
+{
+ for(std::list<Node *>::const_iterator iter=_listOfNode.begin();iter!=_listOfNode.end();iter++)
+ (*iter)->initForDFS();
+}
+
+/**
+ *
+ * @ note : Runtime called method. Indirectly called by ComposedNode::updateStateFrom which has dispatch to this method
+ * 'when event == START'.
+ * WARNING Precondition : '_state == Running' and 'node->_father==this'(garanteed by ComposedNode::notifyFrom)
+ *
+ */
+YACS::Event Bloc::updateStateOnStartEventFrom(Node *node)
+{
+ _state=YACS::ACTIVATED;
+ return YACS::START;
+}
+
+/**
+ *
+ * @ note : Runtime called method. Indirectly called by ComposedNode::updateStateFrom which has dispatch to this method
+ * 'when event == FINISH'.
+ * WARNING Precondition : '_state == Running' and 'node->_father==this'(garanteed by ComposedNode::notifyFrom)
+ *
+ */
+YACS::Event Bloc::updateStateOnFinishedEventFrom(Node *node)
+{
+ //ASSERT(node->_father==this)
+ if(areAllSubNodesFinished())
+ {
+ _state=YACS::DONE;
+ return YACS::FINISH;//notify to father node that 'this' has becomed finished.
+ }
+ //more job to do in 'this'
+ node->_outGate.exNotifyDone();
+ return YACS::NOEVENT;//no notification to father needed because from father point of view nothing happened.
+}
--- /dev/null
+#ifndef __BLOC_HXX__
+#define __BLOC_HXX__
+
+#include "ComposedNode.hxx"
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ class Bloc : public ComposedNode
+ {
+ protected:
+ std::list<Node *> _listOfNode;//OWNERSHIP OF ALL NODES
+ public:
+ Bloc(const std::string& name);
+ ~Bloc();
+ void init();
+ bool isFinished();
+ int getNumberOfCFLinks() const;
+ std::vector<Task *> getNextTasks(bool& isMore);
+ void getReadyTasks(std::vector<Task *>& tasks);
+ std::list<ElementaryNode *> getRecursiveConstituents();
+ void exUpdateState();
+ bool edAddChild(Node *node) throw(Exception);
+ void edRemoveChild(Node *node) throw(Exception);
+ std::list<Node *> getChildren() { return _listOfNode; }
+ void selectRunnableTasks(std::vector<Task *>& tasks);
+ protected:
+ bool areAllSubNodesFinished() const;
+ bool isNodeAlreadyAggregated(Node *node) const;
+ bool isNameAlreadyUsed(const std::string& name) const;
+ void checkNoCyclePassingThrough(Node *node) throw(Exception);
+ YACS::Event updateStateOnStartEventFrom(Node *node);
+ YACS::Event updateStateOnFinishedEventFrom(Node *node);
+ private:
+ void initChildrenForDFS() const;
+ };
+ }
+}
+
+#endif
--- /dev/null
+#include "ComposedNode.hxx"
+#include "InputPort.hxx"
+#include "OutputPort.hxx"
+#include "ElementaryNode.hxx"
+
+#include <set>
+
+using namespace YACS::ENGINE;
+
+ComposedNode::ComposedNode(const std::string& name):Node(name)
+{
+}
+
+/**
+ *
+ * @ note : Runtime called method. Overloads the Scheduler::notifyFrom abstract method. Typically Called in Executor (in a parallel thread or not) by the Task 'task'
+ * to inform the scheduler that an event coded 'event' (in Executor static const var) happened. Contrary to updateStateFrom several level may exist between 'sender' and 'this'.
+ *
+ */
+void ComposedNode::notifyFrom(const Task *sender, //* I : task emitting event
+ YACS::Event event //* I : event emitted
+ )
+{
+ ElementaryNode *taskTyped=dynamic_cast<ElementaryNode *>((Task *)sender);
+ //ASSERT(taskTyped != 0)
+ YACS::Event curEvent=event;
+ Node *lminus1LevelNode=taskTyped;
+ ComposedNode *curLevelNode=taskTyped->_father;
+ curEvent=curLevelNode->updateStateFrom(lminus1LevelNode,curEvent);
+ while(curEvent!=YACS::NOEVENT && curLevelNode!=this)
+ {
+ lminus1LevelNode=curLevelNode;
+ curLevelNode=curLevelNode->_father;
+ curEvent=curLevelNode->updateStateFrom(lminus1LevelNode,curEvent);
+ }
+}
+
+/**
+ * @ note : Add a dataflow link.
+ * Precondition : 'start' AND 'end' are in/outputPort contained in a node in descendance of 'this'.
+ * @ exception : incompatibility between input and output (type), or 'start'/'end' is/are NOT in/outputPort
+ * contained in a node in descendance of 'this', or a mutilple link to an input not supporting it.
+ * @ return : true if a new link has been created, false otherwise.
+ */
+bool ComposedNode::edAddLink(OutputPort *start, InputPort *end) throw(Exception)
+{
+ ComposedNode* lwstCmnAnctr=getLowestCommonAncestor(start->getNode(),end->getNode());
+ std::list<ComposedNode *> allAscendanceOfNodeStart=start->getNode()->getAllAscendanceOf(lwstCmnAnctr);
+ std::list<ComposedNode *> allAscendanceOfNodeEnd=end->getNode()->getAllAscendanceOf(lwstCmnAnctr);
+ checkInMyDescendance(lwstCmnAnctr);
+ ComposedNode *iterS=start->getNode()->_father;
+ OutPort *currentPortO=start;
+ while(iterS!=lwstCmnAnctr)
+ {
+ currentPortO=iterS->buildDelegateOf(currentPortO, allAscendanceOfNodeEnd);
+ iterS=iterS->_father;
+ }
+ iterS=end->getNode()->_father;
+ InPort *currentPortI=end;
+ while(iterS!=lwstCmnAnctr)
+ {
+ currentPortI=iterS->buildDelegateOf(currentPortI, allAscendanceOfNodeEnd);
+ iterS=iterS->_father;
+ }
+ return currentPortO->addInPort(currentPortI);
+}
+
+/**
+ * @ note : Add a controlflow link.
+ * Precondition : 'start' AND 'end' are in/outGate contained in a node in DIRECT descendance of 'this'.
+ * @ exception : If a cycle has been detected, or incompatibility between input and output, or 'start'/'end' is/are NOT in/outputPort
+ * contained in a node in descendance of 'this', or a mutilple link to an input not supporting it.
+ * @ return : true if a new link has been created, false otherwise.
+ */
+bool ComposedNode::edAddLink(OutGate *start, InGate *end) throw(Exception)
+{
+ ComposedNode* father=checkHavingCommonFather(start->getNode(),end->getNode());
+ if(father!=this)
+ {
+ checkInMyDescendance(father);
+ return father->edAddLink(start,end);
+ }
+ bool ret=start->edAddInGate(end);
+ if(ret)
+ checkNoCyclePassingThrough(end->getNode());
+ return ret;
+}
+
+bool ComposedNode::edAddCFLink(Node *nodeS, Node *nodeE) throw(Exception)
+{
+ ComposedNode* father=checkHavingCommonFather(nodeS,nodeE);
+ if(father!=this)
+ {
+ checkInMyDescendance(father);
+ return father->edAddLink(nodeS->getOutGate(),nodeE->getInGate());
+ }
+ bool ret=nodeS->getOutGate()->edAddInGate(nodeE->getInGate());
+ if(ret)
+ checkNoCyclePassingThrough(nodeE);
+ return ret;
+}
+
+/**
+ * @ note : Remove a dataflow link.
+ * Precondition : 'start' AND 'end' are in/outputPort contained in a node in descendance of 'this'.
+ * @ exception : The specified link does not exist. The content of Exception is different in accordance with the link from 'start' to 'end' implies DF/DS gateway.
+ */
+void ComposedNode::edRemoveLink(OutputPort *start, InputPort *end) throw(Exception)
+{
+ ComposedNode* lwstCmnAnctr=getLowestCommonAncestor(start->getNode(),end->getNode());
+ checkInMyDescendance(lwstCmnAnctr);
+ std::list<ComposedNode *> allAscendanceOfNodeStart=start->getNode()->getAllAscendanceOf(lwstCmnAnctr);
+ std::list<ComposedNode *> allAscendanceOfNodeEnd=end->getNode()->getAllAscendanceOf(lwstCmnAnctr);
+ //Part of test if the link from 'start' to 'end' really exist particulary all eventually intermediate ports created
+ ComposedNode *iterS=start->getNode()->_father;
+ OutPort *currentPortO=start;
+ while(iterS!=lwstCmnAnctr)
+ {
+ currentPortO=iterS->getDelegateOf(currentPortO, allAscendanceOfNodeEnd);
+ iterS=iterS->_father;
+ }
+ iterS=end->getNode()->_father;
+ InPort *currentPortI=end;
+ while(iterS!=lwstCmnAnctr)
+ {
+ currentPortI=iterS->getDelegateOf(currentPortI, allAscendanceOfNodeStart);
+ iterS=iterS->_father;
+ }
+ //End of test for evt intermediate ports created
+ currentPortO->removeInPort(currentPortI);
+ //Performing deletion of intermediate ports
+ iterS=start->getNode()->_father;
+ currentPortO=start; currentPortI=end;
+ while(iterS!=lwstCmnAnctr)
+ {
+ currentPortO=iterS->releaseDelegateOf(currentPortO, allAscendanceOfNodeEnd);
+ iterS=iterS->_father;
+ }
+ iterS=end->getNode()->_father;
+ while(iterS!=lwstCmnAnctr)
+ {
+ currentPortI=iterS->releaseDelegateOf(currentPortI, allAscendanceOfNodeStart);
+ iterS=iterS->_father;
+ }
+}
+
+void ComposedNode::edRemoveLink(OutGate *start, InGate *end) throw(Exception)
+{
+ ComposedNode* father=checkHavingCommonFather(start->getNode(),end->getNode());
+ if(father!=this)
+ throw Exception("edRemoveLink : nodes not in direct descendance of this");
+ start->edRemoveInGate(end);
+}
+
+void ComposedNode::publishOutputPort(OutputPort *port) throw(Exception)
+{
+ checkInMyDescendance(port->getNode());
+ _listOfOutputPort.push_back(port);
+}
+
+void ComposedNode::publishInputPort(InputPort *port)
+{
+ _listOfInputPort.push_back(port);
+}
+
+ComposedNode *ComposedNode::getRootNode() throw(Exception)
+{
+ if(!_father)
+ return this;
+ return Node::getRootNode();
+}
+
+/**
+ * @ note : perform the disconnection of all links under the scope of 'this' connected to an input (dataflow or datastream) of node 'node'.
+ * This method is quite heavy because the links are stored in one direction.
+ */
+void ComposedNode::disconnectAllLinksConnectedTo(Node *node)
+{
+ std::list<ElementaryNode *> listOfAllNodes=getRecursiveConstituents();
+ for(std::list<ElementaryNode *>::iterator iter=listOfAllNodes.begin();iter!=listOfAllNodes.end();iter++)
+ (*iter)->disconnectAllLinksConnectedTo(node);
+}
+
+/**
+ * @ note : Check that 'nodeToTest' is in descendance of 'this' OR equal to 'this'
+ * @ exception : If 'nodeToTest' is NOT in descendance of 'this' AND not equal to 'this'
+ */
+void ComposedNode::checkInMyDescendance(Node *nodeToTest) const throw(Exception)
+{
+ const char what[]="check failed : node is not in the correct descendance";
+ if(nodeToTest==0)
+ throw Exception(what);
+ if((ComposedNode *)nodeToTest==this)
+ return;
+ ComposedNode *iter=nodeToTest->_father;
+ while(iter!=0 && iter!=this)
+ iter=iter->_father;
+ if(iter==0)
+ throw Exception(what);
+}
+
+/**
+ *
+ * @ note : Retrieves the lowest common ancestor of 'node1' AND 'node2'. If 'node1' AND 'node2' are equals and are instance of ComposedNode
+ * the father of 'node1' is returned.
+ * @ exception : 'node1' and 'node2' does not share the same genealogy.
+ * @ return : The lowest common ancestor if it exists.
+ *
+ */
+ComposedNode *ComposedNode::getLowestCommonAncestor(Node *node1, Node *node2) throw(Exception)
+{
+ const char what[]="2 nodes does not share the same genealogy";
+ if(node1==0 || node2==0)
+ throw Exception(what);
+ ComposedNode *temp=node1->_father;
+ std::set<ComposedNode *> s;
+ while(temp)
+ {
+ s.insert(temp);
+ temp=temp->_father;
+ }
+ //
+ temp=node2->_father;
+ std::set<ComposedNode *>::iterator iter=s.find(temp);
+ while(temp && iter==s.end())
+ {
+ iter=s.find(temp);
+ temp=temp->_father;
+ }
+ if(iter==s.end())
+ throw Exception(what);
+ return *iter;
+}
+
+/**
+ *
+ * @ note : Runtime called method. Perform, the state updating, from the son node 'node' emitting the event 'event' (among Executor static const var).
+ * WARNING Precondition : this == node->_father
+ * @ return : The event (among Executor static const var) destinated to this->_father node to perform eventually up level update.
+ *
+ */
+YACS::Event ComposedNode::updateStateFrom(Node *node, //* I : node emitting event
+ YACS::Event event //* I : event emitted
+ )
+{
+ switch(event)
+ {
+ case YACS::START:
+ return updateStateOnStartEventFrom(node);
+ break;
+ case YACS::FINISH:
+ return updateStateOnFinishedEventFrom(node);
+ break;
+ default:
+ return YACS::NOEVENT;//TODO unexpected type of event
+ break;
+ }
+}
+
+InPort *ComposedNode::buildDelegateOf(InPort *port, const std::list<ComposedNode *>& pointsOfView)
+{
+ return port;
+}
+
+OutPort *ComposedNode::buildDelegateOf(OutPort *port, const std::list<ComposedNode *>& pointsOfView)
+{
+ return port;
+}
+
+InPort *ComposedNode::getDelegateOf(InPort *port, const std::list<ComposedNode *>& pointsOfView) throw(Exception)
+{
+ return port;
+}
+
+OutPort *ComposedNode::getDelegateOf(OutPort *port, const std::list<ComposedNode *>& pointsOfView) throw(Exception)
+{
+ return port;
+}
+
+InPort *ComposedNode::releaseDelegateOf(InPort *port, const std::list<ComposedNode *>& pointsOfView) throw(Exception)
+{
+ return port;
+}
+
+OutPort *ComposedNode::releaseDelegateOf(OutPort *port, const std::list<ComposedNode *>& pointsOfView) throw(Exception)
+{
+ return port;
+}
--- /dev/null
+#ifndef __COMPOSEDNODE_HXX__
+#define __COMPOSEDNODE_HXX__
+
+#include "Node.hxx"
+#include "Scheduler.hxx"
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ class Bloc;
+ class InPort;
+ class OutPort;
+ class ElementaryNode;
+
+ class ComposedNode : public Node, public Scheduler
+ {
+ friend class Bloc;
+ friend class ElementaryNode;
+ protected:
+ ComposedNode(const std::string& name);
+ public:
+ void notifyFrom(const Task *sender, YACS::Event event);
+ bool edAddLink(OutputPort *start, InputPort *end) throw(Exception);
+ bool edAddLink(OutGate *start, InGate *end) throw(Exception);
+ bool edAddCFLink(Node *nodeS, Node *nodeE) throw(Exception);
+ void edRemoveLink(OutputPort *start, InputPort *end) throw(Exception);
+ void edRemoveLink(OutGate *start, InGate *end) throw(Exception);
+ virtual void publishOutputPort(OutputPort *port) throw(Exception);
+ virtual bool isRepeatedUnpredictablySeveralTimes() const { return false; }
+ protected:
+ ComposedNode *getRootNode() throw(Exception);
+ void disconnectAllLinksConnectedTo(Node *node);
+ virtual void publishInputPort(InputPort *port);
+ YACS::Event updateStateFrom(Node *node, YACS::Event event);//update the state of this. Precondition : node->_father == this
+ virtual YACS::Event updateStateOnStartEventFrom(Node *node) = 0;//transition 3 doc P.R
+ virtual YACS::Event updateStateOnFinishedEventFrom(Node *node) = 0;//transition 9 doc P.R.
+ virtual InPort *buildDelegateOf(InPort *port, const std::list<ComposedNode *>& pointsOfView);
+ virtual OutPort *buildDelegateOf(OutPort *port, const std::list<ComposedNode *>& pointsOfView);
+ virtual InPort *getDelegateOf(InPort *port, const std::list<ComposedNode *>& pointsOfView) throw(Exception);
+ virtual OutPort *getDelegateOf(OutPort *port, const std::list<ComposedNode *>& pointsOfView) throw(Exception);
+ virtual InPort *releaseDelegateOf(InPort *port, const std::list<ComposedNode *>& pointsOfView) throw(Exception);
+ virtual OutPort *releaseDelegateOf(OutPort *port, const std::list<ComposedNode *>& pointsOfView) throw(Exception);
+ virtual void checkNoCyclePassingThrough(Node *node) throw(Exception) = 0;
+ void checkInMyDescendance(Node *nodeToTest) const throw(Exception);
+ static ComposedNode *getLowestCommonAncestor(Node *node1, Node *node2) throw(Exception);
+ };
+ }
+}
+
+#endif
--- /dev/null
+#include "DataFlowPort.hxx"
+
+using namespace YACS::ENGINE;
+using YACS::DynType;
+
+const char DataFlowPort::NAME[]="DataFlowPort";
+
+DataFlowPort::DataFlowPort(const std::string& name, Node *node, DynType type):Port(node),_name(name),_data(type)
+{
+}
+
+std::string DataFlowPort::getNameOfTypeOfCurrentInstance() const
+{
+ return NAME;
+}
+
+DynType DataFlowPort::edGetType() const
+{
+ return _data.edGetType();
+}
+
+void DataFlowPort::edSetType(DynType type)
+{
+ _data.edInitToType(type);
+}
--- /dev/null
+#ifndef __DATAFLOWPORT_HXX__
+#define __DATAFLOWPORT_HXX__
+
+#include "Port.hxx"
+#include "Data.hxx"
+
+#include <string>
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ class DataFlowPort : public virtual Port
+ {
+ protected:
+ Data _data;
+ std::string _name;
+ public:
+ static const char NAME[];
+ protected:
+ DataFlowPort(const std::string& name, Node *node, DynType type);
+ public:
+ std::string getNameOfTypeOfCurrentInstance() const;
+ DynType edGetType() const;
+ virtual void edSetType(DynType type);
+ std::string getName() const { return _name; }
+ };
+ }
+}
+
+#endif
--- /dev/null
+#include "DataStreamPort.hxx"
+
+using namespace YACS::ENGINE;
+
+const char DataStreamPort::NAME[]="DataStreamPort";
+
+DataStreamPort::DataStreamPort(const std::string& name, Node *node, StreamType type):Port(node),_name(name),_edType(type)
+{
+}
+
+std::string DataStreamPort::getNameOfTypeOfCurrentInstance() const
+{
+ return NAME;
+}
--- /dev/null
+#ifndef __DATASTREAMPORT_HXX__
+#define __DATASTREAMPORT_HXX__
+
+#include "Port.hxx"
+#include "define.hxx"
+
+#include <string>
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ class DataStreamPort : public virtual Port
+ {
+ protected:
+ std::string _name;
+ StreamType _edType;
+ public:
+ static const char NAME[];
+ protected:
+ DataStreamPort(const std::string& name, Node *node, StreamType type);
+ public:
+ std::string getNameOfTypeOfCurrentInstance() const;
+ std::string getName() const { return _name; }
+ StreamType edGetType() const { return _edType; }
+ };
+ }
+}
+
+#endif
--- /dev/null
+#include "ElementaryNode.hxx"
+#include "InputPort.hxx"
+#include "OutputPort.hxx"
+#include "ComposedNode.hxx"
+#include "InputDataStreamPort.hxx"
+#include "OutputDataStreamPort.hxx"
+
+using namespace YACS::ENGINE;
+
+ElementaryNode::ElementaryNode(const std::string& name):Node(name)
+{
+}
+
+ElementaryNode::~ElementaryNode()
+{
+ for(std::list<InputPort *>::iterator iter1=_listOfInputPort.begin();iter1!=_listOfInputPort.end();iter1++)
+ delete *iter1;
+ for(std::list<OutputPort *>::iterator iter2=_listOfOutputPort.begin();iter2!=_listOfOutputPort.end();iter2++)
+ delete *iter2;
+ for(std::list<InputDataStreamPort *>::iterator iter3=_listOfInputDataStreamPort.begin();iter3!=_listOfInputDataStreamPort.end();iter3++)
+ delete *iter3;
+ for(std::list<OutputDataStreamPort *>::iterator iter4=_listOfOutputDataStreamPort.begin();iter4!=_listOfOutputDataStreamPort.end();iter4++)
+ delete *iter4;
+}
+
+void ElementaryNode::getReadyTasks(std::vector<Task *>& tasks)
+{
+ if(_state==YACS::TOACTIVATE)
+ tasks.push_back(this);
+}
+
+void ElementaryNode::edRemovePort(Port *port) throw(Exception)
+{
+ if(port->getNode()!=this)
+ throw Exception("ElementaryNode::edRemovePort : Port is not ownered by this");
+ std::string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
+ if(typeOfPortInstance==InputPort::NAME)
+ edRemovePortTypedFromList<InputPort>(dynamic_cast<InputPort *>(port),_listOfInputPort);
+ else if(typeOfPortInstance==OutputPort::NAME)
+ edRemovePortTypedFromList<OutputPort>(dynamic_cast<OutputPort *>(port),_listOfOutputPort);
+ else if(typeOfPortInstance==InputDataStreamPort::NAME)
+ edRemovePortTypedFromList<InputDataStreamPort>(dynamic_cast<InputDataStreamPort *>(port),_listOfInputDataStreamPort);
+ else if(typeOfPortInstance==OutputDataStreamPort::NAME)
+ edRemovePortTypedFromList<OutputDataStreamPort>(dynamic_cast<OutputDataStreamPort *>(port),_listOfOutputDataStreamPort);
+ else
+ throw Exception("ElementaryNode::edRemovePort : unknown port type");
+ delete port;
+}
+
+std::list<ElementaryNode *> ElementaryNode::getRecursiveConstituents()
+{
+ std::list<ElementaryNode *> ret;
+ ret.push_back(this);
+ return ret;
+}
+
+InputPort *ElementaryNode::edAddInputPort(const std::string& inputPortName, YACS::DynType type) throw(Exception)
+{
+ InputPort *ret=edAddPort<InputPort,YACS::DynType>(inputPortName,_listOfInputPort,type);
+ //By default all inputports are seen from upper level nodes NOT outputports
+ ComposedNode *iter=_father;
+ while(iter)
+ {
+ iter->publishInputPort(_listOfInputPort.back());
+ iter=iter->_father;
+ }
+ return ret;
+}
+
+OutputPort *ElementaryNode::edAddOutputPort(const std::string& outputPortName, YACS::DynType type) throw(Exception)
+{
+ return edAddPort<OutputPort,YACS::DynType>(outputPortName,_listOfOutputPort,type);
+}
+
+InputDataStreamPort *ElementaryNode::edAddInputDataStreamPort(const std::string& inputPortDSName, YACS::StreamType type) throw(Exception)
+{
+ return edAddPort<InputDataStreamPort,YACS::StreamType>(inputPortDSName,_listOfInputDataStreamPort,type);
+}
+
+OutputDataStreamPort *ElementaryNode::edAddOutputDataStreamPort(const std::string& outputPortDSName, YACS::StreamType type) throw(Exception)
+{
+ return edAddPort<OutputDataStreamPort,YACS::StreamType>(outputPortDSName,_listOfOutputDataStreamPort,type);
+}
+
+void ElementaryNode::disconnectAllLinksConnectedTo(Node *node)
+{
+ std::list<InputPort *> inputDF=node->getListOfInputPort();
+ for(std::list<OutputPort *>::iterator iter1=_listOfOutputPort.begin();iter1!=_listOfOutputPort.end();iter1++)
+ for(std::list<InputPort *>::iterator iter2=inputDF.begin();iter2!=inputDF.end();iter2++)
+ (*iter1)->edRemoveInputPort(*iter2);
+ std::list<InputDataStreamPort *> inputDS=node->getListOfInputDataStreamPort();
+ for(std::list<OutputDataStreamPort *>::iterator iter3=_listOfOutputDataStreamPort.begin();iter3!=_listOfOutputDataStreamPort.end();iter3++)
+ for(std::list<InputDataStreamPort *>::iterator iter4=inputDS.begin();iter4!=inputDS.end();iter4++)
+ (*iter3)->edRemoveInputDataStreamPort(*iter4);
+}
+
+void ElementaryNode::begin()
+{
+ _state=ACTIVATED;
+}
+
+bool ElementaryNode::isReady()
+{
+ return _state==TOACTIVATE;
+}
+
+void ElementaryNode::finished()
+{
+ _state=DONE;
+}
--- /dev/null
+#ifndef __ELEMENTARYNODE_HXX__
+#define __ELEMENTARYNODE_HXX__
+
+#include "Node.hxx"
+#include "Task.hxx"
+#include "define.hxx"
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ class Port;
+ class InputPort;
+ class OutputPort;
+ class ComposedNode;
+ class InputDataStreamPort;
+ class OutputDataStreamPort;
+
+ class ElementaryNode : public Node, public Task
+ {
+ friend class ComposedNode;
+ protected:
+ ElementaryNode(const std::string& name);
+ ~ElementaryNode();
+ public:
+ void getReadyTasks(std::vector<Task *>& tasks);
+ void edRemovePort(Port *port) throw(Exception);
+ std::list<ElementaryNode *> getRecursiveConstituents();
+ virtual InputPort *edAddInputPort(const std::string& inputPortName, YACS::DynType type) throw(Exception);
+ virtual OutputPort *edAddOutputPort(const std::string& outputPortName, YACS::DynType type) throw(Exception);
+ virtual InputDataStreamPort *edAddInputDataStreamPort(const std::string& inputPortDSName, YACS::StreamType type) throw(Exception);
+ virtual OutputDataStreamPort *edAddOutputDataStreamPort(const std::string& outputPortDSName, YACS::StreamType type) throw(Exception);
+ //run part
+ void begin();
+ bool isReady();
+ void finished();
+ protected:
+ void disconnectAllLinksConnectedTo(Node *node);
+ };
+ }
+}
+
+#endif
--- /dev/null
+#include "Executor.hxx"
+#include "Task.hxx"
+#include "Scheduler.hxx"
+#include <pthread.h>
+#include <iostream>
+
+using namespace YACS::ENGINE;
+
+using YACS::BASES::Mutex;
+using YACS::BASES::Thread;
+using YACS::BASES::Semaphore;
+
+Executor::Executor():_nbOfConcurrentThreads(0)//,_cond(PTHREAD_COND_INITIALIZER)
+{
+}
+
+Executor::~Executor()
+{
+ for(std::list<Thread *>::iterator iter=_groupOfAllThreadsCreated.begin();iter!=_groupOfAllThreadsCreated.end();iter++)
+ delete *iter;
+}
+
+void Executor::RunW(Scheduler *graph)
+{
+ _mainSched=graph;
+ bool isMore;
+ int i=0;
+ graph->init();
+ std::vector<Task *> tasks;
+ std::vector<Task *>::iterator iter;
+ bool toContinue=true;
+ wakeUp();
+ while(toContinue)
+ {
+ sleepWhileNoEventsFromAnyRunningTask();
+ {//Critical section
+ _mutexForSchedulerUpdate.lock();
+ tasks=graph->getNextTasks(isMore);
+ graph->selectRunnableTasks(tasks);
+ _mutexForSchedulerUpdate.unlock();
+ }//End of critical section
+ for(iter=tasks.begin();iter!=tasks.end();iter++)
+ launchTask(*iter);
+ {//Critical section
+ _mutexForSchedulerUpdate.lock();
+ toContinue=!graph->isFinished();
+ _mutexForSchedulerUpdate.unlock();
+ }//End of critical section
+ i++;
+ }
+}
+
+void Executor::launchTask(Task *task)
+{
+ void **args=new void *[3];
+ _mutexForNbOfConcurrentThreads.lock();
+ _groupOfAllThreadsCreated.push_back(0);
+ std::list<Thread *>::iterator iter=_groupOfAllThreadsCreated.end();
+ iter--;
+ _mutexForNbOfConcurrentThreads.unlock();
+ args[0]=(void *)task;
+ args[1]=(void *)_mainSched;
+ args[2]=(void *)this;
+ {//Critical section
+ _mutexForSchedulerUpdate.lock();
+ task->begin();
+ _mainSched->notifyFrom(task,YACS::START);
+ _mutexForSchedulerUpdate.unlock();
+ }//End of critical section
+ _mutexForNbOfConcurrentThreads.lock();
+ //functionForTaskExecution(args);//MultiThreaded=NO
+ // *iter=
+ new Thread(functionForTaskExecution,args);//MultiThreaded=YES
+ _mutexForNbOfConcurrentThreads.unlock();
+}
+
+void Executor::sleepWhileNoEventsFromAnyRunningTask()
+{
+ _semForNewTasksToPerform.wait();
+}
+
+void Executor::notifyEndOfThread(YACS::BASES::Thread *thread)
+{
+ /*_mutexForNbOfConcurrentThreads.lock();
+ _groupOfAllThreadsCreated.remove(thread);
+ delete thread;
+ _mutexForNbOfConcurrentThreads.unlock();*/
+}
+
+void Executor::wakeUp()
+{
+ int val=_semForNewTasksToPerform.getValue();
+ if(!val)
+ _semForNewTasksToPerform.post();
+}
+
+int Executor::getNbOfThreads()
+{
+ int ret;
+ _mutexForNbOfConcurrentThreads.lock();
+ ret=_groupOfAllThreadsCreated.size();
+ _mutexForNbOfConcurrentThreads.unlock();
+ return ret;
+}
+
+void *Executor::functionForTaskExecution(void *arg)
+{
+ void **argT=(void **)arg;
+ Task *task=(Task *)argT[0];
+ Scheduler *sched=(Scheduler *)argT[1];
+ Executor *execInst=(Executor *)argT[2];
+ delete [] argT;
+ task->execute();
+ {//Critical section
+ execInst->_mutexForSchedulerUpdate.lock();
+ task->finished();
+ sched->notifyFrom(task,YACS::FINISH);
+ execInst->_mutexForSchedulerUpdate.unlock();
+ }//End of critical section
+ execInst->wakeUp();
+ execInst->notifyEndOfThread(0);
+ return 0;
+}
--- /dev/null
+#ifndef __EXECUTOR_HXX__
+#define __EXECUTOR_HXX__
+
+#include "Mutex.hxx"
+#include "Thread.hxx"
+#include "Semaphore.hxx"
+
+#include <list>
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ class Scheduler;
+ class Task;
+
+ class Executor
+ {
+ protected:
+ Scheduler *_mainSched;
+ int _nbOfConcurrentThreads;
+ YACS::BASES::Mutex _mutexForNbOfConcurrentThreads;
+ YACS::BASES::Semaphore _semForNewTasksToPerform;
+ YACS::BASES::Mutex _mutexForSchedulerUpdate;
+ pthread_cond_t _cond;
+ std::list< YACS::BASES::Thread * > _groupOfAllThreadsCreated;
+ public:
+ Executor();
+ ~Executor();
+ void RunW(Scheduler *graph);
+ int getNbOfThreads();
+ protected:
+ void launchTask(Task *task);
+ void wakeUp();
+ void sleepWhileNoEventsFromAnyRunningTask();
+ void notifyEndOfThread(YACS::BASES::Thread *thread);
+ protected:
+ static void *functionForTaskExecution(void *);
+ };
+ }
+}
+
+#endif
--- /dev/null
+#include "InGate.hxx"
+#include "Node.hxx"
+
+using namespace YACS::ENGINE;
+
+const char InGate::NAME[]="InGate";
+
+InGate::InGate(Node *node):Port(node),_nbPrecursor(0),_nbPrecursorDone(0),_colour(YACS::White)
+{
+}
+
+std::string InGate::getNameOfTypeOfCurrentInstance() const
+{
+ return NAME;
+}
+
+void InGate::exNotifyFromPrecursor()
+{
+ _nbPrecursorDone++;
+ if(exIsReady() && _node)
+ _node->exUpdateState();
+}
+
+void InGate::edAppendPrecursor()
+{
+ _nbPrecursor++;
+}
+
+void InGate::edRemovePrecursor()
+{
+ _nbPrecursor--;
+}
+
+void InGate::edSet(int nbOfPrecursors)
+{
+ _nbPrecursor=nbOfPrecursors;
+}
+
+void InGate::exReset()
+{
+ _nbPrecursorDone=0;
+}
+
+bool InGate::exIsReady() const
+{
+ return _nbPrecursor==_nbPrecursorDone;
+}
--- /dev/null
+#ifndef __INGATE_HXX__
+#define __INGATE_HXX__
+
+#include "Port.hxx"
+#include "define.hxx"
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ class InGate : public Port
+ {
+ friend class Bloc;
+ friend class Node;
+ protected:
+ int _nbPrecursor;
+ int _nbPrecursorDone;
+ static const char NAME[];
+ private:
+ //for graphs algs
+ mutable Colour _colour;
+ public:
+ InGate(Node *node);
+ std::string getNameOfTypeOfCurrentInstance() const;
+ void exNotifyFromPrecursor();
+ void edAppendPrecursor();
+ void edRemovePrecursor();
+ void edSet(int nbOfPrecursors);
+ void exReset();
+ bool exIsReady() const;
+ private:
+ void initForDFS() const { _colour=YACS::White; }
+ };
+ }
+}
+
+#endif
--- /dev/null
+#include "InPort.hxx"
+
+using namespace YACS::ENGINE;
+
+InPort::InPort(Node *node):Port(node)
+{
+}
--- /dev/null
+#ifndef __INPORT_HXX__
+#define __INPORT_HXX__
+
+#include "Port.hxx"
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ class InPort : public virtual Port
+ {
+ protected:
+ InPort(Node *node);
+ };
+ }
+}
+
+#endif
--- /dev/null
+#include "InputDataStreamPort.hxx"
+
+using namespace YACS::ENGINE;
+
+const char InputDataStreamPort::NAME[]="InputDataStreamPort";
+
+InputDataStreamPort::InputDataStreamPort(const std::string& name, Node *node, StreamType type):DataStreamPort(name,node,type),
+ InPort(node),
+ Port(node)
+{
+}
+
+std::string InputDataStreamPort::getNameOfTypeOfCurrentInstance() const
+{
+ return NAME;
+}
--- /dev/null
+#ifndef __INPUTDATASTREAMPORT_HXX__
+#define __INPUTDATASTREAMPORT_HXX__
+
+#include "InPort.hxx"
+#include "DataStreamPort.hxx"
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ class InputDataStreamPort : public DataStreamPort, public InPort
+ {
+ public:
+ static const char NAME[];
+ public:
+ InputDataStreamPort(const std::string& name, Node *node, StreamType type);
+ std::string getNameOfTypeOfCurrentInstance() const;
+ };
+ }
+}
+
+#endif
--- /dev/null
+#include "InputPort.hxx"
+
+using namespace YACS::ENGINE;
+
+const char InputPort::NAME[]="InputPort";
+
+InputPort::InputPort(const std::string& name, Node *node, DynType type):DataFlowPort(name,node,type),InPort(node),Port(node),_manuallySet(false)
+{
+}
+
+std::string InputPort::getNameOfTypeOfCurrentInstance() const
+{
+ return NAME;
+}
+
+void InputPort::edInit(Data data) throw(ConversionException)
+{
+ _data=data;
+ _manuallySet=true;
+}
+
+void InputPort::edNotifyReferenced()
+{
+ _manuallySet=false;
+}
+
+void InputPort::exInit()
+{
+ if(!_manuallySet)
+ _data.exInit();
+}
+
+Data InputPort::exGet() const
+{
+ return _data;
+}
+
+void InputPort::exAccept(Data data) throw(ConversionException)
+{
+ _data=data;
+}
+
+InputPort::~InputPort()
+{
+}
--- /dev/null
+#ifndef __INPUTPORT_HXX__
+#define __INPUTPORT_HXX__
+
+#include "InPort.hxx"
+#include "DataFlowPort.hxx"
+#include "ConversionException.hxx"
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ class InputPort : public DataFlowPort, public InPort
+ {
+ protected:
+ bool _manuallySet;
+ public:
+ static const char NAME[];
+ public:
+ InputPort(const std::string& name, Node *node, DynType type);
+ std::string getNameOfTypeOfCurrentInstance() const;
+ void edInit(Data data) throw(ConversionException);
+ void edNotifyReferenced();
+ void exInit();
+ Data exGet() const;
+ void exAccept(Data data) throw(ConversionException);
+ ~InputPort();
+ };
+ }
+}
+
+#endif
--- /dev/null
+#include "Loop.hxx"
+#include "InputPort.hxx"
+#include "OutputPort.hxx"
+#include "InputDataStreamPort.hxx"
+#include "OutputDataStreamPort.hxx"
+#include "TypeCheckerDataStream.hxx"
+
+using namespace YACS::ENGINE;
+
+DFToDSForLoop::DFToDSForLoop(Loop *loop, const std::string& name, YACS::DynType type):ElementaryNode(""),_nbOfTimeUsed(1)
+{
+ _name="DF2DS For "; _name+=loop->getName(); _name+=" representing port "; _name+=name;
+ _father=loop;
+ _listOfInputPort.push_back(new InputPort("",this,type));
+ _listOfOutputDataStreamPort.push_back(new OutputDataStreamPort("",this,Loop::MappingDF2DS(type)));
+}
+
+DFToDSForLoop::~DFToDSForLoop()
+{
+}
+
+InputPort *DFToDSForLoop::getInputPort(const std::string& name) const throw(Exception)
+{
+ return (InputPort *) &_listOfInputPort.back();
+}
+
+OutputDataStreamPort *DFToDSForLoop::getOutputDataStreamPort(const std::string& name) const throw(Exception)
+{
+ return (OutputDataStreamPort *) &_listOfOutputDataStreamPort.back();
+}
+
+void DFToDSForLoop::execute()
+{
+ //TO IMPLEMENT
+}
+
+DSToDFForLoop::DSToDFForLoop(Loop *loop, const std::string& name, YACS::StreamType type):ElementaryNode(""),_nbOfTimeUsed(1)
+{
+ _name="DS2DF For "; _name+=loop->getName(); _name+=" representing port "; _name+=name;
+ _father=loop;
+ _listOfOutputPort.push_back(new OutputPort("",this,Loop::MappingDS2DF(type)));
+ _listOfInputDataStreamPort.push_back(new InputDataStreamPort("",this,type));
+}
+
+DSToDFForLoop::~DSToDFForLoop()
+{
+}
+
+OutputPort *DSToDFForLoop::getOutputPort(const std::string& name) const throw(Exception)
+{
+ return (OutputPort *) &_listOfOutputPort.back();
+}
+
+InputDataStreamPort *DSToDFForLoop::getInputDataStreamPort(const std::string& name) const throw(Exception)
+{
+ return (InputDataStreamPort *) &_listOfInputDataStreamPort.back();
+}
+
+void DSToDFForLoop::execute()
+{
+ //TO IMPLEMENT
+}
+
+Loop::Loop(const std::string& name):ComposedNode(name),_node(0)
+{
+}
+
+Loop::~Loop()
+{
+ delete _node;
+}
+
+void Loop::edSetNode(Node *node)
+{
+ delete _node;
+ _node=node;
+}
+
+void Loop::edAddExtraInputPort(const std::string& inputPortName, YACS::DynType type) throw(Exception)
+{
+ edAddPort<InputPort,YACS::DynType>(inputPortName,_listOfExtraInputPort,type);
+}
+
+void Loop::edRemoveExtraInputPort(InputPort *inputPort)
+{
+ edRemovePortTypedFromList<InputPort>(inputPort,_listOfExtraInputPort);
+}
+
+YACS::StreamType Loop::MappingDF2DS(YACS::DynType type) throw(Exception)
+{
+ switch(type)
+ {
+ case Double:
+ return SDouble;
+ }
+ std::string what("Loop::MappingDF2DS : unable to perform DataFlow to DataStream traduction for dataflow type ");
+ what+=Data::edGetTypeInPrintableForm(type);
+ throw Exception(what);
+}
+
+YACS::DynType Loop::MappingDS2DF(YACS::StreamType type) throw(Exception)
+{
+ switch(type)
+ {
+ case SDouble:
+ return Double;
+ }
+ std::string what("Loop::MappingDS2DF : unable to perform DataStream to DataFlow traduction for datastream type ");
+ what+=TypeCheckerDataStream::edGetTypeInPrintableForm(type);
+ throw Exception(what);
+}
+
+InPort *Loop::buildDelegateOf(InPort *port, const std::list<ComposedNode *>& pointsOfView)
+{
+ std::string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
+ if(typeOfPortInstance!=InputPort::NAME)
+ return port;
+ else
+ if(!isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView))
+ return port;
+ InputPort *portCasted=(InputPort *)port;
+ std::list<DSToDFForLoop>::iterator iter;
+ //Determinig if a DSToDFForLoop node has already been created for delegation of 'port'
+ for(iter=_inputsTraducer.begin();iter!=_inputsTraducer.end();iter++)
+ if((*iter).getOutputPort("")->isAlreadyInList(portCasted))
+ break;
+ if(iter==_inputsTraducer.end())
+ {//first time that 'port' is delegated on higher level
+ _inputsTraducer.push_back(DSToDFForLoop(this,portCasted->getName(),Loop::MappingDF2DS(portCasted->edGetType())));
+ iter=_inputsTraducer.end(); iter--;
+ (*iter).getOutputPort("")->edAddInputPort(portCasted);
+ //WARNING control flow has to be added
+ (*iter).getOutGate()->edAddInGate(portCasted->getNode()->getInGate());//WARNING HERE MAYBE HAS TO BE IMPROVED - SEPARATE COUNTERS
+ }
+ else
+ (*iter).loopHasOneMoreRef();
+ return (*iter).getInputDataStreamPort("");
+}
+
+OutPort *Loop::buildDelegateOf(OutPort *port, const std::list<ComposedNode *>& pointsOfView)
+{
+ std::string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
+ if(typeOfPortInstance!=OutputPort::NAME)
+ return port;
+ else
+ if(!isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView))
+ return port;
+ OutputPort *portCasted=(OutputPort *)port;
+ std::list<DFToDSForLoop>::iterator iter;
+ //Determinig if a DFToDSForLoop node has already been created for delegation of 'port'
+ for(iter=_outputsTraducer.begin();iter!=_outputsTraducer.end();iter++)
+ if(portCasted->isAlreadyInList((*iter).getInputPort("")))
+ break;
+ if(iter==_outputsTraducer.end())
+ {//first time that 'port' is delegated on higher level
+ _outputsTraducer.push_back(DFToDSForLoop(this,portCasted->getName(),portCasted->edGetType()));
+ iter=_outputsTraducer.end(); iter--;
+ portCasted->edAddInputPort((*iter).getInputPort(""));
+ //WARNING control flow has to be added
+ portCasted->getNode()->getOutGate()->edAddInGate((*iter).getInGate());//WARNING HERE MAYBE HAS TO BE IMPROVED - SEPARATE COUNTERS
+ }
+ else
+ (*iter).loopHasOneMoreRef();
+ return (*iter).getOutputDataStreamPort("");
+}
+
+InPort *Loop::getDelegateOf(InPort *port, const std::list<ComposedNode *>& pointsOfView) throw(Exception)
+{
+ std::string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
+ if(typeOfPortInstance!=InputPort::NAME)
+ return port;
+ else
+ if(!isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView))
+ return port;
+ InputPort *portCasted=(InputPort *)port;
+ std::list<DSToDFForLoop>::iterator iter;
+ for(iter=_inputsTraducer.begin();iter!=_inputsTraducer.end();iter++)
+ if((*iter).getOutputPort("")->isAlreadyInList(portCasted))
+ break;
+ if(iter==_inputsTraducer.end())
+ {
+ std::string what("Loop::getDelegateOf Port with name "); what+=portCasted->getName(); what+=" not exported by loop "; what+=_name;
+ throw Exception(what);
+ }
+ else
+ return (*iter).getInputDataStreamPort("");
+}
+
+OutPort *Loop::getDelegateOf(OutPort *port, const std::list<ComposedNode *>& pointsOfView) throw(Exception)
+{
+ std::string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
+ if(typeOfPortInstance!=OutputPort::NAME)
+ return port;
+ else
+ if(!isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView))
+ return port;
+ OutputPort *portCasted=(OutputPort *)port;
+ std::list<DFToDSForLoop>::iterator iter;
+ for(iter=_outputsTraducer.begin();iter!=_outputsTraducer.end();iter++)
+ if(portCasted->isAlreadyInList((*iter).getInputPort("")))
+ break;
+ if(iter==_outputsTraducer.end())
+ {
+ std::string what("Loop::getDelegateOf Port with name "); what+=portCasted->getName(); what+=" not exported by loop "; what+=_name;
+ throw Exception(what);
+ }
+ else
+ return (*iter).getOutputDataStreamPort("");
+}
+
+InPort *Loop::releaseDelegateOf(InPort *port, const std::list<ComposedNode *>& pointsOfView) throw(Exception)
+{
+ std::string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
+ if(typeOfPortInstance!=InputPort::NAME)
+ return port;
+ else
+ if(!isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView))
+ return port;
+ InputPort *portCasted=(InputPort *)port;
+ std::list<DSToDFForLoop>::iterator iter;
+ for(iter=_inputsTraducer.begin();iter!=_inputsTraducer.end();iter++)
+ if((*iter).getOutputPort("")->isAlreadyInList(portCasted))
+ break;
+ if(iter==_inputsTraducer.end())
+ {
+ std::string what("Loop::releaseDelegateOf Port with name "); what+=portCasted->getName(); what+=" not exported by loop "; what+=_name;
+ throw Exception(what);
+ }
+ else
+ {
+ InPort *ret=(*iter).getInputDataStreamPort("");
+ if((*iter).loopHasOneLessRef())
+ _inputsTraducer.erase(iter);
+ return ret;
+ }
+}
+
+OutPort *Loop::releaseDelegateOf(OutPort *port, const std::list<ComposedNode *>& pointsOfView) throw(Exception)
+{
+ std::string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
+ if(typeOfPortInstance!=OutputPort::NAME)
+ return port;
+ else
+ if(!isNecessaryToBuildSpecificDelegateDF2DS(pointsOfView))
+ return port;
+ OutputPort *portCasted=(OutputPort *)port;
+ std::list<DFToDSForLoop>::iterator iter;
+ for(iter=_outputsTraducer.begin();iter!=_outputsTraducer.end();iter++)
+ if(portCasted->isAlreadyInList((*iter).getInputPort("")))
+ break;
+ if(iter==_outputsTraducer.end())
+ {
+ std::string what("Loop::releaseDelegateOf Port with name "); what+=portCasted->getName(); what+=" not exported by loop "; what+=_name;
+ throw Exception(what);
+ }
+ else
+ {
+ OutPort *ret=(*iter).getOutputDataStreamPort("");
+ if((*iter).loopHasOneLessRef())
+ _outputsTraducer.erase(iter);
+ return ret;
+ }
+}
+
+void Loop::checkNoCyclePassingThrough(Node *node) throw(Exception)
+{
+ throw Exception("Loop::checkNoCyclePassingThrough : Internal error occured");
+}
+
+/**
+ * @ note : States if a DF port must be considered on an upper level in hierarchy as a DS port or not from 'pointsOfView' observers.
+ * @ return :
+ * - True : a traduction DF->DS has to be done
+ * - False : no traduction needed
+ */
+bool Loop::isNecessaryToBuildSpecificDelegateDF2DS(const std::list<ComposedNode *>& pointsOfView)
+{
+ bool ret=false;
+ for(std::list<ComposedNode *>::const_iterator iter=pointsOfView.begin();iter!=pointsOfView.end() && !ret;iter++)
+ ret=(*iter)->isRepeatedUnpredictablySeveralTimes();
+ return ret;
+}
--- /dev/null
+#ifndef __LOOP_HXX__
+#define __LOOP_HXX__
+
+#include "ComposedNode.hxx"
+#include "ElementaryNode.hxx"
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ class Loop;
+
+ class DFToDSForLoop : public ElementaryNode
+ {
+ friend class Loop;
+ private:
+ int _nbOfTimeUsed;
+ Loop *_loopArtificiallyBuiltMe;
+ private:
+ DFToDSForLoop(Loop *loop, const std::string& name, YACS::DynType type);
+ void loopHasOneMoreRef() { _nbOfTimeUsed++; }
+ bool loopHasOneLessRef() { return --_nbOfTimeUsed==0; }
+ InputPort *getInputPort(const std::string& name) const throw(Exception);
+ OutputDataStreamPort *getOutputDataStreamPort(const std::string& name) const throw(Exception);
+ //run part
+ void execute();
+ public:
+ ~DFToDSForLoop();
+ };
+
+ class DSToDFForLoop : public ElementaryNode
+ {
+ friend class Loop;
+ private:
+ int _nbOfTimeUsed;
+ Loop *_loopArtificiallyBuiltMe;
+ private:
+ DSToDFForLoop(Loop *loop, const std::string& name, YACS::StreamType type);
+ void loopHasOneMoreRef() { _nbOfTimeUsed++; }
+ bool loopHasOneLessRef() { return --_nbOfTimeUsed==0; }
+ OutputPort *getOutputPort(const std::string& name) const throw(Exception);
+ InputDataStreamPort *getInputDataStreamPort(const std::string& name) const throw(Exception);
+ //run part
+ void execute();
+ public:
+ ~DSToDFForLoop();
+ };
+
+ class Loop : public ComposedNode
+ {
+ protected:
+ Node *_node;
+ std::list<InputPort *> _listOfExtraInputPort;
+ std::list<DSToDFForLoop> _inputsTraducer;
+ std::list<DFToDSForLoop> _outputsTraducer;
+ public:
+ Loop(const std::string& name);
+ ~Loop();
+ void edSetNode(Node *node);
+ void edAddExtraInputPort(const std::string& inputPortName, YACS::DynType type) throw(Exception);
+ void edRemoveExtraInputPort(InputPort *inputPort);
+ bool isRepeatedUnpredictablySeveralTimes() const { return true; }
+ static YACS::StreamType MappingDF2DS(YACS::DynType type) throw(Exception);
+ static YACS::DynType MappingDS2DF(YACS::StreamType type) throw(Exception);
+ protected:
+ InPort *buildDelegateOf(InPort *port, const std::list<ComposedNode *>& pointsOfView);
+ OutPort *buildDelegateOf(OutPort *port, const std::list<ComposedNode *>& pointsOfView);
+ InPort *getDelegateOf(InPort *port, const std::list<ComposedNode *>& pointsOfView) throw(Exception);
+ OutPort *getDelegateOf(OutPort *port, const std::list<ComposedNode *>& pointsOfView) throw(Exception);
+ InPort *releaseDelegateOf(InPort *port, const std::list<ComposedNode *>& pointsOfView) throw(Exception);
+ OutPort *releaseDelegateOf(OutPort *port, const std::list<ComposedNode *>& pointsOfView) throw(Exception);
+ void checkNoCyclePassingThrough(Node *node) throw(Exception);
+ static bool isNecessaryToBuildSpecificDelegateDF2DS(const std::list<ComposedNode *>& pointsOfView);
+ };
+ }
+}
+
+#endif
--- /dev/null
+
+include $(top_srcdir)/adm/unix/make_begin.am
+
+SUBDIRS = Test
+
+lib_LTLIBRARIES = libYACSEngine.la
+
+libYACSEngine_la_SOURCES = \
+ Port.cxx InGate.cxx \
+ OutGate.cxx \
+ DataFlowPort.cxx \
+ InPort.cxx \
+ OutPort.cxx \
+ InputPort.cxx \
+ OutputPort.cxx \
+ DataStreamPort.cxx \
+ InputDataStreamPort.cxx \
+ OutputDataStreamPort.cxx \
+ Node.cxx \
+ ElementaryNode.cxx \
+ ComposedNode.cxx \
+ Bloc.cxx \
+ Loop.cxx \
+ Switch.cxx \
+ Scheduler.hxx \
+ Task.hxx \
+ Executor.cxx \
+ $(__dummy__)
+
+EXTRA_libYACSEngine_la_SOURCES = \
+ $(__dummy__)
+
+libYACSEngine_la_LIBADD = ../bases/libYACSBases.la \
+ ../basicData/libYACSBasicData.la
+
+AM_CXXFLAGS = $(THREAD_DEF) \
+ -I$(srcdir)/../bases \
+ -I$(srcdir)/../basicData
+
+include $(top_srcdir)/adm/unix/make_end.am
--- /dev/null
+#include "Node.hxx"
+#include "InputPort.hxx"
+#include "OutputPort.hxx"
+#include "ComposedNode.hxx"
+#include "InputDataStreamPort.hxx"
+#include "OutputDataStreamPort.hxx"
+
+using namespace YACS::ENGINE;
+
+Node::Node(const std::string& name):_name(name),_inGate(this),_outGate(this),_father(0),_colour(YACS::White),_state(YACS::INITED)
+{
+}
+
+Node::~Node()
+{
+}
+
+void Node::init()
+{
+ _inGate.exReset();
+ for(std::list<OutputPort *>::iterator iter=_listOfOutputPort.begin();iter!=_listOfOutputPort.end();iter++)
+ (*iter)->exInit();
+ for(std::list<InputPort *>::iterator iter2=_listOfInputPort.begin();iter2!=_listOfInputPort.end();iter2++)
+ (*iter2)->exInit();
+ if(_inGate.exIsReady())
+ _state=YACS::TOACTIVATE;
+ else
+ _state=YACS::INITED;
+}
+
+std::list<Node *> Node::getOutNodes() const
+{
+ std::list<Node *> ret;
+ std::list<InGate *> inGates=_outGate.edListInGate();
+ for(std::list<InGate *>::iterator iter=inGates.begin();iter!=inGates.end();iter++)
+ ret.push_back((*iter)->getNode());
+ return ret;
+}
+
+/**
+ * @ note : Update the '_state' attribute.
+ * Typically called by 'this->_inGate' when 'this->_inGate' is ready.
+ */
+void Node::exUpdateState()
+{
+ if(_inGate.exIsReady())
+ if(areAllInputPortsValid())
+ _state=YACS::TOACTIVATE;
+ else
+ {
+ std::string what("Node::exUpdateState : Invalid graph given : Node with name \"");
+ what+=_name; what+="\" ready to run whereas some inputports are not set correctly\nCheck coherence DF/CF";
+ throw Exception(what);
+ }
+}
+
+int Node::getNumberOfInputPorts() const
+{
+ return _listOfInputPort.size();
+}
+
+int Node::getNumberOfOutputPorts() const
+{
+ return _listOfOutputPort.size();
+}
+
+InputPort *Node::getInputPort(const std::string& name) const throw(Exception)
+{
+ return getPort<InputPort>(name,_listOfInputPort);
+}
+
+OutputPort *Node::getOutputPort(const std::string& name) const throw(Exception)
+{
+ return getPort<OutputPort>(name,_listOfOutputPort);
+}
+
+InputDataStreamPort *Node::getInputDataStreamPort(const std::string& name) const throw(Exception)
+{
+ return getPort<InputDataStreamPort>(name,_listOfInputDataStreamPort);
+}
+
+OutputDataStreamPort *Node::getOutputDataStreamPort(const std::string& name) const throw(Exception)
+{
+ return getPort<OutputDataStreamPort>(name,_listOfOutputDataStreamPort);
+}
+
+std::list<ComposedNode *> Node::getAllAscendanceOf(ComposedNode *levelToStop)
+{
+ std::list<ComposedNode *> ret;
+ for(ComposedNode *iter=_father;iter!=levelToStop && iter!=0; iter=iter->_father)
+ ret.push_back(iter);
+ return ret;
+}
+
+bool Node::areAllInputPortsValid() const
+{
+ bool ret=true;
+ for(std::list<InputPort *>::const_iterator iter=_listOfInputPort.begin();iter!=_listOfInputPort.end();iter++)
+ ret=!(*iter)->exGet().empty();
+ return ret;
+}
+
+ComposedNode *Node::getRootNode() throw(Exception)
+{
+ if(!_father)
+ throw Exception("No root node");
+ ComposedNode *iter=_father;
+ while(iter->_father)
+ iter=iter->_father;
+ return iter;
+}
+
+void Node::checkValidityOfPortName(const std::string& name) throw(Exception)
+{
+ if(name.find(SEP_CHAR_IN_PORT, 0 )!=std::string::npos)
+ {
+ std::string what("Port name "); what+=name; what+="not valid because it contains character "; what+=SEP_CHAR_IN_PORT;
+ throw Exception(what);
+ }
+}
+
+/**
+ * @ note : Check that 'node1' and 'node2' have exactly the same father
+ * @ exception : If 'node1' and 'node2' have NOT exactly the same father
+ */
+ComposedNode *Node::checkHavingCommonFather(Node *node1, Node *node2) throw(Exception)
+{
+ if(node1!=0 && node2!=0)
+ {
+ if(node1->_father==node2->_father)
+ return node1->_father;
+ }
+ throw Exception("check failed : nodes have not the same father");
+}
+
+void Node::initForDFS() const
+{
+ _colour=YACS::White;
+ std::list<InGate *> inGates=_outGate.edListInGate();
+ for(std::list<InGate *>::iterator iter=inGates.begin();iter!=inGates.end();iter++)
+ (*iter)->initForDFS();
+}
--- /dev/null
+#ifndef __NODE_HXX__
+#define __NODE_HXX__
+
+#include "define.hxx"
+#include "InGate.hxx"
+#include "OutGate.hxx"
+#include "Exception.hxx"
+
+#include <list>
+#include <string>
+#include <vector>
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ class Task;
+ class InputPort;
+ class OutputPort;
+ class ComposedNode;
+ class ElementaryNode;
+ class InputDataStreamPort;
+ class OutputDataStreamPort;
+
+ class Node
+ {
+ friend class Bloc;
+ friend class ComposedNode;
+ friend class ElementaryNode;
+ protected:
+ InGate _inGate;
+ OutGate _outGate;
+ std::string _name;
+ ComposedNode *_father;
+ YACS::StatesForNode _state;
+ std::list<InputPort *> _listOfInputPort;
+ std::list<OutputPort *> _listOfOutputPort;
+ std::list<InputDataStreamPort *> _listOfInputDataStreamPort;
+ std::list<OutputDataStreamPort *> _listOfOutputDataStreamPort;
+ static const char SEP_CHAR_IN_PORT='?';
+ private:
+ //for graphs algorithms
+ mutable YACS::Colour _colour;
+ protected:
+ Node(const std::string& name);
+ public:
+ virtual ~Node();
+ virtual void init();
+ InGate *getInGate() { return &_inGate; }
+ OutGate *getOutGate() { return &_outGate; }
+ const std::string& getName() const { return _name; }
+ std::list<Node *> getOutNodes() const;
+ virtual void exUpdateState();
+ virtual void getReadyTasks(std::vector<Task *>& tasks) = 0;
+ virtual std::list<ElementaryNode *> getRecursiveConstituents() = 0;
+ virtual int getNumberOfInputPorts() const;
+ virtual int getNumberOfOutputPorts() const;
+ virtual std::list<InputPort *> getListOfInputPort() const { return _listOfInputPort; }
+ virtual std::list<OutputPort *> getListOfOutputPort() const { return _listOfOutputPort; }
+ virtual InputPort *getInputPort(const std::string& name) const throw(Exception);
+ virtual OutputPort *getOutputPort(const std::string& name) const throw(Exception);
+ virtual std::list<InputDataStreamPort *> getListOfInputDataStreamPort() const { return _listOfInputDataStreamPort; }
+ virtual std::list<OutputDataStreamPort *> getListOfOutputDataStreamPort() const { return _listOfOutputDataStreamPort; }
+ virtual InputDataStreamPort *getInputDataStreamPort(const std::string& name) const throw(Exception);
+ virtual OutputDataStreamPort *getOutputDataStreamPort(const std::string& name) const throw(Exception);
+ std::list<ComposedNode *> getAllAscendanceOf(ComposedNode *levelToStop = 0);
+ protected:
+ bool areAllInputPortsValid() const;
+ virtual ComposedNode *getRootNode() throw(Exception);
+ virtual void disconnectAllLinksConnectedTo(Node *node) = 0;
+ static void checkValidityOfPortName(const std::string& name) throw(Exception);
+ static ComposedNode *checkHavingCommonFather(Node *node1, Node *node2) throw(Exception);
+ template<class PORT>
+ PORT *getPort(const std::string& name, const std::list<PORT *>& listOfPorts) const throw(Exception);
+ template<class PORT, class ENUMTYPE>
+ PORT *edAddPort(const std::string& portName, std::list<PORT *>& listOfPorts, ENUMTYPE type) throw(Exception);
+ template<class PORT>
+ static void edRemovePortTypedFromList(PORT *port, std::list<PORT *>& listOfPorts) throw(Exception);
+ template<class PORT>
+ static bool isPortNameAlreadyExist(const std::string& portName, const std::list<PORT *>& listOfPorts);
+ private:
+ void initForDFS() const;
+ };
+
+ template<class PORT>
+ PORT *Node::getPort(const std::string& name, const std::list<PORT *>& listOfPorts) const throw(Exception)
+ {
+ for(typename std::list<PORT *>::const_iterator iter=listOfPorts.begin();iter!=listOfPorts.end();iter++)
+ {
+ if((*iter)->getName()==name)
+ return *iter;
+ }
+ std::string what="Node::getPort : unexisting "; what+=PORT::NAME;
+ what+=" with name ";
+ what+=name;
+ throw Exception(what);
+ }
+
+ template<class PORT, class ENUMTYPE>
+ PORT *Node::edAddPort(const std::string& portName, std::list<PORT *>& listOfPorts, ENUMTYPE type) throw(Exception)
+ {
+ checkValidityOfPortName(portName);
+ if(isPortNameAlreadyExist<PORT>(portName, listOfPorts))
+ {
+ std::string what="Port of type "; what+=PORT::NAME; what += " with name : "; what+=portName; what+=" already exists";
+ throw Exception(what);
+ }
+ PORT *ret=new PORT(portName,this,type);
+ listOfPorts.push_back(ret);
+ return ret;
+ }
+
+ template<class PORT>
+ void Node::edRemovePortTypedFromList(PORT *port, std::list<PORT *>& listOfPorts) throw(Exception)
+ {
+ if(!isPortNameAlreadyExist<PORT>(port->getName(), listOfPorts))
+ throw Exception("Port is not part of the list : unable to remove it");
+ listOfPorts.remove(port);
+ }
+
+ template<class PORT>
+ bool Node::isPortNameAlreadyExist(const std::string& portName, const std::list<PORT *>& listOfPorts)
+ {
+ for(typename std::list<PORT *>::const_iterator iter=listOfPorts.begin();iter!=listOfPorts.end();iter++)
+ {
+ if((*iter)->getName()==portName)
+ return true;
+ }
+ return false;
+ }
+ }
+}
+
+#endif
--- /dev/null
+#include "OutGate.hxx"
+#include "InGate.hxx"
+
+using namespace YACS::ENGINE;
+using namespace std;
+
+const char OutGate::NAME[]="OutGate";
+
+OutGate::OutGate(Node *node):Port(node)
+{
+}
+
+std::string OutGate::getNameOfTypeOfCurrentInstance() const
+{
+ return NAME;
+}
+
+void OutGate::exNotifyDone()
+{
+ for(list<InGate *>::iterator iter=_listOfInGate.begin();iter!=_listOfInGate.end();iter++)
+ (*iter)->exNotifyFromPrecursor();
+}
+
+bool OutGate::edAddInGate(InGate *inGate)
+{
+ if(!isAlreadyInList(inGate))
+ {
+ inGate->edAppendPrecursor();
+ _listOfInGate.push_back(inGate);
+ return true;
+ }
+ else
+ return false;
+}
+
+std::list<InGate *> OutGate::edListInGate() const
+{
+ return _listOfInGate;
+}
+
+void OutGate::edRemoveInGate(InGate *inGate) throw(Exception)
+{
+ bool found=false;
+ for(list<InGate *>::iterator iter=_listOfInGate.begin();iter!=_listOfInGate.end() && !found;iter++)
+ if((*iter)==inGate)
+ {
+ _listOfInGate.erase(iter);
+ inGate->edRemovePrecursor();
+ found=true;
+ }
+ if(!found)
+ throw Exception("InGate not already connected to OutGate");
+}
+
+bool OutGate::isAlreadyInList(InGate *inGate) const
+{
+ bool ret=false;
+ for(list<InGate *>::const_iterator iter=_listOfInGate.begin();iter!=_listOfInGate.end() && !ret;iter++)
+ if((*iter)==inGate)
+ ret=true;
+ return ret;
+}
+
+int OutGate::getNbOfInGatesConnected() const
+{
+ return _listOfInGate.size();
+}
--- /dev/null
+#ifndef __OUTGATE_HXX__
+#define __OUTGATE_HXX__
+
+#include "Port.hxx"
+#include "Exception.hxx"
+
+#include <list>
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ class InGate;
+
+ class OutGate : public Port
+ {
+ protected:
+ std::list<InGate *> _listOfInGate;
+ public:
+ static const char NAME[];
+ public:
+ OutGate(Node *node);
+ std::string getNameOfTypeOfCurrentInstance() const;
+ void exNotifyDone();
+ bool edAddInGate(InGate *inGate);
+ std::list<InGate *> edListInGate() const;
+ void edRemoveInGate(InGate *inGate) throw(Exception);
+ int getNbOfInGatesConnected() const;
+ protected:
+ bool isAlreadyInList(InGate *inGate) const;
+ };
+ }
+}
+
+#endif
--- /dev/null
+#include "OutPort.hxx"
+
+using namespace YACS::ENGINE;
+
+OutPort::OutPort(Node *node):Port(node)
+{
+}
--- /dev/null
+#ifndef __OUTPORT_HXX__
+#define __OUTPORT_HXX__
+
+#include "Port.hxx"
+#include "Exception.hxx"
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ class InPort;
+ class OutPort : public virtual Port
+ {
+ protected:
+ OutPort(Node *node);
+ public:
+ virtual bool addInPort(InPort *inPort) throw(Exception) = 0;
+ virtual void removeInPort(InPort *inPort) throw(Exception) = 0;
+ };
+ }
+}
+
+#endif
--- /dev/null
+#include "OutputDataStreamPort.hxx"
+#include "InputDataStreamPort.hxx"
+#include "TypeCheckerDataStream.hxx"
+
+using namespace YACS::ENGINE;
+
+const char OutputDataStreamPort::NAME[]="OutputDataStreamPort";
+
+OutputDataStreamPort::OutputDataStreamPort(const std::string& name, Node *node, StreamType type):DataStreamPort(name,node,type),OutPort(node),Port(node)
+{
+}
+
+std::string OutputDataStreamPort::getNameOfTypeOfCurrentInstance() const
+{
+ return NAME;
+}
+
+bool OutputDataStreamPort::edAddInputDataStreamPort(InputDataStreamPort *port) throw(ConversionException)
+{
+ if(!TypeCheckerDataStream::areStaticallyCompatible(edGetType(),port->edGetType()))
+ throw ConversionException(TypeCheckerDataStream::edGetTypeInPrintableForm(edGetType()),TypeCheckerDataStream::edGetTypeInPrintableForm(port->edGetType()));
+ if(!isAlreadyInList(port))
+ {
+ _listOfInputDataStreamPort.push_back(port);
+ return true;
+ }
+ else
+ return false;
+}
+
+void OutputDataStreamPort::edRemoveInputDataStreamPort(InputDataStreamPort *inputPort)
+{
+ if(isAlreadyInList(inputPort))
+ _listOfInputDataStreamPort.remove(inputPort);
+}
+
+bool OutputDataStreamPort::addInPort(InPort *inPort) throw(Exception)
+{
+}
+
+void OutputDataStreamPort::removeInPort(InPort *inPort) throw(Exception)
+{
+}
+
+bool OutputDataStreamPort::isLinked()
+{
+ return _listOfInputDataStreamPort.empty();
+}
+
+bool OutputDataStreamPort::isAlreadyInList(InputDataStreamPort *inputPort) const
+{
+ bool ret=false;
+ for(std::list<InputDataStreamPort *>::const_iterator iter=_listOfInputDataStreamPort.begin();iter!=_listOfInputDataStreamPort.end();iter++)
+ if((*iter)==inputPort)
+ ret=true;
+ return ret;
+}
--- /dev/null
+#ifndef __OUTPUTDATASTREAMPORT_HXX__
+#define __OUTPUTDATASTREAMPORT_HXX__
+
+#include "OutPort.hxx"
+#include "DataStreamPort.hxx"
+#include "ConversionException.hxx"
+
+#include <list>
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ class InputDataStreamPort;
+
+ class OutputDataStreamPort : public DataStreamPort, public OutPort
+ {
+ protected:
+ std::list<InputDataStreamPort *> _listOfInputDataStreamPort;
+ public:
+ static const char NAME[];
+ public:
+ OutputDataStreamPort(const std::string& name, Node *node, StreamType type);
+ std::string getNameOfTypeOfCurrentInstance() const;
+ bool edAddInputDataStreamPort(InputDataStreamPort *port) throw(ConversionException);
+ void edRemoveInputDataStreamPort(InputDataStreamPort *inputPort);
+ bool addInPort(InPort *inPort) throw(Exception);
+ void removeInPort(InPort *inPort) throw(Exception);
+ bool isLinked();
+ private:
+ bool isAlreadyInList(InputDataStreamPort *inputPort) const;
+ };
+ }
+}
+
+#endif
--- /dev/null
+#include "OutputPort.hxx"
+#include "InputPort.hxx"
+
+using namespace YACS::ENGINE;
+using namespace std;
+
+const char OutputPort::NAME[]="OutputPort";
+
+OutputPort::OutputPort(const std::string& name, Node *node, DynType type):DataFlowPort(name,node,type),OutPort(node),Port(node)
+{
+}
+
+std::string OutputPort::getNameOfTypeOfCurrentInstance() const
+{
+ return NAME;
+}
+
+Data OutputPort::foGet() const
+{
+ return _data;
+}
+
+void OutputPort::exInit()
+{
+ _data.exInit();
+}
+
+void OutputPort::exPut(Data data) throw(ConversionException)
+{
+ _data=data;
+ for(list<InputPort *>::iterator iter=_listOfInputPort.begin();iter!=_listOfInputPort.end();iter++)
+ (*iter)->exAccept(data);
+}
+
+bool OutputPort::edAddInputPort(InputPort *inputPort) throw(ConversionException)
+{
+ if(!Data::areStaticallyCompatible(edGetType(),inputPort->edGetType()))
+ throw ConversionException(Data::edGetTypeInPrintableForm(edGetType()),Data::edGetTypeInPrintableForm(inputPort->edGetType()));
+ if(!isAlreadyInList(inputPort))
+ {
+ _listOfInputPort.push_back(inputPort);
+ inputPort->edNotifyReferenced();
+ return true;
+ }
+ else
+ return false;
+}
+
+list<InputPort *> OutputPort::edListInputPort()
+{
+ return _listOfInputPort;
+}
+
+void OutputPort::edRemoveInputPort(InputPort *inputPort) throw(Exception)
+{
+ if(isAlreadyInList(inputPort))
+ _listOfInputPort.remove(inputPort);
+ else
+ throw Exception("OutputPort::edRemoveInputPort : link does not exist, unable to remove it");
+}
+
+OutputPort::~OutputPort()
+{
+}
+
+bool OutputPort::isAlreadyInList(InputPort *inputPort) const
+{
+ bool ret=false;
+ for(list<InputPort *>::const_iterator iter=_listOfInputPort.begin();iter!=_listOfInputPort.end() && !ret;iter++)
+ if((*iter)==inputPort)
+ ret=true;
+ return ret;
+}
+
+bool OutputPort::addInPort(InPort *inPort) throw(Exception)
+{
+ if(inPort->getNameOfTypeOfCurrentInstance()!=InputPort::NAME)
+ {
+ std::string what="not compatible type of port requested during building of link FROM ";
+ what+=NAME; what+=" TO "; what+=inPort->getNameOfTypeOfCurrentInstance();
+ throw Exception(what);
+ }
+ return edAddInputPort(static_cast<InputPort*>(inPort));
+}
+
+void OutputPort::removeInPort(InPort *inPort) throw(Exception)
+{
+ if(inPort->getNameOfTypeOfCurrentInstance()!=InputPort::NAME)
+ {
+ std::string what="not compatible type of port requested during destruction of for link FROM ";
+ what+=NAME; what+=" TO "; what+=inPort->getNameOfTypeOfCurrentInstance();
+ throw Exception(what);
+ }
+ edRemoveInputPort(static_cast<InputPort*>(inPort));
+}
+
+bool OutputPort::isLinked()
+{
+ return _listOfInputPort.empty();
+}
--- /dev/null
+#ifndef __OUTPUTPORT_HXX__
+#define __OUTPUTPORT_HXX__
+
+#include "OutPort.hxx"
+#include "DataFlowPort.hxx"
+#include "ConversionException.hxx"
+
+#include <list>
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ class InputPort;
+
+ class OutputPort : public DataFlowPort, public OutPort
+ {
+ protected:
+ std::list<InputPort *> _listOfInputPort;
+ public:
+ static const char NAME[];
+ public:
+ OutputPort(const std::string& name, Node *node, DynType type);
+ ~OutputPort();
+ std::string getNameOfTypeOfCurrentInstance() const;
+ Data foGet() const;
+ void exInit();
+ void exPut(Data data) throw(ConversionException);
+ bool edAddInputPort(InputPort *inputPort) throw(ConversionException);
+ std::list<InputPort *> edListInputPort();
+ void edRemoveInputPort(InputPort *inputPort) throw(Exception);
+ bool addInPort(InPort *inPort) throw(Exception);
+ void removeInPort(InPort *inPort) throw(Exception);
+ bool isLinked();
+ bool isAlreadyInList(InputPort *inputPort) const;
+ };
+ }
+}
+
+#endif
--- /dev/null
+#include "Port.hxx"
+
+using namespace YACS::ENGINE;
+
+const char Port::NAME[]="Port";
+
+Port::Port(Node *node):_node(node)
+{
+}
+
+Port::~Port()
+{
+}
+
+std::string Port::getNameOfTypeOfCurrentInstance() const
+{
+ return NAME;
+}
--- /dev/null
+#ifndef __PORT_HXX__
+#define __PORT_HXX__
+
+#include <string>
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ class Node;
+ }
+}
+
+/**
+ *
+ * Not instanciable class that factorizes all basic data and behaviours relative the in and out interfaces of all nodes.
+ * End-user should not neither instanciate a sub-class of 'Port' nor called other methods than accessor.
+ *
+ */
+namespace YACS
+{
+ namespace ENGINE
+ {
+ class Port
+ {
+ protected:
+ Node *_node;//NOT OWNERED
+ public:
+ static const char NAME[];
+ protected:
+ Port(Node *node);
+ public:
+ virtual ~Port();
+ Node *getNode() const { return _node; }
+ virtual std::string getNameOfTypeOfCurrentInstance() const;
+ };
+ }
+}
+
+#endif
--- /dev/null
+#ifndef __SCHEDULER_HXX__
+#define __SCHEDULER_HXX__
+
+#include <vector>
+#include "define.hxx"
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ class Task;
+
+ class Scheduler
+ {
+ public:
+ virtual void init() = 0;
+ virtual bool isFinished() = 0;
+ virtual std::vector<Task *> getNextTasks(bool& isMore) = 0;
+ virtual void selectRunnableTasks(std::vector<Task *>& tasks) = 0;
+ virtual void notifyFrom(const Task *sender, YACS::Event event) = 0;
+ };
+ }
+}
+
+#endif
--- /dev/null
+#include "Switch.hxx"
+
+using namespace YACS::ENGINE;
+
+Switch::Switch(const std::string& name):ComposedNode(name)
+{
+}
+
+Switch::~Switch()
+{
+}
+
+void Switch::edSetNumberOfCases(int numberOfCases)
+{
+ _vectorOfNode.resize(numberOfCases);
+}
+
+void Switch::edSetNode(int caseId, Node *node) throw(Exception)
+{
+ if(caseId>=_vectorOfNode.size())
+ throw Exception("Switch::edSetNode : caseId is too large compared to number of cases");
+ _vectorOfNode[caseId]=node;
+}
+
+void Switch::checkNoCyclePassingThrough(Node *node) throw(Exception)
+{
+ throw Exception("Switch::checkNoCyclePassingThrough : uncorrect control flow link relative to switch");
+}
--- /dev/null
+#ifndef __SWITCH_HXX__
+#define __SWITCH_HXX__
+
+#include "ComposedNode.hxx"
+
+#include <vector>
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ class Switch : public ComposedNode
+ {
+ protected:
+ std::vector<Node *> _vectorOfNode;//Nodes ownered
+ public:
+ Switch(const std::string& name);
+ ~Switch();
+ void edSetNumberOfCases(int numberOfCases);
+ void edSetNode(int caseId, Node *node) throw(Exception);
+ protected:
+ void checkNoCyclePassingThrough(Node *node) throw(Exception);
+ };
+ }
+}
+
+#endif
--- /dev/null
+#ifndef __TASK_HXX__
+#define __TASK_HXX__
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ class Task
+ {
+ public:
+ virtual void begin() = 0;
+ virtual bool isReady() = 0;
+ virtual void execute() = 0;
+ virtual void finished() = 0;
+ };
+ }
+}
+
+#endif
--- /dev/null
+
+include $(top_srcdir)/adm/unix/make_begin.am
+
+check_PROGRAMS = testPorts testBloc
+
+testPorts_SOURCES = testPorts.cxx ToyNode.cxx
+
+testPorts_LDADD = ../libYACSEngine.la \
+ ../../bases/libYACSBases.la \
+ ../../basicData/libYACSBasicData.la
+
+
+testPorts_LDFLAGS = $(CPPUNIT_LIBS) -pthread -ldl
+
+testPorts_CXXFLAGS = $(CPPUNIT_INCLUDES) \
+ -I$(srcdir)/.. \
+ -I$(srcdir)/../../bases \
+ -I$(srcdir)/../../basicData
+
+testBloc_SOURCES = testBloc.cxx ToyNode.cxx
+
+testBloc_LDADD = ../libYACSEngine.la \
+ ../../bases/libYACSBases.la \
+ ../../basicData/libYACSBasicData.la
+
+
+testBloc_LDFLAGS = $(CPPUNIT_LIBS) -pthread -ldl
+
+testBloc_CXXFLAGS = $(THREAD_DEF) $(CPPUNIT_INCLUDES) \
+ -I$(srcdir)/.. \
+ -I$(srcdir)/../../bases \
+ -I$(srcdir)/../../basicData
+
+TESTS = testPorts testBloc
+
+include $(top_srcdir)/adm/unix/make_end.am
--- /dev/null
+#include "ToyNode.hxx"
+#include "InputPort.hxx"
+#include "OutputPort.hxx"
+
+#include <iostream>
+
+using namespace std;
+
+#define TAB_LENGTH 100
+
+using namespace YACS::ENGINE;
+
+ToyNode::ToyNode(const std::string& name, int time):ElementaryNode(name),_time(time)
+{
+}
+InputPort *ToyNode::edAddInputPort(const std::string& inputPortName)
+{
+ return edAddInputPort(inputPortName, YACS::Double);
+}
+
+OutputPort *ToyNode::edAddOutputPort(const std::string& outputPortName)
+{
+ return edAddOutputPort(outputPortName, YACS::Double);
+}
+
+InputPort *ToyNode::edAddInputPort(const std::string& inputPortName, YACS::DynType type) throw(Exception)
+{
+ if(type!=YACS::Double)
+ throw Exception("ToyNode only deals double dataflow ports");
+ return ElementaryNode::edAddInputPort(inputPortName,type);
+}
+
+OutputPort *ToyNode::edAddOutputPort(const std::string& outputPortName, YACS::DynType type) throw(Exception)
+{
+ if(type!=YACS::Double)
+ throw Exception("ToyNode only deals double dataflow ports");
+ return ElementaryNode::edAddOutputPort(outputPortName,type);
+}
+
+InputDataStreamPort *ToyNode::edAddInputDataStreamPort(const std::string& inputPortDSName, YACS::StreamType type) throw(Exception)
+{
+ throw Exception("ToyNode Not designed to support DataStream");
+}
+
+OutputDataStreamPort *ToyNode::edAddOutputDataStreamPort(const std::string& outputPortDSName, YACS::StreamType type) throw(Exception)
+{
+ throw Exception("ToyNode Not designed to support DataStream");
+}
+
+void ToyNode::execute()
+{
+ std::list<InputPort *>::iterator iter;
+ double sum=0.;
+ for(iter=_listOfInputPort.begin();iter!=_listOfInputPort.end();iter++)
+ sum+=(*iter)->exGet().exGet<double>();
+ cerr << "Node " << _name << " executing " << sum << endl;
+ double tab[TAB_LENGTH];
+ if(_time!=0)
+ {
+ for(int i=0;i<100000;i++)
+ for(int j=0;j<20*_time;j++)
+ tab[((i+j)/2)%TAB_LENGTH]=i*i*j;
+ }
+ cerr << "Node " << _name << " executing " << sum << endl;
+ if(_listOfOutputPort.empty())
+ return;
+ sum/=_listOfOutputPort.size();
+ std::list<OutputPort *>::iterator iter2;
+ for(iter2=_listOfOutputPort.begin();iter2!=_listOfOutputPort.end();iter2++)
+ (*iter2)->exPut(sum);
+}
+
--- /dev/null
+#ifndef __TOYNODE_HXX__
+#define __TOYNODE_HXX__
+
+#include "ElementaryNode.hxx"
+
+namespace YACS
+{
+ namespace ENGINE
+ {
+ class ToyNode : public ElementaryNode
+ {
+ private:
+ int _time;
+ public:
+ ToyNode(const std::string& name, int time=0);
+ void setTime(int time) { _time=time; }
+ InputPort *edAddInputPort(const std::string& inputPortName);
+ OutputPort *edAddOutputPort(const std::string& outputPortName);
+ InputPort *edAddInputPort(const std::string& inputPortName, YACS::DynType type) throw(Exception);
+ OutputPort *edAddOutputPort(const std::string& outputPortName, YACS::DynType type) throw(Exception);
+ InputDataStreamPort *edAddInputDataStreamPort(const std::string& inputPortDSName, YACS::StreamType type) throw(Exception);
+ OutputDataStreamPort *edAddOutputDataStreamPort(const std::string& outputPortDSName, YACS::StreamType type) throw(Exception);
+ void execute();
+ };
+ }
+}
+
+#endif
--- /dev/null
+#ifndef __TESTBLOC_HXX__
+#define __TESTBLOC_HXX__
+
+#include "Bloc.hxx"
+#include "Data.hxx"
+#include "ToyNode.hxx"
+#include "Executor.hxx"
+#include "Exception.hxx"
+#include "InputPort.hxx"
+#include "OutputPort.hxx"
+//
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/ui/text/TestRunner.h>
+#include <sstream>
+#include <string.h>
+//
+
+#define DBL_PRECISION_COMPARE 1e-15
+
+using namespace YACS::ENGINE;
+
+class BlocTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE( BlocTest );
+ CPPUNIT_TEST( test1 );
+ CPPUNIT_TEST( test2 );
+ CPPUNIT_TEST( test3 );
+ CPPUNIT_TEST_SUITE_END();
+public:
+ void tearDown();
+ void test1();
+ void test2();
+ void test3();
+};
+
+void BlocTest::tearDown()
+{
+}
+
+//Simplest test to test basic mechanisms like Data, initialisation of ports.
+void BlocTest::test1()
+{
+ ToyNode *n1=new ToyNode("T1");
+ InputPort *i8=n1->edAddInputPort("o");
+ InputPort *i9=n1->edAddInputPort("p");
+ Bloc *graph=new Bloc("toto");
+ graph->edAddChild(n1);
+ OutputPort *o1=n1->edAddOutputPort("b");
+ Data v1(5.67);
+ i9->edInit(v1);
+ v1=2.78;
+ i8->edInit(v1);
+ Executor exe;
+ exe.RunW(graph);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL( o1->foGet().exGet<double>(),8.45,DBL_PRECISION_COMPARE );
+ OutputPort *o2=n1->edAddOutputPort("c");
+ exe.RunW(graph);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL( o1->foGet().exGet<double>(),4.225,DBL_PRECISION_COMPARE );
+ delete graph;
+}
+
+//Only one level(hierarchy) simple graph. Tests DF and CF links.
+void BlocTest::test2()
+{
+ ToyNode *n1=new ToyNode("T1");
+ ToyNode *n2=new ToyNode("T2",50);
+ ToyNode *n3=new ToyNode("T3",20);
+ ToyNode *n4=new ToyNode("T4");
+ Bloc *graph=new Bloc("Global");
+ graph->edAddChild(n1); graph->edAddChild(n2); graph->edAddChild(n3); graph->edAddChild(n4);
+ InputPort *i1_a=n1->edAddInputPort("a"); InputPort *i1_b=n1->edAddInputPort("b"); OutputPort *o1_j=n1->edAddOutputPort("j"); OutputPort *o1_k=n1->edAddOutputPort("k");
+ InputPort *i2_c=n2->edAddInputPort("c"); InputPort *i2_d=n2->edAddInputPort("d"); OutputPort *o2_f=n2->edAddOutputPort("f");
+ InputPort *i3_e=n3->edAddInputPort("e"); OutputPort *o3_g=n3->edAddOutputPort("g"); OutputPort *o3_h=n3->edAddOutputPort("h");
+ InputPort *i4_l=n4->edAddInputPort("l"); InputPort *i4_m=n4->edAddInputPort("m"); OutputPort *o4_i=n4->edAddOutputPort("i");
+ //Retrieving gates
+ InGate *iN1=n1->getInGate(); InGate *iN2=n2->getInGate(); InGate *iN3=n3->getInGate(); InGate *iN4=n4->getInGate();
+ OutGate *oN1=n1->getOutGate(); OutGate *oN2=n2->getOutGate(); OutGate *oN3=n3->getOutGate(); OutGate *oN4=n4->getOutGate();
+ Data v1(1.2);
+ i1_a->edInit(v1);
+ v1=3.4;
+ i1_b->edInit(v1);
+ v1=7;
+ i2_d->edInit(v1);
+ //DF //CF
+ graph->edAddLink(o1_j,i2_c); graph->edAddLink(oN1,iN2);
+ graph->edAddLink(o1_k,i3_e); graph->edAddLink(oN1,iN3);
+ graph->edAddLink(o2_f,i4_l); graph->edAddLink(oN2,iN4);
+ graph->edAddLink(o3_g,i4_m); graph->edAddLink(oN3,iN4);
+ Executor exe;
+ exe.RunW(graph);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL( o4_i->foGet().exGet<double>(),10.45,DBL_PRECISION_COMPARE );
+ n2->setTime(0); n3->setTime(0);
+ exe.RunW(graph);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL( o4_i->foGet().exGet<double>(),10.45,DBL_PRECISION_COMPARE );
+ bool testOfCycleSucceed=false;
+ try
+ { graph->edAddLink(oN4,iN1); }
+ catch(YACS::Exception &e)
+ { if(strcmp(e.what(),"Cycle has been detected")==0)
+ testOfCycleSucceed=true; }
+ CPPUNIT_ASSERT(testOfCycleSucceed);
+ delete graph;
+}
+
+//test multi level graphs
+void BlocTest::test3()
+{
+ Bloc *toto=new Bloc("toto");
+ Bloc *tata=new Bloc("tata");
+ Bloc *titi=new Bloc("titi");
+ ToyNode *n2=new ToyNode("T2"); ToyNode *n3=new ToyNode("T3"); ToyNode *n4=new ToyNode("T4"); ToyNode *n5=new ToyNode("T5"); ToyNode *n6=new ToyNode("T6");
+ ToyNode *n7=new ToyNode("T7",20); ToyNode *n8=new ToyNode("T8");
+ toto->edAddChild(titi); titi->edAddChild(tata); titi->edAddChild(n3); toto->edAddChild(n2); tata->edAddChild(n4); tata->edAddChild(n5); tata->edAddChild(n6);
+ titi->edAddChild(n7); titi->edAddChild(n8);
+ toto->edAddCFLink(n2,titi); toto->edAddCFLink(n3,tata); toto->edAddCFLink(n5,n4); titi->edAddCFLink(n7,n8); titi->edAddCFLink(tata,n8);
+ //
+ InputPort *i2_a=n2->edAddInputPort("a"); OutputPort *o2_a=n2->edAddOutputPort("a"); OutputPort *o2_b=n2->edAddOutputPort("b");
+ InputPort *i3_a=n3->edAddInputPort("a"); OutputPort *o3_a=n3->edAddOutputPort("a"); OutputPort *o3_b=n3->edAddOutputPort("b");
+ InputPort *i4_a=n4->edAddInputPort("a"); InputPort *i4_b=n4->edAddInputPort("b"); OutputPort *o4_a=n4->edAddOutputPort("a"); OutputPort *o4_b=n4->edAddOutputPort("b");
+ InputPort *i5_a=n5->edAddInputPort("a"); InputPort *i5_b=n5->edAddInputPort("b"); OutputPort *o5_a=n5->edAddOutputPort("a");
+ InputPort *i6_a=n6->edAddInputPort("a"); InputPort *i6_b=n6->edAddInputPort("b"); OutputPort *o6_a=n6->edAddOutputPort("a");
+ InputPort *i7_a=n7->edAddInputPort("a"); OutputPort *o7_a=n7->edAddOutputPort("a");
+ InputPort *i8_a=n8->edAddInputPort("a"); InputPort *i8_b=n8->edAddInputPort("b"); OutputPort *o8_a=n8->edAddOutputPort("a");
+ //
+ toto->edAddLink(o2_a,i3_a); toto->edAddLink(o3_a,i5_a); toto->edAddLink(o2_b,i5_b); toto->edAddLink(o2_a,i4_b);
+ toto->edAddLink(o3_b,i6_a); toto->edAddLink(o6_a,i8_a); toto->edAddLink(o7_a,i8_b);
+ //
+ Data v1(1.2);
+ i2_a->edInit(v1);
+ v1=7;
+ i6_b->edInit(v1);
+ i4_a->edInit(v1);
+ v1=3;
+ i7_a->edInit(v1);
+ CPPUNIT_ASSERT( toto->getNumberOfCFLinks()== 1 ); CPPUNIT_ASSERT( titi->getNumberOfCFLinks()== 3 ); CPPUNIT_ASSERT( tata->getNumberOfCFLinks()== 1 );
+ Executor exe;
+ exe.RunW(toto);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL( o6_a->foGet().exGet<double>(),7.3,DBL_PRECISION_COMPARE );
+ CPPUNIT_ASSERT_DOUBLES_EQUAL( o4_a->foGet().exGet<double>(),3.8,DBL_PRECISION_COMPARE );
+ CPPUNIT_ASSERT_DOUBLES_EQUAL( o8_a->foGet().exGet<double>(),10.3,DBL_PRECISION_COMPARE );
+ delete toto;
+}
+
+int main()
+{
+ CppUnit::TextUi::TestRunner runner;
+ runner.addTest( BlocTest::suite() );
+ runner.run();
+ return 0;
+}
+
+
+#endif
--- /dev/null
+#include "Node.hxx"
+#include "Data.hxx"
+#include "InGate.hxx"
+#include "OutGate.hxx"
+#include "InputPort.hxx"
+#include "OutputPort.hxx"
+//
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/ui/text/TestRunner.h>
+#include <sstream>
+//
+
+using namespace YACS::ENGINE;
+
+class PortsTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE( PortsTest );
+ CPPUNIT_TEST( testControlFlow );
+ CPPUNIT_TEST( testDataFlow1 );
+ CPPUNIT_TEST_EXCEPTION( testDataFlowTypeCheck, YACS::ENGINE::ConversionException);
+ CPPUNIT_TEST_SUITE_END();
+public:
+ void tearDown();
+ void testControlFlow();
+ void testDataFlow1();
+ void testDataFlowTypeCheck();
+};
+
+void PortsTest::tearDown()
+{
+}
+
+void PortsTest::testControlFlow()
+{
+ Node *n1=0,*n2=0,*n3=0,*n4=0;
+ OutGate *o1=new OutGate(n1);
+ OutGate *o2=new OutGate(n2);
+ OutGate *o3=new OutGate(n3);
+ OutGate *o4=new OutGate(n4);
+ InGate *i1=new InGate(n1);
+ InGate *i2=new InGate(n2);
+ InGate *i3=new InGate(n3);
+ InGate *i4=new InGate(n4);
+ // Simuling edition
+ o1->edAddInGate(i2); o1->edAddInGate(i3);
+ o2->edAddInGate(i2); o2->edAddInGate(i4);
+ o3->edAddInGate(i2); o3->edAddInGate(i4); o3->edAddInGate(i3);
+ o4->edAddInGate(i2); o4->edAddInGate(i4);
+ // Simuling execution
+ CPPUNIT_ASSERT( i1->exIsReady() ); CPPUNIT_ASSERT( !i2->exIsReady() ); CPPUNIT_ASSERT( !i3->exIsReady() ); CPPUNIT_ASSERT( !i4->exIsReady() );
+ o1->exNotifyDone();
+ CPPUNIT_ASSERT( i1->exIsReady() ); CPPUNIT_ASSERT( !i2->exIsReady() ); CPPUNIT_ASSERT( !i3->exIsReady() ); CPPUNIT_ASSERT( !i4->exIsReady() );
+ o2->exNotifyDone();
+ CPPUNIT_ASSERT( i1->exIsReady() ); CPPUNIT_ASSERT( !i2->exIsReady() ); CPPUNIT_ASSERT( !i3->exIsReady() ); CPPUNIT_ASSERT( !i4->exIsReady() );
+ o3->exNotifyDone();
+ CPPUNIT_ASSERT( i1->exIsReady() ); CPPUNIT_ASSERT( !i2->exIsReady() ); CPPUNIT_ASSERT( i3->exIsReady() ); CPPUNIT_ASSERT( !i4->exIsReady() );
+ o4->exNotifyDone();
+ CPPUNIT_ASSERT( i1->exIsReady() ); CPPUNIT_ASSERT( i2->exIsReady() ); CPPUNIT_ASSERT( i3->exIsReady() ); CPPUNIT_ASSERT( i4->exIsReady() );
+ //
+ delete o1; delete o2; delete o3; delete o4;
+ delete i1; delete i2; delete i3; delete i4;
+}
+
+void PortsTest::testDataFlow1()
+{
+ Node *n1=0,*n2=0,*n3=0,*n4=0;
+ OutputPort *o1=new OutputPort("o1",n1,YACS::Double);
+ OutputPort *o3=new OutputPort("o3",n3,YACS::Int);
+ InputPort *i1=new InputPort("i1",n1,YACS::Double);
+ InputPort *i2=new InputPort("i2",n2,YACS::Int);
+ InputPort *i4=new InputPort("i4",n4,YACS::Bool);
+ // Simuling edition
+ o1->edAddInputPort(i1); o1->edAddInputPort(i2);
+ o3->edAddInputPort(i1); o3->edAddInputPort(i2); o3->edAddInputPort(i4);
+ CPPUNIT_ASSERT( o1->foGet().edGetRepresentation() == "41_NULL" ); CPPUNIT_ASSERT( o3->foGet().edGetRepresentation() == "42_NULL" );
+ CPPUNIT_ASSERT( i1->exGet().edGetRepresentation() == "41_NULL" ); CPPUNIT_ASSERT( i2->exGet().edGetRepresentation() == "42_NULL" ); CPPUNIT_ASSERT( i4->exGet().edGetRepresentation() == "45_NULL" );
+ // Simuling execution
+ o1->exPut(3.14);
+ CPPUNIT_ASSERT( i1->exGet().edGetRepresentation() == "41_3.14" ); CPPUNIT_ASSERT( i2->exGet().edGetRepresentation() == "42_3" ); CPPUNIT_ASSERT( i4->exGet().edGetRepresentation() == "45_NULL" );
+ o3->exPut(325);
+ CPPUNIT_ASSERT( i1->exGet().edGetRepresentation() == "41_325" ); CPPUNIT_ASSERT( i2->exGet().edGetRepresentation() == "42_325" ); CPPUNIT_ASSERT( i4->exGet().edGetRepresentation() == "45_1" );
+ o1->exPut(-2.78);
+ CPPUNIT_ASSERT( i1->exGet().edGetRepresentation() == "41_-2.78" ); CPPUNIT_ASSERT( i2->exGet().edGetRepresentation() == "42_-2" ); CPPUNIT_ASSERT( i4->exGet().edGetRepresentation() == "45_1" );
+ //
+ delete o1; delete o3;
+ delete i1; delete i2; delete i4;
+}
+
+void PortsTest::testDataFlowTypeCheck()
+{
+ Node *n1=0;
+ OutputPort o1("o1",n1,YACS::Double);
+ InputPort i1("i1",n1,YACS::Bool);
+ o1.edAddInputPort(&i1);//Should throw exception
+}
+
+int main()
+{
+ CppUnit::TextUi::TestRunner runner;
+ runner.addTest( PortsTest::suite() );
+ runner.run();
+ return 0;
+}