<commit_before>// btlso_defaulteventmanager_devpoll.cpp                              -*-C++-*-

// ----------------------------------------------------------------------------
//                                   NOTICE
//
// This component is not up to date with current BDE coding standards, and
// should not be used as an example for new development.
// ----------------------------------------------------------------------------

#include <btlso_defaulteventmanager_devpoll.h>

#include <bsls_ident.h>
BSLS_IDENT_RCSID(btlso_defaulteventmanager_devpoll_cpp,"$Id$ $CSID$")

#include <btlso_timemetrics.h>
#include <btlso_flag.h>

#include <bsls_timeinterval.h>
#include <bdlb_bitmaskutil.h>
#include <bdlb_bitutil.h>
#include <bdlt_currenttime.h>
#include <bsls_assert.h>

#if defined(BSLS_PLATFORM_OS_SOLARIS) || defined(BSLS_PLATFORM_OS_HPUX)
#include <sys/devpoll.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/file.h>
#include <bsl_algorithm.h>
#include <bsl_c_errno.h>
#include <bsl_cstring.h>
#include <bsl_limits.h>
#include <bsl_utility.h>

namespace BloombergLP {

namespace btlso {

namespace {
    // unnamed namespace for private resources

enum {
    MIN_IOCTL_TIMEOUT_MS = 333  // force spinning of devpoll every 333ms,
                                // otherwise a bug on Solaris may cause
                                // missing events if passing a longer timeout
                                // to ioctl(fd, DP_POLL, ...)
};

const int k_POLLFD_SIZE = static_cast<int>(sizeof(struct ::pollfd));

// This object is used to initialize and grow the working arrays passed to
// ioctl.  This is not strictly necessary but prevents frequent warnings about
// uninitialized memory reads in Purify and similar tools without meaningful
// cost.
static struct ::pollfd DEFAULT_POLLFD; // initialized to 0 as a static

struct PollRemoveVisitor {
    // Visit a set of sockets and populate an array of pollfd to deregister
    // those sockets.

    struct ::pollfd *d_pollfdArray;
    int              d_index;

    PollRemoveVisitor(struct ::pollfd *pollfdArray) {
        d_pollfdArray = pollfdArray;
        d_index = -1;
    }

    void operator()(int fd) {
        int i = ++d_index;
        d_pollfdArray[i].fd = fd;
        d_pollfdArray[i].events = POLLREMOVE;
        d_pollfdArray[i].revents = 0;
    }
};

static
short convertMask(uint32_t eventMask)
// Return a mask with POLLIN set if READ or ACCEPT is set in 'eventMask',
// and with POLLOUT set if WRITE or CONNECT is set in 'eventMask'.
// Assert that if multiple events are registered, they are READ and WRITE.
{

    int pollinEvents =
        bdlb::BitUtil::numBitsSet(eventMask & EventType::k_INBOUND_EVENTS);
    int polloutEvents =
        bdlb::BitUtil::numBitsSet(eventMask & EventType::k_OUTBOUND_EVENTS);
    BSLS_ASSERT(2 > pollinEvents);
    BSLS_ASSERT(2 > polloutEvents);
    BSLS_ASSERT(!(pollinEvents && polloutEvents) ||
                (eventMask & bdlb::BitMaskUtil::eq(EventType::e_READ) &&
                 eventMask & bdlb::BitMaskUtil::eq(EventType::e_WRITE)));

    return (POLLIN * (short)pollinEvents) | (POLLOUT * (short)polloutEvents);
}

static
inline int dispatchCallbacks(bsl::vector<struct ::pollfd>&  signaled,
                             int                            rfds,
                             EventCallbackRegistry         *callbacks)
{
    int numCallbacks = 0;

    for (int i = 0; i < rfds && i < signaled.size(); ++i) {
        const struct ::pollfd& currData = signaled[i];

        BSLS_ASSERT(currData.revents);

        int eventMask = callbacks->getRegisteredEventMask(currData.fd);

        // Read/Accept.

        if (currData.revents & POLLIN) {
            if (eventMask & bdlb::BitMaskUtil::eq(EventType::e_READ)) {
                numCallbacks += !callbacks->invoke(Event(currData.fd,
                                                         EventType::e_READ));
            } else {
                numCallbacks += !callbacks->invoke(Event(currData.fd,
                                                         EventType::e_ACCEPT));
            }
        }

        // Write/Connect.

        if (currData.revents & POLLOUT) {
            if (eventMask & bdlb::BitMaskUtil::eq(EventType::e_WRITE)) {
                numCallbacks += !callbacks->invoke(Event(currData.fd,
                                                         EventType::e_WRITE));
            } else {
                numCallbacks += !callbacks->invoke(Event(currData.fd,
                                                         EventType::e_CONNECT));
            }
        }
    }
    return numCallbacks;
}

} // close unnamed namespace

         // --------------------------------------------
         // class DefaultEventManager<Platform::DEVPOLL>
         // --------------------------------------------

// CREATORS
DefaultEventManager<Platform::DEVPOLL>::DefaultEventManager(
                                              TimeMetrics      *timeMetric,
                                              bslma::Allocator *basicAllocator)
: d_callbacks(basicAllocator)
, d_timeMetric_p(timeMetric)
, d_signaled(basicAllocator)
, d_dpFd(open("/dev/poll", O_RDWR))
{

}

DefaultEventManager<Platform::DEVPOLL>::~DefaultEventManager()
{
    int rc = close(d_dpFd);
    BSLS_ASSERT(0 == rc);
}

// MANIPULATORS
int DefaultEventManager<Platform::DEVPOLL>::dispatch(
                                             const bsls::TimeInterval& timeout,
                                             int                       flags)
{
    bsls::TimeInterval now(bdlt::CurrentTime::now());

    if (!numEvents()) {
        if (timeout <= now) {
            return 0;                                                 // RETURN
        }
        while (timeout > now) {
            bsls::TimeInterval currTimeout(timeout - now);
            struct timespec    ts;
            ts.tv_sec = static_cast<time_t>(
                bsl::min(static_cast<bsls::Types::Int64>(
                             bsl::numeric_limits<time_t>::max()),
                         currTimeout.seconds()));
            ts.tv_nsec = currTimeout.nanoseconds();

            // Sleep till it's time.

            int savedErrno;
            int rc;
            if (d_timeMetric_p) {
                d_timeMetric_p->switchTo(TimeMetrics::e_IO_BOUND);
                rc = nanosleep(&ts, 0);
                savedErrno = errno;
                d_timeMetric_p->switchTo(TimeMetrics::e_CPU_BOUND);
            }
            else {
                rc = nanosleep(&ts, 0);
                savedErrno = errno;
            }

            errno = 0;
            if (0 > rc) {
                if (EINTR == savedErrno) {
                    if (flags & btlso::Flag::k_ASYNC_INTERRUPT) {
                        return -1;                                    // RETURN
                    }
                }
                else {
                    return -2;                                        // RETURN
                }
            }
            now = bdlt::CurrentTime::now();
        }
        return 0;                                                     // RETURN
    }

    int ncbs = 0;                    // number of callbacks dispatched

    do {
        int rfds;                    // number of returned sockets
        int savedErrno = 0;          // saved errno value set by poll
        do {
            d_signaled.resize(d_callbacks.numSockets(), DEFAULT_POLLFD);

            struct dvpoll dopoll;
            dopoll.dp_nfds = d_signaled.size();
            dopoll.dp_fds  = &d_signaled.front();

            if (timeout < now) {
                // The ioctl() call should return immediately.

                dopoll.dp_timeout = 0;
            }
            else {
                // Calculate the time remaining for the ioctl() call.

                bsls::TimeInterval curr_timeout(timeout - now);

                // Convert this timeout to a 32 bit value in milliseconds.

                dopoll.dp_timeout = static_cast<int>(
                    bsl::min(static_cast<bsls::Types::Int64>(
                                 bsl::numeric_limits<int>::max()),
                             curr_timeout.seconds() * 1000 +
                                 curr_timeout.nanoseconds() / 1000000 + 1));
            }
            dopoll.dp_timeout = bsl::min(
                                       dopoll.dp_timeout,
                                       static_cast<int>(MIN_IOCTL_TIMEOUT_MS));

            if (d_timeMetric_p) {
                d_timeMetric_p->switchTo(TimeMetrics::e_IO_BOUND);
                rfds = ioctl(d_dpFd, DP_POLL, &dopoll);
                savedErrno = errno;
                d_timeMetric_p->switchTo(TimeMetrics::e_CPU_BOUND);
            }
            else {
                rfds = ioctl(d_dpFd, DP_POLL, &dopoll);
                savedErrno = errno;
            }
            errno = 0;
            now = bdlt::CurrentTime::now();
        } while ((0 > rfds && EINTR == savedErrno)
              && !(btlso::Flag::k_ASYNC_INTERRUPT & flags)
              && now < timeout);

        if (0 >= rfds) {
            return rfds
                   ? -1 == rfds && EINTR == savedErrno
                     ? -1
                     : -2
                   : 0;                                               // RETURN
        }

        ncbs += dispatchCallbacks(d_signaled, rfds, &d_callbacks);
        now = bdlt::CurrentTime::now();
    } while (0 == ncbs && now < timeout);

    return ncbs;
}

int DefaultEventManager<Platform::DEVPOLL>::dispatch(int flags)
{
    if (!numEvents()) {
        return 0;                                                     // RETURN
    }

    int ncbs = 0;                    // number of callbacks dispatched
    while (0 == ncbs) {
        int rfds;                    // number of returned fds
        int savedErrno = 0;          // saved errno value set by 'poll'

        d_signaled.resize(d_callbacks.numSockets(), DEFAULT_POLLFD);

        struct dvpoll dopoll;
        dopoll.dp_nfds    = d_signaled.size();
        dopoll.dp_fds     = &d_signaled.front();
        dopoll.dp_timeout = MIN_IOCTL_TIMEOUT_MS;

        do {
            if (d_timeMetric_p) {
                d_timeMetric_p->switchTo(TimeMetrics::e_IO_BOUND);
                rfds = ioctl(d_dpFd, DP_POLL, &dopoll);
                savedErrno = errno;
                d_timeMetric_p->switchTo(TimeMetrics::e_CPU_BOUND);
            }
            else {
                rfds = ioctl(d_dpFd, DP_POLL, &dopoll);
                savedErrno = errno;
            }
            errno = 0;
        } while ((0 > rfds && EINTR == savedErrno)
              && !(btlso::Flag::k_ASYNC_INTERRUPT & flags));

        if (0 >= rfds) {
            return rfds
                   ? -1 == rfds && EINTR == savedErrno
                     ? -1
                     : -2
                   : 0;                                               // RETURN
        }

        ncbs += dispatchCallbacks(d_signaled, rfds, &d_callbacks);
    }
    return ncbs;
}

int DefaultEventManager<Platform::DEVPOLL>::registerSocketEvent(
                                        const SocketHandle::Handle&   handle,
                                        const EventType::Type         event,
                                        const EventManager::Callback& callback)
{
    Event handleEvent(handle, event);

    uint32_t newMask = d_callbacks.registerCallback(handleEvent, callback);
    if (0 == newMask) {
        // We replaced an existing callback function.
        return 0;                                                     // RETURN
    }

    // Prepare a ::pollfd object to write to /dev/poll

    struct ::pollfd pfd;
    pfd.fd = handle;
    pfd.revents = 0;      // just to satisfy purify

    // Calculate the new event mask
    pfd.events = convertMask(newMask);

    // Write the new event mask for this fd to /dev/poll.
    ssize_t rc = write(d_dpFd, &pfd, k_POLLFD_SIZE);
    if (k_POLLFD_SIZE != rc) {
        // Unregister the event we added earlier.
        d_callbacks.remove(handleEvent);
        return errno;                                                 // RETURN
    }

    return 0;
}

void DefaultEventManager<Platform::DEVPOLL>::deregisterSocketEvent(
                                            const SocketHandle::Handle& handle,
                                            EventType::Type             event)
{
    Event handleEvent(handle, event);

    bool removed = d_callbacks.remove(handleEvent);
    BSLS_ASSERT(removed);

    // Retrieve the new event mask
    int eventmask = convertMask(d_callbacks.getRegisteredEventMask(handle));

    // Prepare a ::pollfd object to write to /dev/poll
    // First, we need to remove this socket handle from the set.
    // The write it out with a new mask, if applicable.

    struct ::pollfd pfd;
    pfd.fd      = handle;
    pfd.events  = POLLREMOVE;
    pfd.revents = 0;      // just to satisfy purify

    ssize_t rc = write(d_dpFd, &pfd, k_POLLFD_SIZE);
    BSLS_ASSERT(k_POLLFD_SIZE == rc);

    if (eventmask) {
        // Write the new event mask for this fd to /dev/poll.

        pfd.events = static_cast<short>(eventmask);
        ssize_t rc = write(d_dpFd, &pfd, k_POLLFD_SIZE);
        BSLS_ASSERT(k_POLLFD_SIZE == rc);
    }
}

int DefaultEventManager<Platform::DEVPOLL>::deregisterSocket(
                                            const SocketHandle::Handle& handle)
{
    int eventmask = d_callbacks.getRegisteredEventMask(handle);
    if (0 == eventmask) {
        // No registered events, nothing to do.
        return 0;                                                     // RETURN
    }

    struct ::pollfd req;
    req.fd      = handle;
    req.events  = POLLREMOVE;
    req.revents = 0;

    ssize_t rc = ::write(d_dpFd, &req, k_POLLFD_SIZE);
    BSLS_ASSERT(k_POLLFD_SIZE == rc);

    return d_callbacks.removeSocket(handle);
}

void DefaultEventManager<Platform::DEVPOLL>::deregisterAll()
{
    bsl::vector<struct ::pollfd> removed(d_callbacks.numSockets(),
                                         DEFAULT_POLLFD);

    if (!removed.empty()) {
        PollRemoveVisitor visitor(&removed.front());
        d_callbacks.visitSockets(&visitor);

        int pollfdSize = removed.size() * k_POLLFD_SIZE;
        ssize_t rc = write(d_dpFd, &removed.front(), pollfdSize);

        BSLS_ASSERT(pollfdSize == rc);
    }

    d_callbacks.removeAll();
}

// ACCESSORS
int DefaultEventManager<Platform::DEVPOLL>::numSocketEvents(
                                      const SocketHandle::Handle& handle) const
{
    return bdlb::BitUtil::numBitsSet(
                                  d_callbacks.getRegisteredEventMask(handle));
}

int DefaultEventManager<Platform::DEVPOLL>::numEvents() const
{
    return d_callbacks.numCallbacks();
}

int DefaultEventManager<Platform::DEVPOLL>::isRegistered(
                                       const SocketHandle::Handle& handle,
                                       const EventType::Type       event) const
{
    return d_callbacks.contains(Event(handle, event));
}

}  // close package namespace

}  // close namespace BloombergLP

#endif

// ----------------------------------------------------------------------------
// Copyright 2015 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------
<commit_msg>fix nightly build for sun gcc 4.9.2<commit_after>// btlso_defaulteventmanager_devpoll.cpp                              -*-C++-*-

// ----------------------------------------------------------------------------
//                                   NOTICE
//
// This component is not up to date with current BDE coding standards, and
// should not be used as an example for new development.
// ----------------------------------------------------------------------------

#include <btlso_defaulteventmanager_devpoll.h>

#include <bsls_ident.h>
BSLS_IDENT_RCSID(btlso_defaulteventmanager_devpoll_cpp,"$Id$ $CSID$")

#include <btlso_timemetrics.h>
#include <btlso_flag.h>

#include <bsls_timeinterval.h>
#include <bdlb_bitmaskutil.h>
#include <bdlb_bitutil.h>
#include <bdlt_currenttime.h>
#include <bsls_assert.h>

#if defined(BSLS_PLATFORM_OS_SOLARIS) || defined(BSLS_PLATFORM_OS_HPUX)
#include <sys/devpoll.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/file.h>
#include <bsl_algorithm.h>
#include <bsl_c_errno.h>
#include <bsl_cstring.h>
#include <bsl_limits.h>
#include <bsl_utility.h>

namespace BloombergLP {

namespace btlso {

namespace {
    // unnamed namespace for private resources

enum {
    MIN_IOCTL_TIMEOUT_MS = 333  // force spinning of devpoll every 333ms,
                                // otherwise a bug on Solaris may cause
                                // missing events if passing a longer timeout
                                // to ioctl(fd, DP_POLL, ...)
};

const int k_POLLFD_SIZE = static_cast<int>(sizeof(struct ::pollfd));

// This object is used to initialize and grow the working arrays passed to
// ioctl.  This is not strictly necessary but prevents frequent warnings about
// uninitialized memory reads in Purify and similar tools without meaningful
// cost.
static struct ::pollfd DEFAULT_POLLFD; // initialized to 0 as a static

struct PollRemoveVisitor {
    // Visit a set of sockets and populate an array of pollfd to deregister
    // those sockets.

    struct ::pollfd *d_pollfdArray;
    int              d_index;

    PollRemoveVisitor(struct ::pollfd *pollfdArray) {
        d_pollfdArray = pollfdArray;
        d_index = -1;
    }

    void operator()(int fd) {
        int i = ++d_index;
        d_pollfdArray[i].fd = fd;
        d_pollfdArray[i].events = POLLREMOVE;
        d_pollfdArray[i].revents = 0;
    }
};

static
short convertMask(uint32_t eventMask)
// Return a mask with POLLIN set if READ or ACCEPT is set in 'eventMask',
// and with POLLOUT set if WRITE or CONNECT is set in 'eventMask'.
// Assert that if multiple events are registered, they are READ and WRITE.
{

    int pollinEvents =
        bdlb::BitUtil::numBitsSet(eventMask & EventType::k_INBOUND_EVENTS);
    int polloutEvents =
        bdlb::BitUtil::numBitsSet(eventMask & EventType::k_OUTBOUND_EVENTS);
    BSLS_ASSERT(2 > pollinEvents);
    BSLS_ASSERT(2 > polloutEvents);
    BSLS_ASSERT(!(pollinEvents && polloutEvents) ||
                (eventMask & bdlb::BitMaskUtil::eq(EventType::e_READ) &&
                 eventMask & bdlb::BitMaskUtil::eq(EventType::e_WRITE)));

    return static_cast<short>(  (POLLIN  * static_cast<short>(pollinEvents))
                              | (POLLOUT * static_cast<short>(polloutEvents)));
}

static
inline int dispatchCallbacks(bsl::vector<struct ::pollfd>&  signaled,
                             int                            rfds,
                             EventCallbackRegistry         *callbacks)
{
    int numCallbacks = 0;

    for (int i = 0; i < rfds && i < static_cast<int>(signaled.size()); ++i) {
        const struct ::pollfd& currData = signaled[i];

        BSLS_ASSERT(currData.revents);

        int eventMask = callbacks->getRegisteredEventMask(currData.fd);

        // Read/Accept.

        if (currData.revents & POLLIN) {
            if (eventMask & bdlb::BitMaskUtil::eq(EventType::e_READ)) {
                numCallbacks += !callbacks->invoke(Event(currData.fd,
                                                         EventType::e_READ));
            } else {
                numCallbacks += !callbacks->invoke(Event(currData.fd,
                                                         EventType::e_ACCEPT));
            }
        }

        // Write/Connect.

        if (currData.revents & POLLOUT) {
            if (eventMask & bdlb::BitMaskUtil::eq(EventType::e_WRITE)) {
                numCallbacks += !callbacks->invoke(Event(currData.fd,
                                                         EventType::e_WRITE));
            } else {
                numCallbacks += !callbacks->invoke(Event(currData.fd,
                                                         EventType::e_CONNECT));
            }
        }
    }
    return numCallbacks;
}

} // close unnamed namespace

         // --------------------------------------------
         // class DefaultEventManager<Platform::DEVPOLL>
         // --------------------------------------------

// CREATORS
DefaultEventManager<Platform::DEVPOLL>::DefaultEventManager(
                                              TimeMetrics      *timeMetric,
                                              bslma::Allocator *basicAllocator)
: d_callbacks(basicAllocator)
, d_timeMetric_p(timeMetric)
, d_signaled(basicAllocator)
, d_dpFd(open("/dev/poll", O_RDWR))
{

}

DefaultEventManager<Platform::DEVPOLL>::~DefaultEventManager()
{
    int rc = close(d_dpFd);
    BSLS_ASSERT(0 == rc);
}

// MANIPULATORS
int DefaultEventManager<Platform::DEVPOLL>::dispatch(
                                             const bsls::TimeInterval& timeout,
                                             int                       flags)
{
    bsls::TimeInterval now(bdlt::CurrentTime::now());

    if (!numEvents()) {
        if (timeout <= now) {
            return 0;                                                 // RETURN
        }
        while (timeout > now) {
            bsls::TimeInterval currTimeout(timeout - now);
            struct timespec    ts;
            ts.tv_sec = static_cast<time_t>(
                bsl::min(static_cast<bsls::Types::Int64>(
                             bsl::numeric_limits<time_t>::max()),
                         currTimeout.seconds()));
            ts.tv_nsec = currTimeout.nanoseconds();

            // Sleep till it's time.

            int savedErrno;
            int rc;
            if (d_timeMetric_p) {
                d_timeMetric_p->switchTo(TimeMetrics::e_IO_BOUND);
                rc = nanosleep(&ts, 0);
                savedErrno = errno;
                d_timeMetric_p->switchTo(TimeMetrics::e_CPU_BOUND);
            }
            else {
                rc = nanosleep(&ts, 0);
                savedErrno = errno;
            }

            errno = 0;
            if (0 > rc) {
                if (EINTR == savedErrno) {
                    if (flags & btlso::Flag::k_ASYNC_INTERRUPT) {
                        return -1;                                    // RETURN
                    }
                }
                else {
                    return -2;                                        // RETURN
                }
            }
            now = bdlt::CurrentTime::now();
        }
        return 0;                                                     // RETURN
    }

    int ncbs = 0;                    // number of callbacks dispatched

    do {
        int rfds;                    // number of returned sockets
        int savedErrno = 0;          // saved errno value set by poll
        do {
            d_signaled.resize(d_callbacks.numSockets(), DEFAULT_POLLFD);

            struct dvpoll dopoll;
            dopoll.dp_nfds = d_signaled.size();
            dopoll.dp_fds  = &d_signaled.front();

            if (timeout < now) {
                // The ioctl() call should return immediately.

                dopoll.dp_timeout = 0;
            }
            else {
                // Calculate the time remaining for the ioctl() call.

                bsls::TimeInterval curr_timeout(timeout - now);

                // Convert this timeout to a 32 bit value in milliseconds.

                dopoll.dp_timeout = static_cast<int>(
                    bsl::min(static_cast<bsls::Types::Int64>(
                                 bsl::numeric_limits<int>::max()),
                             curr_timeout.seconds() * 1000 +
                                 curr_timeout.nanoseconds() / 1000000 + 1));
            }
            dopoll.dp_timeout = bsl::min(
                                       dopoll.dp_timeout,
                                       static_cast<int>(MIN_IOCTL_TIMEOUT_MS));

            if (d_timeMetric_p) {
                d_timeMetric_p->switchTo(TimeMetrics::e_IO_BOUND);
                rfds = ioctl(d_dpFd, DP_POLL, &dopoll);
                savedErrno = errno;
                d_timeMetric_p->switchTo(TimeMetrics::e_CPU_BOUND);
            }
            else {
                rfds = ioctl(d_dpFd, DP_POLL, &dopoll);
                savedErrno = errno;
            }
            errno = 0;
            now = bdlt::CurrentTime::now();
        } while ((0 > rfds && EINTR == savedErrno)
              && !(btlso::Flag::k_ASYNC_INTERRUPT & flags)
              && now < timeout);

        if (0 >= rfds) {
            return rfds
                   ? -1 == rfds && EINTR == savedErrno
                     ? -1
                     : -2
                   : 0;                                               // RETURN
        }

        ncbs += dispatchCallbacks(d_signaled, rfds, &d_callbacks);
        now = bdlt::CurrentTime::now();
    } while (0 == ncbs && now < timeout);

    return ncbs;
}

int DefaultEventManager<Platform::DEVPOLL>::dispatch(int flags)
{
    if (!numEvents()) {
        return 0;                                                     // RETURN
    }

    int ncbs = 0;                    // number of callbacks dispatched
    while (0 == ncbs) {
        int rfds;                    // number of returned fds
        int savedErrno = 0;          // saved errno value set by 'poll'

        d_signaled.resize(d_callbacks.numSockets(), DEFAULT_POLLFD);

        struct dvpoll dopoll;
        dopoll.dp_nfds    = d_signaled.size();
        dopoll.dp_fds     = &d_signaled.front();
        dopoll.dp_timeout = MIN_IOCTL_TIMEOUT_MS;

        do {
            if (d_timeMetric_p) {
                d_timeMetric_p->switchTo(TimeMetrics::e_IO_BOUND);
                rfds = ioctl(d_dpFd, DP_POLL, &dopoll);
                savedErrno = errno;
                d_timeMetric_p->switchTo(TimeMetrics::e_CPU_BOUND);
            }
            else {
                rfds = ioctl(d_dpFd, DP_POLL, &dopoll);
                savedErrno = errno;
            }
            errno = 0;
        } while ((0 > rfds && EINTR == savedErrno)
              && !(btlso::Flag::k_ASYNC_INTERRUPT & flags));

        if (0 >= rfds) {
            return rfds
                   ? -1 == rfds && EINTR == savedErrno
                     ? -1
                     : -2
                   : 0;                                               // RETURN
        }

        ncbs += dispatchCallbacks(d_signaled, rfds, &d_callbacks);
    }
    return ncbs;
}

int DefaultEventManager<Platform::DEVPOLL>::registerSocketEvent(
                                        const SocketHandle::Handle&   handle,
                                        const EventType::Type         event,
                                        const EventManager::Callback& callback)
{
    Event handleEvent(handle, event);

    uint32_t newMask = d_callbacks.registerCallback(handleEvent, callback);
    if (0 == newMask) {
        // We replaced an existing callback function.
        return 0;                                                     // RETURN
    }

    // Prepare a ::pollfd object to write to /dev/poll

    struct ::pollfd pfd;
    pfd.fd = handle;
    pfd.revents = 0;      // just to satisfy purify

    // Calculate the new event mask
    pfd.events = convertMask(newMask);

    // Write the new event mask for this fd to /dev/poll.
    ssize_t rc = write(d_dpFd, &pfd, k_POLLFD_SIZE);
    if (k_POLLFD_SIZE != rc) {
        // Unregister the event we added earlier.
        d_callbacks.remove(handleEvent);
        return errno;                                                 // RETURN
    }

    return 0;
}

void DefaultEventManager<Platform::DEVPOLL>::deregisterSocketEvent(
                                            const SocketHandle::Handle& handle,
                                            EventType::Type             event)
{
    Event handleEvent(handle, event);

    bool removed = d_callbacks.remove(handleEvent);
    BSLS_ASSERT(removed);

    // Retrieve the new event mask
    int eventmask = convertMask(d_callbacks.getRegisteredEventMask(handle));

    // Prepare a ::pollfd object to write to /dev/poll
    // First, we need to remove this socket handle from the set.
    // The write it out with a new mask, if applicable.

    struct ::pollfd pfd;
    pfd.fd      = handle;
    pfd.events  = POLLREMOVE;
    pfd.revents = 0;      // just to satisfy purify

    ssize_t rc = write(d_dpFd, &pfd, k_POLLFD_SIZE);
    BSLS_ASSERT(k_POLLFD_SIZE == rc);

    if (eventmask) {
        // Write the new event mask for this fd to /dev/poll.

        pfd.events = static_cast<short>(eventmask);
        ssize_t rc = write(d_dpFd, &pfd, k_POLLFD_SIZE);
        BSLS_ASSERT(k_POLLFD_SIZE == rc);
    }
}

int DefaultEventManager<Platform::DEVPOLL>::deregisterSocket(
                                            const SocketHandle::Handle& handle)
{
    int eventmask = d_callbacks.getRegisteredEventMask(handle);
    if (0 == eventmask) {
        // No registered events, nothing to do.
        return 0;                                                     // RETURN
    }

    struct ::pollfd req;
    req.fd      = handle;
    req.events  = POLLREMOVE;
    req.revents = 0;

    ssize_t rc = ::write(d_dpFd, &req, k_POLLFD_SIZE);
    BSLS_ASSERT(k_POLLFD_SIZE == rc);

    return d_callbacks.removeSocket(handle);
}

void DefaultEventManager<Platform::DEVPOLL>::deregisterAll()
{
    bsl::vector<struct ::pollfd> removed(d_callbacks.numSockets(),
                                         DEFAULT_POLLFD);

    if (!removed.empty()) {
        PollRemoveVisitor visitor(&removed.front());
        d_callbacks.visitSockets(&visitor);

        int pollfdSize = removed.size() * k_POLLFD_SIZE;
        ssize_t rc = write(d_dpFd, &removed.front(), pollfdSize);

        BSLS_ASSERT(pollfdSize == rc);
    }

    d_callbacks.removeAll();
}

// ACCESSORS
int DefaultEventManager<Platform::DEVPOLL>::numSocketEvents(
                                      const SocketHandle::Handle& handle) const
{
    return bdlb::BitUtil::numBitsSet(
                                  d_callbacks.getRegisteredEventMask(handle));
}

int DefaultEventManager<Platform::DEVPOLL>::numEvents() const
{
    return d_callbacks.numCallbacks();
}

int DefaultEventManager<Platform::DEVPOLL>::isRegistered(
                                       const SocketHandle::Handle& handle,
                                       const EventType::Type       event) const
{
    return d_callbacks.contains(Event(handle, event));
}

}  // close package namespace

}  // close namespace BloombergLP

#endif

// ----------------------------------------------------------------------------
// Copyright 2015 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------
<|endoftext|>


<commit_before>#include <iostream>
#include <stdlib.h>
#include <stddef.h>
#include <libpstack/dwarf.h>
#include <libpstack/proc.h>
#include <python2.7/Python.h>
#include <python2.7/frameobject.h>

static bool
pthreadTidOffset(const Process &proc, size_t *offsetp)
{
    static size_t offset;
    static enum { notDone, notFound, found } status;
    if (status == notDone) {
        try {
            auto addr = proc.findNamedSymbol(0, "_thread_db_pthread_tid");
            uint32_t desc[3];
            proc.io->readObj(addr, &desc[0], 3);
            offset = desc[2];
            status = found;
            if (verbose)
                *debug << "found thread offset " << offset <<  "\n";
        } catch (const std::exception &ex) {
           if (verbose)
               *debug << "failed to find offset of tid in pthread: " << ex.what();
            status = notFound;
        }
    }
    if (status == found) {
        *offsetp = offset;
        return true;
    }
    return false;
}

/*
 * process one python thread in an interpreter, at remote addr "ptr".
 * returns the address of the next thread on the list.
 */
Elf_Addr
doPyThread(Process &proc, std::ostream &os, Elf_Addr ptr)
{
    PyThreadState thread;
    proc.io->readObj(ptr, &thread);
    PyFrameObject frame;

    size_t toff;
    if (thread.thread_id && pthreadTidOffset(proc, &toff)) {
        Elf_Addr tidptr = thread.thread_id + toff;
        pid_t tid;
        proc.io->readObj(tidptr, &tid);
        os << "pthread: 0x" << std::hex << thread.thread_id << std::dec << ", lwp " << tid;
    } else {
       os << "anonymous thread";
    }
    os << "\n";
    for (auto framePtr = Elf_Addr(thread.frame); framePtr != 0; framePtr = Elf_Addr(frame.f_back)) {
        proc.io->readObj(framePtr, &frame);
        PyCodeObject code;
        proc.io->readObj(Elf_Addr(frame.f_code), &code);
        auto func = proc.io->readString(Elf_Addr(code.co_name) + offsetof(PyStringObject, ob_sval));
        auto file = proc.io->readString(Elf_Addr(code.co_filename) + offsetof(PyStringObject, ob_sval));
        os << "\t" << func << " in " << file << ":" << frame.f_lineno << "\n";
    }
    return Elf_Addr(thread.next);
}

/*
 * Process one python interpreter in the process at remote address ptr
 * Returns the address of the next interpreter on on the process's list.
 */
Elf32_Addr
doPyInterp(Process &proc, std::ostream &os, Elf_Addr ptr)
{
    PyInterpreterState state;
    proc.io->readObj(ptr, &state);
    os << "---- interpreter @" << std::hex << ptr << std::dec << " -----" << std::endl ;
    for (Elf_Addr tsp = reinterpret_cast<Elf_Addr>(state.tstate_head); tsp; ) {
        tsp = doPyThread(proc, os, tsp);
        os << std::endl;
    }
    return reinterpret_cast<Elf_Addr>(state.next);
}

/*
 * Print all python stack traces from this process.
 */
std::ostream &
pythonStack(Process &proc, std::ostream &os, const PstackOptions &)
{
    // Find the python library.
    for (auto &o : proc.objects) {
        std::string module = stringify(*o.object->io);
        if (module.find("python") == std::string::npos)
            continue;
        auto dwarf = proc.imageCache.getDwarf(ElfObject::getDebug(o.object));
        if (!dwarf)
            continue;
        for (auto u : dwarf->getUnits()) {
            // For each unit
            for (const DwarfEntry *compile : u->entries) {
                if (compile->type->tag != DW_TAG_compile_unit)
                    continue;
                // Do we have a global variable called interp_head?
                for (const DwarfEntry *var : compile->children) {
                    if (var->type->tag != DW_TAG_variable)
                        continue;
                    if (var->name() != "interp_head")
                        continue;
                    // Yes - let's run through the interpreters, and dump their stacks.
                    DwarfExpressionStack evalStack;
                    auto addr = evalStack.eval(proc, var->attrForName(DW_AT_location), 0, o.reloc);
                    Elf_Addr ptr;
                    for (proc.io->readObj(addr, &ptr); ptr; )
                        ptr = doPyInterp(proc, os, ptr);
                }
            }
        }
    }
    return os;
}
<commit_msg>Fix line numbers for python traces.<commit_after>#include <iostream>
#include <stdlib.h>
#include <stddef.h>
#include <libpstack/dwarf.h>
#include <libpstack/proc.h>
#include <python2.7/Python.h>
#include <python2.7/frameobject.h>

static bool
pthreadTidOffset(const Process &proc, size_t *offsetp)
{
    static size_t offset;
    static enum { notDone, notFound, found } status;
    if (status == notDone) {
        try {
            auto addr = proc.findNamedSymbol(0, "_thread_db_pthread_tid");
            uint32_t desc[3];
            proc.io->readObj(addr, &desc[0], 3);
            offset = desc[2];
            status = found;
            if (verbose)
                *debug << "found thread offset " << offset <<  "\n";
        } catch (const std::exception &ex) {
           if (verbose)
               *debug << "failed to find offset of tid in pthread: " << ex.what();
            status = notFound;
        }
    }
    if (status == found) {
        *offsetp = offset;
        return true;
    }
    return false;
}

// This reimplements PyCode_Addr2Line
int getLine(Process *proc, const PyCodeObject *code, const PyFrameObject *frame)
{
    PyVarObject lnotab;
    proc->io->readObj(Elf_Addr(code->co_lnotab), &lnotab);
    unsigned char linedata[lnotab.ob_size];
    proc->io->readObj(Elf_Addr(code->co_lnotab) + offsetof(PyStringObject, ob_sval),
            &linedata[0], lnotab.ob_size);
    int line = code->co_firstlineno;
    int addr = 0;
    unsigned char *p = linedata;
    unsigned char *e = linedata + lnotab.ob_size;
    while (p < e) {
        addr += *p++;
        if (addr > frame->f_lasti) {
            break;
        }
        line += *p++;
    }
    return line;
}

/*
 * process one python thread in an interpreter, at remote addr "ptr".
 * returns the address of the next thread on the list.
 */
Elf_Addr
doPyThread(Process &proc, std::ostream &os, Elf_Addr ptr)
{
    PyThreadState thread;
    proc.io->readObj(ptr, &thread);
    PyFrameObject frame;

    size_t toff;
    if (thread.thread_id && pthreadTidOffset(proc, &toff)) {
        Elf_Addr tidptr = thread.thread_id + toff;
        pid_t tid;
        proc.io->readObj(tidptr, &tid);
        os << "pthread: 0x" << std::hex << thread.thread_id << std::dec << ", lwp " << tid;
    } else {
       os << "anonymous thread";
    }
    os << "\n";
    for (auto framePtr = Elf_Addr(thread.frame); framePtr != 0; framePtr = Elf_Addr(frame.f_back)) {
        proc.io->readObj(framePtr, &frame);
        PyCodeObject code;
        proc.io->readObj(Elf_Addr(frame.f_code), &code);
        auto lineNo = getLine(&proc, &code, &frame);
        auto func = proc.io->readString(Elf_Addr(code.co_name) + offsetof(PyStringObject, ob_sval));
        auto file = proc.io->readString(Elf_Addr(code.co_filename) + offsetof(PyStringObject, ob_sval));
        os << "\t" << func << " in " << file << ":" << lineNo << "\n";
    }
    return Elf_Addr(thread.next);
}

/*
 * Process one python interpreter in the process at remote address ptr
 * Returns the address of the next interpreter on on the process's list.
 */
Elf32_Addr
doPyInterp(Process &proc, std::ostream &os, Elf_Addr ptr)
{
    PyInterpreterState state;
    proc.io->readObj(ptr, &state);
    os << "---- interpreter @" << std::hex << ptr << std::dec << " -----" << std::endl ;
    for (Elf_Addr tsp = reinterpret_cast<Elf_Addr>(state.tstate_head); tsp; ) {
        tsp = doPyThread(proc, os, tsp);
        os << std::endl;
    }
    return reinterpret_cast<Elf_Addr>(state.next);
}

/*
 * Print all python stack traces from this process.
 */
std::ostream &
pythonStack(Process &proc, std::ostream &os, const PstackOptions &)
{
    // Find the python library.
    for (auto &o : proc.objects) {
        std::string module = stringify(*o.object->io);
        if (module.find("python") == std::string::npos)
            continue;
        auto dwarf = proc.imageCache.getDwarf(ElfObject::getDebug(o.object));
        if (!dwarf)
            continue;
        for (auto u : dwarf->getUnits()) {
            // For each unit
            for (const DwarfEntry *compile : u->entries) {
                if (compile->type->tag != DW_TAG_compile_unit)
                    continue;
                // Do we have a global variable called interp_head?
                for (const DwarfEntry *var : compile->children) {
                    if (var->type->tag != DW_TAG_variable)
                        continue;
                    if (var->name() != "interp_head")
                        continue;
                    // Yes - let's run through the interpreters, and dump their stacks.
                    DwarfExpressionStack evalStack;
                    auto addr = evalStack.eval(proc, var->attrForName(DW_AT_location), 0, o.reloc);
                    Elf_Addr ptr;
                    for (proc.io->readObj(addr, &ptr); ptr; )
                        ptr = doPyInterp(proc, os, ptr);
                }
            }
        }
    }
    return os;
}
<|endoftext|>


<commit_before>#include <boost/test/unit_test.hpp>
#include "SoftXMT.hpp"
#include "Addressing.hpp"
#include "Cache.hpp"
#include "ForkJoin.hpp"
#include "GlobalAllocator.hpp"

BOOST_AUTO_TEST_SUITE( ForkJoin_tests );

#define MEM_SIZE 1<<24;

struct func_initialize : public ForkJoinIteration {
  GlobalAddress<int64_t> base_addr;
  int64_t value;
  void operator()(int64_t index) {
    VLOG(2) << "called func_initialize with index = " << index;
    Incoherent<int64_t>::RW c(base_addr+index, 1);
    c[0] = value+index;
  }
};

struct func_hello : public ForkJoinIteration {
  void operator()(int64_t index) {
    LOG(INFO) << "Hello from " << index << "!";
  }
};

static void user_main(Thread * me, void * args) {

  LOG(INFO) << "beginning user main... (" << SoftXMT_mynode() << ")";

  {
    size_t N = 128;
    GlobalAddress<int64_t> data = SoftXMT_typed_malloc<int64_t>(N);

    func_initialize a; a.base_addr = data; a.value = 0;
    fork_join(&a, 0, N);

    for (size_t i=0; i<N; i++) {
      Incoherent<int64_t>::RO c(data+i, 1);
      VLOG(2) << i << " == " << *c;
      BOOST_CHECK_EQUAL(i, *c);
    }
    SoftXMT_free(data);
  }
  {
    size_t N = 101;
    GlobalAddress<int64_t> data = SoftXMT_typed_malloc<int64_t>(N);

    func_initialize a; a.base_addr = data; a.value = 0;
    fork_join(&a, 0, N);

    for (size_t i=0; i<N; i++) {
      Incoherent<int64_t>::RO c(data+i, 1);
      VLOG(2) << i << " == " << *c;
      BOOST_CHECK_EQUAL(i, *c);
    }
    SoftXMT_free(data);
  }
  {
    func_hello f;
    fork_join_custom(&f);
  }
  {
    size_t N = fLI64::FLAGS_max_forkjoin_threads_per_node * SoftXMT_nodes() * 3 + 13;
    GlobalAddress<int64_t> data = SoftXMT_typed_malloc<int64_t>(N);

    func_initialize a; a.base_addr = data; a.value = 0;
    fork_join(&a, 0, N);

    for (size_t i=0; i<N; i++) {
      Incoherent<int64_t>::RO c(data+i, 1);
      VLOG(2) << i << " == " << *c;
      BOOST_CHECK_EQUAL(i, *c);
    }
    SoftXMT_free(data);
  }

  SoftXMT_signal_done();
}

BOOST_AUTO_TEST_CASE( test1 ) {
  SoftXMT_init( &(boost::unit_test::framework::master_test_suite().argc),
               &(boost::unit_test::framework::master_test_suite().argv), 1<<14);
  SoftXMT_activate();

  SoftXMT_run_user_main(&user_main, NULL);

  LOG(INFO) << "finishing...";
	SoftXMT_finish( 0 );
}

BOOST_AUTO_TEST_SUITE_END();
<commit_msg>Fixed ForkJoin_test for user_main as task<commit_after>#include <boost/test/unit_test.hpp>
#include "SoftXMT.hpp"
#include "Addressing.hpp"
#include "Cache.hpp"
#include "ForkJoin.hpp"
#include "GlobalAllocator.hpp"

BOOST_AUTO_TEST_SUITE( ForkJoin_tests );

#define MEM_SIZE 1<<24;

struct func_initialize : public ForkJoinIteration {
  GlobalAddress<int64_t> base_addr;
  int64_t value;
  void operator()(int64_t index) {
    VLOG(2) << "called func_initialize with index = " << index;
    Incoherent<int64_t>::RW c(base_addr+index, 1);
    c[0] = value+index;
  }
};

struct func_hello : public ForkJoinIteration {
  void operator()(int64_t index) {
    LOG(INFO) << "Hello from " << index << "!";
  }
};

static void user_main(int * args) {

  LOG(INFO) << "beginning user main.... (" << SoftXMT_mynode() << ")";

  {
    size_t N = 128;
    GlobalAddress<int64_t> data = SoftXMT_typed_malloc<int64_t>(N);

    func_initialize a; a.base_addr = data; a.value = 0;
    fork_join(&a, 0, N);

    for (size_t i=0; i<N; i++) {
      Incoherent<int64_t>::RO c(data+i, 1);
      VLOG(2) << i << " == " << *c;
      BOOST_CHECK_EQUAL(i, *c);
    }
    SoftXMT_free(data);
  }
  {
    size_t N = 101;
    GlobalAddress<int64_t> data = SoftXMT_typed_malloc<int64_t>(N);

    func_initialize a; a.base_addr = data; a.value = 0;
    fork_join(&a, 0, N);

    for (size_t i=0; i<N; i++) {
      Incoherent<int64_t>::RO c(data+i, 1);
      VLOG(2) << i << " == " << *c;
      BOOST_CHECK_EQUAL(i, *c);
    }
    SoftXMT_free(data);
  }
  {
    func_hello f;
    fork_join_custom(&f);
  }
  {
    size_t N = 128 + 13;
    GlobalAddress<int64_t> data = SoftXMT_typed_malloc<int64_t>(N);

    func_initialize a; a.base_addr = data; a.value = 0;
    fork_join(&a, 0, N);

	VLOG(2) << "done with init";

    for (size_t i=0; i<N; i++) {
      Incoherent<int64_t>::RO c(data+i, 1);
      VLOG(2) << i << " == " << *c;
      BOOST_CHECK_EQUAL(i, *c);
    }
    SoftXMT_free(data);
  }

}

BOOST_AUTO_TEST_CASE( test1 ) {
  SoftXMT_init( &(boost::unit_test::framework::master_test_suite().argc),
               &(boost::unit_test::framework::master_test_suite().argv), 1<<20);
  SoftXMT_activate();

  SoftXMT_run_user_main(&user_main, (int*)NULL);

  LOG(INFO) << "finishing...";
	SoftXMT_finish( 0 );
}

BOOST_AUTO_TEST_SUITE_END();
<|endoftext|>


<commit_before>// Copyright (c) 2019 by Robert Bosch GmbH. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "iceoryx_posh/popo/modern_api/typed_subscriber.hpp"
#include "iceoryx_posh/popo/wait_set.hpp"
#include "iceoryx_posh/runtime/posh_runtime.hpp"
#include "topic_data.hpp"

#include <chrono>
#include <csignal>
#include <iostream>

bool killswitch = false;

static void sigHandler(int f_sig [[gnu::unused]])
{
    // caught SIGINT, now exit gracefully
    killswitch = true;
}

int main()
{
    // register sigHandler for SIGINT
    signal(SIGINT, sigHandler);

    // initialize runtime
    iox::runtime::PoshRuntime::getInstance("/iox-ex-subscriber-typed-modern");

    // initialized subscribers
    iox::popo::TypedSubscriber<Position> typedSubscriber({"Odometry", "Position", "Vehicle"});
    typedSubscriber.subscribe();

    // set up waitset
    iox::popo::WaitSet waitSet{};
    waitSet.attachCondition(typedSubscriber);

    // run until interrupted
    while(!killswitch)
    {
        auto triggeredConditions = waitSet.wait();
        for(auto& condition : triggeredConditions)
        {
            /// @todo How to ensure the condition is a subscriber ? What about guard conditions?
            auto subscriber = dynamic_cast<iox::popo::TypedSubscriber<Position>*>(condition);
            subscriber->receive().and_then([](iox::cxx::optional<iox::popo::Sample<const Position>>& maybePosition){
                if(maybePosition.has_value())
                {
                    auto& position = maybePosition.value();
                    std::cout << "Got value: (" << position->x << ", " << position->y << ", " << position->z << ")" << std::endl;
                }
            });

        }
    }

    waitSet.detachAllConditions();

    return (EXIT_SUCCESS);
}
<commit_msg>iox-#252 Move subscriber handling logic to own thread and set up guard condition to shutdown gracefully.<commit_after>// Copyright (c) 2019 by Robert Bosch GmbH. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "iceoryx_posh/popo/modern_api/typed_subscriber.hpp"
#include "iceoryx_posh/popo/guard_condition.hpp"
#include "iceoryx_posh/popo/wait_set.hpp"
#include "iceoryx_posh/runtime/posh_runtime.hpp"
#include "topic_data.hpp"

#include <chrono>
#include <csignal>
#include <iostream>

bool killswitch = false;
iox::popo::GuardCondition shutdownGuard;

static void sigHandler(int f_sig [[gnu::unused]])
{
    // caught SIGINT, now exit gracefully
    killswitch = true;
    shutdownGuard.trigger(); // unblock waitsets
}

void handler(iox::popo::WaitSet& waitSet)
{
    // run until interrupted
    while(!killswitch)
    {
        auto triggeredConditions = waitSet.wait();
        for(auto& condition : triggeredConditions)
        {
            auto subscriber = dynamic_cast<iox::popo::TypedSubscriber<Position>*>(condition);
            if(subscriber)
            {
                // new data received on an attached subscriber

                subscriber->receive().and_then([](iox::cxx::optional<iox::popo::Sample<const Position>>& maybePosition){
                    if(maybePosition.has_value())
                    {
                        auto& position = maybePosition.value();
                        std::cout << "Got value: (" << position->x << ", " << position->y << ", " << position->z << ")" << std::endl;
                    }
                });
            }
            else
            {
                // shutdown guard has triggered
                std::cout << "Shutdown Guard triggered. Shutting down." << std::endl;
            }
        }
    }
}

int main()
{
    // register sigHandler for SIGINT
    signal(SIGINT, sigHandler);

    // initialize runtime
    iox::runtime::PoshRuntime::getInstance("/iox-ex-subscriber-typed-modern");

    // initialized subscribers
    iox::popo::TypedSubscriber<Position> typedSubscriber({"Odometry", "Position", "Vehicle"});
    typedSubscriber.subscribe();

    // set up waitset
    iox::popo::WaitSet waitSet{};
    waitSet.attachCondition(typedSubscriber);
    waitSet.attachCondition(shutdownGuard);

    // delegate handling of received data to another thread
    std::thread handlerThread(handler, std::ref(waitSet));
    handlerThread.join();

    // clean up
    waitSet.detachAllConditions();

    return (EXIT_SUCCESS);
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "vie_autotest.h"

#include "base_primitives.h"
#include "general_primitives.h"
#include "tb_interfaces.h"
#include "vie_autotest_defines.h"
#include "video_capture_factory.h"

class BaseObserver : public webrtc::ViEBaseObserver {
 public:
  BaseObserver()
      : cpu_load_(0) {}

  virtual void PerformanceAlarm(const unsigned int cpu_load) {
    cpu_load_ = cpu_load;
  }
  unsigned int cpu_load_;
};

void ViEAutoTest::ViEBaseStandardTest() {
  // ***************************************************************
  // Begin create/initialize WebRTC Video Engine for testing
  // ***************************************************************

  TbInterfaces interfaces("ViEBaseStandardTest");

  // ***************************************************************
  // Engine ready. Set up the test case:
  // ***************************************************************
  int video_channel = -1;
  EXPECT_EQ(0, interfaces.base->CreateChannel(video_channel));

  webrtc::VideoCaptureModule* video_capture_module(NULL);
  const unsigned int kMaxDeviceNameLength = 128;
  char device_name[kMaxDeviceNameLength];
  memset(device_name, 0, kMaxDeviceNameLength);
  int capture_id;

  webrtc::ViEBase *base_interface = interfaces.base;
  webrtc::ViERender *render_interface = interfaces.render;
  webrtc::ViECapture *capture_interface = interfaces.capture;

  FindCaptureDeviceOnSystem(capture_interface,
                            device_name,
                            kMaxDeviceNameLength,
                            &capture_id,
                            &video_capture_module);

  EXPECT_EQ(0, capture_interface->ConnectCaptureDevice(capture_id,
                                                       video_channel));
  EXPECT_EQ(0, capture_interface->StartCapture(capture_id));

  ConfigureRtpRtcp(interfaces.rtp_rtcp, video_channel);

  EXPECT_EQ(0, render_interface->RegisterVideoRenderModule(*_vrm1));
  EXPECT_EQ(0, render_interface->RegisterVideoRenderModule(*_vrm2));

  RenderInWindow(render_interface, capture_id, _window1, 0);
  RenderInWindow(render_interface, video_channel, _window2, 1);

  // ***************************************************************
  // Run the actual test:
  // ***************************************************************
  ViETest::Log("You should shortly see a local preview from camera %s"
      " in window 1 and the remote video in window 2.", device_name);
  ::TestI420CallSetup(interfaces.codec, interfaces.video_engine,
                      base_interface, interfaces.network, video_channel,
                      device_name);

  // ***************************************************************
  // Testing finished. Tear down Video Engine
  // ***************************************************************
  EXPECT_EQ(0, capture_interface->StopCapture(capture_id));
  EXPECT_EQ(0, base_interface->StopReceive(video_channel));

  StopAndRemoveRenderers(base_interface, render_interface, video_channel,
                         capture_id);

  EXPECT_EQ(0, render_interface->DeRegisterVideoRenderModule(*_vrm1));
  EXPECT_EQ(0, render_interface->DeRegisterVideoRenderModule(*_vrm2));

  EXPECT_EQ(0, capture_interface->ReleaseCaptureDevice(capture_id));

  video_capture_module->Release();
  video_capture_module = NULL;

  EXPECT_EQ(0, base_interface->DeleteChannel(video_channel));
}

void ViEAutoTest::ViEBaseExtendedTest() {
  // Start with standard test
  ViEBaseAPITest();
  ViEBaseStandardTest();

    // ***************************************************************
    // Test BaseObserver
    // ***************************************************************
    // TODO(mflodman) Add test for base observer. Cpu load must be over 75%.
//    BaseObserver base_observer;
//    EXPECT_EQ(ptrViEBase->RegisterObserver(base_observer), 0);
//
//    AutoTestSleep(KAutoTestSleepTimeMs);
//
//    EXPECT_EQ(ptrViEBase->DeregisterObserver(), 0);
//    EXPECT_GT(base_observer.cpu_load, 0);
}

void ViEAutoTest::ViEBaseAPITest() {
  // ***************************************************************
  // Begin create/initialize WebRTC Video Engine for testing
  // ***************************************************************
  // Get the ViEBase API
  webrtc::ViEBase* ptrViEBase = webrtc::ViEBase::GetInterface(NULL);
  EXPECT_EQ(NULL, ptrViEBase) << "Should return null for a bad ViE pointer";

  webrtc::VideoEngine* ptrViE = webrtc::VideoEngine::Create();
  EXPECT_TRUE(NULL != ptrViE);

  std::string trace_file_path =
      ViETest::GetResultOutputPath() + "ViEBaseAPI_trace.txt";
  EXPECT_EQ(0, ptrViE->SetTraceFile(trace_file_path.c_str()));

  ptrViEBase = webrtc::ViEBase::GetInterface(ptrViE);
  EXPECT_TRUE(NULL != ptrViEBase);

  // ***************************************************************
  // Engine ready. Begin testing class
  // ***************************************************************
  char version[1024] = "";
  EXPECT_EQ(0, ptrViEBase->GetVersion(version));
  EXPECT_EQ(0, ptrViEBase->LastError());

  // Create without init
  int videoChannel = -1;
  EXPECT_NE(0, ptrViEBase->CreateChannel(videoChannel)) <<
      "Should fail since Init has not been called yet";
  EXPECT_EQ(0, ptrViEBase->Init());
  EXPECT_EQ(0, ptrViEBase->CreateChannel(videoChannel));

  int videoChannel2 = -1;
  EXPECT_EQ(0, ptrViEBase->CreateChannel(videoChannel2));
  EXPECT_NE(videoChannel, videoChannel2) <<
      "Should allocate new number for independent channel";

  EXPECT_EQ(0, ptrViEBase->DeleteChannel(videoChannel2));

  EXPECT_EQ(-1, ptrViEBase->CreateChannel(videoChannel2, videoChannel + 1)) <<
      "Should fail since neither channel exists (the second must)";

  EXPECT_EQ(0, ptrViEBase->CreateChannel(videoChannel2, videoChannel));

  // Test Voice Engine integration with Video Engine.
  webrtc::VoiceEngine* ptrVoE = NULL;
  webrtc::VoEBase* ptrVoEBase = NULL;
  int audioChannel = -1;

  ptrVoE = webrtc::VoiceEngine::Create();
  EXPECT_TRUE(NULL != ptrVoE);

  ptrVoEBase = webrtc::VoEBase::GetInterface(ptrVoE);
  EXPECT_TRUE(NULL != ptrVoEBase);
  EXPECT_EQ(0, ptrVoEBase->Init());

  audioChannel = ptrVoEBase->CreateChannel();
  EXPECT_NE(-1, audioChannel);

  // Connect before setting VoE.
  EXPECT_NE(0, ptrViEBase->ConnectAudioChannel(videoChannel, audioChannel)) <<
      "Should fail since Voice Engine is not set yet.";

  // Then do it right.
  EXPECT_EQ(0, ptrViEBase->SetVoiceEngine(ptrVoE));
  EXPECT_EQ(0, ptrViEBase->ConnectAudioChannel(videoChannel, audioChannel));

  // ***************************************************************
  // Testing finished. Tear down Video Engine
  // ***************************************************************
  EXPECT_NE(0, ptrViEBase->DisconnectAudioChannel(videoChannel + 5)) <<
      "Should fail: disconnecting bogus channel";

  EXPECT_EQ(0, ptrViEBase->DisconnectAudioChannel(videoChannel));

  // Clean up voice engine
  EXPECT_EQ(0, ptrViEBase->SetVoiceEngine(NULL));
  EXPECT_EQ(0, ptrVoEBase->Release());
  EXPECT_TRUE(webrtc::VoiceEngine::Delete(ptrVoE));

  webrtc::ViEBase* ptrViEBase2 = webrtc::ViEBase::GetInterface(ptrViE);
  EXPECT_TRUE(NULL != ptrViEBase2);

  EXPECT_EQ(1, ptrViEBase->Release()) << "There should be one interface left.";

  EXPECT_FALSE(webrtc::VideoEngine::Delete(ptrViE)) <<
      "Should fail since there are interfaces left.";

  EXPECT_EQ(0, ptrViEBase->Release());
  EXPECT_TRUE(webrtc::VideoEngine::Delete(ptrViE));
}
<commit_msg>nits<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "vie_autotest.h"

#include "base_primitives.h"
#include "general_primitives.h"
#include "tb_interfaces.h"
#include "vie_autotest_defines.h"
#include "video_capture_factory.h"

class BaseObserver : public webrtc::ViEBaseObserver {
 public:
  BaseObserver()
      : cpu_load_(0) {}

  virtual void PerformanceAlarm(const unsigned int cpu_load) {
    cpu_load_ = cpu_load;
  }
  unsigned int cpu_load_;
};

void ViEAutoTest::ViEBaseStandardTest() {
  // ***************************************************************
  // Begin create/initialize WebRTC Video Engine for testing
  // ***************************************************************

  TbInterfaces interfaces("ViEBaseStandardTest");

  // ***************************************************************
  // Engine ready. Set up the test case:
  // ***************************************************************
  int video_channel = -1;
  EXPECT_EQ(0, interfaces.base->CreateChannel(video_channel));

  webrtc::VideoCaptureModule* video_capture_module(NULL);
  const unsigned int kMaxDeviceNameLength = 128;
  char device_name[kMaxDeviceNameLength];
  memset(device_name, 0, kMaxDeviceNameLength);
  int capture_id;

  webrtc::ViEBase *base_interface = interfaces.base;
  webrtc::ViERender *render_interface = interfaces.render;
  webrtc::ViECapture *capture_interface = interfaces.capture;

  FindCaptureDeviceOnSystem(capture_interface,
                            device_name,
                            kMaxDeviceNameLength,
                            &capture_id,
                            &video_capture_module);

  EXPECT_EQ(0, capture_interface->ConnectCaptureDevice(capture_id,
                                                       video_channel));
  EXPECT_EQ(0, capture_interface->StartCapture(capture_id));

  ConfigureRtpRtcp(interfaces.rtp_rtcp, video_channel);

  EXPECT_EQ(0, render_interface->RegisterVideoRenderModule(*_vrm1));
  EXPECT_EQ(0, render_interface->RegisterVideoRenderModule(*_vrm2));

  RenderInWindow(render_interface, capture_id, _window1, 0);
  RenderInWindow(render_interface, video_channel, _window2, 1);

  // ***************************************************************
  // Run the actual test:
  // ***************************************************************
  ViETest::Log("You should shortly see a local preview from camera %s"
      " in window 1 and the remote video in window 2.", device_name);
  ::TestI420CallSetup(interfaces.codec, interfaces.video_engine,
                      base_interface, interfaces.network, video_channel,
                      device_name);

  // ***************************************************************
  // Testing finished. Tear down Video Engine
  // ***************************************************************
  EXPECT_EQ(0, capture_interface->StopCapture(capture_id));
  EXPECT_EQ(0, base_interface->StopReceive(video_channel));

  StopAndRemoveRenderers(base_interface, render_interface, video_channel,
                         capture_id);

  EXPECT_EQ(0, render_interface->DeRegisterVideoRenderModule(*_vrm1));
  EXPECT_EQ(0, render_interface->DeRegisterVideoRenderModule(*_vrm2));

  EXPECT_EQ(0, capture_interface->ReleaseCaptureDevice(capture_id));

  video_capture_module->Release();
  video_capture_module = NULL;

  EXPECT_EQ(0, base_interface->DeleteChannel(video_channel));
}

void ViEAutoTest::ViEBaseExtendedTest() {
  // Start with standard test
  ViEBaseAPITest();
  ViEBaseStandardTest();

    // ***************************************************************
    // Test BaseObserver
    // ***************************************************************
    // TODO(mflodman) Add test for base observer. Cpu load must be over 75%.
//    BaseObserver base_observer;
//    EXPECT_EQ(ptrViEBase->RegisterObserver(base_observer), 0);
//
//    AutoTestSleep(KAutoTestSleepTimeMs);
//
//    EXPECT_EQ(ptrViEBase->DeregisterObserver(), 0);
//    EXPECT_GT(base_observer.cpu_load, 0);
}

void ViEAutoTest::ViEBaseAPITest() {
  // ***************************************************************
  // Begin create/initialize WebRTC Video Engine for testing
  // ***************************************************************
  // Get the ViEBase API
  webrtc::ViEBase* ptrViEBase = webrtc::ViEBase::GetInterface(NULL);
  EXPECT_EQ(NULL, ptrViEBase) << "Should return null for a bad ViE pointer";

  webrtc::VideoEngine* ptrViE = webrtc::VideoEngine::Create();
  EXPECT_TRUE(NULL != ptrViE);

  std::string trace_file_path =
      ViETest::GetResultOutputPath() + "ViEBaseAPI_trace.txt";
  EXPECT_EQ(0, ptrViE->SetTraceFile(trace_file_path.c_str()));

  ptrViEBase = webrtc::ViEBase::GetInterface(ptrViE);
  EXPECT_TRUE(NULL != ptrViEBase);

  // ***************************************************************
  // Engine ready. Begin testing class
  // ***************************************************************
  char version[1024] = "";
  EXPECT_EQ(0, ptrViEBase->GetVersion(version));
  EXPECT_EQ(0, ptrViEBase->LastError());

  // Create without init
  int videoChannel = -1;
  EXPECT_NE(0, ptrViEBase->CreateChannel(videoChannel)) <<
      "Should fail since Init has not been called yet";
  EXPECT_EQ(0, ptrViEBase->Init());
  EXPECT_EQ(0, ptrViEBase->CreateChannel(videoChannel));

  int videoChannel2 = -1;
  EXPECT_EQ(0, ptrViEBase->CreateChannel(videoChannel2));
  EXPECT_NE(videoChannel, videoChannel2) <<
      "Should allocate new number for independent channel";

  EXPECT_EQ(0, ptrViEBase->DeleteChannel(videoChannel2));

  EXPECT_EQ(-1, ptrViEBase->CreateChannel(videoChannel2, videoChannel + 1)) <<
      "Should fail since neither channel exists (the second must)";

  EXPECT_EQ(0, ptrViEBase->CreateChannel(videoChannel2, videoChannel));

  // Test Voice Engine integration with Video Engine.
  webrtc::VoiceEngine* ptrVoE = NULL;
  webrtc::VoEBase* ptrVoEBase = NULL;
  int audioChannel = -1;

  ptrVoE = webrtc::VoiceEngine::Create();
  EXPECT_TRUE(NULL != ptrVoE);

  ptrVoEBase = webrtc::VoEBase::GetInterface(ptrVoE);
  EXPECT_TRUE(NULL != ptrVoEBase);
  EXPECT_EQ(0, ptrVoEBase->Init());

  audioChannel = ptrVoEBase->CreateChannel();
  EXPECT_NE(-1, audioChannel);

  // Connect before setting VoE.
  EXPECT_NE(0, ptrViEBase->ConnectAudioChannel(videoChannel, audioChannel)) <<
      "Should fail since Voice Engine is not set yet.";

  // Then do it right.
  EXPECT_EQ(0, ptrViEBase->SetVoiceEngine(ptrVoE));
  EXPECT_EQ(0, ptrViEBase->ConnectAudioChannel(videoChannel, audioChannel));

  // ***************************************************************
  // Testing finished. Tear down Video Engine
  // ***************************************************************
  EXPECT_NE(0, ptrViEBase->DisconnectAudioChannel(videoChannel + 5)) <<
      "Should fail: disconnecting bogus channel";

  EXPECT_EQ(0, ptrViEBase->DisconnectAudioChannel(videoChannel));

  // Clean up voice engine
  EXPECT_EQ(0, ptrViEBase->SetVoiceEngine(NULL));
  EXPECT_EQ(0, ptrVoEBase->Release());
  EXPECT_TRUE(webrtc::VoiceEngine::Delete(ptrVoE));

  webrtc::ViEBase* ptrViEBase2 = webrtc::ViEBase::GetInterface(ptrViE);
  EXPECT_TRUE(NULL != ptrViEBase2);

  EXPECT_EQ(1, ptrViEBase->Release()) << "There should be one interface left.";

  EXPECT_FALSE(webrtc::VideoEngine::Delete(ptrViE)) <<
      "Should fail since there are interfaces left.";

  EXPECT_EQ(0, ptrViEBase->Release());
  EXPECT_TRUE(webrtc::VideoEngine::Delete(ptrViE));
}
<|endoftext|>


<commit_before>/*****************************************************************************************
 *                                                                                *
 * GHOUL                                                                                *
 * General Helpful Open Utility Library                                                  *
 *                                                                                *
 * Copyright (c) 2012-2014                                                               *
 *                                                                                *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this  *
 * software and associated documentation files (the "Software"), to deal in the Software *
 * without restriction, including without limitation the rights to use, copy, modify,    *
 * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to    *
 * permit persons to whom the Software is furnished to do so, subject to the following   *
 * conditions:                                                                           *
 *                                                                                *
 * The above copyright notice and this permission notice shall be included in all copies *
 * or substantial portions of the Software.                                              *
 *                                                                                *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,   *
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A         *
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT    *
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF  *
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE  *
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                                         *
 ****************************************************************************************/

#include <ghoul/filesystem/directory.h>

#include <ghoul/filesystem/filesystem.h>

#include <algorithm>
#include <stack>

#ifdef WIN32
#include <windows.h>
#include <tchar.h>
#include <direct.h>
#else
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#endif

using std::string;
using std::vector;

namespace ghoul {
namespace filesystem {

namespace {
#ifdef WIN32
    const char pathSeparator = '\\';
#else
    const char pathSeparator = '/';
#endif
}

Directory::Directory()
    : _directoryPath(FileSys.absolutePath("."))
{}

Directory::Directory(const char* path, bool isRawPath) {
    if (isRawPath)
        _directoryPath = string(path);
    else
        _directoryPath = FileSys.absolutePath(string(path));
}

Directory::Directory(std::string path, bool isRawPath) {
    if (isRawPath)
        _directoryPath = path.empty() ? "." : std::move(path);
    else
        _directoryPath = std::move(FileSys.absolutePath(path.empty() ? "." : path));
}

Directory::operator const std::string&() const {
    return _directoryPath;
}

const std::string& Directory::path() const {
    return _directoryPath;
}

Directory Directory::parentDirectory(bool absolutePath) const {
#ifdef WIN32
    if (_directoryPath.back() == pathSeparator)
        return Directory(_directoryPath + "..", !absolutePath);
    else
        return Directory(_directoryPath + pathSeparator + "..",
                         !absolutePath);
#else
    size_t length = _directoryPath.length();
    size_t position = _directoryPath.find_last_of(pathSeparator);
    if(position == length && length > 1)
        position = _directoryPath.find_last_of(pathSeparator, length-1);

    return Directory(_directoryPath.substr(0, position));
#endif
}

std::vector<std::string> Directory::read(bool recursiveSearch, bool sort) const {
    vector<string> result;
    readDirectories(result, _directoryPath, recursiveSearch);
    readFiles(result, _directoryPath, recursiveSearch);
    if (sort)
        std::sort(result.begin(), result.end());
    return result;
}

std::vector<std::string> Directory::readFiles(bool recursiveSearch, bool sort) const {
    vector<string> result;
    readFiles(result, _directoryPath, recursiveSearch);
    if (sort)
        std::sort(result.begin(), result.end());
    return result;
}

void Directory::readFiles(std::vector<std::string>& result,
                          const std::string& path, bool recursiveSearch) const
{
    std::stack<string> directories;
#ifdef WIN32
    WIN32_FIND_DATA findFileData = {0};
    const string& directory = path + "\\*";

    HANDLE findHandle = FindFirstFile(directory.c_str(), &findFileData);
    if (findHandle != INVALID_HANDLE_VALUE) {
        do {
            string file(findFileData.cFileName);
            const DWORD isDir = findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
            if (!isDir)
                result.push_back(path + "/" + file);
            if (recursiveSearch && isDir && file != "." && file != "..")
                directories.push(path + "/" + file);
        } while (FindNextFile(findHandle, &findFileData) != 0);
    }
    FindClose(findHandle);
#else
    DIR* dir = opendir(path.c_str());
    struct dirent* ent;
    if (dir != NULL) {
        string name;
        while ((ent = readdir(dir))) {
            name = ent->d_name;
            if ((name != ".") && (name != "..")) {
                if (ent->d_type != DT_DIR)
                    result.push_back(path + "/" + ent->d_name);
                if (recursiveSearch && (ent->d_type == DT_DIR))
                    directories.push(path + "/" + ent->d_name);
            }
        }
    }
    closedir(dir);
#endif
    while (!directories.empty()) {
        const string& directory = directories.top();
        readFiles(result, directory, recursiveSearch);
        directories.pop();
    }
}

std::vector<std::string> Directory::readDirectories(bool recursiveSearch, bool sort) const {
    std::vector<std::string> result;
    readDirectories(result, _directoryPath, recursiveSearch);
    if (sort)
        std::sort(result.begin(), result.end());
    return result;
}

void Directory::readDirectories(
    std::vector<std::string>& result,
    const std::string& path,
    bool recursiveSearch) const
{
    std::stack<string> directories;

#ifdef WIN32
    WIN32_FIND_DATA findFileData = {0};
    std::string directory = path + "\\*";

    HANDLE findHandle = FindFirstFile(directory.c_str(), &findFileData);
    if (findHandle != INVALID_HANDLE_VALUE) {
        do {
            string file(findFileData.cFileName);
            const DWORD isDir = findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
            if (isDir && (file != ".") && (file != "..")) {
                result.push_back(path + "\\" + file);
                if (recursiveSearch)
                    directories.push(path + "\\" + file);
            }
        } while (FindNextFile(findHandle, &findFileData) != 0);
    }
    FindClose(findHandle);
#else
    DIR* dir = opendir(path.c_str());
    struct dirent* ent;
    if (dir != NULL) {
        string name;
        while ((ent = readdir(dir))) {
            name = ent->d_name;
            if ((ent->d_type == DT_DIR) && (name != ".") && (name != "..")) {
                result.push_back(path + "/" + ent->d_name);
                if (recursiveSearch)
                    directories.push(path + "/" + ent->d_name);
            }
        }
    }
    closedir(dir);
#endif
    while (!directories.empty()) {
        const string& directory = directories.top();
        readDirectories(result, directory, recursiveSearch);
        directories.pop();
    }
}

std::ostream& operator<<(std::ostream& os, const Directory& d) {
    return os << d.path();
}

} // filesystem
} // ghoul
<commit_msg>Trying to remove a compiler warning<commit_after>/*****************************************************************************************
 *                                                                                *
 * GHOUL                                                                                *
 * General Helpful Open Utility Library                                                  *
 *                                                                                *
 * Copyright (c) 2012-2014                                                               *
 *                                                                                *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this  *
 * software and associated documentation files (the "Software"), to deal in the Software *
 * without restriction, including without limitation the rights to use, copy, modify,    *
 * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to    *
 * permit persons to whom the Software is furnished to do so, subject to the following   *
 * conditions:                                                                           *
 *                                                                                *
 * The above copyright notice and this permission notice shall be included in all copies *
 * or substantial portions of the Software.                                              *
 *                                                                                *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,   *
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A         *
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT    *
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF  *
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE  *
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                                         *
 ****************************************************************************************/

#include <ghoul/filesystem/directory.h>

#include <ghoul/filesystem/filesystem.h>

#include <algorithm>
#include <stack>

#ifdef WIN32
#include <windows.h>
#include <tchar.h>
#include <direct.h>
#else
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#endif

using std::string;
using std::vector;

namespace ghoul {
namespace filesystem {

namespace {
#ifdef WIN32
    const char pathSeparator = '\\';
#else
    const char pathSeparator = '/';
#endif
}

Directory::Directory()
    : _directoryPath(FileSys.absolutePath("."))
{}

Directory::Directory(const char* path, bool isRawPath) {
    if (isRawPath)
        _directoryPath = string(path);
    else
        _directoryPath = FileSys.absolutePath(string(path));
}

Directory::Directory(std::string path, bool isRawPath) {
    if (isRawPath)
        _directoryPath = path.empty() ? "." : std::move(path);
    else
        _directoryPath = std::move(FileSys.absolutePath(path.empty() ? "." : path));
}

Directory::operator const std::string&() const {
    return _directoryPath;
}

const std::string& Directory::path() const {
    return _directoryPath;
}

Directory Directory::parentDirectory(bool absolutePath) const {
#ifdef WIN32
    if (_directoryPath.back() == pathSeparator)
        return Directory(_directoryPath + "..", !absolutePath);
    else
        return Directory(_directoryPath + pathSeparator + "..",
                         !absolutePath);
#else
#pragma unused (absolutePath)
    size_t length = _directoryPath.length();
    size_t position = _directoryPath.find_last_of(pathSeparator);
    if(position == length && length > 1)
        position = _directoryPath.find_last_of(pathSeparator, length-1);

    return Directory(_directoryPath.substr(0, position));
#endif
}

std::vector<std::string> Directory::read(bool recursiveSearch, bool sort) const {
    vector<string> result;
    readDirectories(result, _directoryPath, recursiveSearch);
    readFiles(result, _directoryPath, recursiveSearch);
    if (sort)
        std::sort(result.begin(), result.end());
    return result;
}

std::vector<std::string> Directory::readFiles(bool recursiveSearch, bool sort) const {
    vector<string> result;
    readFiles(result, _directoryPath, recursiveSearch);
    if (sort)
        std::sort(result.begin(), result.end());
    return result;
}

void Directory::readFiles(std::vector<std::string>& result,
                          const std::string& path, bool recursiveSearch) const
{
    std::stack<string> directories;
#ifdef WIN32
    WIN32_FIND_DATA findFileData = {0};
    const string& directory = path + "\\*";

    HANDLE findHandle = FindFirstFile(directory.c_str(), &findFileData);
    if (findHandle != INVALID_HANDLE_VALUE) {
        do {
            string file(findFileData.cFileName);
            const DWORD isDir = findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
            if (!isDir)
                result.push_back(path + "/" + file);
            if (recursiveSearch && isDir && file != "." && file != "..")
                directories.push(path + "/" + file);
        } while (FindNextFile(findHandle, &findFileData) != 0);
    }
    FindClose(findHandle);
#else
    DIR* dir = opendir(path.c_str());
    struct dirent* ent;
    if (dir != NULL) {
        string name;
        while ((ent = readdir(dir))) {
            name = ent->d_name;
            if ((name != ".") && (name != "..")) {
                if (ent->d_type != DT_DIR)
                    result.push_back(path + "/" + ent->d_name);
                if (recursiveSearch && (ent->d_type == DT_DIR))
                    directories.push(path + "/" + ent->d_name);
            }
        }
    }
    closedir(dir);
#endif
    while (!directories.empty()) {
        const string& directory = directories.top();
        readFiles(result, directory, recursiveSearch);
        directories.pop();
    }
}

std::vector<std::string> Directory::readDirectories(bool recursiveSearch, bool sort) const {
    std::vector<std::string> result;
    readDirectories(result, _directoryPath, recursiveSearch);
    if (sort)
        std::sort(result.begin(), result.end());
    return result;
}

void Directory::readDirectories(
    std::vector<std::string>& result,
    const std::string& path,
    bool recursiveSearch) const
{
    std::stack<string> directories;

#ifdef WIN32
    WIN32_FIND_DATA findFileData = {0};
    std::string directory = path + "\\*";

    HANDLE findHandle = FindFirstFile(directory.c_str(), &findFileData);
    if (findHandle != INVALID_HANDLE_VALUE) {
        do {
            string file(findFileData.cFileName);
            const DWORD isDir = findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
            if (isDir && (file != ".") && (file != "..")) {
                result.push_back(path + "\\" + file);
                if (recursiveSearch)
                    directories.push(path + "\\" + file);
            }
        } while (FindNextFile(findHandle, &findFileData) != 0);
    }
    FindClose(findHandle);
#else
    DIR* dir = opendir(path.c_str());
    struct dirent* ent;
    if (dir != NULL) {
        string name;
        while ((ent = readdir(dir))) {
            name = ent->d_name;
            if ((ent->d_type == DT_DIR) && (name != ".") && (name != "..")) {
                result.push_back(path + "/" + ent->d_name);
                if (recursiveSearch)
                    directories.push(path + "/" + ent->d_name);
            }
        }
    }
    closedir(dir);
#endif
    while (!directories.empty()) {
        const string& directory = directories.top();
        readDirectories(result, directory, recursiveSearch);
        directories.pop();
    }
}

std::ostream& operator<<(std::ostream& os, const Directory& d) {
    return os << d.path();
}

} // filesystem
} // ghoul
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/remoting/remoting_options_handler.h"

#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/service/service_process_control_manager.h"
#include "chrome/common/remoting/chromoting_host_info.h"
#include "content/browser/webui/web_ui.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"

namespace remoting {

RemotingOptionsHandler::RemotingOptionsHandler()
    : web_ui_(NULL),
      process_control_(NULL) {
}

RemotingOptionsHandler::~RemotingOptionsHandler() {
  if (process_control_)
    process_control_->RemoveMessageHandler(this);
}

void RemotingOptionsHandler::Init(WebUI* web_ui) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  web_ui_ = web_ui;

  process_control_ =
      ServiceProcessControlManager::GetInstance()->GetProcessControl(
          web_ui_->GetProfile());
  process_control_->AddMessageHandler(this);

  if (!process_control_->RequestRemotingHostStatus()) {
    // Assume that host is not started if we can't request status.
    SetStatus(false, "");
  }
}

// ServiceProcessControl::MessageHandler interface
void RemotingOptionsHandler::OnRemotingHostInfo(
    const remoting::ChromotingHostInfo& host_info) {
  SetStatus(host_info.enabled, host_info.login);
}

void RemotingOptionsHandler::SetStatus(
    bool enabled, const std::string& login) {
  string16 status;
  if (enabled) {
    status = l10n_util::GetStringFUTF16(IDS_REMOTING_STATUS_ENABLED_TEXT,
                                        UTF8ToUTF16(login));
  } else {
    status = l10n_util::GetStringUTF16(IDS_REMOTING_STATUS_DISABLED_TEXT);
  }

  FundamentalValue enabled_value(enabled);
  StringValue status_value(status);
  web_ui_->CallJavascriptFunction(L"options.AdvancedOptions.SetRemotingStatus",
                                  enabled_value, status_value);
}

}  // namespace remoting
<commit_msg>Fix build failure in remoting option handler<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/remoting/remoting_options_handler.h"

#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/service/service_process_control_manager.h"
#include "chrome/common/remoting/chromoting_host_info.h"
#include "content/browser/webui/web_ui.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"

namespace remoting {

RemotingOptionsHandler::RemotingOptionsHandler()
    : web_ui_(NULL),
      process_control_(NULL) {
}

RemotingOptionsHandler::~RemotingOptionsHandler() {
  if (process_control_)
    process_control_->RemoveMessageHandler(this);
}

void RemotingOptionsHandler::Init(WebUI* web_ui) {
  web_ui_ = web_ui;

  process_control_ =
      ServiceProcessControlManager::GetInstance()->GetProcessControl(
          web_ui_->GetProfile());
  process_control_->AddMessageHandler(this);

  if (!process_control_->RequestRemotingHostStatus()) {
    // Assume that host is not started if we can't request status.
    SetStatus(false, "");
  }
}

// ServiceProcessControl::MessageHandler interface
void RemotingOptionsHandler::OnRemotingHostInfo(
    const remoting::ChromotingHostInfo& host_info) {
  SetStatus(host_info.enabled, host_info.login);
}

void RemotingOptionsHandler::SetStatus(
    bool enabled, const std::string& login) {
  string16 status;
  if (enabled) {
    status = l10n_util::GetStringFUTF16(IDS_REMOTING_STATUS_ENABLED_TEXT,
                                        UTF8ToUTF16(login));
  } else {
    status = l10n_util::GetStringUTF16(IDS_REMOTING_STATUS_DISABLED_TEXT);
  }

  FundamentalValue enabled_value(enabled);
  StringValue status_value(status);
  web_ui_->CallJavascriptFunction(L"options.AdvancedOptions.SetRemotingStatus",
                                  enabled_value, status_value);
}

}  // namespace remoting
<|endoftext|>


<commit_before>// FRAGMENT(includes)
#include <iostream>
#include <seqan/align.h>
#include <seqan/index.h>
#include <seqan/misc/misc_random.h>

using namespace seqan;

// FRAGMENT(matrix_init)
template <typename TStringSet, typename TIndexSpec>
void qgramCounting(TStringSet &set, TIndexSpec)
{
	typedef Index<TStringSet, TIndexSpec> TIndex;
	typedef typename Fibre<TIndex, QGram_Counts>::Type TCounts;
	typedef typename Fibre<TIndex, QGram_CountsDir>::Type TCountsDir;
	typedef typename Value<TCountsDir>::Type TDirValue;
	typedef typename Iterator<TCounts, Standard>::Type TIterCounts;
	typedef typename Iterator<TCountsDir, Standard>::Type TIterCountsDir;

	TIndex index(set);
	indexRequire(index, QGram_Counts());

	// initialize distance matrix
	int seqNum = countSequences(index);
	Matrix<int, 2> distMat;
	setLength(distMat, 0, seqNum);
	setLength(distMat, 1, seqNum);
	fill(distMat, 0);

	std::cout << std::endl << "Length of the CountsDir fibre: " << length(indexCountsDir(index)) << std::endl;
	TIterCountsDir itCountsDir = begin(indexCountsDir(index), Standard());
	TIterCountsDir itCountsDirEnd = end(indexCountsDir(index), Standard());
	TIterCounts itCountsBegin = begin(indexCounts(index), Standard());

// FRAGMENT(matrix_calculation)
	// for each bucket count common q-grams for each sequence pair
	TDirValue bucketBegin = *itCountsDir;
	for(++itCountsDir; itCountsDir != itCountsDirEnd; ++itCountsDir)
	{
		TDirValue bucketEnd = *itCountsDir;

		// q-gram must occur in at least 2 different sequences
		if (bucketBegin != bucketEnd)
		{
			TIterCounts itA = itCountsBegin + bucketBegin;
			TIterCounts itEnd = itCountsBegin + bucketEnd;
			for(; itA != itEnd; ++itA)
				for(TIterCounts itB = itA; itB != itEnd; ++itB)
					distMat((*itA).i1, (*itB).i1) += _min((*itA).i2, (*itB).i2);
		}
		bucketBegin = bucketEnd;
	}

	std::cout << std::endl << "Common 5-mers for Seq_i, Seq_j" << std::endl;
	std::cout << distMat;
}

// FRAGMENT(initialization)
int main ()
{
	//  for the sake of reproducibility
	mtRandInit(false);

	// create StringSet of 3 random sequences
	StringSet<DnaString> stringSet;
	reserve(stringSet, 3);
	for (int seqNo = 0; seqNo < 3; ++seqNo)
	{
		DnaString tmp;
		int len = mtRand() % 100 + 10;
		for (int i = 0; i < len; ++i)
			appendValue(tmp, Dna(mtRand() % 4));
		appendValue(stringSet, tmp);
		std::cout << ">Seq" << seqNo << std::endl << tmp << std::endl;
	}

	qgramCounting(stringSet, Index_QGram<UngappedShape<5> >());
	qgramCounting(stringSet, Index_QGram<UngappedShape<5>, OpenAddressing>());
	return 0;
}

<commit_msg>switched to the new RNG<commit_after>// FRAGMENT(includes)
#include <iostream>
#include <seqan/align.h>
#include <seqan/index.h>
#include <seqan/random.h>

using namespace seqan;

// FRAGMENT(matrix_init)
template <typename TStringSet, typename TIndexSpec>
void qgramCounting(TStringSet &set, TIndexSpec)
{
	typedef Index<TStringSet, TIndexSpec> TIndex;
	typedef typename Fibre<TIndex, QGram_Counts>::Type TCounts;
	typedef typename Fibre<TIndex, QGram_CountsDir>::Type TCountsDir;
	typedef typename Value<TCountsDir>::Type TDirValue;
	typedef typename Iterator<TCounts, Standard>::Type TIterCounts;
	typedef typename Iterator<TCountsDir, Standard>::Type TIterCountsDir;

	TIndex index(set);
	indexRequire(index, QGram_Counts());

	// initialize distance matrix
	int seqNum = countSequences(index);
	Matrix<int, 2> distMat;
	setLength(distMat, 0, seqNum);
	setLength(distMat, 1, seqNum);
	fill(distMat, 0);

	std::cout << std::endl << "Length of the CountsDir fibre: " << length(indexCountsDir(index)) << std::endl;
	TIterCountsDir itCountsDir = begin(indexCountsDir(index), Standard());
	TIterCountsDir itCountsDirEnd = end(indexCountsDir(index), Standard());
	TIterCounts itCountsBegin = begin(indexCounts(index), Standard());

// FRAGMENT(matrix_calculation)
	// for each bucket count common q-grams for each sequence pair
	TDirValue bucketBegin = *itCountsDir;
	for(++itCountsDir; itCountsDir != itCountsDirEnd; ++itCountsDir)
	{
		TDirValue bucketEnd = *itCountsDir;

		// q-gram must occur in at least 2 different sequences
		if (bucketBegin != bucketEnd)
		{
			TIterCounts itA = itCountsBegin + bucketBegin;
			TIterCounts itEnd = itCountsBegin + bucketEnd;
			for(; itA != itEnd; ++itA)
				for(TIterCounts itB = itA; itB != itEnd; ++itB)
					distMat((*itA).i1, (*itB).i1) += _min((*itA).i2, (*itB).i2);
		}
		bucketBegin = bucketEnd;
	}

	std::cout << std::endl << "Common 5-mers for Seq_i, Seq_j" << std::endl;
	std::cout << distMat;
}

// FRAGMENT(initialization)
int main ()
{
	//  for the sake of reproducibility
	RNG<MersenneTwister> rng;

	// create StringSet of 3 random sequences
	StringSet<DnaString> stringSet;
	reserve(stringSet, 3);
	for (int seqNo = 0; seqNo < 3; ++seqNo)
	{
		DnaString tmp;
		int len = pickRandomNumber(rng) % 100 + 10;
		for (int i = 0; i < len; ++i)
			appendValue(tmp, Dna(pickRandomNumber(rng) % 4));
		appendValue(stringSet, tmp);
		std::cout << ">Seq" << seqNo << std::endl << tmp << std::endl;
	}

	qgramCounting(stringSet, Index_QGram<UngappedShape<5> >());
	qgramCounting(stringSet, Index_QGram<UngappedShape<5>, OpenAddressing>());
	return 0;
}

<|endoftext|>


<commit_before>#ifndef b_array_View_hxx_
#define b_array_View_hxx_

#include "b/b_assert.hxx"
#include "b/Unsigned.hxx"

namespace b {
namespace array {

template <typename Element>
struct View
{
    //--------------------------------------------------------------------------------------------//
    // Constructors

    constexpr
    View(Element* data, Unsigned length)
        : __0(data)
        , __n(data + length)
    {
    }

    template <Unsigned length>
    constexpr explicit
    View(Element(& data)[length])
        : View(data, length)
    {
    }

    //--------------------------------------------------------------------------------------------//
    // Sized

    constexpr
    Unsigned
    length() const
    {
        return (reinterpret_cast<Unsigned>(this->__n) -
                reinterpret_cast<Unsigned>(this->__0));
    }

    //--------------------------------------------------------------------------------------------//
    // Iterable

    constexpr
    Element*
    begin() const
    {
        return this->__0;
    }

    constexpr
    Element*
    end() const
    {
        return this->__n;
    }

    //--------------------------------------------------------------------------------------------//
    // Container

    constexpr
    Element&
    operator
    [](Unsigned offset) const
    {
        b_assert(offset < this->length(), "out of bounds");
        return this->__0[offset];
    }

  private:
    Element*
    __0;

    Element*
    __n;
};

} // namespace array
} // namespace b

#endif
<commit_msg>array::View.contains<commit_after>#ifndef b_array_View_hxx_
#define b_array_View_hxx_

#include "b/b_assert.hxx"
#include "b/Unsigned.hxx"

namespace b {
namespace array {

template <typename Element>
struct View
{
    //--------------------------------------------------------------------------------------------//
    // Constructors

    constexpr
    View(Element* data, Unsigned length)
        : __0(data)
        , __n(data + length)
    {
    }

    template <Unsigned length>
    constexpr explicit
    View(Element(& data)[length])
        : View(data, length)
    {
    }

    //--------------------------------------------------------------------------------------------//
    // Sized

    constexpr
    Unsigned
    length() const
    {
        return (reinterpret_cast<Unsigned>(this->__n) -
                reinterpret_cast<Unsigned>(this->__0));
    }

    //--------------------------------------------------------------------------------------------//
    // Iterable

    constexpr
    Element*
    begin() const
    {
        return this->__0;
    }

    constexpr
    Element*
    end() const
    {
        return this->__n;
    }

    //--------------------------------------------------------------------------------------------//
    // Container

    constexpr
    bool
    contains(const Element& element) const noexcept
    {
        for (auto curr : *this)
            if (curr == element)
                return true;

        return false;
    }

    constexpr
    Element&
    operator
    [](Unsigned offset) const
    {
        b_assert(offset < this->length(), "out of bounds");
        return this->__0[offset];
    }

  private:
    Element*
    __0;

    Element*
    __n;
};

} // namespace array
} // namespace b

#endif
<|endoftext|>