<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#include    "../StroikaPreComp.h"

#include    <mutex>

#include    "../Containers/Mapping.h"
#include    "../Debug/Trace.h"
#include    "../Containers/Concrete/Queue_Array.h"

#include    "BlockingQueue.h"
#include    "Thread.h"

#include    "SignalHandlers.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Execution;
using   namespace   Stroika::Foundation::Memory;

using   Containers::Mapping;
using   Containers::Queue;
using   Containers::Set;

// maybe useful while debugging signal code, but VERY unsafe
// and could easily be the source of bugs/deadlocks!
#ifndef qDoDbgTraceOnSignalHandlers_
#define qDoDbgTraceOnSignalHandlers_    0
#endif

struct SignalHandlerRegistry::SafeSignalsManager::Rep_ {
    Rep_ ();
    ~Rep_ ();
    Containers::Mapping<SignalID, Containers::Set<SignalHandler>>   fHandlers_;
    BlockingQueue<SignalID>                                         fIncomingSafeSignals_;
    Thread                                                          fBlockingQueuePusherThread_;
};

namespace   {
    bool    IsSigIgnore_ (const Set<SignalHandler>& sigSet)
    {
        return sigSet.size () == 1 and sigSet.Contains (SignalHandlerRegistry::kIGNORED);
    }
}

/*
 ********************************************************************************
 *********** Execution::SignalHandlerRegistry::SafeSignalsManager ***************
 ********************************************************************************
 */
namespace {
    Queue<SignalID> mkQ_ ()
    {
        Containers::Concrete::Queue_Array<SignalID> signalQ;
        signalQ.SetCapacity (100);  // quite arbitrary - @todo make configurable somehow...
        return signalQ;
    }
}

SignalHandlerRegistry::SafeSignalsManager::Rep_::Rep_  ()
    : fIncomingSafeSignals_ (mkQ_ ())
    , fBlockingQueuePusherThread_ ()
{
    Thread watcherThread ([this] () {
        // This is a safe context
        Debug::TraceContextBumper trcCtx (SDKSTR ("Stroika::Foundation::Execution::Signals::{}::fBlockingQueueDelegatorThread_"));
        while (true) {
            Debug::TraceContextBumper trcCtx (SDKSTR ("waiting for next signal"));
            SignalID    i   =   fIncomingSafeSignals_.RemoveHead ();
            DbgTrace (L"got signal: %s; ... delegating to safe handlers...", SignalToName (i).c_str ());
            for (SignalHandler sh : SignalHandlerRegistry::Get ().GetSignalHandlers (i)) {
                if (sh.GetType () == SignalHandler::Type::eSafe) {
                    IgnoreExceptionsExceptThreadAbortForCall (sh (i));
                }
            }
        }
    });
    watcherThread.SetThreadName (L"Signal Handler Safe Execution Thread");
    watcherThread.Start ();
    fBlockingQueuePusherThread_ = std::move (watcherThread);
}

SignalHandlerRegistry::SafeSignalsManager::Rep_::~Rep_ ()
{
    fBlockingQueuePusherThread_.AbortAndWaitForDone ();
}

/*
 ********************************************************************************
 *********** Execution::SignalHandlerRegistry::SafeSignalsManager ***************
 ********************************************************************************
 */
shared_ptr<SignalHandlerRegistry::SafeSignalsManager::Rep_>  SignalHandlerRegistry::SafeSignalsManager::sThe_;

SignalHandlerRegistry::SafeSignalsManager::SafeSignalsManager ()
{
    Assert (sThe_ == nullptr);
    sThe_ = shared_ptr<SignalHandlerRegistry::SafeSignalsManager::Rep_> (new Rep_ ());
}

SignalHandlerRegistry::SafeSignalsManager::~SafeSignalsManager ()
{
    Assert (sThe_ != nullptr);
    sThe_->fBlockingQueuePusherThread_.AbortAndWaitForDone ();
    sThe_.reset ();
}

/*
 ********************************************************************************
 ******************** Execution::SignalHandlerRegistry **************************
 ********************************************************************************
 */
const   SignalHandler   SignalHandlerRegistry::kIGNORED =   SignalHandler (SIG_IGN, SignalHandler::Type::eDirect);

SignalHandlerRegistry&  SignalHandlerRegistry::Get ()
{
    static  SignalHandlerRegistry   sThe_;
    return sThe_;
}

SignalHandlerRegistry::SignalHandlerRegistry ()
    : fDirectHandlers_ ()
{
}

SignalHandlerRegistry::~SignalHandlerRegistry ()
{
    Assert (SafeSignalsManager::sThe_ == nullptr);  // must be cleared first
}

Set<SignalID>   SignalHandlerRegistry::GetHandledSignals () const
{
    // @todo redo using Mapping<>::Keys () when implemented...
    Set<SignalID>   result;
    for (auto i : fDirectHandlers_) {
        result.Add (i.fKey);
    }
    shared_ptr<SafeSignalsManager::Rep_> tmp = SafeSignalsManager::sThe_;
    if (tmp != nullptr) {
        for (auto i : tmp->fHandlers_) {
            result.Add (i.fKey);
        }
    }
    return result;
}

Set<SignalHandler>  SignalHandlerRegistry::GetSignalHandlers (SignalID signal) const
{
    Set<SignalHandler>  result  =   fDirectHandlers_.LookupValue (signal);
    shared_ptr<SafeSignalsManager::Rep_> tmp = SafeSignalsManager::sThe_;
    if (tmp != nullptr) {
        result += tmp->fHandlers_.LookupValue (signal);
    }
    return result;
}

void    SignalHandlerRegistry::SetSignalHandlers (SignalID signal)
{
    SetSignalHandlers (signal, Set<SignalHandler> ());
}

void    SignalHandlerRegistry::SetSignalHandlers (SignalID signal, SignalHandler handler)
{
    SetSignalHandlers (signal, Set<SignalHandler> ({handler}));
}

void    SignalHandlerRegistry::SetSignalHandlers (SignalID signal, const Set<SignalHandler>& handlers)
{
    Debug::TraceContextBumper trcCtx (SDKSTR ("Stroika::Foundation::Execution::Signals::{}::SetSignalHandlers"));
    DbgTrace (L"(signal = %s, handlers.size () = %d, ....)", SignalToName (signal).c_str (), handlers.size ());

    shared_ptr<SignalHandlerRegistry::SafeSignalsManager::Rep_> tmp = SignalHandlerRegistry::SafeSignalsManager::sThe_;
    if (handlers.empty ()) {
        /*
         *  No handlers means use default.
         */
        fDirectHandlers_.Remove (signal);
        if (tmp != nullptr) {
            tmp->fHandlers_.Remove (signal);
        }
        (void)::signal (signal, SIG_DFL);
    }
    else if (IsSigIgnore_ (handlers)) {
        Assert (handlers.size () == 1);
        fDirectHandlers_.Add (signal, handlers);
        if (tmp != nullptr) {
            tmp->fHandlers_.Remove (signal);
        }
        (void)::signal (signal, SIG_IGN);
    }
    else {
        Set<SignalHandler>  directHandlers;
        Set<SignalHandler>  safeHandlers;
        handlers.Apply ([&directHandlers, &safeHandlers] (SignalHandler si) {
            switch (si.GetType ()) {
                case SignalHandler::Type::eDirect: {
                        directHandlers.Add (si);
                    }
                    break;
                case SignalHandler::Type::eSafe: {
                        safeHandlers.Add (si);
                    }
                    break;
            }
        });
        Assert (directHandlers.size () + safeHandlers.size () == handlers.size ());
        fDirectHandlers_.Add (signal, directHandlers);
        if (not safeHandlers.empty ()) {
            // To use safe signal handlers, you must have a SignalHandlerRegistry::SafeSignalsManager
            // defined first. It is recommended that you define an instance of
            // SignalHandlerRegistry::SafeSignalsManager handler; should be defined in main ()
            Require (SafeSignalsManager::sThe_ != nullptr);
        }
        if (tmp != nullptr) {
            tmp->fHandlers_.Add (signal, safeHandlers);
        }
        (void)::signal (signal, FirstPassSignalHandler_);
    }
}

void    SignalHandlerRegistry::AddSignalHandler (SignalID signal, SignalHandler handler)
{
    Set<SignalHandler>  s   =   GetSignalHandlers (signal);
    s.Add (handler);
    SetSignalHandlers (signal, s);
}

void    SignalHandlerRegistry::RemoveSignalHandler (SignalID signal, SignalHandler handler)
{
    Set<SignalHandler>  s   =   GetSignalHandlers (signal);
    Require (s.Contains (handler));
    s.Remove (handler);
    SetSignalHandlers (signal, s);
}

void    SignalHandlerRegistry::DefaultCrashSignalHandler (SignalID signal)
{
    DbgTrace (L"Serious Signal Error trapped: %s ... Aborting", SignalToName (signal).c_str ());
    abort ();
}

void    SignalHandlerRegistry::SetStandardCrashHandlerSignals (SignalHandler handler, const Set<SignalID>& excludedSignals)
{
    if (not excludedSignals.Contains (SIGINT))      {  SetSignalHandlers (SIGINT, handler);        }
    if (not excludedSignals.Contains (SIGILL))      {  SetSignalHandlers (SIGILL, handler);        }
    if (not excludedSignals.Contains (SIGFPE))      {  SetSignalHandlers (SIGFPE, handler);        }
    if (not excludedSignals.Contains (SIGSEGV))     {  SetSignalHandlers (SIGSEGV, handler);       }
    if (not excludedSignals.Contains (SIGTERM))     {  SetSignalHandlers (SIGTERM, handler);       }
#if     qPlatform_POSIX
    if (not excludedSignals.Contains (SIGSYS))      {  SetSignalHandlers (SIGSYS, handler);        }
    if (not excludedSignals.Contains (SIGBUS))      {  SetSignalHandlers (SIGBUS, handler);        }
    if (not excludedSignals.Contains (SIGQUIT))     {  SetSignalHandlers (SIGQUIT, handler);       }
    if (not excludedSignals.Contains (SIGPIPE))     {  SetSignalHandlers (SIGPIPE, handler);       }
    if (not excludedSignals.Contains (SIGHUP))      {  SetSignalHandlers (SIGHUP, handler);        }
    if (not excludedSignals.Contains (SIGXCPU))     {  SetSignalHandlers (SIGXCPU, handler);       }
    if (not excludedSignals.Contains (SIGXFSZ))     {  SetSignalHandlers (SIGXFSZ, handler);       }
#endif
}

void    SignalHandlerRegistry::FirstPassSignalHandler_ (SignalID signal)
{
#if     qDoDbgTraceOnSignalHandlers_
    Debug::TraceContextBumper trcCtx (SDKSTR ("Stroika::Foundation::Execution::Signals::{}::FirstPassSignalHandler_"));
    DbgTrace (L"(signal = %s)", SignalToName (signal).c_str ());
#endif
    SignalHandlerRegistry&  SHR =   Get ();

    for (SignalHandler sh : SHR.fDirectHandlers_.LookupValue (signal)) {
        sh (signal);
    }
    shared_ptr<SignalHandlerRegistry::SafeSignalsManager::Rep_> tmp = SignalHandlerRegistry::SafeSignalsManager::sThe_;
    if (tmp != nullptr) {
        tmp->fIncomingSafeSignals_.AddTail (signal);
    }
}

#if     qPlatform_POSIX
/*
 ********************************************************************************
 ************* Execution::ScopedBlockCurrentThreadSignal ************************
 ********************************************************************************
 */
ScopedBlockCurrentThreadSignal::ScopedBlockCurrentThreadSignal (SignalID signal)
    : fSignal_ (signal)
    , fRestoreMask_ ()
{
    //DbgTrace (L"ScopedBlockCurrentThreadSignal blocking signals for %s", SignalToName (signal).c_str ());
    sigset_t    mySet;
    sigemptyset (&mySet);
    (void)::sigaddset (&mySet, signal);
    sigemptyset (&fRestoreMask_);           // Unclear if this emptyset call is needed?
    Verify (pthread_sigmask (SIG_BLOCK,  &mySet, &fRestoreMask_) == 0);
}

ScopedBlockCurrentThreadSignal::~ScopedBlockCurrentThreadSignal ()
{
    //DbgTrace (L"ScopedBlockCurrentThreadSignal restoriing signals for %s", SignalToName (fSignal_).c_str ());
    Verify (pthread_sigmask (SIG_SETMASK,  &fRestoreMask_, nullptr) == 0);
}
#endif
<commit_msg>cleanups of SignalHandlerRegistry code<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#include    "../StroikaPreComp.h"

#include    <mutex>

#include    "../Containers/Mapping.h"
#include    "../Debug/Trace.h"
#include    "../Containers/Concrete/Queue_Array.h"

#include    "BlockingQueue.h"
#include    "Thread.h"

#include    "SignalHandlers.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Execution;
using   namespace   Stroika::Foundation::Memory;

using   Containers::Mapping;
using   Containers::Queue;
using   Containers::Set;

// maybe useful while debugging signal code, but VERY unsafe
// and could easily be the source of bugs/deadlocks!
#ifndef qDoDbgTraceOnSignalHandlers_
#define qDoDbgTraceOnSignalHandlers_    0
#endif

struct SignalHandlerRegistry::SafeSignalsManager::Rep_ {
    Rep_ ();
    ~Rep_ ();
    Containers::Mapping<SignalID, Containers::Set<SignalHandler>>   fHandlers_;
    BlockingQueue<SignalID>                                         fIncomingSafeSignals_;
    Thread                                                          fBlockingQueuePusherThread_;
};

namespace   {
    bool    IsSigIgnore_ (const Set<SignalHandler>& sigSet)
    {
        return sigSet.size () == 1 and sigSet.Contains (SignalHandlerRegistry::kIGNORED);
    }
}

/*
 ********************************************************************************
 *********** Execution::SignalHandlerRegistry::SafeSignalsManager ***************
 ********************************************************************************
 */
namespace {
    Queue<SignalID> mkQ_ ()
    {
        Containers::Concrete::Queue_Array<SignalID> signalQ;
        signalQ.SetCapacity (100);  // quite arbitrary - @todo make configurable somehow...
        return signalQ;
    }
}

SignalHandlerRegistry::SafeSignalsManager::Rep_::Rep_  ()
    : fHandlers_ ()
    , fIncomingSafeSignals_ (mkQ_ ())
    , fBlockingQueuePusherThread_ ()
{
    Thread watcherThread ([this] () {
        // This is a safe context
        Debug::TraceContextBumper trcCtx (SDKSTR ("Stroika::Foundation::Execution::Signals::{}::fBlockingQueueDelegatorThread_"));
        while (true) {
            Debug::TraceContextBumper trcCtx1 (SDKSTR ("waiting for next signal"));
            SignalID    i   =   fIncomingSafeSignals_.RemoveHead ();
            Debug::TraceContextBumper trcCtx2 (SDKSTR ("Invoking SAFE signal handlers"));
            DbgTrace (L"(signal: %s)", SignalToName (i).c_str ());
            for (SignalHandler sh : fHandlers_.LookupValue (i)) {
                if (sh.GetType () == SignalHandler::Type::eSafe) {
                    IgnoreExceptionsExceptThreadAbortForCall (sh (i));
                }
            }
        }
    });
    watcherThread.SetThreadName (L"Signal Handler Safe Execution Thread");
    watcherThread.Start ();
    fBlockingQueuePusherThread_ = std::move (watcherThread);
}

SignalHandlerRegistry::SafeSignalsManager::Rep_::~Rep_ ()
{
    Debug::TraceContextBumper trcCtx (SDKSTR ("Stroika::Foundation::Execution::SignalHandlerRegistry::SafeSignalsManager::Rep_::~Rep_"));
    fBlockingQueuePusherThread_.AbortAndWaitForDone ();
}

/*
 ********************************************************************************
 *********** Execution::SignalHandlerRegistry::SafeSignalsManager ***************
 ********************************************************************************
 */
shared_ptr<SignalHandlerRegistry::SafeSignalsManager::Rep_>  SignalHandlerRegistry::SafeSignalsManager::sThe_;

SignalHandlerRegistry::SafeSignalsManager::SafeSignalsManager ()
{
    Debug::TraceContextBumper trcCtx (SDKSTR ("Stroika::Foundation::Execution::SignalHandlerRegistry::CTOR"));
    Assert (sThe_ == nullptr);
    sThe_ = shared_ptr<SignalHandlerRegistry::SafeSignalsManager::Rep_> (new Rep_ ());
}

SignalHandlerRegistry::SafeSignalsManager::~SafeSignalsManager ()
{
    Debug::TraceContextBumper trcCtx (SDKSTR ("Stroika::Foundation::Execution::SignalHandlerRegistry::DTOR"));
    Assert (sThe_ != nullptr);
    sThe_->fBlockingQueuePusherThread_.AbortAndWaitForDone ();
    sThe_.reset ();
}

/*
 ********************************************************************************
 ******************** Execution::SignalHandlerRegistry **************************
 ********************************************************************************
 */
const   SignalHandler   SignalHandlerRegistry::kIGNORED =   SignalHandler (SIG_IGN, SignalHandler::Type::eDirect);

SignalHandlerRegistry&  SignalHandlerRegistry::Get ()
{
    static  SignalHandlerRegistry   sThe_;
    return sThe_;
}

SignalHandlerRegistry::SignalHandlerRegistry ()
    : fDirectHandlers_ ()
{
    Debug::TraceContextBumper trcCtx (SDKSTR ("Stroika::Foundation::Execution::SignalHandlerRegistry::CTOR"));
}

SignalHandlerRegistry::~SignalHandlerRegistry ()
{
    Debug::TraceContextBumper trcCtx (SDKSTR ("Stroika::Foundation::Execution::SignalHandlerRegistry::DTOR"));
    Assert (SafeSignalsManager::sThe_ == nullptr);  // must be cleared first
}

Set<SignalID>   SignalHandlerRegistry::GetHandledSignals () const
{
    // @todo redo using Mapping<>::Keys () when implemented...
    Set<SignalID>   result;
    for (auto i : fDirectHandlers_) {
        result.Add (i.fKey);
    }
    shared_ptr<SafeSignalsManager::Rep_> tmp = SafeSignalsManager::sThe_;
    if (tmp != nullptr) {
        for (auto i : tmp->fHandlers_) {
            result.Add (i.fKey);
        }
    }
    return result;
}

Set<SignalHandler>  SignalHandlerRegistry::GetSignalHandlers (SignalID signal) const
{
    Set<SignalHandler>  result  =   fDirectHandlers_.LookupValue (signal);
    shared_ptr<SafeSignalsManager::Rep_> tmp = SafeSignalsManager::sThe_;
    if (tmp != nullptr) {
        result += tmp->fHandlers_.LookupValue (signal);
    }
    return result;
}

void    SignalHandlerRegistry::SetSignalHandlers (SignalID signal)
{
    SetSignalHandlers (signal, Set<SignalHandler> ());
}

void    SignalHandlerRegistry::SetSignalHandlers (SignalID signal, SignalHandler handler)
{
    SetSignalHandlers (signal, Set<SignalHandler> ({handler}));
}

void    SignalHandlerRegistry::SetSignalHandlers (SignalID signal, const Set<SignalHandler>& handlers)
{
    Debug::TraceContextBumper trcCtx (SDKSTR ("Stroika::Foundation::Execution::SignalHandlerRegistry::{}::SetSignalHandlers"));
    DbgTrace (L"(signal = %s, handlers.size () = %d, ....)", SignalToName (signal).c_str (), handlers.size ());

    shared_ptr<SignalHandlerRegistry::SafeSignalsManager::Rep_> tmp = SignalHandlerRegistry::SafeSignalsManager::sThe_;
    if (handlers.empty ()) {
        /*
         *  No handlers means use default.
         */
        fDirectHandlers_.Remove (signal);
        if (tmp != nullptr) {
            tmp->fHandlers_.Remove (signal);
        }
        (void)::signal (signal, SIG_DFL);
    }
    else if (IsSigIgnore_ (handlers)) {
        Assert (handlers.size () == 1);
        fDirectHandlers_.Add (signal, handlers);
        if (tmp != nullptr) {
            tmp->fHandlers_.Remove (signal);
        }
        (void)::signal (signal, SIG_IGN);
    }
    else {
        Set<SignalHandler>  directHandlers;
        Set<SignalHandler>  safeHandlers;
        handlers.Apply ([&directHandlers, &safeHandlers] (SignalHandler si) {
            switch (si.GetType ()) {
                case SignalHandler::Type::eDirect: {
                        directHandlers.Add (si);
                    }
                    break;
                case SignalHandler::Type::eSafe: {
                        safeHandlers.Add (si);
                    }
                    break;
            }
        });
        Assert (directHandlers.size () + safeHandlers.size () == handlers.size ());
        fDirectHandlers_.Add (signal, directHandlers);
        if (not safeHandlers.empty ()) {
            // To use safe signal handlers, you must have a SignalHandlerRegistry::SafeSignalsManager
            // defined first. It is recommended that you define an instance of
            // SignalHandlerRegistry::SafeSignalsManager handler; should be defined in main ()
            Require (SafeSignalsManager::sThe_ != nullptr);
        }
        if (tmp != nullptr) {
            tmp->fHandlers_.Add (signal, safeHandlers);
        }
        (void)::signal (signal, FirstPassSignalHandler_);
    }
}

void    SignalHandlerRegistry::AddSignalHandler (SignalID signal, SignalHandler handler)
{
    Set<SignalHandler>  s   =   GetSignalHandlers (signal);
    s.Add (handler);
    SetSignalHandlers (signal, s);
}

void    SignalHandlerRegistry::RemoveSignalHandler (SignalID signal, SignalHandler handler)
{
    Set<SignalHandler>  s   =   GetSignalHandlers (signal);
    Require (s.Contains (handler));
    s.Remove (handler);
    SetSignalHandlers (signal, s);
}

void    SignalHandlerRegistry::DefaultCrashSignalHandler (SignalID signal)
{
    DbgTrace (L"Serious Signal Error trapped: %s ... Aborting", SignalToName (signal).c_str ());
    abort ();
}

void    SignalHandlerRegistry::SetStandardCrashHandlerSignals (SignalHandler handler, const Set<SignalID>& excludedSignals)
{
    if (not excludedSignals.Contains (SIGINT))      {  SetSignalHandlers (SIGINT, handler);        }
    if (not excludedSignals.Contains (SIGILL))      {  SetSignalHandlers (SIGILL, handler);        }
    if (not excludedSignals.Contains (SIGFPE))      {  SetSignalHandlers (SIGFPE, handler);        }
    if (not excludedSignals.Contains (SIGSEGV))     {  SetSignalHandlers (SIGSEGV, handler);       }
    if (not excludedSignals.Contains (SIGTERM))     {  SetSignalHandlers (SIGTERM, handler);       }
#if     qPlatform_POSIX
    if (not excludedSignals.Contains (SIGSYS))      {  SetSignalHandlers (SIGSYS, handler);        }
    if (not excludedSignals.Contains (SIGBUS))      {  SetSignalHandlers (SIGBUS, handler);        }
    if (not excludedSignals.Contains (SIGQUIT))     {  SetSignalHandlers (SIGQUIT, handler);       }
    if (not excludedSignals.Contains (SIGPIPE))     {  SetSignalHandlers (SIGPIPE, handler);       }
    if (not excludedSignals.Contains (SIGHUP))      {  SetSignalHandlers (SIGHUP, handler);        }
    if (not excludedSignals.Contains (SIGXCPU))     {  SetSignalHandlers (SIGXCPU, handler);       }
    if (not excludedSignals.Contains (SIGXFSZ))     {  SetSignalHandlers (SIGXFSZ, handler);       }
#endif
}

void    SignalHandlerRegistry::FirstPassSignalHandler_ (SignalID signal)
{
#if     qDoDbgTraceOnSignalHandlers_
    Debug::TraceContextBumper trcCtx (SDKSTR ("Stroika::Foundation::Execution::SignalHandlerRegistry::FirstPassSignalHandler_"));
    DbgTrace (L"(signal = %s)", SignalToName (signal).c_str ());
#endif
    SignalHandlerRegistry&  SHR =   Get ();

    for (SignalHandler sh : SHR.fDirectHandlers_.LookupValue (signal)) {
        sh (signal);
    }
    shared_ptr<SignalHandlerRegistry::SafeSignalsManager::Rep_> tmp = SignalHandlerRegistry::SafeSignalsManager::sThe_;
    if (tmp != nullptr) {
        tmp->fIncomingSafeSignals_.AddTail (signal);
    }
}

#if     qPlatform_POSIX
/*
 ********************************************************************************
 ************* Execution::ScopedBlockCurrentThreadSignal ************************
 ********************************************************************************
 */
ScopedBlockCurrentThreadSignal::ScopedBlockCurrentThreadSignal (SignalID signal)
    : fSignal_ (signal)
    , fRestoreMask_ ()
{
    //DbgTrace (L"ScopedBlockCurrentThreadSignal blocking signals for %s", SignalToName (signal).c_str ());
    sigset_t    mySet;
    sigemptyset (&mySet);
    (void)::sigaddset (&mySet, signal);
    sigemptyset (&fRestoreMask_);           // Unclear if this emptyset call is needed?
    Verify (pthread_sigmask (SIG_BLOCK,  &mySet, &fRestoreMask_) == 0);
}

ScopedBlockCurrentThreadSignal::~ScopedBlockCurrentThreadSignal ()
{
    //DbgTrace (L"ScopedBlockCurrentThreadSignal restoriing signals for %s", SignalToName (fSignal_).c_str ());
    Verify (pthread_sigmask (SIG_SETMASK,  &fRestoreMask_, nullptr) == 0);
}
#endif
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#ifndef _Stroika_Foundation_IO_Network_SocketAddress_inl_
#define _Stroika_Foundation_IO_Network_SocketAddress_inl_  1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
namespace   Stroika {
    namespace   Foundation {
        namespace   IO {
            namespace   Network {

                /*
                 ********************************************************************************
                 *********************** IO::Network::SocketAddress *****************************
                 ********************************************************************************
                 */
                inline  SocketAddress::SocketAddress ()
                    : fSocketAddress_ ()
                {
                    ::memset (&fSocketAddress_, 0, sizeof (fSocketAddress_));
                }
                inline  SocketAddress::SocketAddress (const sockaddr& iaddr)
                    : fSocketAddress_ ()
                {
                    Assert  (sizeof (fSocketAddress_) == sizeof (sockaddr));
                    ::memcpy (&fSocketAddress_, &iaddr, sizeof (fSocketAddress_));
                }
                inline  SocketAddress::SocketAddress (const sockaddr_in& iaddr)
                    : fSocketAddress_ ()
                {
                    Assert  (sizeof (fSocketAddress_) == sizeof (sockaddr));
                    Assert  (sizeof (fSocketAddress_) == sizeof (sockaddr_in));
                    ::memcpy (&fSocketAddress_, &iaddr, sizeof (fSocketAddress_));
                }
                inline  SocketAddress::SocketAddress (const InternetAddress& iaddr, uint16_t portNumber)
                    : fSocketAddress_ ()
                {
                    ::memset (&fSocketAddress_, 0, sizeof (fSocketAddress_));
                    switch (iaddr.GetAddressFamily ()) {
                        case    InternetAddress::AddressFamily::V4: {
                                Assert (sizeof (sockaddr_in) == sizeof (sockaddr));
                                sockaddr_in& as = reinterpret_cast<sockaddr_in&> (fSocketAddress_);
                                as.sin_family = AF_INET;
                                as.sin_port = htons (portNumber);
                                as.sin_addr = iaddr.As<in_addr> ();
                            }
                            break;
                        case    InternetAddress::AddressFamily::V6: {
                                Assert (sizeof (sockaddr_in) == sizeof (sockaddr));
                                sockaddr_in6& as = reinterpret_cast<sockaddr_in6&> (fSocketAddress_);
                                as.sin6_family = AF_INET6;
                                as.sin6_port = htons (portNumber);
                                as.sin6_addr = iaddr.As<in6_addr> ();
                            }
                            break;
                        default: {
                                // just leave blank - no assert?
                            }
                            break;
                    }
                }
                inline  bool    SocketAddress::empty () const
                {
                    return fSocketAddress_.sa_family == AF_UNSPEC;
                    //constexpr sockaddr kZero_ = { 0 };
                    //return ::memcmp (&fSocketAddress_, &kZero_, sizeof (kZero_)) == 0;
                }
                inline  void    SocketAddress::clear ()
                {
                    fSocketAddress_.sa_family = AF_UNSPEC;
                    //::memset (&fSocketAddress_, 0, sizeof (fSocketAddress_));
                }
                inline  SocketAddress::FamilyType    SocketAddress::GetAddressFamily () const
                {
                    return fSocketAddress_.sa_family;
                }
                inline  bool    SocketAddress::IsInternetAddress () const
                {
                    return fSocketAddress_.sa_family == AF_INET or fSocketAddress_.sa_family == AF_INET6;
                }
                inline  InternetAddress    SocketAddress::GetInternetAddress () const
                {
                    Require (IsInternetAddress ());
                    switch (fSocketAddress_.sa_family) {
                        case AF_INET: {
                                Assert (sizeof (sockaddr_in) == sizeof (sockaddr));
                                const sockaddr_in& as = reinterpret_cast<const sockaddr_in&> (fSocketAddress_);
                                return InternetAddress (as.sin_addr);
                            }
                        case AF_INET6: {
                                Assert (sizeof (sockaddr_in6) == sizeof (sockaddr));
                                const sockaddr_in6& as = reinterpret_cast<const sockaddr_in6&> (fSocketAddress_);
                                return InternetAddress (as.sin6_addr);
                            }
                        default: {
                                AssertNotReached ();
                                return InternetAddress ();
                            }
                    }
                }
                inline  uint16_t    SocketAddress::GetPort () const
                {
                    Require (IsInternetAddress ());
                    switch (fSocketAddress_.sa_family) {
                        case AF_INET: {
                                Assert (sizeof (sockaddr_in) == sizeof (sockaddr));
                                const sockaddr_in& as = reinterpret_cast<const sockaddr_in&> (fSocketAddress_);
                                return ntohs (as.sin_port);
                            }
                        case AF_INET6: {
                                Assert (sizeof (sockaddr_in6) == sizeof (sockaddr));
                                const sockaddr_in6& as = reinterpret_cast<const sockaddr_in6&> (fSocketAddress_);
                                return ntohs (as.sin6_port);
                            }
                        default: {
                                AssertNotReached ();
                                return 0;
                            }
                    }
                }
                template    <typename T>
                T   SocketAddress::As () const
                {
#if     qCompilerAndStdLib_StaticAssertionsInTemplateFunctionsWhichShouldNeverBeExpanded_Buggy
                    RequireNotReached ();
#else
                    static_assert (false, "Only specifically specialized variants are supported");
#endif
                }
                template    <>
                inline  sockaddr   SocketAddress::As<sockaddr> () const
                {
                    return fSocketAddress_;
                }
                template    <>
                inline  sockaddr_in   SocketAddress::As<sockaddr_in> () const
                {
                    Assert (sizeof (sockaddr_in) == sizeof (fSocketAddress_));
                    const sockaddr_in& as = reinterpret_cast<const sockaddr_in&> (fSocketAddress_);
                    return as;
                }
                template    <>
                inline  sockaddr_in6   SocketAddress::As<sockaddr_in6> () const
                {
                    Assert (sizeof (sockaddr_in6) == sizeof (fSocketAddress_));
                    const sockaddr_in6& as = reinterpret_cast<const sockaddr_in6&> (fSocketAddress_);
                    return as;
                }

            }
        }
    }
}
#endif  /*_Stroika_Foundation_IO_Network_SocketAddress_inl_*/
<commit_msg>cleanup clang++ warning<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#ifndef _Stroika_Foundation_IO_Network_SocketAddress_inl_
#define _Stroika_Foundation_IO_Network_SocketAddress_inl_  1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
namespace   Stroika {
    namespace   Foundation {
        namespace   IO {
            namespace   Network {

                /*
                 ********************************************************************************
                 *********************** IO::Network::SocketAddress *****************************
                 ********************************************************************************
                 */
                inline  SocketAddress::SocketAddress ()
                    : fSocketAddress_ ()
                {
                    ::memset (&fSocketAddress_, 0, sizeof (fSocketAddress_));
                }
                inline  SocketAddress::SocketAddress (const sockaddr& iaddr)
                    : fSocketAddress_ ()
                {
                    Assert  (sizeof (fSocketAddress_) == sizeof (sockaddr));
                    ::memcpy (&fSocketAddress_, &iaddr, sizeof (fSocketAddress_));
                }
                inline  SocketAddress::SocketAddress (const sockaddr_in& iaddr)
                    : fSocketAddress_ ()
                {
                    Assert  (sizeof (fSocketAddress_) == sizeof (sockaddr));
                    Assert  (sizeof (fSocketAddress_) == sizeof (sockaddr_in));
                    ::memcpy (&fSocketAddress_, &iaddr, sizeof (fSocketAddress_));
                }
                inline  SocketAddress::SocketAddress (const InternetAddress& iaddr, uint16_t portNumber)
                    : fSocketAddress_ ()
                {
                    ::memset (&fSocketAddress_, 0, sizeof (fSocketAddress_));
                    switch (iaddr.GetAddressFamily ()) {
                        case    InternetAddress::AddressFamily::V4: {
                                Assert (sizeof (sockaddr_in) == sizeof (sockaddr));
                                sockaddr_in& as = reinterpret_cast<sockaddr_in&> (fSocketAddress_);
                                as.sin_family = AF_INET;
                                DISABLE_COMPILER_CLANG_WARNING_START("clang diagnostic ignored \"-Wdeprecated\"");  // macro uses 'register' - htons not deprecated
                                as.sin_port = htons (portNumber);
                                DISABLE_COMPILER_CLANG_WARNING_END("clang diagnostic ignored \"-Wdeprecated\"");
                                as.sin_addr = iaddr.As<in_addr> ();
                            }
                            break;
                        case    InternetAddress::AddressFamily::V6: {
                                Assert (sizeof (sockaddr_in) == sizeof (sockaddr));
                                sockaddr_in6& as = reinterpret_cast<sockaddr_in6&> (fSocketAddress_);
                                as.sin6_family = AF_INET6;
                                DISABLE_COMPILER_CLANG_WARNING_START("clang diagnostic ignored \"-Wdeprecated\"");  // macro uses 'register' - htons not deprecated
                                as.sin6_port = htons (portNumber);
                                DISABLE_COMPILER_CLANG_WARNING_END("clang diagnostic ignored \"-Wdeprecated\"");
                                as.sin6_addr = iaddr.As<in6_addr> ();
                            }
                            break;
                        default: {
                                // just leave blank - no assert?
                            }
                            break;
                    }
                }
                inline  bool    SocketAddress::empty () const
                {
                    return fSocketAddress_.sa_family == AF_UNSPEC;
                    //constexpr sockaddr kZero_ = { 0 };
                    //return ::memcmp (&fSocketAddress_, &kZero_, sizeof (kZero_)) == 0;
                }
                inline  void    SocketAddress::clear ()
                {
                    fSocketAddress_.sa_family = AF_UNSPEC;
                    //::memset (&fSocketAddress_, 0, sizeof (fSocketAddress_));
                }
                inline  SocketAddress::FamilyType    SocketAddress::GetAddressFamily () const
                {
                    return fSocketAddress_.sa_family;
                }
                inline  bool    SocketAddress::IsInternetAddress () const
                {
                    return fSocketAddress_.sa_family == AF_INET or fSocketAddress_.sa_family == AF_INET6;
                }
                inline  InternetAddress    SocketAddress::GetInternetAddress () const
                {
                    Require (IsInternetAddress ());
                    switch (fSocketAddress_.sa_family) {
                        case AF_INET: {
                                Assert (sizeof (sockaddr_in) == sizeof (sockaddr));
                                const sockaddr_in& as = reinterpret_cast<const sockaddr_in&> (fSocketAddress_);
                                return InternetAddress (as.sin_addr);
                            }
                        case AF_INET6: {
                                Assert (sizeof (sockaddr_in6) == sizeof (sockaddr));
                                const sockaddr_in6& as = reinterpret_cast<const sockaddr_in6&> (fSocketAddress_);
                                return InternetAddress (as.sin6_addr);
                            }
                        default: {
                                AssertNotReached ();
                                return InternetAddress ();
                            }
                    }
                }
                inline  uint16_t    SocketAddress::GetPort () const
                {
                    Require (IsInternetAddress ());
                    switch (fSocketAddress_.sa_family) {
                        case AF_INET: {
                                Assert (sizeof (sockaddr_in) == sizeof (sockaddr));
                                const sockaddr_in& as = reinterpret_cast<const sockaddr_in&> (fSocketAddress_);
                                return ntohs (as.sin_port);
                            }
                        case AF_INET6: {
                                Assert (sizeof (sockaddr_in6) == sizeof (sockaddr));
                                const sockaddr_in6& as = reinterpret_cast<const sockaddr_in6&> (fSocketAddress_);
                                return ntohs (as.sin6_port);
                            }
                        default: {
                                AssertNotReached ();
                                return 0;
                            }
                    }
                }
                template    <typename T>
                T   SocketAddress::As () const
                {
#if     qCompilerAndStdLib_StaticAssertionsInTemplateFunctionsWhichShouldNeverBeExpanded_Buggy
                    RequireNotReached ();
#else
                    static_assert (false, "Only specifically specialized variants are supported");
#endif
                }
                template    <>
                inline  sockaddr   SocketAddress::As<sockaddr> () const
                {
                    return fSocketAddress_;
                }
                template    <>
                inline  sockaddr_in   SocketAddress::As<sockaddr_in> () const
                {
                    Assert (sizeof (sockaddr_in) == sizeof (fSocketAddress_));
                    const sockaddr_in& as = reinterpret_cast<const sockaddr_in&> (fSocketAddress_);
                    return as;
                }
                template    <>
                inline  sockaddr_in6   SocketAddress::As<sockaddr_in6> () const
                {
                    Assert (sizeof (sockaddr_in6) == sizeof (fSocketAddress_));
                    const sockaddr_in6& as = reinterpret_cast<const sockaddr_in6&> (fSocketAddress_);
                    return as;
                }

            }
        }
    }
}
#endif  /*_Stroika_Foundation_IO_Network_SocketAddress_inl_*/
<|endoftext|>


<commit_before><commit_msg>CppunitTest_sw_rtfimport: disable 3 checks for now<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: accgraphic.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2007-09-27 08:21:32 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _ACCGRAPHIC_HXX
#define _ACCGRAPHIC_HXX
#ifndef _ACCNOTEXTFRAME_HXX
#include "accnotextframe.hxx"
#endif

class SwAccessibleGraphic : public  SwAccessibleNoTextFrame
{

protected:

    virtual ~SwAccessibleGraphic();

public:

    SwAccessibleGraphic( SwAccessibleMap* pInitMap,
                         const SwFlyFrm *pFlyFrm );

    //=====  XServiceInfo  ====================================================

    /** Returns an identifier for the implementation of this object.
    */
    virtual ::rtl::OUString SAL_CALL
        getImplementationName (void)
        throw (::com::sun::star::uno::RuntimeException);

    /** Return whether the specified service is supported by this class.
    */
    virtual sal_Bool SAL_CALL
        supportsService (const ::rtl::OUString& sServiceName)
        throw (::com::sun::star::uno::RuntimeException);

    /** Returns a list of all supported services.  In this case that is just
        the AccessibleContext service.
    */
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
        getSupportedServiceNames (void)
        throw (::com::sun::star::uno::RuntimeException);

    //=====  XTypeProvider  ====================================================
    virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId(  ) throw(::com::sun::star::uno::RuntimeException);
};

#endif
<commit_msg>INTEGRATION: CWS changefileheader (1.5.242); FILE MERGED 2008/04/01 12:53:45 thb 1.5.242.2: #i85898# Stripping all external header guards 2008/03/31 16:53:38 rt 1.5.242.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: accgraphic.hxx,v $
 * $Revision: 1.6 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef _ACCGRAPHIC_HXX
#define _ACCGRAPHIC_HXX
#include "accnotextframe.hxx"

class SwAccessibleGraphic : public  SwAccessibleNoTextFrame
{

protected:

    virtual ~SwAccessibleGraphic();

public:

    SwAccessibleGraphic( SwAccessibleMap* pInitMap,
                         const SwFlyFrm *pFlyFrm );

    //=====  XServiceInfo  ====================================================

    /** Returns an identifier for the implementation of this object.
    */
    virtual ::rtl::OUString SAL_CALL
        getImplementationName (void)
        throw (::com::sun::star::uno::RuntimeException);

    /** Return whether the specified service is supported by this class.
    */
    virtual sal_Bool SAL_CALL
        supportsService (const ::rtl::OUString& sServiceName)
        throw (::com::sun::star::uno::RuntimeException);

    /** Returns a list of all supported services.  In this case that is just
        the AccessibleContext service.
    */
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
        getSupportedServiceNames (void)
        throw (::com::sun::star::uno::RuntimeException);

    //=====  XTypeProvider  ====================================================
    virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId(  ) throw(::com::sun::star::uno::RuntimeException);
};

#endif
<|endoftext|>


<commit_before>
#include "LocaleSharedMemory.hpp"

#ifndef SHMMAX
#error "no SHMMAX defined for this system -- look it up with the command: `sysctl -A | grep shm`"
#endif

const int64_t default_locale_reserved_size = (1L << 32);
DEFINE_int64( locale_reserved_size, default_locale_reserved_size, "Shared memory between cores on node, reserved for runtime" );
DEFINE_int64( locale_shared_size, SHMMAX + FLAGS_locale_reserved_size, "Total shared memory between cores on node" );

DECLARE_bool( global_memory_use_hugepages );

// forward declarations
namespace Grappa {
namespace impl {

/// called on failures to backtrace and pause for debugger
extern void failure_function();

/// how much memory do we expect to allocate?
extern int64_t global_memory_size_bytes;
extern int64_t global_bytes_per_core;
extern int64_t global_bytes_per_locale;

}
}

namespace Grappa {
namespace impl {

/// global LocaleSharedMemory instance
LocaleSharedMemory locale_shared_memory;

void LocaleSharedMemory::create() {
  region_size = FLAGS_locale_shared_size;
  VLOG(2) << "Creating LocaleSharedMemory region " << region_name
          << " with " << region_size << " bytes"
          << " on " << global_communicator.mycore()
          << " of " << global_communicator.cores();

  // if possible, delete this user's old leftover share memory regions
  // if this returns false, either there was nothing to delete or
  // there was something owned by somebody else.
  bool deleted_one = boost::interprocess::shared_memory_object::remove( region_name.c_str() );
  if( deleted_one ) {
    VLOG(1) << "Deleted an old, leftover " << region_name.c_str();
  }

  // now, try to allocate a new one
  try {
    segment = boost::interprocess::fixed_managed_shared_memory( boost::interprocess::create_only,
                                                                region_name.c_str(),
                                                                region_size,
                                                                base_address);
  }
  catch(...){
    boost::interprocess::shared_memory_object::remove( region_name.c_str() );
    failure_function();
    throw;
  }
  VLOG(2) << "Created LocaleSharedMemory region " << region_name
          << " with " << region_size << " bytes"
          << " on " << global_communicator.mycore()
          << " of " << global_communicator.cores();
}

void LocaleSharedMemory::attach() {
  // first, check that we can create something large enough
  CHECK_GE( FLAGS_locale_shared_size, global_bytes_per_locale )
    << "Can't accomodate " << global_bytes_per_locale << " bytes of shared heap per locale with "
    << FLAGS_locale_shared_size << " total shared bytes.";

  VLOG(2) << "Attaching to LocaleSharedMemory region " << region_name
          << " on " << global_communicator.mycore()
          << " of " << global_communicator.cores();
  try {
    segment = boost::interprocess::fixed_managed_shared_memory( boost::interprocess::open_only,
                                                                region_name.c_str(),
                                                                base_address );
  }
  catch(...){
    boost::interprocess::shared_memory_object::remove( region_name.c_str() );
    failure_function();
    throw;
  }
  VLOG(2) << "Attached to LocaleSharedMemory region " << region_name
          << " on " << global_communicator.mycore()
          << " of " << global_communicator.cores();
}

void LocaleSharedMemory::destroy() {
  VLOG(2) << "Removing LocaleSharedMemory region " << region_name
          << " on " << global_communicator.mycore()
          << " of " << global_communicator.cores();
  boost::interprocess::shared_memory_object::remove( region_name.c_str() );
  VLOG(2) << "Removed LocaleSharedMemory region " << region_name
          << " on " << global_communicator.mycore()
          << " of " << global_communicator.cores();
}

LocaleSharedMemory::LocaleSharedMemory()
  : region_size( FLAGS_locale_shared_size )
  , region_name( "GrappaLocaleSharedMemory" )
  , base_address( reinterpret_cast<void*>( 0x400000000000L ) )
  , segment() // default constructor; initialize later
{
  boost::interprocess::shared_memory_object::remove( region_name.c_str() );

  // TODO: figure out reasonable region size
  // maybe reuse SHMMAX stuff?

}

LocaleSharedMemory::~LocaleSharedMemory() {
  boost::interprocess::shared_memory_object::remove( region_name.c_str() );
}

void LocaleSharedMemory::init() {
  if( FLAGS_locale_reserved_size != default_locale_reserved_size ) {
    FLAGS_locale_shared_size = SHMMAX + FLAGS_locale_reserved_size;
  }
}

void LocaleSharedMemory::activate() {
  if( Grappa::locale_mycore() == 0 ) { create(); }
  global_communicator.barrier();
  if( Grappa::locale_mycore() != 0 ) { attach(); }
  global_communicator.barrier();
}

void LocaleSharedMemory::finish() {
  global_communicator.barrier();
  if( Grappa::locale_mycore() == 0 ) { destroy(); }
}

void * LocaleSharedMemory::allocate( size_t size ) {
  void * p = NULL;
  try {
    p = Grappa::impl::locale_shared_memory.segment.allocate( size );
  }
  catch(...){
    LOG(ERROR) << "Allocation failed with size " << size;
    failure_function();
    throw;
  }
  return p;
}

void * LocaleSharedMemory::allocate_aligned( size_t size, size_t alignment ) {
  void * p = NULL;
  try {
    p = Grappa::impl::locale_shared_memory.segment.allocate_aligned( size, alignment );
  }
  catch(...){
    LOG(ERROR) << "Aligned allocation failed with size " << size << " alignment " << alignment;
    failure_function();
    throw;
  }
  return p;
}

void LocaleSharedMemory::deallocate( void * ptr ) {
  try {
    Grappa::impl::locale_shared_memory.segment.deallocate( ptr );
  }
  catch(...){
    failure_function();
    throw;
  }
}

} // namespace impl
} // namespace Grappa
<commit_msg>Add better logging from allocation failures<commit_after>
#include "LocaleSharedMemory.hpp"

#ifndef SHMMAX
#error "no SHMMAX defined for this system -- look it up with the command: `sysctl -A | grep shm`"
#endif

const int64_t default_locale_reserved_size = (1L << 32);
DEFINE_int64( locale_reserved_size, default_locale_reserved_size, "Shared memory between cores on node, reserved for runtime" );
DEFINE_int64( locale_shared_size, SHMMAX + FLAGS_locale_reserved_size, "Total shared memory between cores on node" );

DECLARE_bool( global_memory_use_hugepages );

// forward declarations
namespace Grappa {
namespace impl {

/// called on failures to backtrace and pause for debugger
extern void failure_function();

/// how much memory do we expect to allocate?
extern int64_t global_memory_size_bytes;
extern int64_t global_bytes_per_core;
extern int64_t global_bytes_per_locale;

}
}

namespace Grappa {
namespace impl {

/// global LocaleSharedMemory instance
LocaleSharedMemory locale_shared_memory;

void LocaleSharedMemory::create() {
  region_size = FLAGS_locale_shared_size;
  VLOG(2) << "Creating LocaleSharedMemory region " << region_name
          << " with " << region_size << " bytes"
          << " on " << global_communicator.mycore()
          << " of " << global_communicator.cores();

  // if possible, delete this user's old leftover share memory regions
  // if this returns false, either there was nothing to delete or
  // there was something owned by somebody else.
  bool deleted_one = boost::interprocess::shared_memory_object::remove( region_name.c_str() );
  if( deleted_one ) {
    VLOG(1) << "Deleted an old, leftover " << region_name.c_str();
  }

  // now, try to allocate a new one
  try {
    segment = boost::interprocess::fixed_managed_shared_memory( boost::interprocess::create_only,
                                                                region_name.c_str(),
                                                                region_size,
                                                                base_address);
  }
  catch(...){
    boost::interprocess::shared_memory_object::remove( region_name.c_str() );
    failure_function();
    throw;
  }
  VLOG(2) << "Created LocaleSharedMemory region " << region_name
          << " with " << region_size << " bytes"
          << " on " << global_communicator.mycore()
          << " of " << global_communicator.cores();
}

void LocaleSharedMemory::attach() {
  // first, check that we can create something large enough
  CHECK_GE( FLAGS_locale_shared_size, global_bytes_per_locale )
    << "Can't accomodate " << global_bytes_per_locale << " bytes of shared heap per locale with "
    << FLAGS_locale_shared_size << " total shared bytes.";

  VLOG(2) << "Attaching to LocaleSharedMemory region " << region_name
          << " on " << global_communicator.mycore()
          << " of " << global_communicator.cores();
  try {
    segment = boost::interprocess::fixed_managed_shared_memory( boost::interprocess::open_only,
                                                                region_name.c_str(),
                                                                base_address );
  }
  catch(...){
    boost::interprocess::shared_memory_object::remove( region_name.c_str() );
    failure_function();
    throw;
  }
  VLOG(2) << "Attached to LocaleSharedMemory region " << region_name
          << " on " << global_communicator.mycore()
          << " of " << global_communicator.cores();
}

void LocaleSharedMemory::destroy() {
  VLOG(2) << "Removing LocaleSharedMemory region " << region_name
          << " on " << global_communicator.mycore()
          << " of " << global_communicator.cores();
  boost::interprocess::shared_memory_object::remove( region_name.c_str() );
  VLOG(2) << "Removed LocaleSharedMemory region " << region_name
          << " on " << global_communicator.mycore()
          << " of " << global_communicator.cores();
}

LocaleSharedMemory::LocaleSharedMemory()
  : region_size( FLAGS_locale_shared_size )
  , region_name( "GrappaLocaleSharedMemory" )
  , base_address( reinterpret_cast<void*>( 0x400000000000L ) )
  , segment() // default constructor; initialize later
{
  boost::interprocess::shared_memory_object::remove( region_name.c_str() );

  // TODO: figure out reasonable region size
  // maybe reuse SHMMAX stuff?

}

LocaleSharedMemory::~LocaleSharedMemory() {
  boost::interprocess::shared_memory_object::remove( region_name.c_str() );
}

void LocaleSharedMemory::init() {
  if( FLAGS_locale_reserved_size != default_locale_reserved_size ) {
    FLAGS_locale_shared_size = SHMMAX + FLAGS_locale_reserved_size;
  }
}

void LocaleSharedMemory::activate() {
  if( Grappa::locale_mycore() == 0 ) { create(); }
  global_communicator.barrier();
  if( Grappa::locale_mycore() != 0 ) { attach(); }
  global_communicator.barrier();
}

void LocaleSharedMemory::finish() {
  global_communicator.barrier();
  if( Grappa::locale_mycore() == 0 ) { destroy(); }
}

void * LocaleSharedMemory::allocate( size_t size ) {
  void * p = NULL;
  try {
    p = Grappa::impl::locale_shared_memory.segment.allocate( size );
  }
  catch(...){
    LOG(ERROR) << "Allocation of " << size << " bytes failed with "
               << get_free_memory() << " free.";
    failure_function();
    throw;
  }
  return p;
}

void * LocaleSharedMemory::allocate_aligned( size_t size, size_t alignment ) {
  void * p = NULL;
  try {
    p = Grappa::impl::locale_shared_memory.segment.allocate_aligned( size, alignment );
  }
  catch(...){
    LOG(ERROR) << "Allocation of " << size << " bytes with alignment " << alignment
               << " failed with " << get_free_memory() << " free.";
    failure_function();
    throw;
  }
  return p;
}

void LocaleSharedMemory::deallocate( void * ptr ) {
  try {
    Grappa::impl::locale_shared_memory.segment.deallocate( ptr );
  }
  catch(...){
    LOG(ERROR) << "Deallocation of " << ptr
               << " failed with " << get_free_memory() << " free.";
    failure_function();
    throw;
  }
}

} // namespace impl
} // namespace Grappa
<|endoftext|>


<commit_before>#ifndef DUNE_STUFF_DISCRETEFUNCTION_PROJECTION_DIRICHLET_HH
#define DUNE_STUFF_DISCRETEFUNCTION_PROJECTION_DIRICHLET_HH

#ifdef HAVE_CMAKE_CONFIG
  #include "cmake_config.h"
#else
  #include "config.h"
#endif // ifdef HAVE_CMAKE_CONFIG

#include <vector>

#include <dune/common/shared_ptr.hh>

#if HAVE_DUNE_DETAILED_DISCRETIZATIONS
  #include <dune/detailed/discretizations/discretefunction/default.hh>
#endif // HAVE_DUNE_DETAILED_DISCRETIZATIONS

#include <dune/stuff/grid/boundaryinfo.hh>
#include <dune/stuff/grid/intersection.hh>

namespace Dune {
namespace Stuff {
namespace DiscreteFunction {
namespace Projection {
namespace Dirichlet {

#if HAVE_DUNE_DETAILED_DISCRETIZATIONS
template< class FunctionType,
          class DiscreteFunctionSpaceType, class VectorType >
void project(const Dune::Stuff::Grid::BoundaryInfo::Interface< typename DiscreteFunctionSpaceType::GridViewType >& boundaryInfo,
             const FunctionType& function,
             Dune::Detailed::Discretizations::DiscreteFunction::Default< DiscreteFunctionSpaceType, VectorType >& discreteFunction)
{
  // some types
  typedef Dune::Detailed::Discretizations::DiscreteFunction::Default< DiscreteFunctionSpaceType, VectorType > DiscreteFunctionType;
  typedef typename DiscreteFunctionSpaceType::GridPartType GridPartType;
  typedef typename GridPartType::template Codim< 0 >::IteratorType EntityIteratorType;
  typedef typename GridPartType::template Codim< 0 >::EntityType EntityType;
  typedef typename EntityType::Geometry GeometryType;
  typedef typename GridPartType::IntersectionIteratorType IntersectionIteratorType;
  typedef typename IntersectionIteratorType::Intersection IntersectionType;
  typedef typename DiscreteFunctionSpaceType::BaseFunctionSetType BaseFunctionSetType;
  typedef typename DiscreteFunctionType::LocalFunctionType LocalFunctionType;
  typedef typename DiscreteFunctionSpaceType::FunctionSpaceType FunctionSpaceType;
  typedef typename FunctionSpaceType::DomainType DomainType;
  typedef typename FunctionSpaceType::RangeType RangeType;
  // preparations
  RangeType tmpEvaluation(0.0);
  const DiscreteFunctionSpaceType& space = discreteFunction.space();
  const GridPartType& gridPart = space.gridPart();
  discreteFunction.clear();
  // walk the grid
  for (EntityIteratorType entityIt = gridPart.template begin< 0 >();
       entityIt != gridPart.template end< 0 >();
       ++entityIt)
  {
    // only consider entities with boundary intersection
    const EntityType& entity = *entityIt;
    const GeometryType& geometry = entity.geometry();
    if(entity.hasBoundaryIntersections()) {
      // local function of destination
      LocalFunctionType localFunction = discreteFunction.localFunction(entity);
      // get the Lagrange point set
      typedef typename DiscreteFunctionSpaceType::MapperType::LagrangePointSetType LagrangePointSetType;
      const LagrangePointSetType lagrangePointSet = space.map().lagrangePointSet(entity);
      // get the lagrange points' coordinates
      typedef typename LagrangePointSetType::CoordinateType LagrangePointCoordinateType;
      std::vector< LagrangePointCoordinateType > lagrangePointsGlobal(lagrangePointSet.nop(),
                                                                      LagrangePointCoordinateType(0.0));
      for (unsigned int i = 0; i < lagrangePointSet.nop(); ++i)
        lagrangePointsGlobal[i] = geometry.global(lagrangePointSet.point(i));
      // walk all intersections
      for (IntersectionIteratorType intersectionIt = gridPart.ibegin(entity);
           intersectionIt != gridPart.iend( entity );
           ++intersectionIt) {
        const IntersectionType& intersection = *intersectionIt;
        // only consider dirichlet boundary intersection
        if (boundaryInfo.dirichlet(intersection)) {
          // loop over all lagrange points
          for (unsigned int i = 0; i < lagrangePointSet.nop(); ++i )
          {
            // if dof lies on the boundary intersection
            if (Dune::Stuff::Grid::intersectionContains(intersection, lagrangePointsGlobal[i])) {
              // evaluate the function
              function.evaluate(lagrangePointsGlobal[i], tmpEvaluation);
              // set the corresponding local dof
              localFunction.set(i, tmpEvaluation);
            } // if dof lies on the boundary intersection
          } // loop over all lagrange points
        } // only consider dirichlet boundary intersection
      } // walk all intersections
    } // only consider entities with boundary intersection
  } // walk the grid
} // static void project()
#endif // HAVE_DUNE_DETAILED_DISCRETIZATIONS

} // namespace Dirichlet
} // namespace Projection
} // namespace DiscreteFunction
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_DISCRETEFUNCTION_PROJECTION_DIRICHLET_HH
<commit_msg>[discretefunction.projection.dirichlet] update<commit_after>#ifndef DUNE_STUFF_DISCRETEFUNCTION_PROJECTION_DIRICHLET_HH
#define DUNE_STUFF_DISCRETEFUNCTION_PROJECTION_DIRICHLET_HH

#ifdef HAVE_CMAKE_CONFIG
  #include "cmake_config.h"
#else
  #include "config.h"
#endif // ifdef HAVE_CMAKE_CONFIG

#include <vector>

#include <dune/common/shared_ptr.hh>

#if HAVE_DUNE_DETAILED_DISCRETIZATIONS
  #include <dune/detailed/discretizations/discretefunction/default.hh>
#endif // HAVE_DUNE_DETAILED_DISCRETIZATIONS

#include <dune/stuff/grid/boundaryinfo.hh>
#include <dune/stuff/grid/intersection.hh>

namespace Dune {
namespace Stuff {
namespace DiscreteFunction {
namespace Projection {
namespace Dirichlet {

#if HAVE_DUNE_DETAILED_DISCRETIZATIONS
template< class FunctionType,
          class DiscreteFunctionSpaceType, class VectorType >
void project(const Dune::Stuff::GridboundaryInterface< typename DiscreteFunctionSpaceType::GridViewType >& boundaryInfo,
             const FunctionType& function,
             Dune::Detailed::Discretizations::DiscreteFunction::Default< DiscreteFunctionSpaceType, VectorType >& discreteFunction)
{
  // some types
  typedef Dune::Detailed::Discretizations::DiscreteFunction::Default< DiscreteFunctionSpaceType, VectorType > DiscreteFunctionType;
  typedef typename DiscreteFunctionSpaceType::GridPartType GridPartType;
  typedef typename GridPartType::template Codim< 0 >::IteratorType EntityIteratorType;
  typedef typename GridPartType::template Codim< 0 >::EntityType EntityType;
  typedef typename EntityType::Geometry GeometryType;
  typedef typename GridPartType::IntersectionIteratorType IntersectionIteratorType;
  typedef typename IntersectionIteratorType::Intersection IntersectionType;
  typedef typename DiscreteFunctionSpaceType::BaseFunctionSetType BaseFunctionSetType;
  typedef typename DiscreteFunctionType::LocalFunctionType LocalFunctionType;
  typedef typename DiscreteFunctionSpaceType::FunctionSpaceType FunctionSpaceType;
  typedef typename FunctionSpaceType::DomainType DomainType;
  typedef typename FunctionSpaceType::RangeType RangeType;
  // preparations
  RangeType tmpEvaluation(0.0);
  const DiscreteFunctionSpaceType& space = discreteFunction.space();
  const GridPartType& gridPart = space.gridPart();
  discreteFunction.clear();
  // walk the grid
  for (EntityIteratorType entityIt = gridPart.template begin< 0 >();
       entityIt != gridPart.template end< 0 >();
       ++entityIt)
  {
    // only consider entities with boundary intersection
    const EntityType& entity = *entityIt;
    const GeometryType& geometry = entity.geometry();
    if(entity.hasBoundaryIntersections()) {
      // local function of destination
      LocalFunctionType localFunction = discreteFunction.localFunction(entity);
      // get the Lagrange point set
      typedef typename DiscreteFunctionSpaceType::MapperType::LagrangePointSetType LagrangePointSetType;
      const LagrangePointSetType lagrangePointSet = space.map().lagrangePointSet(entity);
      // get the lagrange points' coordinates
      typedef typename LagrangePointSetType::CoordinateType LagrangePointCoordinateType;
      std::vector< LagrangePointCoordinateType > lagrangePointsGlobal(lagrangePointSet.nop(),
                                                                      LagrangePointCoordinateType(0.0));
      for (unsigned int i = 0; i < lagrangePointSet.nop(); ++i)
        lagrangePointsGlobal[i] = geometry.global(lagrangePointSet.point(i));
      // walk all intersections
      for (IntersectionIteratorType intersectionIt = gridPart.ibegin(entity);
           intersectionIt != gridPart.iend( entity );
           ++intersectionIt) {
        const IntersectionType& intersection = *intersectionIt;
        // only consider dirichlet boundary intersection
        if (boundaryInfo.dirichlet(intersection)) {
          // loop over all lagrange points
          for (unsigned int i = 0; i < lagrangePointSet.nop(); ++i )
          {
            // if dof lies on the boundary intersection
            if (Dune::Stuff::Grid::intersectionContains(intersection, lagrangePointsGlobal[i])) {
              // evaluate the function
              function.evaluate(lagrangePointsGlobal[i], tmpEvaluation);
              // set the corresponding local dof
              localFunction.set(i, tmpEvaluation);
            } // if dof lies on the boundary intersection
          } // loop over all lagrange points
        } // only consider dirichlet boundary intersection
      } // walk all intersections
    } // only consider entities with boundary intersection
  } // walk the grid
} // static void project()
#endif // HAVE_DUNE_DETAILED_DISCRETIZATIONS

} // namespace Dirichlet
} // namespace Projection
} // namespace DiscreteFunction
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_DISCRETEFUNCTION_PROJECTION_DIRICHLET_HH
<|endoftext|>


<commit_before>//=============================================================================================================
/**
* @file     test_spectral_connectivity.cpp
* @author   Daniel Strohmeier <daniel.strohmeier@tu-ilmenau.de>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     May, 2018
*
* @section  LICENSE
*
* Copyright (C) 2018, Daniel Strohmeier and Matti Hamalainen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
*       following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
*       the following disclaimer in the documentation and/or other materials provided with the distribution.
*     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
*       to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* @brief    The spectral connectivity test implementation
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include <iostream>
#include <mne/mne.h>
#include <utils/ioutils.h>
#include "connectivity/metrics/coherence.h"

//*************************************************************************************************************
//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QtTest>

//*************************************************************************************************************
//=============================================================================================================
// Eigen INCLUDES
//=============================================================================================================

#include <Eigen/Core>

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace Eigen;
using namespace CONNECTIVITYLIB;
using namespace UTILSLIB;

//=============================================================================================================
/**
* DECLARE CLASS TestSpectralConnectivity
*
* @brief The TestSpectralConnectivity class provides spectral connectivity tests
*
*/
class TestSpectralConnectivity: public QObject
{
    Q_OBJECT

public:
    TestSpectralConnectivity();

private slots:
    void initTestCase();
    void spectralConnectivityCoherence();
    void spectralConnectivityImagCoherence();
    void spectralConnectivityPLV();
    void spectralConnectivityPLI();
    void spectralConnectivityPLI2();
    void spectralConnectivityWPLI();
    void spectralConnectivityWPLI2();
    void cleanupTestCase();

private:
    void compareConnectivity();
    double epsilon;
    RowVectorXd m_ConnectivityOutput;
    RowVectorXd m_RefConnectivityOutput;
};

//*************************************************************************************************************

TestSpectralConnectivity::TestSpectralConnectivity()
: epsilon(0.000001)
{
}

//*************************************************************************************************************

void TestSpectralConnectivity::TestSpectralConnectivity()
{

}

//*************************************************************************************************************

void TestSpectralConnectivity::spectralConnectivityCoherence()
{
    //*********************************************************************************************************
    // Load Data
    //*********************************************************************************************************

    inputTrials = MatrixXd();
    QString dataFileName(QDir::currentPath()+"/mne-cpp-test-data/MEG/sample/data_spectral_connectivity.txt");
    IOUtils::read_eigen_matrix(inputTrials, dataFileName);
    int iNTrials = inputTrials.rows() / 2;
    int iNfft = inputTrials.cols();
    QString sWindowType = "hanning";

    QList<MatrixXd> matDataList;
    for (int i = 0; i < iNTrials; ++i)
    {
        matDataList.append(inputTrials.middleRows(i * 2, 2));
    }

    //*********************************************************************************************************
    // Compute Connectivity
    //*********************************************************************************************************

    QVector<MatrixXd> Coh = Coherence::computeCoherence(matDataList, iNfft, sWindowType);
    m_ConnectivityOutput = Coh.at(0).row(1);

    //*********************************************************************************************************
    // Load MNE-PYTHON Results As Reference
    //*********************************************************************************************************

    refConnectivity = MatrixXd();
    QString refFileName(QDir::currentPath()+"/mne-cpp-test-data/Result/ref_spectral_connectivity_coh.txt");
    IOUtils::read_eigen_matrix(refConnectivity, refFileName);
    m_RefConnectivityOutput = refConnectivity.row(0);

    //*********************************************************************************************************
    // Compare Connectivity
    //*********************************************************************************************************

    compareConnectivity();
}

//*************************************************************************************************************

void TestSpectralConnectivity::compareConnectivity()
{
    //*********************************************************************************************************
    // Compare Spectral Connectvitity Result to MNE-PYTHON
    //*********************************************************************************************************

    printf(">>>>>>>>>>>>>>>>>>>>>>>>> Compare Spectral Connectivities >>>>>>>>>>>>>>>>>>>>>>>>>\n");

    QVERIFY( m_ConnectivityOutput.cols() == m_RefConnectivityOutput.cols() );
    for (int i = 0; i < m_ConnectivityOutput.cols(); ++i)
    {
        QVERIFY( (m_ConnectivityOutput(i) - m_RefConnectivityOutput(i)) / m_RefConnectivityOutput(i) < epsilon );
    }

    printf("<<<<<<<<<<<<<<<<<<<<<<<<< Compare Spectral Connectivities Finished <<<<<<<<<<<<<<<<<<<<<<<<<\n");
}

//*************************************************************************************************************

void TestSpectralConnectivity::cleanupTestCase()
{
}

//*************************************************************************************************************
//=============================================================================================================
// MAIN
//=============================================================================================================

QTEST_APPLESS_MAIN(TestSpectralConnectivity)
<commit_msg>added imagcoh test<commit_after>//=============================================================================================================
/**
* @file     test_spectral_connectivity.cpp
* @author   Daniel Strohmeier <daniel.strohmeier@tu-ilmenau.de>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     May, 2018
*
* @section  LICENSE
*
* Copyright (C) 2018, Daniel Strohmeier and Matti Hamalainen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
*       following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
*       the following disclaimer in the documentation and/or other materials provided with the distribution.
*     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
*       to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* @brief    The spectral connectivity test implementation
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include <iostream>
#include <mne/mne.h>
#include <utils/ioutils.h>
#include "connectivity/metrics/coherence.h"
#include "connectivity/metrics/imagcoherence.h"

//*************************************************************************************************************
//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QtTest>

//*************************************************************************************************************
//=============================================================================================================
// Eigen INCLUDES
//=============================================================================================================

#include <Eigen/Core>

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace Eigen;
using namespace CONNECTIVITYLIB;
using namespace UTILSLIB;

//=============================================================================================================
/**
* DECLARE CLASS TestSpectralConnectivity
*
* @brief The TestSpectralConnectivity class provides spectral connectivity tests
*
*/
class TestSpectralConnectivity: public QObject
{
    Q_OBJECT

public:
    TestSpectralConnectivity();

private slots:
    void initTestCase();
    void spectralConnectivityCoherence();
    void spectralConnectivityImagCoherence();
    void spectralConnectivityPLV();
    void spectralConnectivityPLI();
    void spectralConnectivityPLI2();
    void spectralConnectivityWPLI();
    void spectralConnectivityWPLI2();
    void cleanupTestCase();

private:
    void compareConnectivity();
    double epsilon;
    RowVectorXd m_ConnectivityOutput;
    RowVectorXd m_RefConnectivityOutput;
};

//*************************************************************************************************************

TestSpectralConnectivity::TestSpectralConnectivity()
: epsilon(0.000001)
{
}

//*************************************************************************************************************

void TestSpectralConnectivity::TestSpectralConnectivity()
{

}

//*************************************************************************************************************

void TestSpectralConnectivity::spectralConnectivityCoherence()
{
    //*********************************************************************************************************
    // Load Data
    //*********************************************************************************************************

    inputTrials = MatrixXd();
    QString dataFileName(QDir::currentPath()+"/mne-cpp-test-data/MEG/sample/data_spectral_connectivity.txt");
    IOUtils::read_eigen_matrix(inputTrials, dataFileName);
    int iNTrials = inputTrials.rows() / 2;
    int iNfft = inputTrials.cols();
    QString sWindowType = "hanning";

    QList<MatrixXd> matDataList;
    for (int i = 0; i < iNTrials; ++i)
    {
        matDataList.append(inputTrials.middleRows(i * 2, 2));
    }

    //*********************************************************************************************************
    // Compute Connectivity
    //*********************************************************************************************************

    QVector<MatrixXd> Coh = Coherence::computeCoherence(matDataList, iNfft, sWindowType);
    m_ConnectivityOutput = Coh.at(0).row(1);

    //*********************************************************************************************************
    // Load MNE-PYTHON Results As Reference
    //*********************************************************************************************************

    refConnectivity = MatrixXd();
    QString refFileName(QDir::currentPath()+"/mne-cpp-test-data/Result/Connectivity/ref_spectral_connectivity_coh.txt");
    IOUtils::read_eigen_matrix(refConnectivity, refFileName);
    m_RefConnectivityOutput = refConnectivity.row(0);

    //*********************************************************************************************************
    // Compare Connectivity
    //*********************************************************************************************************

    compareConnectivity();
}

//*************************************************************************************************************

void TestSpectralConnectivity::spectralConnectivityImagCoherence()
{
    //*********************************************************************************************************
    // Load Data
    //*********************************************************************************************************

    inputTrials = MatrixXd();
    QString dataFileName(QDir::currentPath()+"/mne-cpp-test-data/MEG/sample/data_spectral_connectivity.txt");
    IOUtils::read_eigen_matrix(inputTrials, dataFileName);
    int iNTrials = inputTrials.rows() / 2;
    int iNfft = inputTrials.cols();
    QString sWindowType = "hanning";

    QList<MatrixXd> matDataList;
    for (int i = 0; i < iNTrials; ++i)
    {
        matDataList.append(inputTrials.middleRows(i * 2, 2));
    }

    //*********************************************************************************************************
    // Compute Connectivity
    //*********************************************************************************************************

    QVector<MatrixXd> Coh = Coherence::computeImagCoherence(matDataList, iNfft, sWindowType);
    m_ConnectivityOutput = Coh.at(0).row(1);

    //*********************************************************************************************************
    // Load MNE-PYTHON Results As Reference
    //*********************************************************************************************************

    refConnectivity = MatrixXd();
    QString refFileName(QDir::currentPath()+"/mne-cpp-test-data/Result/Connectivty/ref_spectral_connectivity_icoh.txt");
    IOUtils::read_eigen_matrix(refConnectivity, refFileName);
    m_RefConnectivityOutput = refConnectivity.row(0);

    //*********************************************************************************************************
    // Compare Connectivity
    //*********************************************************************************************************

    compareConnectivity();
}

//*************************************************************************************************************

void TestSpectralConnectivity::compareConnectivity()
{
    //*********************************************************************************************************
    // Compare Spectral Connectvitity Result to MNE-PYTHON
    //*********************************************************************************************************

    printf(">>>>>>>>>>>>>>>>>>>>>>>>> Compare Spectral Connectivities >>>>>>>>>>>>>>>>>>>>>>>>>\n");

    QVERIFY( m_ConnectivityOutput.cols() == m_RefConnectivityOutput.cols() );
    for (int i = 0; i < m_ConnectivityOutput.cols(); ++i)
    {
        QVERIFY( (m_ConnectivityOutput(i) - m_RefConnectivityOutput(i)) / m_RefConnectivityOutput(i) < epsilon );
    }

    printf("<<<<<<<<<<<<<<<<<<<<<<<<< Compare Spectral Connectivities Finished <<<<<<<<<<<<<<<<<<<<<<<<<\n");
}

//*************************************************************************************************************

void TestSpectralConnectivity::cleanupTestCase()
{
}

//*************************************************************************************************************
//=============================================================================================================
// MAIN
//=============================================================================================================

QTEST_APPLESS_MAIN(TestSpectralConnectivity)
<|endoftext|>