3
\$\begingroup\$

Preface

I have decided to let my pet project created some years ago to undergo a code review here.

The review will be broken into parts according to meta question Multiple reviews or one big review?.

The overall concept and motivation can be inspected here (be patient, it takes some time to load).

The doxygen generated documentation can be accessed online here (it loads a bit quicker).



Part II: Abstraction of asynchronous/concurrency features

Beyond the basic GoF State Pattern the UML State Machine diagrams introduce several aspects of execution concurrency, that need to be abstracted in a scalable framework.

Varying from thread safety for simple StateMachine implementations, up to several UML State Diagram aspects like Regions, Forks, Joins and Junctions (these will be availble for review in another part later) there's need to provide abstraction for handling such features. Best as much independent from the underlying OS or target system, scalable and configurable.

So these abstractions will setup the base for the above mentioned features.

The mainly used design pattern for these interfaces is the CRTP. All that stuff is an internal implementation feature.

SttclThread.h

#ifndef STTCLTHREAD_H_
#define STTCLTHREAD_H_

#ifndef STTCL_DEFAULT_THREADIMPL
#if defined(STTCL_POSIX_THREADS) or defined(STTCL_POSIX_IMPL)
#include "../PosixThreads/SttclPosixThread.h"
#define STTCL_DEFAULT_THREADIMPL sttcl::internal::posix_impl::SttclPosixThread
#elif defined(STTCL_BOOST_THREADS) or defined(STTCL_BOOST_IMPL)
#include "../BoostThreads/SttclBoostThread.h"
#define STTCL_DEFAULT_THREADIMPL sttcl::internal::boost_impl::SttclBoostThread
#elif defined(STTCL_CX11_THREADS) or defined(STTCL_CX11_IMPL)
#include "../C++11Threads/SttclCx11Thread.h"
#define STTCL_DEFAULT_THREADIMPL sttcl::internal::cx11_impl::SttclCx11Thread
#endif

#ifndef STTCL_DEFAULT_THREADIMPL
#error "You need to define a default thread implementation for sttcl"
#endif
#endif

#include "SttclTime.h"

namespace sttcl
{

namespace internal
{

/**
 * Adapter class for a (OS-)specific thread implementation.
 * @tparam Impl Selects a (OS-)specific thread implementation.
 *
 * @todo Implement a static interface check for the Impl class.
 */
template<class Impl = STTCL_DEFAULT_THREADIMPL>
class SttclThread
: public Impl
{
public:
    /**
     * Defines the method pointer signature used for the thread method.
     */
    typedef void* (*ThreadMethodPtr)(void*);

    /**
     * Constructor for class SttclThread.
     * @param argThreadMethod A pointer tor the method that should be executed as thread method.
     */
    SttclThread(ThreadMethodPtr argThreadMethod) : Impl(argThreadMethod)
    {
    }
    /**
     * Destructor for class SttclThread.
     */
    ~SttclThread() {}

    /**
     * Runs the thread method within a separate thread.
     * @param args Arguments passed to the thread method.
     */
    bool run(void* args)
    {
        return static_cast<Impl*>(this)->run(args);
    }

    /**
     * Waits blocking forever until the thread method exits.
     */
    void join()
    {
        static_cast<Impl*>(this)->join();
    }

    /**
     * Kills the thread method.
     */
    void detach()
    {
        static_cast<Impl*>(this)->detach();
    }

    /**
     * Returns \c true if the other thread reference represents the thread method path, \c false
     * otherwise.
     * @param otherThread A thread reference.
     */
    static bool isSelf(const Impl& otherThread)
    {
        return Impl::isSelf(otherThread);
    }

    /**
     * Blocks the current thead at least for the specified \em duration.
     * @param duration The minimum duration to block the currently running thread.
     */
    static void sleep(const TimeDuration<>& duration)
    {
        Impl::sleep(duration);
    }

private:
    SttclThread(); //!< Forbidden
    SttclThread(const SttclThread<Impl>& rhs); //!< Forbidden
    SttclThread<Impl>& operator=(const SttclThread<Impl>& rhs); //!< Forbidden
};
}
}

#endif /* STTCLTHREAD_H_ */

ClassMethodThread.h

#ifndef CLASSMETHODTHREAD_H_
#define CLASSMETHODTHREAD_H_

#include "SttclThread.h"
#include "SttclMutex.h"

namespace sttcl
{
/**
 * Represents a thread running a class member method of \em T.
 * @tparam T The class providing the thread method.
 * @tparam UserArgs The optional user arguments type passed to the thread method, the default is
 *                  void.
 * @tparam The optional thread class implementation, the default is STTCL_DEFAULT_THREADIMPL.
 */
template
< class T
, class UserArgs = void
, class ThreadImpl = STTCL_DEFAULT_THREADIMPL
, class MutexImpl = STTCL_DEFAULT_MUTEXIMPL
>
class ClassMethodThread
: public sttcl::internal::SttclThread<ThreadImpl>
{
public:
    /**
     * Defines the method pointer signature used for the thread method.
     */
    typedef void* (T::*ThreadMethodPtr)(UserArgs*);

private:
    struct RunArgs
    {
        ClassMethodThread<T,UserArgs,ThreadImpl,MutexImpl>* threadInstance;
        T* instance;
        ThreadMethodPtr threadMethod;
        UserArgs* userArgs;

        RunArgs(ClassMethodThread<T,UserArgs,ThreadImpl,MutexImpl>* argThreadInstance,T* argInstance, ThreadMethodPtr argThreadMethod, UserArgs* argUserArgs = 0)
        : threadInstance(argThreadInstance)
        , instance(argInstance)
        , threadMethod(argThreadMethod)
        , userArgs(argUserArgs)
        {
        }
        RunArgs(const RunArgs& rhs)
        : threadInstance(rhs.threadInstance)
        , instance(rhs.instance)
        , threadMethod(rhs.threadMethod)
        , userArgs(rhs.userArgs)
        {
        }
        RunArgs& operator=(const RunArgs& rhs)
        {
            threadInstance = rhs.threadInstance;
            instance = rhs.instance;
            threadMethod = rhs.threadMethod;
            userArgs = rhs.userArgs;
            return *this;
        }

    private:
        RunArgs(); //!< Forbidden
    };
public:
    /**
     * Constructor for the ClassMethodThread class.
     * @param argInstance The instance providing the thread method.
     * @param argThreadMethod A function pointer for the thread method.
     */
    ClassMethodThread(T* argInstance, ThreadMethodPtr argThreadMethod)
    : sttcl::internal::SttclThread<ThreadImpl>(internalThreadMethod)
    , runArgs(this,argInstance,argThreadMethod)
    , running(false)
    , threadMutex()
    {
    }

    /**
     * Destructor for the ClassMethodThread class.
     */
    virtual ~ClassMethodThread()
    {
    }

    /**
     * Runs the thread method within a separate thread.
     * @param userArgs Arguments passed to the thread method.
     */
    bool run(UserArgs* userArgs = 0)
    {
        if(!isRunning())
        {
            runArgs.userArgs = userArgs;
            return sttcl::internal::SttclThread<ThreadImpl>::run(&runArgs);
        }
        return false;
    }

    bool isRunning()
    {
        sttcl::internal::AutoLocker<MutexImpl> lock(threadMutex);
        return running;
    }

    void join()
    {
        if(!this->isSelf(*this))
        {
            sttcl::internal::SttclThread<ThreadImpl>::join();
        }
    }

private:
    static void* internalThreadMethod(void* args)
    {
        void * result = 0;
        RunArgs* runArgs = reinterpret_cast<RunArgs*>(args);
        ClassMethodThread<T,UserArgs,ThreadImpl,MutexImpl>* thisPtr = runArgs->threadInstance;

//      if(!isSelf(*thisPtr) && !thisPtr->isRunning())
//      {
            { sttcl::internal::AutoLocker<MutexImpl> lock(thisPtr->threadMutex);
                thisPtr->running = true;
            }
            T* instance = runArgs->instance;
            ThreadMethodPtr threadMethod = runArgs->threadMethod;
            result = (instance->*threadMethod)(runArgs->userArgs);
            { sttcl::internal::AutoLocker<MutexImpl> lock(thisPtr->threadMutex);
                thisPtr->running = false;
            }
//      }
        return result;
    }

    ClassMethodThread(); //!< Forbidden
    ClassMethodThread(const ClassMethodThread<T,UserArgs,ThreadImpl>& rhs); //!< Forbidden
    ClassMethodThread<T,UserArgs,ThreadImpl>& operator=(const ClassMethodThread<T,UserArgs,ThreadImpl>& rhs); //!< Forbidden

    RunArgs runArgs;
    bool running;
    MutexImpl threadMutex;
};

}
#endif /* CLASSMETHODTHREAD_H_ */

SttclMutex.h

#ifndef STTCLMUTEX_H_
#define STTCLMUTEX_H_

#include "SttclTime.h"

#ifndef STTCL_DEFAULT_MUTEXIMPL
#if defined(STTCL_POSIX_THREADS) or defined(STTCL_POSIX_IMPL)
#include "../PosixThreads/SttclPosixMutex.h"
#define STTCL_DEFAULT_MUTEXIMPL sttcl::internal::posix_impl::SttclPosixMutex
#elif defined(STTCL_BOOST_THREADS) or defined(STTCL_BOOST_IMPL)
#include "../BoostThreads/SttclBoostMutex.h"
#define STTCL_DEFAULT_MUTEXIMPL sttcl::internal::boost_impl::SttclBoostMutex
#elif defined(STTCL_CX11_THREADS) or defined(STTCL_CX11_IMPL)
#include "../C++11Threads/SttclCx11Mutex.h"
#define STTCL_DEFAULT_MUTEXIMPL sttcl::internal::cx11_impl::SttclCx11Mutex
#endif

#ifndef STTCL_DEFAULT_MUTEXIMPL
#error "You need to define a default mutex implementation for sttcl"
#endif
#endif

namespace sttcl
{

namespace internal
{

/**
 * Adapter class for a (OS-)specific mutex implementation.
 * @tparam Impl Selects a (OS-)specific mutex implementation.
 *
 * @todo Implement a static interface check for the Impl class.
 */
template
< class Impl = STTCL_DEFAULT_MUTEXIMPL
, class TimeDurationType = TimeDuration<STTCL_DEFAULT_TIMEDURATIONIMPL>
>
class SttclMutex
: public Impl
{
public:
    /**
     * Constructor for class SttclMutex.
     */
    SttclMutex() : Impl() {}
    /**
     * Destructor for class SttclMutex.
     */
    ~SttclMutex() {}

    /**
     * Locks the mutex. Waits blocking forever until the mutex becomes lockable.
     */
    void lock()
    {
        static_cast<Impl*>(this)->lock();
    }

    /**
     * Tries to lock the mutex within the specified \em timeout parameter.
     * The \em timeout value TimeDurationType::Zero will return success or failure
     * immediately.
     * @param timeout The maximum duration to wait until the mutex becomes lockable.
     * @return \c true if the mutex is lockable. \c false if the \em timeout duration
     * expired.
     */
    bool try_lock(const TimeDurationType& timeout = TimeDurationType::Zero)
    {
        return static_cast<Impl*>(this)->try_lock(timeout);
    }

    /**
     * Unlocks the mutex.
     */
    void unlock()
    {
        static_cast<Impl*>(this)->unlock();
    }
};

/**
 * Helper class to create a properly scoped lock of a mutex object.
 * @tparam Lockable The mutex class type.
 */
template<class Lockable>
class AutoLocker
{
public:
    /**
     * Constructor for class AutoLocker. Locks the \em argLockableRef object.
     * @param argLockableRef A reference to a mutex (or other \em Lockable implementation).
     */
    AutoLocker(Lockable& argLockableRef)
    : ref(argLockableRef)
    {
        ref.lock();
    }

    /**
     * Destructor for class AutoLocker. Unlocks the object reference passed with the constructor.
     */
    ~AutoLocker()
    {
        ref.unlock();
    }
private:
    Lockable& ref;
};

}
}

#endif /* STTCLMUTEX_H_ */

SttclSemaphore.h

#ifndef STTCLSEMAPHORE_H_
#define STTCLSEMAPHORE_H_

#include "SttclTime.h"

#ifndef STTCL_DEFAULT_SEMAPHOREIMPL
#if defined(STTCL_POSIX_SEMAPHORE) or defined(STTCL_POSIX_IMPL)
#include "../PosixThreads/SttclPosixSemaphore.h"
#define STTCL_DEFAULT_SEMAPHOREIMPL sttcl::internal::posix_impl::SttclPosixSemaphore
#elif defined(STTCL_BOOST_SEMAPHORE) or defined(STTCL_BOOST_IMPL)
#include "../BoostThreads/SttclBoostSemaphore.h"
#define STTCL_DEFAULT_SEMAPHOREIMPL sttcl::internal::boost_impl::SttclBoostSemaphore
#elif defined(STTCL_CX11_SEMAPHORE) or defined(STTCL_CX11_IMPL)
#include "../C++11Threads/SttclCx11Semaphore.h"
#define STTCL_DEFAULT_SEMAPHOREIMPL sttcl::internal::cx11_impl::SttclCx11Semaphore
#endif

#ifndef STTCL_DEFAULT_SEMAPHOREIMPL
#error "You need to define a default semaphore implementation for sttcl"
#endif
#endif

namespace sttcl
{

namespace internal
{
/**
 * Adapter class for a (OS-)specific semaphore implementation.
 * @tparam Impl Selects a (OS-)specific semaphore implementation.
 *
 * @todo Implement a static interface check for the Impl class.
 */
template
< class Impl = STTCL_DEFAULT_SEMAPHOREIMPL
, class TimeDurationType = TimeDuration<STTCL_DEFAULT_TIMEDURATIONIMPL>
>
class SttclSemaphore
: public Impl
{
public:
    /**
     * Constructor for class SttclSemaphore.
     * @param initialCount Sets the initial semaphore count.
     */
    SttclSemaphore(unsigned int initialCount = 0) : Impl(initialCount) {}
    /**
     * Destructor for class SttclSemaphore.
     */
    ~SttclSemaphore() {}

    /**
     * Waits blocking forever until the semaphore is incremented.
     */
    void wait()
    {
        static_cast<Impl*>(this)->wait();
    }

    /**
     * Waits until the semaphore is incremented within the specified \em timeout duration.
     * A \em timeout value of TimeDurationType::Zero returns the semaphore state immediatly.
     * @param timeout Specifies the maximum duration to wait until the semaphore is incremented.
     * @return \c true if the semaphore was successfully decremented.
     */
    bool try_wait(const TimeDurationType& timeout = TimeDurationType::Zero)
    {
        return static_cast<Impl*>(this)->try_wait(timeout);
    }

    /**
     * Increments the semaphore.
     */
    void post()
    {
        static_cast<Impl*>(this)->post();
    }
};

}
}

#endif /* STTCLSEMAPHORE_H_ */

SttclTime.h

#ifndef STTCLTIME_H_
#define STTCLTIME_H_

#ifndef STTCL_DEFAULT_TIMEDURATIONIMPL
#if defined(STTCL_POSIX_TIME)  or defined(STTCL_POSIX_IMPL)
#include "../PosixTime/SttclPosixTime.h"
#define STTCL_DEFAULT_TIMEDURATIONIMPL sttcl::internal::posix_impl::SttclPosixTimeDuration
#elif defined(STTCL_BOOST_TIME) or defined(STTCL_BOOST_IMPL)
#include "../BoostTime/SttclBoostTime.h"
#define STTCL_DEFAULT_TIMEDURATIONIMPL sttcl::internal::boost_impl::SttclBoostTimeDuration
#elif defined(STTCL_CX11_TIME) or defined(STTCL_CX11_IMPL)
#include "../C++11Time/SttclCx11Time.h"
#define STTCL_DEFAULT_TIMEDURATIONIMPL sttcl::internal::cx11_impl::SttclCx11TimeDuration
#endif

#ifndef STTCL_DEFAULT_TIMEDURATIONIMPL
#error "You need to define a default time duration implementation for sttcl"
#endif
#endif

namespace sttcl
{

/**
 * Adapter class for a (OS-)specific "real"-time duration representation implementation.
 * @tparam Implementation Selects a (OS-)specific "real"-time duration representation implementation.
 *
 * @todo Implement a static interface check for the Impl class.
 */
template<class Implementation = STTCL_DEFAULT_TIMEDURATIONIMPL>
class TimeDuration
: public Implementation
{
public:
    /**
     * The class type of the native "real"-time duration representation.
     */
    typedef typename Implementation::NativeTimeDuration NativeTimeDuration;

    /**
     * Represents a zero time duration.
     */
    static const TimeDuration<Implementation> Zero;

    /**
     * Constructor for class TimeDuration.
     * @param argHours The hours represented in this instance.
     * @param argMinutes The minutes represented in this instance.
     * @param argSeconds  The seconds represented in this instance.
     * @param argMilliSeconds The milliseconds represented in this instance.
     * @param argMicroSeconds The microseconds represented in this instance.
     * @param argNanoSeconds The nanoseconds represented in this instance.
     */
    TimeDuration(unsigned int argHours = 0, unsigned int argMinutes = 0, unsigned int argSeconds = 0, unsigned int argMilliSeconds = 0, unsigned long argMicroSeconds = 0, unsigned long argNanoSeconds = 0)
    : Implementation(argHours,argMinutes,argSeconds,argMilliSeconds,argMicroSeconds,argNanoSeconds)
    {
    }

    /**
     * Copy constructor for class TimeDuration.
     * @param rhs Another instance of TimeDuration.
     */
    TimeDuration(const TimeDuration<Implementation>& rhs)
    : Implementation(static_cast<const Implementation&>(rhs))
    {
    }
    /**
     * Constructor for class TimeDuration.
     * @param nativeTimeDuration An instance of the NativeTimeDuration value.
     */
    TimeDuration(const NativeTimeDuration& nativeTimeDuration)
    : Implementation(nativeTimeDuration)
    {
    }
    /**
     * Destructor for class TimeDuration.
     */
    ~TimeDuration()
    {
    }

    /**
     * Assignment operator for class TimeDuration.
     * @param rhs Another instance of TimeDuration.
     * @return A reference to the assigned TimeDuration instance.
     */
    TimeDuration<Implementation>& operator=(const TimeDuration<Implementation>& rhs)
    {
        Implementation::operator=(static_cast<const Implementation&>(rhs));
        return *this;
    }

    /**
     * Assignment operator for class TimeDuration.
     * @param nativeTimeDuration An instance of the NativeTimeDuration value.
     * @return A reference to the assigned TimeDuration instance.
     */
    TimeDuration<Implementation>& operator=(const NativeTimeDuration& nativeTimeDuration)
    {
        Implementation::operator=(static_cast<const Implementation&>(nativeTimeDuration));
        return *this;
    }

    /**
     * Equality comparison operator for class TimeDuration.
     * @param rhs Another instance of TimeDuration.
     * @return \c true if \em rhs time duration equals this instance, \c false otherwise.
     */
    bool operator==(const TimeDuration<Implementation>& rhs) const
    {
        return Implementation::operator==(static_cast<const Implementation&>(rhs));
    }
    /**
     * Inequality comparison operator for class TimeDuration.
     * @param rhs Another instance of TimeDuration.
     * @return \c true if \em rhs time duration doesn't equal this instance, \c false otherwise.
     */
    bool operator!=(const TimeDuration<Implementation>& rhs) const
    {
        return Implementation::operator!=(static_cast<const Implementation&>(rhs));
    }
    /**
     * Less comparison operator for class TimeDuration.
     * @param rhs Another instance of TimeDuration.
     * @return \c true if \em rhs time duration is less than this instance, \c false otherwise.
     */
    bool operator<(const TimeDuration<Implementation>& rhs) const
    {
        return Implementation::operator<(static_cast<const Implementation&>(rhs));
    }
    /**
     * Less or equality comparison operator for class TimeDuration.
     * @param rhs Another instance of TimeDuration.
     * @return \c true if \em rhs time duration is less than or equals this instance, \c false otherwise.
     */
    bool operator<=(const TimeDuration<Implementation>& rhs) const
    {
        return Implementation::operator<=(static_cast<const Implementation&>(rhs));
    }
    /**
     * Greater comparison operator for class TimeDuration.
     * @param rhs Another instance of TimeDuration.
     * @return \c true if \em rhs time duration is greater than this instance, \c false otherwise.
     */
    bool operator>(const TimeDuration<Implementation>& rhs) const
    {
        return Implementation::operator>(static_cast<const Implementation&>(rhs));
    }
    /**
     * Greater or equality comparison operator for class TimeDuration.
     * @param rhs Another instance of TimeDuration.
     * @return \c true if \em rhs time duration is greater than or equals this instance, \c false otherwise.
     */
    bool operator>=(const TimeDuration<Implementation>& rhs) const
    {
        return Implementation::operator>=(static_cast<const Implementation&>(rhs));
    }

    /**
     * Adds the \em rhs time duration to this instance.
     * @param rhs Another instance of TimeDuration.
     * @return A reference to the modified TimeDuration instance.
     */
    TimeDuration<Implementation>& operator+=(const TimeDuration<Implementation>& rhs)
    {
        Implementation::operator+=(static_cast<const Implementation&>(rhs));
        return *this;
    }

    /**
     * Substracts the \em rhs time duration from this instance.
     * @param rhs Another instance of TimeDuration.
     * @return A reference to the modified TimeDuration instance.
     */
    TimeDuration<Implementation>& operator-=(const TimeDuration<Implementation>& rhs)
    {
        Implementation::operator-=(static_cast<const Implementation&>(rhs));
        return *this;
    }

    /**
     * Multiplies the \em time duration from of this instance with \em factor.
     * @param factor The multiplication factor.
     * @return A reference to the modified TimeDuration instance.
     */
    TimeDuration<Implementation>& operator*=(int factor)
    {
        Implementation::operator*=(factor);
        return *this;
    }

    /**
     * Divides the \em time duration from of this instance by \em divider.
     * @param divider The divider.
     * @return A reference to the modified TimeDuration instance.
     */
    TimeDuration<Implementation>& operator/=(int divider)
    {
        Implementation::operator/=(divider);
        return *this;
    }

    /**
     * Gets the hours represented in this instance.
     */
    long hours() const
    {
        return Implementation::hours();
    }
    /**
     * Gets the minutes represented in this instance.
     */
    long minutes() const
    {
        return Implementation::minutes();
    }
    /**
     * Gets the seconds represented in this instance.
     */
    long seconds() const
    {
        return Implementation::seconds();
    }
    /**
     * Gets the milliseconds represented in this instance.
     */
    long milliseconds() const
    {
        return Implementation::milliseconds();
    }
    /**
     * Gets the microseconds represented in this instance.
     */
    long microseconds() const
    {
        return Implementation::microseconds();
    }
    /**
     * Gets the nanoseconds represented in this instance.
     */
    long nanoseconds() const
    {
        return Implementation::nanoseconds();
    }

    /**
     * Sets the hours represented in this instance.
     */
    void hours(int newHours)
    {
        Implementation::hours(newHours);
    }
    /**
     * Sets the minutes represented in this instance.
     */
    void minutes(int newMinutes)
    {
        Implementation::minutes(newMinutes);
    }
    /**
     * Sets the seconds represented in this instance.
     */
    void seconds(int newSeconds)
    {
        Implementation::seconds(newSeconds);
    }

    /**
     * @todo Implement methods to set milliseconds, microseconds and nanoseconds in a consistent way with the getters.
     */
    /**
     * Sets the milliseconds represented in this instance.
     */
    /*
    void milliseconds(int newMilliSeconds)
    {
        Implementation::milliseconds(newMilliSeconds);
    }
    */
    /**
     * Sets the microseconds represented in this instance.
     */
    /*
    void microseconds(int newMicroSeconds)
    {
        Implementation::microseconds(newMicroSeconds);
    }
    */
    /**
     * Sets the nanoseconds represented in this instance.
     */
    /*
    void nanoseconds(long newNanoSeconds)
    {
        Implementation::nanoseconds(newNanoSeconds);
    }
    */

    /**
     * Gets the native "real"-time duration representation.
     * @return
     */
    const NativeTimeDuration& getNativeValue() const
    {
        return Implementation::getNativeValue();
    }
};


}

template<class Implementation>
static sttcl::TimeDuration<Implementation> operator+(const sttcl::TimeDuration<Implementation>& op1, const sttcl::TimeDuration<Implementation>& op2)
{
    sttcl::TimeDuration<Implementation> result(op1);
    return result += op2;
}

template<class Implementation>
static sttcl::TimeDuration<Implementation> operator-(const sttcl::TimeDuration<Implementation>& op1, const sttcl::TimeDuration<Implementation>& op2)
{
    sttcl::TimeDuration<Implementation> result(op1);
    return result -= op2;
}
template<class Implementation>
static sttcl::TimeDuration<Implementation> operator*(const sttcl::TimeDuration<Implementation>& op1, int op2)
{
    sttcl::TimeDuration<Implementation> result(op1);
    return result *= op2;
}
template<class Implementation>
static sttcl::TimeDuration<Implementation> operator/(const sttcl::TimeDuration<Implementation>& op1, int op2)
{
    sttcl::TimeDuration<Implementation> result(op1);
    return result /= op2;
}

template<class Implementation>
const sttcl::TimeDuration<Implementation> sttcl::TimeDuration<Implementation>::Zero = sttcl::TimeDuration<Implementation>();
#endif /* STTCLTIME_H_ */

That's merely everything that's needed for the STTCL framework features.

Some intrinsic implementations can be found here:


Boost


Posix


C++ 11


Through using the configuration features, it should be easy to provide more adapters (e.g. for FreeRTOS or other environments) on your own.



Proceed to Part III: Policy based design of higher level State Machine constructs

\$\endgroup\$
1
  • \$\begingroup\$ One thing I can spot here myself, is that detach() doesn't really kill the thread, but just detaches it. Either the semantical description or naming seems wrong. \$\endgroup\$ Apr 11, 2017 at 20:02

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.