<commit_before>#pragma once

#include <string>
#include <vector>
#include <map>

#include "rapidjson/writer.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/error/en.h"
#include "rapidjson/stringbuffer.h"

#include "acmacs-base/read-file.hh"

// ----------------------------------------------------------------------

template <typename RW> class JsonWriterT : public RW
{
 public:
    inline JsonWriterT(std::string aKeyword) : RW(mBuffer), mKeyword(aKeyword) {}
    inline operator std::string() const { return mBuffer.GetString(); }
    inline std::string keyword() const { return mKeyword; }

 private:
    rapidjson::StringBuffer mBuffer;
    std::string mKeyword;
};

// template <> inline JsonWriterT<rapidjson::PrettyWriter<rapidjson::StringBuffer>>::JsonWriterT(std::string aKeyword)
//     : rapidjson::PrettyWriter<rapidjson::StringBuffer>(mBuffer), mKeyword(aKeyword)
// {
//     SetIndent(' ', 1);
// }

typedef JsonWriterT<rapidjson::Writer<rapidjson::StringBuffer>> JsonWriter;
typedef JsonWriterT<rapidjson::PrettyWriter<rapidjson::StringBuffer>> JsonPrettyWriter;

// ----------------------------------------------------------------------

enum _StartArray { StartArray };
enum _EndArray { EndArray };
enum _StartObject { StartObject };
enum _EndObject { EndObject };

template <typename RW> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, _StartArray) { writer.StartArray(); return writer; }
template <typename RW> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, _EndArray) { writer.EndArray(); return writer; }
template <typename RW> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, _StartObject) { writer.StartObject(); return writer; }
template <typename RW> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, _EndObject) { writer.EndObject(); return writer; }

template <typename RW> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, const char* s) { writer.String(s, static_cast<unsigned>(strlen(s))); return writer; }
template <typename RW> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, std::string s) { writer.String(s.c_str(), static_cast<unsigned>(s.size())); return writer; }
template <typename RW> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, int value) { writer.Int(value); return writer; }
template <typename RW> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, bool value) { writer.Bool(value); return writer; }
template <typename RW> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, double value) { writer.Double(value); return writer; }

class JsonObjectKey
{
 public:
    inline JsonObjectKey(const char* v) : value(v) {}
    inline JsonObjectKey(std::string v) : value(v.c_str()) {}
    inline operator const char*() const { return value; }

 private:
    const char* value;
};

template <typename RW> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, JsonObjectKey value) { writer.Key(value); return writer; }

// ----------------------------------------------------------------------

template <typename RW, typename T> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, const std::vector<T>& list)
{
    writer << StartArray;
    for (const auto& e: list)
        writer << e;
    return writer << EndArray;
}

// ----------------------------------------------------------------------

template <typename RW> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, const std::vector<std::vector<std::string>>& list_list_strings)
{
    writer << StartArray;
    for (const auto& e: list_list_strings)
        writer << e;
    return writer << EndArray;
}

// ----------------------------------------------------------------------

template <typename RW> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, const std::map<std::string, std::vector<std::string>>& map_list_strings)
{
    writer << StartObject;
    for (const auto& e: map_list_strings)
        writer << JsonObjectKey(e.first) << e.second;
    return writer << EndObject;
}

// ----------------------------------------------------------------------

namespace json_writer { namespace _internal
{
      // void_t is a C++17 feature
    template<class ...> using void_t = void; // http://stackoverflow.com/questions/26513095/void-t-can-implement-concepts
    template <typename T, typename = void> struct castable_to_char : public std::false_type {};
    template <typename T> struct castable_to_char<T, void_t<decltype(static_cast<char>(std::declval<T>()))>> : public std::true_type {};
}}

template <typename RW, typename Key, typename std::enable_if<json_writer::_internal::castable_to_char<Key>{}>::type* = nullptr>
                     inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, Key key)
{
    const char k = static_cast<char>(key);
    writer.Key(&k, 1, false);
    return writer;
}

// ----------------------------------------------------------------------
// ----------------------------------------------------------------------

template <typename Key, typename Value> class _if_not_empty
{
 public:
    inline _if_not_empty(Key&& key, Value&& value) : mKey(key), mValue(value) {}

    template <typename RW> friend inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, const _if_not_empty<Key, Value>& data)
        {
            if (!data.mValue.empty())
                writer << data.mKey << data.mValue;
            return writer;
        }

 private:
    Key mKey;
    Value mValue;
};

template <typename Key, typename Value> inline auto if_not_empty(Key&& key, Value&& value) { return _if_not_empty<Key, Value>(std::forward<Key>(key), std::forward<Value>(value)); }
template <typename Value> inline auto if_not_empty(const char* key, Value&& value) { return _if_not_empty<JsonObjectKey, Value>(JsonObjectKey(key), std::forward<Value>(value)); }

// ----------------------------------------------------------------------

template <typename Key, typename Value> class _if_non_negative
{
 public:
    inline _if_non_negative(Key&& key, Value&& value) : mKey(key), mValue(value) {}

    template <typename RW> friend inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, const _if_non_negative<Key, Value>& data)
        {
            if (data.mValue >= 0.0)
                writer << data.mKey << data.mValue;
            return writer;
        }

 private:
    Key mKey;
    Value mValue;
};

template <typename Key, typename Value> inline auto if_non_negative(Key&& key, Value&& value) { return _if_non_negative<Key, Value>(std::forward<Key>(key), std::forward<Value>(value)); }
template <typename Value> inline auto if_non_negative(const char* key, Value&& value) { return _if_non_negative<JsonObjectKey, Value>(JsonObjectKey(key), std::forward<Value>(value)); }

// ----------------------------------------------------------------------
// ----------------------------------------------------------------------

template <typename V> inline std::string pretty_json(const V& value, std::string keyword, size_t indent, bool insert_emacs_indent_hint)
{
    JsonPrettyWriter writer(keyword);
    writer.SetIndent(' ', static_cast<unsigned int>(indent));
    writer << value;
    std::string result = writer;
    if (insert_emacs_indent_hint && result[0] == '{') {
        const std::string ind(indent - 1, ' ');
        result.insert(1, ind + "\"_\": \"-*- js-indent-level: " + std::to_string(indent) + " -*-\",");
    }
    return result;
}

template <typename V> inline std::string compact_json(const V& value, std::string keyword)
{
    JsonWriter writer(keyword);
    return writer << value;
}

template <typename V> inline std::string json(const V& value, std::string keyword, size_t indent, bool insert_emacs_indent_hint = true)
{
    if (indent)
        return pretty_json(value, keyword, indent, insert_emacs_indent_hint);
    else
        return compact_json(value, keyword);
}

// ----------------------------------------------------------------------

template <typename V> inline void export_to_json(const V& value, std::string keyword, std::string filename, size_t indent, bool insert_emacs_indent_hint = true)
{
    acmacs_base::write_file(filename, json(value, keyword, indent, insert_emacs_indent_hint));
}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>writing size_t to json<commit_after>#pragma once

#include <string>
#include <vector>
#include <map>

#include "rapidjson/writer.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/error/en.h"
#include "rapidjson/stringbuffer.h"

#include "acmacs-base/read-file.hh"

// ----------------------------------------------------------------------

template <typename RW> class JsonWriterT : public RW
{
 public:
    inline JsonWriterT(std::string aKeyword) : RW(mBuffer), mKeyword(aKeyword) {}
    inline operator std::string() const { return mBuffer.GetString(); }
    inline std::string keyword() const { return mKeyword; }

 private:
    rapidjson::StringBuffer mBuffer;
    std::string mKeyword;
};

// template <> inline JsonWriterT<rapidjson::PrettyWriter<rapidjson::StringBuffer>>::JsonWriterT(std::string aKeyword)
//     : rapidjson::PrettyWriter<rapidjson::StringBuffer>(mBuffer), mKeyword(aKeyword)
// {
//     SetIndent(' ', 1);
// }

typedef JsonWriterT<rapidjson::Writer<rapidjson::StringBuffer>> JsonWriter;
typedef JsonWriterT<rapidjson::PrettyWriter<rapidjson::StringBuffer>> JsonPrettyWriter;

// ----------------------------------------------------------------------

enum _StartArray { StartArray };
enum _EndArray { EndArray };
enum _StartObject { StartObject };
enum _EndObject { EndObject };

template <typename RW> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, _StartArray) { writer.StartArray(); return writer; }
template <typename RW> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, _EndArray) { writer.EndArray(); return writer; }
template <typename RW> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, _StartObject) { writer.StartObject(); return writer; }
template <typename RW> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, _EndObject) { writer.EndObject(); return writer; }

template <typename RW> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, const char* s) { writer.String(s, static_cast<unsigned>(strlen(s))); return writer; }
template <typename RW> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, std::string s) { writer.String(s.c_str(), static_cast<unsigned>(s.size())); return writer; }
template <typename RW> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, int value) { writer.Int(value); return writer; }
template <typename RW> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, size_t value) { writer.Uint64(value); return writer; }
template <typename RW> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, bool value) { writer.Bool(value); return writer; }
template <typename RW> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, double value) { writer.Double(value); return writer; }

class JsonObjectKey
{
 public:
    inline JsonObjectKey(const char* v) : value(v) {}
    inline JsonObjectKey(std::string v) : value(v.c_str()) {}
    inline operator const char*() const { return value; }

 private:
    const char* value;
};

template <typename RW> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, JsonObjectKey value) { writer.Key(value); return writer; }

// ----------------------------------------------------------------------

template <typename RW, typename T> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, const std::vector<T>& list)
{
    writer << StartArray;
    for (const auto& e: list)
        writer << e;
    return writer << EndArray;
}

// ----------------------------------------------------------------------

template <typename RW> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, const std::vector<std::vector<std::string>>& list_list_strings)
{
    writer << StartArray;
    for (const auto& e: list_list_strings)
        writer << e;
    return writer << EndArray;
}

// ----------------------------------------------------------------------

template <typename RW> inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, const std::map<std::string, std::vector<std::string>>& map_list_strings)
{
    writer << StartObject;
    for (const auto& e: map_list_strings)
        writer << JsonObjectKey(e.first) << e.second;
    return writer << EndObject;
}

// ----------------------------------------------------------------------

namespace json_writer { namespace _internal
{
      // void_t is a C++17 feature
    template<class ...> using void_t = void; // http://stackoverflow.com/questions/26513095/void-t-can-implement-concepts
    template <typename T, typename = void> struct castable_to_char : public std::false_type {};
    template <typename T> struct castable_to_char<T, void_t<decltype(static_cast<char>(std::declval<T>()))>> : public std::true_type {};
}}

template <typename RW, typename Key, typename std::enable_if<json_writer::_internal::castable_to_char<Key>{}>::type* = nullptr>
                     inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, Key key)
{
    const char k = static_cast<char>(key);
    writer.Key(&k, 1, false);
    return writer;
}

// ----------------------------------------------------------------------
// ----------------------------------------------------------------------

template <typename Key, typename Value> class _if_not_empty
{
 public:
    inline _if_not_empty(Key&& key, Value&& value) : mKey(key), mValue(value) {}

    template <typename RW> friend inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, const _if_not_empty<Key, Value>& data)
        {
            if (!data.mValue.empty())
                writer << data.mKey << data.mValue;
            return writer;
        }

 private:
    Key mKey;
    Value mValue;
};

template <typename Key, typename Value> inline auto if_not_empty(Key&& key, Value&& value) { return _if_not_empty<Key, Value>(std::forward<Key>(key), std::forward<Value>(value)); }
template <typename Value> inline auto if_not_empty(const char* key, Value&& value) { return _if_not_empty<JsonObjectKey, Value>(JsonObjectKey(key), std::forward<Value>(value)); }

// ----------------------------------------------------------------------

template <typename Key, typename Value> class _if_non_negative
{
 public:
    inline _if_non_negative(Key&& key, Value&& value) : mKey(key), mValue(value) {}

    template <typename RW> friend inline JsonWriterT<RW>& operator <<(JsonWriterT<RW>& writer, const _if_non_negative<Key, Value>& data)
        {
            if (data.mValue >= 0.0)
                writer << data.mKey << data.mValue;
            return writer;
        }

 private:
    Key mKey;
    Value mValue;
};

template <typename Key, typename Value> inline auto if_non_negative(Key&& key, Value&& value) { return _if_non_negative<Key, Value>(std::forward<Key>(key), std::forward<Value>(value)); }
template <typename Value> inline auto if_non_negative(const char* key, Value&& value) { return _if_non_negative<JsonObjectKey, Value>(JsonObjectKey(key), std::forward<Value>(value)); }

// ----------------------------------------------------------------------
// ----------------------------------------------------------------------

template <typename V> inline std::string pretty_json(const V& value, std::string keyword, size_t indent, bool insert_emacs_indent_hint)
{
    JsonPrettyWriter writer(keyword);
    writer.SetIndent(' ', static_cast<unsigned int>(indent));
    writer << value;
    std::string result = writer;
    if (insert_emacs_indent_hint && result[0] == '{') {
        const std::string ind(indent - 1, ' ');
        result.insert(1, ind + "\"_\": \"-*- js-indent-level: " + std::to_string(indent) + " -*-\",");
    }
    return result;
}

template <typename V> inline std::string compact_json(const V& value, std::string keyword)
{
    JsonWriter writer(keyword);
    return writer << value;
}

template <typename V> inline std::string json(const V& value, std::string keyword, size_t indent, bool insert_emacs_indent_hint = true)
{
    if (indent)
        return pretty_json(value, keyword, indent, insert_emacs_indent_hint);
    else
        return compact_json(value, keyword);
}

// ----------------------------------------------------------------------

template <typename V> inline void export_to_json(const V& value, std::string keyword, std::string filename, size_t indent, bool insert_emacs_indent_hint = true)
{
    acmacs_base::write_file(filename, json(value, keyword, indent, insert_emacs_indent_hint));
}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>//-----------------------------------
// Copyright Pierric Gimmig 2013-2017
//-----------------------------------

#include "TimerManager.h"
#include "Threading.h"
#include "Message.h"
#include "TcpForward.h"
#include "TcpClient.h"
#include "Params.h"
#include "OrbitLib.h"

#ifdef _WIN32
#include <direct.h>
#endif

std::unique_ptr<TimerManager> GTimerManager;

//-----------------------------------------------------------------------------
TimerManager::TimerManager( bool a_IsClient ) : m_LockFreeQueue(65534), m_IsClient(a_IsClient)
{
    m_Paused = false;
    m_IsFull = false;
    m_IsRecording = false;
    m_ExitRequested = false;
    m_FlushRequested = false;
    m_NumQueuedEntries = 0;
    m_NumQueuedTimers = 0;
    m_NumQueuedMessages = 0;
    m_TimerIndex = 0;
    m_NumTimersFromPreviousSession = 0;
    m_NumFlushedTimers = 0;

    InitProfiling();

    if( m_IsClient )
    {
        GTcpClient->Start();
        m_ConsumerThread = new std::thread([&](){ SendTimers(); });
    }
}

//-----------------------------------------------------------------------------
TimerManager::~TimerManager()
{
}

//-----------------------------------------------------------------------------
void TimerManager::StartRecording()
{
    if( m_IsRecording )
    {
        return;
    }

    if( !m_ConsumerThread )
    {
        m_ConsumerThread = new std::thread([&](){ ConsumeTimers(); });
    }

    m_IsRecording = true;
}

//-----------------------------------------------------------------------------
void TimerManager::StopRecording()
{
    m_IsRecording = false;
    FlushQueue();
}

//-----------------------------------------------------------------------------
void TimerManager::StartClient()
{
    m_IsRecording = true;
}

//-----------------------------------------------------------------------------
void TimerManager::StopClient()
{
    m_IsRecording = false;
    GTimerManager->FlushQueue();

    if( GTcpClient )
    {
        GTcpClient->FlushSendQueue();
    }
}

//-----------------------------------------------------------------------------
void TimerManager::FlushQueue()
{
    m_FlushRequested = true;

    const size_t numTimers = 4096;
    Timer Timers[numTimers];
    m_NumFlushedTimers = 0;

    while (!m_ExitRequested)
    {
        size_t numDequeued = m_LockFreeQueue.try_dequeue_bulk(Timers, numTimers);

        if (numDequeued == 0)
            break;

        m_NumQueuedEntries -= (int)numDequeued;
        m_NumFlushedTimers += (int)numDequeued;

        if( m_IsClient )
        {
            int numEntries = m_NumFlushedTimers;
            GTcpClient->Send( Msg_NumFlushedEntries, numEntries );
        }
    }

    m_FlushRequested = false;
    m_ConditionVariable.signal();
}

//-----------------------------------------------------------------------------
void TimerManager::Stop()
{
    m_IsRecording = false;
    m_ExitRequested = true;
    m_ConditionVariable.signal();

    if( m_ConsumerThread )
    {
        m_ConsumerThread->join();
    }
}

//-----------------------------------------------------------------------------
void TimerManager::ConsumeTimers()
{
    SetCurrentThreadName( L"OrbitConsumeTimers" );
#ifdef _WIN32
    SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL );
#endif

    Timer Timer;

    while( !m_ExitRequested )
    {
        m_ConditionVariable.wait();

        while( !m_ExitRequested && !m_FlushRequested && m_LockFreeQueue.try_dequeue( Timer ) )
        {
            --m_NumQueuedEntries;
            --m_NumQueuedTimers;

            if( Timer.m_SessionID == Message::GSessionID )
            {
                for (TimerAddedCallback & Callback : m_TimerAddedCallbacks)
                {
                    Callback(Timer);
                }
            }
            else
            {
                ++m_NumTimersFromPreviousSession;
            }
        }
    }
}

//-----------------------------------------------------------------------------
void TimerManager::SendTimers()
{
    SetCurrentThreadName( L"OrbitSendTimers" );

    const size_t numTimers = 4096;
    Timer Timers[numTimers];

    while( !m_ExitRequested )
    {
        Message Msg(Msg_Timer);

        // Wait for non-empty queue
        while( m_NumQueuedEntries <= 0 && !m_ExitRequested )
        {
            m_ConditionVariable.wait();
        }

        size_t numDequeued = m_LockFreeQueue.try_dequeue_bulk(Timers, numTimers);
        m_NumQueuedEntries -= (int)numDequeued;
        m_NumQueuedTimers  -= (int)numDequeued;
        Msg.m_Size = (int)numDequeued*sizeof(Timer);

		GTcpClient->Send(Msg, (void*)Timers);

        int numEntries = m_NumQueuedEntries;
        GTcpClient->Send( Msg_NumQueuedEntries, numEntries );

        while (m_LockFreeMessageQueue.try_dequeue(Msg) && !m_ExitRequested)
        {
            --m_NumQueuedEntries;
            --m_NumQueuedMessages;
            GTcpClient->Send(Msg);
        }
    }
}

//-----------------------------------------------------------------------------
void TimerManager::Add( const Timer& a_Timer )
{
    if( m_IsRecording )
    {
        m_LockFreeQueue.enqueue(a_Timer);
        m_ConditionVariable.signal();
        ++m_NumQueuedEntries;
        ++m_NumQueuedTimers;
    }
}

//-----------------------------------------------------------------------------
void TimerManager::Add( const Message& a_Message )
{
    if( m_IsRecording || m_IsClient )
    {
        m_LockFreeMessageQueue.enqueue(a_Message);
        m_ConditionVariable.signal();
        ++m_NumQueuedEntries;
        ++m_NumQueuedMessages;
    }
}

//-----------------------------------------------------------------------------
void TimerManager::Add( const ContextSwitch & a_CS )
{
    m_ContextSwitchAddedCallback( a_CS );
}
<commit_msg>Temporarily disable session check when receiving remote timers.  Need to fix for remote captures.<commit_after>//-----------------------------------
// Copyright Pierric Gimmig 2013-2017
//-----------------------------------

#include "TimerManager.h"
#include "Threading.h"
#include "Message.h"
#include "TcpForward.h"
#include "TcpClient.h"
#include "Params.h"
#include "OrbitLib.h"

#ifdef _WIN32
#include <direct.h>
#endif

std::unique_ptr<TimerManager> GTimerManager;

//-----------------------------------------------------------------------------
TimerManager::TimerManager( bool a_IsClient ) : m_LockFreeQueue(65534), m_IsClient(a_IsClient)
{
    m_Paused = false;
    m_IsFull = false;
    m_IsRecording = false;
    m_ExitRequested = false;
    m_FlushRequested = false;
    m_NumQueuedEntries = 0;
    m_NumQueuedTimers = 0;
    m_NumQueuedMessages = 0;
    m_TimerIndex = 0;
    m_NumTimersFromPreviousSession = 0;
    m_NumFlushedTimers = 0;

    InitProfiling();

    if( m_IsClient )
    {
        GTcpClient->Start();
        m_ConsumerThread = new std::thread([&](){ SendTimers(); });
    }
}

//-----------------------------------------------------------------------------
TimerManager::~TimerManager()
{
}

//-----------------------------------------------------------------------------
void TimerManager::StartRecording()
{
    if( m_IsRecording )
    {
        return;
    }

    if( !m_ConsumerThread )
    {
        m_ConsumerThread = new std::thread([&](){ ConsumeTimers(); });
    }

    m_IsRecording = true;
}

//-----------------------------------------------------------------------------
void TimerManager::StopRecording()
{
    m_IsRecording = false;
    FlushQueue();
}

//-----------------------------------------------------------------------------
void TimerManager::StartClient()
{
    m_IsRecording = true;
}

//-----------------------------------------------------------------------------
void TimerManager::StopClient()
{
    m_IsRecording = false;
    GTimerManager->FlushQueue();

    if( GTcpClient )
    {
        GTcpClient->FlushSendQueue();
    }
}

//-----------------------------------------------------------------------------
void TimerManager::FlushQueue()
{
    m_FlushRequested = true;

    const size_t numTimers = 4096;
    Timer Timers[numTimers];
    m_NumFlushedTimers = 0;

    while (!m_ExitRequested)
    {
        size_t numDequeued = m_LockFreeQueue.try_dequeue_bulk(Timers, numTimers);

        if (numDequeued == 0)
            break;

        m_NumQueuedEntries -= (int)numDequeued;
        m_NumFlushedTimers += (int)numDequeued;

        if( m_IsClient )
        {
            int numEntries = m_NumFlushedTimers;
            GTcpClient->Send( Msg_NumFlushedEntries, numEntries );
        }
    }

    m_FlushRequested = false;
    m_ConditionVariable.signal();
}

//-----------------------------------------------------------------------------
void TimerManager::Stop()
{
    m_IsRecording = false;
    m_ExitRequested = true;
    m_ConditionVariable.signal();

    if( m_ConsumerThread )
    {
        m_ConsumerThread->join();
    }
}

//-----------------------------------------------------------------------------
void TimerManager::ConsumeTimers()
{
    SetCurrentThreadName( L"OrbitConsumeTimers" );
#ifdef _WIN32
    SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL );
#endif

    Timer Timer;

    while( !m_ExitRequested )
    {
        m_ConditionVariable.wait();

        while( !m_ExitRequested && !m_FlushRequested && m_LockFreeQueue.try_dequeue( Timer ) )
        {
            --m_NumQueuedEntries;
            --m_NumQueuedTimers;

            //if( Timer.m_SessionID == Message::GSessionID ) // TODO: re-enable check.
            {
                for (TimerAddedCallback & Callback : m_TimerAddedCallbacks)
                {
                    Callback(Timer);
                }
            }
            /*else
            {
                ++m_NumTimersFromPreviousSession;
            }*/
        }
    }
}

//-----------------------------------------------------------------------------
void TimerManager::SendTimers()
{
    SetCurrentThreadName( L"OrbitSendTimers" );

    const size_t numTimers = 4096;
    Timer Timers[numTimers];

    while( !m_ExitRequested )
    {
        Message Msg(Msg_Timer);

        // Wait for non-empty queue
        while( m_NumQueuedEntries <= 0 && !m_ExitRequested )
        {
            m_ConditionVariable.wait();
        }

        size_t numDequeued = m_LockFreeQueue.try_dequeue_bulk(Timers, numTimers);
        m_NumQueuedEntries -= (int)numDequeued;
        m_NumQueuedTimers  -= (int)numDequeued;
        Msg.m_Size = (int)numDequeued*sizeof(Timer);

		GTcpClient->Send(Msg, (void*)Timers);

        int numEntries = m_NumQueuedEntries;
        GTcpClient->Send( Msg_NumQueuedEntries, numEntries );

        while (m_LockFreeMessageQueue.try_dequeue(Msg) && !m_ExitRequested)
        {
            --m_NumQueuedEntries;
            --m_NumQueuedMessages;
            GTcpClient->Send(Msg);
        }
    }
}

//-----------------------------------------------------------------------------
void TimerManager::Add( const Timer& a_Timer )
{
    if( m_IsRecording )
    {
        m_LockFreeQueue.enqueue(a_Timer);
        m_ConditionVariable.signal();
        ++m_NumQueuedEntries;
        ++m_NumQueuedTimers;
    }
}

//-----------------------------------------------------------------------------
void TimerManager::Add( const Message& a_Message )
{
    if( m_IsRecording || m_IsClient )
    {
        m_LockFreeMessageQueue.enqueue(a_Message);
        m_ConditionVariable.signal();
        ++m_NumQueuedEntries;
        ++m_NumQueuedMessages;
    }
}

//-----------------------------------------------------------------------------
void TimerManager::Add( const ContextSwitch & a_CS )
{
    m_ContextSwitchAddedCallback( a_CS );
}
<|endoftext|>


<commit_before>/*ckwg +5
 * Copyright 2012 by Kitware, Inc. All Rights Reserved. Please refer to
 * KITWARE_LICENSE.TXT for licensing information, or contact General Counsel,
 * Kitware, Inc., 28 Corporate Drive, Clifton Park, NY 12065.
 */

#include "helpers/pipeline_builder.h"
#include "helpers/tool_main.h"
#include "helpers/tool_usage.h"

#include <vistk/pipeline_util/pipe_declaration_types.h>

#include <vistk/pipeline/config.h>
#include <vistk/pipeline/modules.h>
#include <vistk/pipeline/pipeline.h>
#include <vistk/pipeline/types.h>

#include <vistk/utilities/path.h>

#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/foreach.hpp>
#include <boost/variant.hpp>

#include <iostream>

#include <cstdlib>

class config_printer
  : public boost::static_visitor<>
{
  public:
    config_printer(std::ostream& ostr, vistk::pipeline_t const& pipe, vistk::config_t const& conf);
    ~config_printer();

    void operator () (vistk::config_pipe_block const& config_block) const;
    void operator () (vistk::process_pipe_block const& process_block) const;
    void operator () (vistk::connect_pipe_block const& connect_block) const;
  private:
    void print_config_value(vistk::config_value_t const& config_value) const;

    std::ostream& m_ostr;
    vistk::pipeline_t const m_pipe;
    vistk::config_t const m_config;
};

int
tool_main(int argc, char* argv[])
{
  vistk::load_known_modules();

  boost::program_options::options_description desc;
  desc
    .add(tool_common_options())
    .add(pipeline_common_options())
    .add(pipeline_input_options())
    .add(pipeline_output_options());

  boost::program_options::variables_map const vm = tool_parse(argc, argv, desc);

  pipeline_builder const builder(vm, desc);

  vistk::pipeline_t const pipe = builder.pipeline();
  vistk::config_t const config = builder.config();
  vistk::pipe_blocks const blocks = builder.blocks();

  if (!pipe)
  {
    std::cerr << "Error: Unable to bake pipeline" << std::endl;

    return EXIT_FAILURE;
  }

  std::ostream* postr;
  boost::filesystem::ofstream fout;

  vistk::path_t const opath = vm["output"].as<vistk::path_t>();

  if (opath == vistk::path_t("-"))
  {
    postr = &std::cout;
  }
  else
  {
    fout.open(opath);

    if (fout.bad())
    {
      std::cerr << "Error: Unable to open output file" << std::endl;

      return EXIT_FAILURE;
    }

    postr = &fout;
  }

  std::ostream& ostr = *postr;

  config_printer const printer(ostr, pipe, config);

  std::for_each(blocks.begin(), blocks.end(), boost::apply_visitor(printer));

  return EXIT_SUCCESS;
}

config_printer
::config_printer(std::ostream& ostr, vistk::pipeline_t const& pipe, vistk::config_t const& conf)
  : m_ostr(ostr)
  , m_pipe(pipe)
  , m_config(conf)
{
}

config_printer
::~config_printer()
{
}

class key_printer
{
  public:
    key_printer(std::ostream& ostr);
    ~key_printer();

    void operator () (vistk::config_value_t const& config_value) const;
  private:
    std::ostream& m_ostr;
};

void
config_printer
::operator () (vistk::config_pipe_block const& config_block) const
{
  vistk::config::keys_t const& keys = config_block.key;
  vistk::config_values_t const& values = config_block.values;

  vistk::config::key_t const key_path = boost::join(keys, vistk::config::block_sep);

  m_ostr << "config " << key_path << std::endl;

  key_printer const printer(m_ostr);

  std::for_each(values.begin(), values.end(), printer);

  m_ostr << std::endl;
}

void
config_printer
::operator () (vistk::process_pipe_block const& process_block) const
{
  vistk::process::name_t const& name = process_block.name;
  vistk::process::type_t const& type = process_block.type;
  vistk::config_values_t const& values = process_block.config_values;

  m_ostr << "process " << name << std::endl;
  m_ostr << "  :: " << type << std::endl;

  key_printer const printer(m_ostr);

  std::for_each(values.begin(), values.end(), printer);

  vistk::process_t const proc = m_pipe->process_by_name(name);

  vistk::config::keys_t const keys = proc->available_config();

  BOOST_FOREACH (vistk::config::key_t const& key, keys)
  {
    if (boost::starts_with(key, "_"))
    {
      continue;
    }

    m_ostr << std::endl;

    vistk::process::conf_info_t const& info = proc->config_info(key);

    vistk::config::description_t const desc = boost::replace_all_copy(info->description, "\n", "\n  #   ");

    m_ostr << "  # Key: " << key << std::endl;

    m_ostr << "  # Description: " << desc << std::endl;

    vistk::config::value_t const& def = info->def;

    if (def.empty())
    {
      m_ostr << "  # No default value" << std::endl;
    }
    else
    {
      m_ostr << "  # Default value: " << def << std::endl;
    }

    vistk::config::key_t const resolved_key = name + vistk::config::block_sep + key;

    if (m_config->has_value(resolved_key))
    {
      vistk::config::value_t const cur_value = m_config->get_value<vistk::config::value_t>(resolved_key);

      m_ostr << "  # Current value: " << cur_value << std::endl;
    }
    else
    {
      m_ostr << "  # No current value" << std::endl;
    }
  }

  m_ostr << std::endl;
}

void
config_printer
::operator () (vistk::connect_pipe_block const& connect_block) const
{
  vistk::process::port_addr_t const& upstream_addr = connect_block.from;
  vistk::process::port_addr_t const& downstream_addr = connect_block.to;

  vistk::process::name_t const& upstream_name = upstream_addr.first;
  vistk::process::port_t const& upstream_port = upstream_addr.second;
  vistk::process::name_t const& downstream_name = downstream_addr.first;
  vistk::process::port_t const& downstream_port = downstream_addr.second;

  m_ostr << "connect from " << upstream_name << "." << upstream_port << std::endl;
  m_ostr << "        to   " << downstream_name << "." << downstream_port << std::endl;

  m_ostr << std::endl;
}

key_printer
::key_printer(std::ostream& ostr)
  : m_ostr(ostr)
{
}

key_printer
::~key_printer()
{
}

void
key_printer
::operator () (vistk::config_value_t const& config_value) const
{
  vistk::config_key_t const& key = config_value.key;
  vistk::config::value_t const& value = config_value.value;

  vistk::config::keys_t const& keys = key.key_path;
  vistk::config_key_options_t const& options = key.options;

  vistk::config::key_t const key_path = boost::join(keys, vistk::config::block_sep);

  boost::optional<vistk::config_flags_t> const& flags = options.flags;
  boost::optional<vistk::config_provider_t> const& provider = options.provider;

  m_ostr << "  " << vistk::config::block_sep << key_path;

  if (flags)
  {
    vistk::config_flag_t const flag_list = boost::join(*flags, ",");

    m_ostr << "[" << flag_list << "]";
  }

  if (provider)
  {
    m_ostr << "{" << *provider << "}";
  }

  m_ostr << " " << value << std::endl;
}
<commit_msg>Support clusters declared as process blocks<commit_after>/*ckwg +5
 * Copyright 2012-2013 by Kitware, Inc. All Rights Reserved. Please refer to
 * KITWARE_LICENSE.TXT for licensing information, or contact General Counsel,
 * Kitware, Inc., 28 Corporate Drive, Clifton Park, NY 12065.
 */

#include "helpers/pipeline_builder.h"
#include "helpers/tool_main.h"
#include "helpers/tool_usage.h"

#include <vistk/pipeline_util/pipe_declaration_types.h>

#include <vistk/pipeline/config.h>
#include <vistk/pipeline/modules.h>
#include <vistk/pipeline/pipeline.h>
#include <vistk/pipeline/pipeline_exception.h>
#include <vistk/pipeline/process.h>
#include <vistk/pipeline/process_cluster.h>
#include <vistk/pipeline/types.h>

#include <vistk/utilities/path.h>

#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/foreach.hpp>
#include <boost/variant.hpp>

#include <iostream>
#include <stdexcept>

#include <cstdlib>

class config_printer
  : public boost::static_visitor<>
{
  public:
    config_printer(std::ostream& ostr, vistk::pipeline_t const& pipe, vistk::config_t const& conf);
    ~config_printer();

    void operator () (vistk::config_pipe_block const& config_block) const;
    void operator () (vistk::process_pipe_block const& process_block) const;
    void operator () (vistk::connect_pipe_block const& connect_block) const;
  private:
    void print_config_value(vistk::config_value_t const& config_value) const;

    std::ostream& m_ostr;
    vistk::pipeline_t const m_pipe;
    vistk::config_t const m_config;
};

int
tool_main(int argc, char* argv[])
{
  vistk::load_known_modules();

  boost::program_options::options_description desc;
  desc
    .add(tool_common_options())
    .add(pipeline_common_options())
    .add(pipeline_input_options())
    .add(pipeline_output_options());

  boost::program_options::variables_map const vm = tool_parse(argc, argv, desc);

  pipeline_builder const builder(vm, desc);

  vistk::pipeline_t const pipe = builder.pipeline();
  vistk::config_t const config = builder.config();
  vistk::pipe_blocks const blocks = builder.blocks();

  if (!pipe)
  {
    std::cerr << "Error: Unable to bake pipeline" << std::endl;

    return EXIT_FAILURE;
  }

  std::ostream* postr;
  boost::filesystem::ofstream fout;

  vistk::path_t const opath = vm["output"].as<vistk::path_t>();

  if (opath == vistk::path_t("-"))
  {
    postr = &std::cout;
  }
  else
  {
    fout.open(opath);

    if (fout.bad())
    {
      std::cerr << "Error: Unable to open output file" << std::endl;

      return EXIT_FAILURE;
    }

    postr = &fout;
  }

  std::ostream& ostr = *postr;

  config_printer const printer(ostr, pipe, config);

  std::for_each(blocks.begin(), blocks.end(), boost::apply_visitor(printer));

  return EXIT_SUCCESS;
}

config_printer
::config_printer(std::ostream& ostr, vistk::pipeline_t const& pipe, vistk::config_t const& conf)
  : m_ostr(ostr)
  , m_pipe(pipe)
  , m_config(conf)
{
}

config_printer
::~config_printer()
{
}

class key_printer
{
  public:
    key_printer(std::ostream& ostr);
    ~key_printer();

    void operator () (vistk::config_value_t const& config_value) const;
  private:
    std::ostream& m_ostr;
};

void
config_printer
::operator () (vistk::config_pipe_block const& config_block) const
{
  vistk::config::keys_t const& keys = config_block.key;
  vistk::config_values_t const& values = config_block.values;

  vistk::config::key_t const key_path = boost::join(keys, vistk::config::block_sep);

  m_ostr << "config " << key_path << std::endl;

  key_printer const printer(m_ostr);

  std::for_each(values.begin(), values.end(), printer);

  m_ostr << std::endl;
}

void
config_printer
::operator () (vistk::process_pipe_block const& process_block) const
{
  vistk::process::name_t const& name = process_block.name;
  vistk::process::type_t const& type = process_block.type;
  vistk::config_values_t const& values = process_block.config_values;

  m_ostr << "process " << name << std::endl;
  m_ostr << "  :: " << type << std::endl;

  key_printer const printer(m_ostr);

  std::for_each(values.begin(), values.end(), printer);

  vistk::process_t proc;

  try
  {
    proc = m_pipe->process_by_name(name);
  }
  catch (vistk::no_such_process_exception const& /*e*/)
  {
    try
    {
      vistk::process_cluster_t const cluster = m_pipe->cluster_by_name(name);

      proc = boost::static_pointer_cast<vistk::process>(cluster);
    }
    catch (vistk::no_such_process_exception const& /*e*/)
    {
      std::string const reason = "A process block did not result in a process being "
                                 "added to the pipeline: " + name;

      throw std::logic_error(reason);
    }
  }

  vistk::config::keys_t const keys = proc->available_config();

  BOOST_FOREACH (vistk::config::key_t const& key, keys)
  {
    if (boost::starts_with(key, "_"))
    {
      continue;
    }

    m_ostr << std::endl;

    vistk::process::conf_info_t const& info = proc->config_info(key);

    vistk::config::description_t const desc = boost::replace_all_copy(info->description, "\n", "\n  #   ");

    m_ostr << "  # Key: " << key << std::endl;

    m_ostr << "  # Description: " << desc << std::endl;

    vistk::config::value_t const& def = info->def;

    if (def.empty())
    {
      m_ostr << "  # No default value" << std::endl;
    }
    else
    {
      m_ostr << "  # Default value: " << def << std::endl;
    }

    vistk::config::key_t const resolved_key = name + vistk::config::block_sep + key;

    if (m_config->has_value(resolved_key))
    {
      vistk::config::value_t const cur_value = m_config->get_value<vistk::config::value_t>(resolved_key);

      m_ostr << "  # Current value: " << cur_value << std::endl;
    }
    else
    {
      m_ostr << "  # No current value" << std::endl;
    }
  }

  m_ostr << std::endl;
}

void
config_printer
::operator () (vistk::connect_pipe_block const& connect_block) const
{
  vistk::process::port_addr_t const& upstream_addr = connect_block.from;
  vistk::process::port_addr_t const& downstream_addr = connect_block.to;

  vistk::process::name_t const& upstream_name = upstream_addr.first;
  vistk::process::port_t const& upstream_port = upstream_addr.second;
  vistk::process::name_t const& downstream_name = downstream_addr.first;
  vistk::process::port_t const& downstream_port = downstream_addr.second;

  m_ostr << "connect from " << upstream_name << "." << upstream_port << std::endl;
  m_ostr << "        to   " << downstream_name << "." << downstream_port << std::endl;

  m_ostr << std::endl;
}

key_printer
::key_printer(std::ostream& ostr)
  : m_ostr(ostr)
{
}

key_printer
::~key_printer()
{
}

void
key_printer
::operator () (vistk::config_value_t const& config_value) const
{
  vistk::config_key_t const& key = config_value.key;
  vistk::config::value_t const& value = config_value.value;

  vistk::config::keys_t const& keys = key.key_path;
  vistk::config_key_options_t const& options = key.options;

  vistk::config::key_t const key_path = boost::join(keys, vistk::config::block_sep);

  boost::optional<vistk::config_flags_t> const& flags = options.flags;
  boost::optional<vistk::config_provider_t> const& provider = options.provider;

  m_ostr << "  " << vistk::config::block_sep << key_path;

  if (flags)
  {
    vistk::config_flag_t const flag_list = boost::join(*flags, ",");

    m_ostr << "[" << flag_list << "]";
  }

  if (provider)
  {
    m_ostr << "{" << *provider << "}";
  }

  m_ostr << " " << value << std::endl;
}
<|endoftext|>


<commit_before>//=== NoReturnFunctionChecker.cpp -------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This defines NoReturnFunctionChecker, which evaluates functions that do not
// return to the caller.
//
//===----------------------------------------------------------------------===//

#include "ClangSACheckers.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/DataTypes.h"

using namespace clang;
using namespace ento;

namespace {

class NoReturnFunctionChecker : public Checker< check::PostStmt<CallExpr>,
                                                check::PostObjCMessage > {
public:
  void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
  void checkPostObjCMessage(const ObjCMessage &msg, CheckerContext &C) const;
};

}

void NoReturnFunctionChecker::checkPostStmt(const CallExpr *CE,
                                            CheckerContext &C) const {
  const ProgramState *state = C.getState();
  const Expr *Callee = CE->getCallee();

  bool BuildSinks = getFunctionExtInfo(Callee->getType()).getNoReturn();

  if (!BuildSinks) {
    SVal L = state->getSVal(Callee);
    const FunctionDecl *FD = L.getAsFunctionDecl();
    if (!FD)
      return;

    if (FD->getAttr<AnalyzerNoReturnAttr>())
      BuildSinks = true;
    else if (const IdentifierInfo *II = FD->getIdentifier()) {
      // HACK: Some functions are not marked noreturn, and don't return.
      //  Here are a few hardwired ones.  If this takes too long, we can
      //  potentially cache these results.
      BuildSinks
        = llvm::StringSwitch<bool>(StringRef(II->getName()))
            .Case("exit", true)
            .Case("panic", true)
            .Case("error", true)
            .Case("Assert", true)
            // FIXME: This is just a wrapper around throwing an exception.
            //  Eventually inter-procedural analysis should handle this easily.
            .Case("ziperr", true)
            .Case("assfail", true)
            .Case("db_error", true)
            .Case("__assert", true)
            .Case("__assert_rtn", true)
            .Case("__assert_fail", true)
            .Case("dtrace_assfail", true)
            .Case("yy_fatal_error", true)
            .Case("_XCAssertionFailureHandler", true)
            .Case("_DTAssertionFailureHandler", true)
            .Case("_TSAssertionFailureHandler", true)
            .Default(false);
    }
  }

  if (BuildSinks)
    C.generateSink(CE);
}

static bool END_WITH_NULL isMultiArgSelector(Selector Sel, ...) {
  va_list argp;
  va_start(argp, Sel);

  unsigned Slot = 0;
  const char *Arg;
  while ((Arg = va_arg(argp, const char *))) {
    if (!Sel.getNameForSlot(Slot).equals(Arg))
      break; // still need to va_end!
    ++Slot;
  }

  va_end(argp);

  // We only succeeded if we made it to the end of the argument list.
  return (Arg == NULL);
}

void NoReturnFunctionChecker::checkPostObjCMessage(const ObjCMessage &Msg,
                                                   CheckerContext &C) const {
  // HACK: This entire check is to handle two messages in the Cocoa frameworks:
  // -[NSAssertionHandler
  //    handleFailureInMethod:object:file:lineNumber:description:]
  // -[NSAssertionHandler
  //    handleFailureInFunction:file:lineNumber:description:]
  // Eventually these should be annotated with __attribute__((noreturn)).
  // Because ObjC messages use dynamic dispatch, it is not generally safe to
  // assume certain methods can't return. In cases where it is definitely valid,
  // see if you can mark the methods noreturn or analyzer_noreturn instead of
  // adding more explicit checks to this method.

  if (!Msg.isInstanceMessage())
    return;

  const ObjCInterfaceDecl *Receiver = Msg.getReceiverInterface();
  if (!Receiver)
    return;
  if (!Receiver->getIdentifier()->isStr("NSAssertionHandler"))
    return;

  Selector Sel = Msg.getSelector();
  switch (Sel.getNumArgs()) {
  default:
    return;
  case 4:
    if (!isMultiArgSelector(Sel, "handleFailureInFunction", "file",
                            "lineNumber", "description", NULL))
      return;
    break;
  case 5:
    if (!isMultiArgSelector(Sel, "handleFailureInMethod", "object", "file",
                            "lineNumber", "description", NULL))
      return;
    break;
  }

  // If we got here, it's one of the messages we care about.
  C.generateSink();
}

void ento::registerNoReturnFunctionChecker(CheckerManager &mgr) {
  mgr.registerChecker<NoReturnFunctionChecker>();
}
<commit_msg>Fix compile on platforms that don't implicitly include stdarg.h here.<commit_after>//=== NoReturnFunctionChecker.cpp -------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This defines NoReturnFunctionChecker, which evaluates functions that do not
// return to the caller.
//
//===----------------------------------------------------------------------===//

#include "ClangSACheckers.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "llvm/ADT/StringSwitch.h"
#include <cstdarg>

using namespace clang;
using namespace ento;

namespace {

class NoReturnFunctionChecker : public Checker< check::PostStmt<CallExpr>,
                                                check::PostObjCMessage > {
public:
  void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
  void checkPostObjCMessage(const ObjCMessage &msg, CheckerContext &C) const;
};

}

void NoReturnFunctionChecker::checkPostStmt(const CallExpr *CE,
                                            CheckerContext &C) const {
  const ProgramState *state = C.getState();
  const Expr *Callee = CE->getCallee();

  bool BuildSinks = getFunctionExtInfo(Callee->getType()).getNoReturn();

  if (!BuildSinks) {
    SVal L = state->getSVal(Callee);
    const FunctionDecl *FD = L.getAsFunctionDecl();
    if (!FD)
      return;

    if (FD->getAttr<AnalyzerNoReturnAttr>())
      BuildSinks = true;
    else if (const IdentifierInfo *II = FD->getIdentifier()) {
      // HACK: Some functions are not marked noreturn, and don't return.
      //  Here are a few hardwired ones.  If this takes too long, we can
      //  potentially cache these results.
      BuildSinks
        = llvm::StringSwitch<bool>(StringRef(II->getName()))
            .Case("exit", true)
            .Case("panic", true)
            .Case("error", true)
            .Case("Assert", true)
            // FIXME: This is just a wrapper around throwing an exception.
            //  Eventually inter-procedural analysis should handle this easily.
            .Case("ziperr", true)
            .Case("assfail", true)
            .Case("db_error", true)
            .Case("__assert", true)
            .Case("__assert_rtn", true)
            .Case("__assert_fail", true)
            .Case("dtrace_assfail", true)
            .Case("yy_fatal_error", true)
            .Case("_XCAssertionFailureHandler", true)
            .Case("_DTAssertionFailureHandler", true)
            .Case("_TSAssertionFailureHandler", true)
            .Default(false);
    }
  }

  if (BuildSinks)
    C.generateSink(CE);
}

static bool END_WITH_NULL isMultiArgSelector(Selector Sel, ...) {
  va_list argp;
  va_start(argp, Sel);

  unsigned Slot = 0;
  const char *Arg;
  while ((Arg = va_arg(argp, const char *))) {
    if (!Sel.getNameForSlot(Slot).equals(Arg))
      break; // still need to va_end!
    ++Slot;
  }

  va_end(argp);

  // We only succeeded if we made it to the end of the argument list.
  return (Arg == NULL);
}

void NoReturnFunctionChecker::checkPostObjCMessage(const ObjCMessage &Msg,
                                                   CheckerContext &C) const {
  // HACK: This entire check is to handle two messages in the Cocoa frameworks:
  // -[NSAssertionHandler
  //    handleFailureInMethod:object:file:lineNumber:description:]
  // -[NSAssertionHandler
  //    handleFailureInFunction:file:lineNumber:description:]
  // Eventually these should be annotated with __attribute__((noreturn)).
  // Because ObjC messages use dynamic dispatch, it is not generally safe to
  // assume certain methods can't return. In cases where it is definitely valid,
  // see if you can mark the methods noreturn or analyzer_noreturn instead of
  // adding more explicit checks to this method.

  if (!Msg.isInstanceMessage())
    return;

  const ObjCInterfaceDecl *Receiver = Msg.getReceiverInterface();
  if (!Receiver)
    return;
  if (!Receiver->getIdentifier()->isStr("NSAssertionHandler"))
    return;

  Selector Sel = Msg.getSelector();
  switch (Sel.getNumArgs()) {
  default:
    return;
  case 4:
    if (!isMultiArgSelector(Sel, "handleFailureInFunction", "file",
                            "lineNumber", "description", NULL))
      return;
    break;
  case 5:
    if (!isMultiArgSelector(Sel, "handleFailureInMethod", "object", "file",
                            "lineNumber", "description", NULL))
      return;
    break;
  }

  // If we got here, it's one of the messages we care about.
  C.generateSink();
}

void ento::registerNoReturnFunctionChecker(CheckerManager &mgr) {
  mgr.registerChecker<NoReturnFunctionChecker>();
}
<|endoftext|>


<commit_before>#include "stdafx.h"

bool  XInputController::Init(DWORD index)
{
	_lastState = _currentState;
	/*memcpy(&_lastState, &_currentState, sizeof(_currentState));*/
	DWORD dwResult;
	ZeroMemory(&_currentState, sizeof(XINPUT_STATE));
	dwResult = XInputGetState(index, &_currentState);

	return dwResult == ERROR_SUCCESS;
}

	bool XInputController::ButtonDown(WORD btnMask)
	{
		return (_currentState.Gamepad.wButtons & btnMask) == btnMask && (_lastState.Gamepad.wButtons & btnMask) != btnMask;

	}

	bool XInputController::ButtonUp(WORD btnMask)
	{
		return (_currentState.Gamepad.wButtons & btnMask) != btnMask && (_lastState.Gamepad.wButtons & btnMask) == btnMask;

	}

	bool XInputController::Button(WORD btnMask)
	{
		return (_currentState.Gamepad.wButtons & btnMask) == btnMask;

	}

	bool XInputController::LeftTriggerDown()
	{
		float t1, t2;
		LeftTrigger(t1,_currentState);
		LeftTrigger(t2, _lastState);
		return t1 != -2 && t2 == -2;
	}

	bool XInputController::RightTriggerDown()
	{
		float t1, t2;
		RightTrigger(t1, _currentState);
		RightTrigger(t2, _lastState);
		return t1 != -2 && t2 == -2;
	}

	bool XInputController::LeftTriggerUp()
	{
		float t1, t2;
		LeftTrigger(t1, _currentState);
		LeftTrigger(t2, _lastState);
		return t1 == -2 && t2 != -2;
	}

	bool XInputController::RightTriggerUp()
	{
		float t1, t2;
		RightTrigger(t1, _currentState);
		RightTrigger(t2, _lastState);
		return t1 == -2 && t2 != -2;
	}

	bool XInputController::LeftTrigger()
	{
		float t = 0;
		LeftTrigger(t);
		return t != -2;
	}

	bool XInputController::RightTrigger()
	{
		float t = 0;
		RightTrigger(t);
		return t != -2;
	}

	void XInputController::LeftTrigger(float &t)
	{
		LeftTrigger(t, _currentState);
	}

	void XInputController::RightTrigger(float &t)
	{
		RightTrigger(t, _currentState);
	}

	void XInputController::LeftTrigger(float &t, XINPUT_STATE state)
	{
		if (state.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
		{
			t = state.Gamepad.bLeftTrigger;
		}
		else
			t = -2; // Since -1 is a valid value, -2 means false
	}

	void XInputController::RightTrigger(float &t, XINPUT_STATE state)
	{
		if (state.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
		{
			t = state.Gamepad.bRightTrigger;
		}
		else
			t = -2;
	}

	void XInputController::ThumbStickLeft(float &x, float &y)
	{

		ThumbStick(_currentState.Gamepad.sThumbLX, _currentState.Gamepad.sThumbLY, XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, x, y);

	}

	void XInputController::ThumbStickRight(float &x, float &y)
	{

		 ThumbStick(_currentState.Gamepad.sThumbRX, _currentState.Gamepad.sThumbRY, XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE,x,y);

	}

	void XInputController::ThumbStick(SHORT lx, SHORT ly, SHORT ld, float &x, float &y)
	{

		//determine the direction the controller is pushed
		float normalizedLX = (1 / (float)32767) * lx;
		float normalizedLY = (1 / (float)32767) * ly;
		float normalizedLD = (1 / (float)32767) * ld;

		//cout << normalizedLY << endl;

		if (normalizedLX > 0 && normalizedLX < normalizedLD
			|| normalizedLX < 0 && normalizedLX > -normalizedLD)

		{
			// Since -2 isnt a legit value, this means its inside deadzone.
			x = -2;

		}
		else x = normalizedLX;

		if (normalizedLY > 0 && normalizedLY < normalizedLD
			|| normalizedLY < 0 && normalizedLY > -normalizedLD)

		{

			y = -2;

		}
		else
		{
			y = normalizedLY;
			//cout << y << endl;
		}

	}
<commit_msg>Fixed includings<commit_after>#include <Windows.h>
#include <Xinput.h>
#include "XInputController.h"

bool  XInputController::Init(DWORD index)
{
	_lastState = _currentState;
	/*memcpy(&_lastState, &_currentState, sizeof(_currentState));*/
	DWORD dwResult;
	ZeroMemory(&_currentState, sizeof(XINPUT_STATE));
	dwResult = XInputGetState(index, &_currentState);

	return dwResult == ERROR_SUCCESS;
}

	bool XInputController::ButtonDown(WORD btnMask)
	{
		return (_currentState.Gamepad.wButtons & btnMask) == btnMask && (_lastState.Gamepad.wButtons & btnMask) != btnMask;

	}

	bool XInputController::ButtonUp(WORD btnMask)
	{
		return (_currentState.Gamepad.wButtons & btnMask) != btnMask && (_lastState.Gamepad.wButtons & btnMask) == btnMask;

	}

	bool XInputController::Button(WORD btnMask)
	{
		return (_currentState.Gamepad.wButtons & btnMask) == btnMask;

	}

	bool XInputController::LeftTriggerDown()
	{
		float t1, t2;
		LeftTrigger(t1,_currentState);
		LeftTrigger(t2, _lastState);
		return t1 != -2 && t2 == -2;
	}

	bool XInputController::RightTriggerDown()
	{
		float t1, t2;
		RightTrigger(t1, _currentState);
		RightTrigger(t2, _lastState);
		return t1 != -2 && t2 == -2;
	}

	bool XInputController::LeftTriggerUp()
	{
		float t1, t2;
		LeftTrigger(t1, _currentState);
		LeftTrigger(t2, _lastState);
		return t1 == -2 && t2 != -2;
	}

	bool XInputController::RightTriggerUp()
	{
		float t1, t2;
		RightTrigger(t1, _currentState);
		RightTrigger(t2, _lastState);
		return t1 == -2 && t2 != -2;
	}

	bool XInputController::LeftTrigger()
	{
		float t = 0;
		LeftTrigger(t);
		return t != -2;
	}

	bool XInputController::RightTrigger()
	{
		float t = 0;
		RightTrigger(t);
		return t != -2;
	}

	void XInputController::LeftTrigger(float &t)
	{
		LeftTrigger(t, _currentState);
	}

	void XInputController::RightTrigger(float &t)
	{
		RightTrigger(t, _currentState);
	}

	void XInputController::LeftTrigger(float &t, XINPUT_STATE state)
	{
		if (state.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
		{
			t = state.Gamepad.bLeftTrigger;
		}
		else
			t = -2; // Since -1 is a valid value, -2 means false
	}

	void XInputController::RightTrigger(float &t, XINPUT_STATE state)
	{
		if (state.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
		{
			t = state.Gamepad.bRightTrigger;
		}
		else
			t = -2;
	}

	void XInputController::ThumbStickLeft(float &x, float &y)
	{

		ThumbStick(_currentState.Gamepad.sThumbLX, _currentState.Gamepad.sThumbLY, XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, x, y);

	}

	void XInputController::ThumbStickRight(float &x, float &y)
	{

		 ThumbStick(_currentState.Gamepad.sThumbRX, _currentState.Gamepad.sThumbRY, XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE,x,y);

	}

	void XInputController::ThumbStick(SHORT lx, SHORT ly, SHORT ld, float &x, float &y)
	{

		//determine the direction the controller is pushed
		float normalizedLX = (1 / (float)32767) * lx;
		float normalizedLY = (1 / (float)32767) * ly;
		float normalizedLD = (1 / (float)32767) * ld;

		//cout << normalizedLY << endl;

		if (normalizedLX > 0 && normalizedLX < normalizedLD
			|| normalizedLX < 0 && normalizedLX > -normalizedLD)

		{
			// Since -2 isnt a legit value, this means its inside deadzone.
			x = -2;

		}
		else x = normalizedLX;

		if (normalizedLY > 0 && normalizedLY < normalizedLD
			|| normalizedLY < 0 && normalizedLY > -normalizedLD)

		{

			y = -2;

		}
		else
		{
			y = normalizedLY;
			//cout << y << endl;
		}

	}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2008-2009
 *
 * Copyright (c) 2015 Tiago Cogumbreiro
 *
 * School of Computing, University of Utah,
 * Salt Lake City, UT 84112, USA
 *
 * and the Gauss Group
 * http://www.cs.utah.edu/formal_verification
 *
 * See LICENSE.ISP for licensing information
 */

#ifndef _CALL_HPP
#define _CALL_HPP

#include <vector>
#include <map>
#include <set>
#include <utility>

#include "name2id.hpp"

using std::set;
using std::vector;
using std::map;

struct WInt {
    WInt() : wildcard(true), value(0)  {}
    WInt(int v) : wildcard(false), value(v) {}
    WInt(const WInt &c) : wildcard(c.wildcard), value(c.value) {}
    bool operator== (const WInt &r) const {
        return wildcard == r.wildcard && value == r.value;
    }

    WInt & operator=(const WInt & other) {
        wildcard = other.wildcard;
        value = other.value;
        return *this;
    }

    bool isWildcard() const {
        return wildcard;
    }
    int get() const {
        return value;
    }
    bool matches(const WInt &other) const {
        return isWildcard() || *this == other;
    }
private:
    bool wildcard;
    int value;
};

static WInt WILDCARD = WInt();

struct Recv {
    Recv() : src(0), tag(0) {}
    Recv(const Recv &r) : src(r.src), tag(r.tag) {}

    WInt src;
    WInt tag;
    inline bool completesBefore(const Recv &rhs) const {
        return src.matches(rhs.src) && tag.matches(rhs.tag);
    }
    bool operator== (const Recv &r) const {
        return src == r.src && tag == r.tag;
    }
};

struct Send {
    Send() : dest(0), tag(0) {}
    Send(const Send &s) : dest(s.dest), tag(s.tag) {}

    int dest;
    int tag;
    inline bool completesBefore(const Send &rhs) const {
        return dest == rhs.dest && rhs.tag == tag;
    }

    bool canSend(const Recv & recv) const {
        return recv.src.matches(dest) && recv.tag.matches(tag);
    }

    bool operator== (const Send &s) const {
        return dest == s.dest && tag == s.tag;
    }

};

struct Wait {
    Wait(): requests() {}
    Wait(const Wait &w) : requests(w.requests) {}

    inline bool requested(int handle) const {
        return requests.find(handle) != requests.end();
    }
    void addRequest(int handle) {
        requests.insert(handle);
    }
    bool operator== (const Wait &w) const {
        return requests == w.requests;
    }
private:
    std::set<int> requests;
};

enum class Field {
    Source,
    Destination,
    Datatype,
    Root,
    Communicator,
    Op,
    Sendcount,
    Recvcount,
};

/*
 * Represents an MPI call issued by a certain process with a `pid`.
 * Each process has a logical closs to uniquely identify its issuing calls,
 * here it is defined as field `cid`.
 * The `envelope` holds information about the MPI call.
 */
struct Call {
    /** The process id of the issuer. */
    int pid;
    /** The logical time at which this call has been issued (monotonic). */
    int handle;
    /** The op type defines which payload to use */
    OpType call_type;
    /** The payload of the MPI call */
    Recv recv;
    Send send;
    Wait wait;
    map<Field, int> metadata;
    /** Defines each field of this object. */
    Call(int p, int i);
    /** Copy ctor as one would expect. */
    Call(const Call & c);
    /** Default ctor. */
    Call();
    /** Checks if this call precedes another with the completes-before rel */
    bool completesBefore(Call const&) const;
    /** Checks if pid and cid are the same. */
    bool operator== (const Call &c) const;
    /** Default. */
    bool operator!= (const Call &c) const;
    /** Checks if this call can send to the given receive */
    bool canSend(const Call & recv) const;
    /**
     * pre-condition: all members of `call` must have the same `pid` as this
     * instance.
     */
    bool hasAncestors(const set<Call> & call) const;
    /** Holds if the pids are smaller or, when they match if the cid is smaller. */
    friend bool operator< (const Call &a, const Call &b) {
        return a.pid < b.pid || (a.pid == b.pid && a.handle < b.handle);
    }
};

struct Process {
    int pid;
    int curr_handle;
    Process(int pid) : pid(pid), curr_handle(0) {}

    Call create() {
        return Call(pid, curr_handle++);
    }

    // REMOVE THIS FROM HERE:

    Call ISend(int dest) {
        Call c = create();
        c.send.dest = dest;
        c.call_type = OpType::ISEND;
        return c;
    }

    Call Barrier() {
        Call c = create();
        c.call_type = OpType::BARRIER;
        return c;
    }

    Call IRecv(int src) {
        return IRecv(src, WILDCARD);
    }

    Call IRecv(WInt src, WInt rtag) {
        Call c = create();
        c.recv.src = src;
        c.call_type = OpType::IRECV;
        c.recv.tag = rtag;
        // XXX: e.count
        // XXX: e.comm
        return c;
    }
    Call IRecv(WInt src) {
        return IRecv(src, WILDCARD);
    }

    Call Wait(int req) {
        Call c = create();
        c.call_type = OpType::WAIT;
        c.wait.addRequest(req);
        // XXX: e.count
        return c;
    }
};
#endif
<commit_msg>Added support for all p-t-p instructions.<commit_after>/*
 * Copyright (c) 2008-2009
 *
 * Copyright (c) 2015 Tiago Cogumbreiro
 *
 * School of Computing, University of Utah,
 * Salt Lake City, UT 84112, USA
 *
 * and the Gauss Group
 * http://www.cs.utah.edu/formal_verification
 *
 * See LICENSE.ISP for licensing information
 */

#ifndef _CALL_HPP
#define _CALL_HPP

#include <vector>
#include <map>
#include <set>
#include <utility>

#include "name2id.hpp"

using std::set;
using std::vector;
using std::map;

struct WInt {
    WInt() : wildcard(true), value(0)  {}
    WInt(int v) : wildcard(false), value(v) {}
    WInt(const WInt &c) : wildcard(c.wildcard), value(c.value) {}
    bool operator== (const WInt &r) const {
        return wildcard == r.wildcard && value == r.value;
    }

    WInt & operator=(const WInt & other) {
        wildcard = other.wildcard;
        value = other.value;
        return *this;
    }

    bool isWildcard() const {
        return wildcard;
    }
    int get() const {
        return value;
    }
    bool matches(const WInt &other) const {
        return isWildcard() || *this == other;
    }
private:
    bool wildcard;
    int value;
};

static WInt WILDCARD = WInt();

struct Recv {
    Recv() : src(0), tag(0) {}
    Recv(const Recv &r) : src(r.src), tag(r.tag) {}

    WInt src;
    WInt tag;
    inline bool completesBefore(const Recv &rhs) const {
        return src.matches(rhs.src) && tag.matches(rhs.tag);
    }
    bool operator== (const Recv &r) const {
        return src == r.src && tag == r.tag;
    }
};

struct Send {
    Send() : dest(0), tag(0) {}
    Send(const Send &s) : dest(s.dest), tag(s.tag) {}

    int dest;
    int tag;
    inline bool completesBefore(const Send &rhs) const {
        return dest == rhs.dest && rhs.tag == tag;
    }

    bool canSend(const Recv & recv) const {
        return recv.src.matches(dest) && recv.tag.matches(tag);
    }

    bool operator== (const Send &s) const {
        return dest == s.dest && tag == s.tag;
    }

};

struct Wait {
    Wait(): requests() {}
    Wait(const Wait &w) : requests(w.requests) {}

    inline bool requested(int handle) const {
        return requests.find(handle) != requests.end();
    }
    void addRequest(int handle) {
        requests.insert(handle);
    }
    bool operator== (const Wait &w) const {
        return requests == w.requests;
    }
private:
    std::set<int> requests;
};

enum class Field {
    Source,
    Destination,
    Datatype,
    Root,
    Communicator,
    Op,
    Count,
    Sendcount,
    Recvcount,
};

/*
 * Represents an MPI call issued by a certain process with a `pid`.
 * Each process has a logical closs to uniquely identify its issuing calls,
 * here it is defined as field `cid`.
 * The `envelope` holds information about the MPI call.
 */
struct Call {
    /** The process id of the issuer. */
    int pid;
    /** The logical time at which this call has been issued (monotonic). */
    int handle;
    /** The op type defines which payload to use */
    OpType call_type;
    /** The payload of the MPI call */
    Recv recv;
    Send send;
    Wait wait;
    map<Field, int> metadata;
    /** Defines each field of this object. */
    Call(int p, int i);
    /** Copy ctor as one would expect. */
    Call(const Call & c);
    /** Default ctor. */
    Call();
    /** Checks if this call precedes another with the completes-before rel */
    bool completesBefore(Call const&) const;
    /** Checks if pid and cid are the same. */
    bool operator== (const Call &c) const;
    /** Default. */
    bool operator!= (const Call &c) const;
    /** Checks if this call can send to the given receive */
    bool canSend(const Call & recv) const;
    /**
     * pre-condition: all members of `call` must have the same `pid` as this
     * instance.
     */
    bool hasAncestors(const set<Call> & call) const;
    /** Holds if the pids are smaller or, when they match if the cid is smaller. */
    friend bool operator< (const Call &a, const Call &b) {
        return a.pid < b.pid || (a.pid == b.pid && a.handle < b.handle);
    }
};

struct Process {
    int pid;
    int curr_handle;
    Process(int pid) : pid(pid), curr_handle(0) {}

    Call create() {
        return Call(pid, curr_handle++);
    }

    // REMOVE THIS FROM HERE:

    Call ISend(int dest) {
        Call c = create();
        c.send.dest = dest;
        c.call_type = OpType::ISEND;
        return c;
    }

    Call Barrier() {
        Call c = create();
        c.call_type = OpType::BARRIER;
        return c;
    }

    Call IRecv(int src) {
        return IRecv(WInt(src));
    }

    Call IRecv(WInt src) {
        return IRecv(0, 0, src, WILDCARD, 0);
    }

    Call IRecv(int count, int datatype, WInt src, WInt rtag, int comm) {
        Call c = create();
        c.recv.src = src;
        c.call_type = OpType::IRECV;
        c.recv.tag = rtag;
        c.metadata[Field::Count] = count;
        c.metadata[Field::Datatype] = datatype;
        c.metadata[Field::Communicator] = comm;
        return c;
    }

    Call Recv(int count, int datatype, WInt src, WInt rtag, int comm) {
        Call c = create();
        c.recv.src = src;
        c.call_type = OpType::RECV;
        c.recv.tag = rtag;
        c.metadata[Field::Count] = count;
        c.metadata[Field::Datatype] = datatype;
        c.metadata[Field::Communicator] = comm;
        return c;
    }

    Call Send(int count, int datatype, int dest, int tag, int comm) {
        Call c = create();
        c.call_type = OpType::SEND;
        c.send.dest = dest;
        c.send.tag = tag;
        c.metadata[Field::Count] = count;
        c.metadata[Field::Datatype] = datatype;
        c.metadata[Field::Communicator] = comm;
        return c;
    }

    Call Ssend(int count, int datatype, int dest, int tag, int comm) {
        Call c = create();
        c.call_type = OpType::SSEND;
        c.send.dest = dest;
        c.send.tag = tag;
        c.metadata[Field::Count] = count;
        c.metadata[Field::Datatype] = datatype;
        c.metadata[Field::Communicator] = comm;
        return c;
    }

    Call Isend(int count, int datatype, int dest, int tag, int comm) {
        Call c = create();
        c.call_type = OpType::ISEND;
        c.send.dest = dest;
        c.send.tag = tag;
        c.metadata[Field::Count] = count;
        c.metadata[Field::Datatype] = datatype;
        c.metadata[Field::Communicator] = comm;
        return c;
    }

    Call Wait(int req) {
        Call c = create();
        c.call_type = OpType::WAIT;
        c.wait.addRequest(req);
        // XXX: e.count
        return c;
    }
};
#endif
<|endoftext|>


<commit_before>
#include <libclientserver.h>

int Caps::HasCap(int cap)
{
	cap_t caps;
	cap_flag_value_t value = CAP_CLEAR;

	caps = cap_get_proc();

	if (cap_get_flag(caps, cap, CAP_EFFECTIVE, &value) < 0)
	{
		int err = errno;
		cap_free(caps);
		return -err;
	}

	cap_free(caps);
	return value;
}

int Caps::SetCap(int cap)
{
	cap_t caps;
	cap_value_t cap_list[1] { cap };

	caps = cap_get_proc();
	if (caps == NULL)
		return -errno;

	if (cap_set_flag(caps, CAP_EFFECTIVE, 1, cap_list, CAP_SET) == -1)
	{
		int err = errno;
		cap_free(caps);
		return -err;
	}

	if (cap_set_flag(caps, CAP_PERMITTED, 1, cap_list, CAP_SET) == -1)
	{
		int err = errno;
		cap_free(caps);
		return -err;
	}

	if (cap_set_proc(caps) < 0)
	{
		int err = errno;
		cap_free(caps);
		return -err;
	}

	cap_free(caps);
	return 0;
}

int Caps::Keep()
{
	if (prctl(PR_SET_KEEPCAPS, 1, 0, 0) < 0)
		return -errno;
	return 0;
}

int Caps::UnKeep()
{
	if (prctl(PR_SET_KEEPCAPS, 0, 0, 0) < 0)
		return -errno;
	return 0;
}

<commit_msg>Fixed syntax problem with array<commit_after>
#include <libclientserver.h>

int Caps::HasCap(int cap)
{
	cap_t caps;
	cap_flag_value_t value = CAP_CLEAR;

	caps = cap_get_proc();

	if (cap_get_flag(caps, cap, CAP_EFFECTIVE, &value) < 0)
	{
		int err = errno;
		cap_free(caps);
		return -err;
	}

	cap_free(caps);
	return value;
}

int Caps::SetCap(int cap)
{
	cap_t caps;
	cap_value_t cap_list[1] = { cap };

	caps = cap_get_proc();
	if (caps == NULL)
		return -errno;

	if (cap_set_flag(caps, CAP_EFFECTIVE, 1, cap_list, CAP_SET) == -1)
	{
		int err = errno;
		cap_free(caps);
		return -err;
	}

	if (cap_set_flag(caps, CAP_PERMITTED, 1, cap_list, CAP_SET) == -1)
	{
		int err = errno;
		cap_free(caps);
		return -err;
	}

	if (cap_set_proc(caps) < 0)
	{
		int err = errno;
		cap_free(caps);
		return -err;
	}

	cap_free(caps);
	return 0;
}

int Caps::Keep()
{
	if (prctl(PR_SET_KEEPCAPS, 1, 0, 0) < 0)
		return -errno;
	return 0;
}

int Caps::UnKeep()
{
	if (prctl(PR_SET_KEEPCAPS, 0, 0, 0) < 0)
		return -errno;
	return 0;
}

<|endoftext|>


<commit_before>#ifndef CARD_HPP
#define CARD_HPP
class IDeck;
enum class Suit
{
	CLUBS,
	DIAMONDS,
	HEARTS,
	SPADES
};

enum class Rank
{
	TWO,
	THREE,
	FOUR,
	FIVE,
	SIX,
	SEVEN,
	EIGHT,
	NINE,
	TEN,
	JACK,
	QUEEN,
	KING,
	ACE
};

struct Card
{
	public:
	Suit suit;
	Rank rank;
	Card(Suit, Rank);
};

#endif
<commit_msg>Card :(<commit_after>#ifndef CARD_HPP
#define CARD_HPP

enum class Suit
{
	CLUBS,
	DIAMONDS,
	HEARTS,
	SPADES
};

enum class Rank
{
	TWO,
	THREE,
	FOUR,
	FIVE,
	SIX,
	SEVEN,
	EIGHT,
	NINE,
	TEN,
	JACK,
	QUEEN,
	KING,
	ACE
};

struct Card
{
	public:
	Suit suit;
	Rank rank;
	Card(Suit, Rank);
};

#endif
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2017, Image Engine. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//      * Redistributions of source code must retain the above
//        copyright notice, this list of conditions and the following
//        disclaimer.
//
//      * Redistributions in binary form must reproduce the above
//        copyright notice, this list of conditions and the following
//        disclaimer in the documentation and/or other materials provided with
//        the distribution.
//
//      * Neither the name of John Haddon nor the names of
//        any other contributors to this software may be used to endorse or
//        promote products derived from this software without specific prior
//        written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "boost/container/flat_map.hpp"
#include "boost/algorithm/string/predicate.hpp"
#include "boost/algorithm/string.hpp"

#include "IECore/Light.h"
#include "IECore/Shader.h"

#include "IECoreGL/Group.h"
#include "IECoreGL/Primitive.h"

#include "GafferSceneUI/LightFilterVisualiser.h"
#include "GafferSceneUI/AttributeVisualiser.h"

using namespace std;
using namespace Imath;
using namespace GafferSceneUI;

//////////////////////////////////////////////////////////////////////////
// Internal implementation details
//////////////////////////////////////////////////////////////////////////

namespace
{

typedef std::pair<IECore::InternedString, IECore::InternedString> AttributeAndShaderNames;

typedef boost::container::flat_map<AttributeAndShaderNames, ConstLightFilterVisualiserPtr> LightFilterVisualisers;
LightFilterVisualisers &lightFilterVisualisers()
{
	static LightFilterVisualisers l;
	return l;
}

/// Class for visualisation of light filters. All light filters in Gaffer are represented
/// as IECore::Shader objects, but we need to visualise them differently
/// depending on their shader name (accessed using `IECore::Shader::getName()`). A
/// factory mechanism is provided to map from this type to a specialised
/// LightFilterVisualiser.
class AttributeVisualiserForLightFilters : public AttributeVisualiser
{

	public :

		IE_CORE_DECLAREMEMBERPTR( AttributeVisualiserForLightFilters )

		/// Uses a custom visualisation registered via `registerLightFilterVisualiser()` if one
		/// is available, if not falls back to a basic visualisation.
		virtual IECoreGL::ConstRenderablePtr visualise( const IECore::CompoundObject *attributes, IECoreGL::ConstStatePtr &state ) const;

	protected :

		static AttributeVisualiser::AttributeVisualiserDescription<AttributeVisualiserForLightFilters> g_visualiserDescription;

};

} // namespace

IECoreGL::ConstRenderablePtr AttributeVisualiserForLightFilters::visualise( const IECore::CompoundObject *attributes, IECoreGL::ConstStatePtr &state ) const
{
	if( !attributes )
	{
		return nullptr;
	}

	IECoreGL::GroupPtr resultGroup = nullptr;
	IECoreGL::StatePtr resultState = nullptr;

	/// This seems pretty expensive to do everywhere.
	/// The alternative would be to register attribute visualisers to specific attributes.
	/// But then we wouldn't be able to have a visualiser that is influenced by multiple attributes simultaneously
	for( const auto& it : attributes->members() )
	{
		const std::string &attributeName = it.first.string();
		if( attributeName.find( ":lightFilter" ) == std::string::npos )
		{
			continue;
		}

		const IECore::ObjectVector *filterShaderVector = IECore::runTimeCast<const IECore::ObjectVector>( it.second.get() );
		if( !filterShaderVector || filterShaderVector->members().empty() )
		{
			continue;
		}

		IECore::InternedString filterShaderName;
		if( const IECore::Shader *filterShader = IECore::runTimeCast<const IECore::Shader>( filterShaderVector->members().back().get() ) )
		{
			filterShaderName = filterShader->getName();
		}

		if( filterShaderName.string().empty() )
		{
			continue;
		}

		// find the light shader influenced by the filter

		std::vector<std::string> tokens;
		boost::split( tokens, attributeName, boost::is_any_of(":") );
		auto lightIt = attributes->members().find( tokens.front() + ":light" );

		if( lightIt == attributes->members().end() )
		{
			continue;
		}

		const IECore::ObjectVector *lightShaderVector = IECore::runTimeCast<const IECore::ObjectVector>( lightIt->second.get() );
		if( !lightShaderVector || lightShaderVector->members().empty() )
		{
			continue;
		}

		const LightFilterVisualisers &l = lightFilterVisualisers();

		// light filters are stored in attributes following this syntax:
		// renderer:lightFilter:optionalName. Visualisers get registered to
		// renderer:lightFilter only, though. It's therefore necessary to strip off
		// the optional part
		std::string attrLookup = tokens[0] + ":" + tokens[1];

		const LightFilterVisualiser *visualiser = nullptr;
		auto visIt = l.find( AttributeAndShaderNames( attrLookup, filterShaderName ) );
		if( visIt != l.end() )
		{
			visualiser = visIt->second.get();
		}
		else
		{
			continue;
		}

		IECoreGL::ConstStatePtr curState = nullptr;
		IECoreGL::ConstRenderablePtr curVis = visualiser->visualise( attributeName, filterShaderVector, lightShaderVector, curState );

		if( curVis )
		{
			if( !resultGroup )
			{
				resultGroup = new IECoreGL::Group();
			}
			// resultGroup will be returned as const, so const-casting the children in order to add them is safe
			resultGroup->addChild( const_cast<IECoreGL::Renderable*>( curVis.get() ) );
		}

		if( curState )
		{
			if( !resultState )
			{
				resultState = new IECoreGL::State( false );
			}
			resultState->add( const_cast<IECoreGL::State*>( curState.get() ) );
		}
	}

	state = resultState;
	return resultGroup;
}

AttributeVisualiser::AttributeVisualiserDescription<AttributeVisualiserForLightFilters> AttributeVisualiserForLightFilters::g_visualiserDescription;

//////////////////////////////////////////////////////////////////////////
// LightVisualiser class
//////////////////////////////////////////////////////////////////////////

LightFilterVisualiser::LightFilterVisualiser()
{
}

LightFilterVisualiser::~LightFilterVisualiser()
{
}

void LightFilterVisualiser::registerLightFilterVisualiser( const IECore::InternedString &attributeName, const IECore::InternedString &shaderName, ConstLightFilterVisualiserPtr visualiser )
{
	lightFilterVisualisers()[AttributeAndShaderNames( attributeName, shaderName )] = visualiser;
}
<commit_msg>LightFilterVisualiser : Remove unused include<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2017, Image Engine. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//      * Redistributions of source code must retain the above
//        copyright notice, this list of conditions and the following
//        disclaimer.
//
//      * Redistributions in binary form must reproduce the above
//        copyright notice, this list of conditions and the following
//        disclaimer in the documentation and/or other materials provided with
//        the distribution.
//
//      * Neither the name of John Haddon nor the names of
//        any other contributors to this software may be used to endorse or
//        promote products derived from this software without specific prior
//        written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "boost/container/flat_map.hpp"
#include "boost/algorithm/string/predicate.hpp"
#include "boost/algorithm/string.hpp"

#include "IECore/Shader.h"

#include "IECoreGL/Group.h"
#include "IECoreGL/Primitive.h"

#include "GafferSceneUI/LightFilterVisualiser.h"
#include "GafferSceneUI/AttributeVisualiser.h"

using namespace std;
using namespace Imath;
using namespace GafferSceneUI;

//////////////////////////////////////////////////////////////////////////
// Internal implementation details
//////////////////////////////////////////////////////////////////////////

namespace
{

typedef std::pair<IECore::InternedString, IECore::InternedString> AttributeAndShaderNames;

typedef boost::container::flat_map<AttributeAndShaderNames, ConstLightFilterVisualiserPtr> LightFilterVisualisers;
LightFilterVisualisers &lightFilterVisualisers()
{
	static LightFilterVisualisers l;
	return l;
}

/// Class for visualisation of light filters. All light filters in Gaffer are represented
/// as IECore::Shader objects, but we need to visualise them differently
/// depending on their shader name (accessed using `IECore::Shader::getName()`). A
/// factory mechanism is provided to map from this type to a specialised
/// LightFilterVisualiser.
class AttributeVisualiserForLightFilters : public AttributeVisualiser
{

	public :

		IE_CORE_DECLAREMEMBERPTR( AttributeVisualiserForLightFilters )

		/// Uses a custom visualisation registered via `registerLightFilterVisualiser()` if one
		/// is available, if not falls back to a basic visualisation.
		virtual IECoreGL::ConstRenderablePtr visualise( const IECore::CompoundObject *attributes, IECoreGL::ConstStatePtr &state ) const;

	protected :

		static AttributeVisualiser::AttributeVisualiserDescription<AttributeVisualiserForLightFilters> g_visualiserDescription;

};

} // namespace

IECoreGL::ConstRenderablePtr AttributeVisualiserForLightFilters::visualise( const IECore::CompoundObject *attributes, IECoreGL::ConstStatePtr &state ) const
{
	if( !attributes )
	{
		return nullptr;
	}

	IECoreGL::GroupPtr resultGroup = nullptr;
	IECoreGL::StatePtr resultState = nullptr;

	/// This seems pretty expensive to do everywhere.
	/// The alternative would be to register attribute visualisers to specific attributes.
	/// But then we wouldn't be able to have a visualiser that is influenced by multiple attributes simultaneously
	for( const auto& it : attributes->members() )
	{
		const std::string &attributeName = it.first.string();
		if( attributeName.find( ":lightFilter" ) == std::string::npos )
		{
			continue;
		}

		const IECore::ObjectVector *filterShaderVector = IECore::runTimeCast<const IECore::ObjectVector>( it.second.get() );
		if( !filterShaderVector || filterShaderVector->members().empty() )
		{
			continue;
		}

		IECore::InternedString filterShaderName;
		if( const IECore::Shader *filterShader = IECore::runTimeCast<const IECore::Shader>( filterShaderVector->members().back().get() ) )
		{
			filterShaderName = filterShader->getName();
		}

		if( filterShaderName.string().empty() )
		{
			continue;
		}

		// find the light shader influenced by the filter

		std::vector<std::string> tokens;
		boost::split( tokens, attributeName, boost::is_any_of(":") );
		auto lightIt = attributes->members().find( tokens.front() + ":light" );

		if( lightIt == attributes->members().end() )
		{
			continue;
		}

		const IECore::ObjectVector *lightShaderVector = IECore::runTimeCast<const IECore::ObjectVector>( lightIt->second.get() );
		if( !lightShaderVector || lightShaderVector->members().empty() )
		{
			continue;
		}

		const LightFilterVisualisers &l = lightFilterVisualisers();

		// light filters are stored in attributes following this syntax:
		// renderer:lightFilter:optionalName. Visualisers get registered to
		// renderer:lightFilter only, though. It's therefore necessary to strip off
		// the optional part
		std::string attrLookup = tokens[0] + ":" + tokens[1];

		const LightFilterVisualiser *visualiser = nullptr;
		auto visIt = l.find( AttributeAndShaderNames( attrLookup, filterShaderName ) );
		if( visIt != l.end() )
		{
			visualiser = visIt->second.get();
		}
		else
		{
			continue;
		}

		IECoreGL::ConstStatePtr curState = nullptr;
		IECoreGL::ConstRenderablePtr curVis = visualiser->visualise( attributeName, filterShaderVector, lightShaderVector, curState );

		if( curVis )
		{
			if( !resultGroup )
			{
				resultGroup = new IECoreGL::Group();
			}
			// resultGroup will be returned as const, so const-casting the children in order to add them is safe
			resultGroup->addChild( const_cast<IECoreGL::Renderable*>( curVis.get() ) );
		}

		if( curState )
		{
			if( !resultState )
			{
				resultState = new IECoreGL::State( false );
			}
			resultState->add( const_cast<IECoreGL::State*>( curState.get() ) );
		}
	}

	state = resultState;
	return resultGroup;
}

AttributeVisualiser::AttributeVisualiserDescription<AttributeVisualiserForLightFilters> AttributeVisualiserForLightFilters::g_visualiserDescription;

//////////////////////////////////////////////////////////////////////////
// LightVisualiser class
//////////////////////////////////////////////////////////////////////////

LightFilterVisualiser::LightFilterVisualiser()
{
}

LightFilterVisualiser::~LightFilterVisualiser()
{
}

void LightFilterVisualiser::registerLightFilterVisualiser( const IECore::InternedString &attributeName, const IECore::InternedString &shaderName, ConstLightFilterVisualiserPtr visualiser )
{
	lightFilterVisualisers()[AttributeAndShaderNames( attributeName, shaderName )] = visualiser;
}
<|endoftext|>