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

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */

#include    "../Debug/Trace.h"

namespace   Stroika {
    namespace   Foundation {
        namespace   Memory {

            /*
            ********************************************************************************
            ************** SharedByValue_CopyByFunction<T,SHARED_IMLP> *********************
            ********************************************************************************
            */
#if     qCompilerAndStdLib_lambda_default_argument_with_template_param_as_function_cast_Buggy
            template    <typename   T, typename SHARED_IMLP>
            SHARED_IMLP  SharedByValue_CopyByFunction<T, SHARED_IMLP>::DefaultElementCopier_ (const T& t)
            {
                return SHARED_IMLP (new T (t));
            }
#endif
            template    <typename   T, typename SHARED_IMLP>
            inline  SharedByValue_CopyByFunction<T, SHARED_IMLP>::SharedByValue_CopyByFunction (SHARED_IMLP (*copier) (const T&)) noexcept
:
            fCopier (copier)
            {
                RequireNotNull (copier);
            }
            template    <typename   T, typename SHARED_IMLP>
            inline  SHARED_IMLP  SharedByValue_CopyByFunction<T, SHARED_IMLP>::Copy (const T& t) const
            {
                AssertNotNull (fCopier);
                return (*fCopier) (t);
            }

            /*
            ********************************************************************************
            *************** SharedByValue_CopyByDefault<T,SHARED_IMLP> *********************
            ********************************************************************************
            */
            template    <typename   T, typename SHARED_IMLP>
            inline  SHARED_IMLP  SharedByValue_CopyByDefault<T, SHARED_IMLP>::Copy (const T& t)
            {
                return SHARED_IMLP (new T (t));
            }

            /*
            ********************************************************************************
            ****** SharedByValue_CopySharedPtrExternallySynchonized<T,SHARED_IMLP> *********
            ********************************************************************************
            */
            template    <typename   T, typename SHARED_IMLP>
            inline  SHARED_IMLP     SharedByValue_CopySharedPtrExternallySynchonized<T, SHARED_IMLP>::Load (const SHARED_IMLP& copyFrom)
            {
                return copyFrom;
            }
            template    <typename   T, typename SHARED_IMLP>
            inline  void            SharedByValue_CopySharedPtrExternallySynchonized<T, SHARED_IMLP>::Store (SHARED_IMLP* storeTo, SHARED_IMLP o)
            {
                RequireNotNull (storeTo);
                *storeTo = o;
            }

            /*
            ********************************************************************************
            ********* SharedByValue_CopySharedPtrAtomicSynchonized<T,SHARED_IMLP> **********
            ********************************************************************************
            */
            template    <typename   T, typename SHARED_IMLP>
            inline  SHARED_IMLP     SharedByValue_CopySharedPtrAtomicSynchonized<T, SHARED_IMLP>::Load (const SHARED_IMLP& copyFrom)
            {
                return atomic_load (&copyFrom);
            }
            template    <typename   T, typename SHARED_IMLP>
            inline  void            SharedByValue_CopySharedPtrAtomicSynchonized<T, SHARED_IMLP>::Store (SHARED_IMLP* storeTo, SHARED_IMLP o)
            {
                RequireNotNull (storeTo);
                atomic_store (storeTo, o);
            }

            /*
            ********************************************************************************
            ****************************** SharedByValue<TRAITS> ***************************
            ********************************************************************************
            */
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue () noexcept
:
            fCopier_ (element_copier_type ())
            , fSharedImpl_ ()
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue (nullptr_t n) noexcept
:
            fCopier_ (element_copier_type ())
            , fSharedImpl_ ()
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue (const SharedByValue<TRAITS>& from) noexcept
:
            fCopier_ (from.fCopier_)
            , fSharedImpl_ (shared_impl_copier_type::Load (from.fSharedImpl_))
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue (SharedByValue<TRAITS>&& from) noexcept
:
            fCopier_ (from.fCopier_)
            , fSharedImpl_ (std::move (from.fSharedImpl_))
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue (const shared_ptr_type& from, const element_copier_type& copier) noexcept
:
            fCopier_ (copier)
            , fSharedImpl_ (shared_impl_copier_type::Load (from))
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue (shared_ptr_type&& from, const element_copier_type&& copier) noexcept
:
            fCopier_ (move (copier))
            , fSharedImpl_ (move (from))
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue (element_type* from, const element_copier_type& copier)
                : fCopier_ (copier)
                , fSharedImpl_ (from)
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>& SharedByValue<TRAITS>::operator= (const SharedByValue<TRAITS>& src)
            {
                if (this != &src) {
                    fCopier_ = src.fCopier_;
                    shared_impl_copier_type::Store (&fSharedImpl_, shared_impl_copier_type::Load (src.fSharedImpl_));
                }
                return *this;
            }
            template    <typename TRAITS>
            inline  const typename SharedByValue<TRAITS>::element_type*    SharedByValue<TRAITS>::get () const
            {
                return fSharedImpl_.get ();
            }
            template    <typename TRAITS>
            template    <typename... COPY_ARGS>
            inline  typename SharedByValue<TRAITS>::element_type* SharedByValue<TRAITS>::get (COPY_ARGS&& ... copyArgs)
            {
                element_type*  ptr =   fSharedImpl_.get ();
                /*
                 * For non-const pointing, we must clone ourselves (if there are
                 * extra referneces). If we are a nullptr pointer, nobody could actually
                 * rereference it anyhow, so don't bother with the Assure1Reference()
                 * in that case.
                 */
                if (ptr != nullptr) {
                    Assure1Reference (forward<COPY_ARGS> (copyArgs)...);
                    ptr = fSharedImpl_.get ();
                    EnsureNotNull (ptr);
                }
                return ptr;
            }
            template    <typename TRAITS>
            inline  const typename SharedByValue<TRAITS>::element_type*    SharedByValue<TRAITS>::cget () const
            {
                return get ();
            }
            template    <typename TRAITS>
            inline  const typename SharedByValue<TRAITS>::element_type*    SharedByValue<TRAITS>::operator-> () const
            {
                return fSharedImpl_.get ();
            }
            template    <typename TRAITS>
            inline  typename SharedByValue<TRAITS>::element_type* SharedByValue<TRAITS>::operator-> ()
            {
                return get ();
            }
            template    <typename TRAITS>
            inline  const typename SharedByValue<TRAITS>::element_type&    SharedByValue<TRAITS>::operator* () const
            {
                const element_type*  ptr =   get ();
                EnsureNotNull (ptr);
                return *ptr;
            }
            template    <typename TRAITS>
            inline  typename SharedByValue<TRAITS>::element_type&   SharedByValue<TRAITS>::operator* ()
            {
                /*
                 * For non-const dereferencing, we must clone ourselves (if there are
                 * extra referneces).
                 */
                Assure1Reference ();
                element_type*  ptr =   get ();
                EnsureNotNull (ptr);
                return *ptr;
            }
            template    <typename TRAITS>
            inline  bool    SharedByValue<TRAITS>::operator== (const SharedByValue<TRAITS>& rhs) const
            {
                return fSharedImpl_ == rhs.fSharedImpl_;
            }
            template    <typename TRAITS>
            inline  bool    SharedByValue<TRAITS>::operator!= (const SharedByValue<TRAITS>& rhs) const
            {
                return fSharedImpl_ != rhs.fSharedImpl_;
            }
            template    <typename TRAITS>
            inline  SharedByValue_State    SharedByValue<TRAITS>::GetSharingState () const
            {
                switch (fSharedImpl_.use_count ()) {
                    case 0:
                        Assert (fSharedImpl_.get () == nullptr);
                        return SharedByValue_State::eNull;
                    case 1:
                        Assert (fSharedImpl_.get () != nullptr);
                        Assert (fSharedImpl_.unique ());
                        return SharedByValue_State::eSolo;
                    default:
                        Assert (fSharedImpl_.get () != nullptr);
                        Assert (not fSharedImpl_.unique ());
                        return SharedByValue_State::eShared;
                }
            }
            template    <typename TRAITS>
            inline  bool    SharedByValue<TRAITS>::unique () const
            {
                return fSharedImpl_.unique ();
            }
            template    <typename TRAITS>
            template    <typename... COPY_ARGS>
            inline  void    SharedByValue<TRAITS>::Assure1Reference (COPY_ARGS&& ... copyArgs)
            {
                if (not fSharedImpl_.unique ()) {
                    BreakReferences_ (forward<COPY_ARGS> (copyArgs)...);
                }
            }
            template    <typename TRAITS>
            template    <typename... COPY_ARGS>
            void    SharedByValue<TRAITS>::BreakReferences_ (COPY_ARGS&& ... copyArgs)
            {
                shared_ptr_type     ptr2Clone   { shared_impl_copier_type::Load (fSharedImpl_) };       // other thread could change this (if other thread accesses same envelope)
                // but this copy prevents the bare ptr from possibly becoming invalidated
                element_type*  ptr =   ptr2Clone.get ();
                RequireNotNull (ptr);
                /*
                 *      For a valid pointer that is reference counted and multiply shared,
                 *  make a copy of that pointer via our fCloner function, and assign
                 *  that cloned reference to this.
                 *
                 *      Note that by doing so, we remove any references to the current
                 *  item, and end up with our having the sole reference to the new copy of fPtr.
                 *
                 *      Since we will be cloning the given pointer, we assume(assert) that
                 *  it is non-nullptr.
                 */
                //Require (!SHARED_IMLP::unique ());    This is not NECESSARILY so. Another thread could have just released this pointer, in which case
                // the creation of a new object was pointless, but harmless, as the assignemnt should decrement to zero the old
                // value and it should go away.
                *this = SharedByValue<TRAITS> (fCopier_.Copy (*ptr, forward<COPY_ARGS>(copyArgs)...), fCopier_);

#if     qDebug
                //Ensure (fSharedImpl_.unique ());
                // technically not 100% gauranteed if two threads did this at the same time, but so rare interesting if ever triggered.
                // may need to lose this assert - maybe replace with #if qDebug DbgTrace
                if (not fSharedImpl_.unique ()) {
                    DbgTrace ("probably a bug, but not necessarily...");
                }
#endif
            }

            /*
            ********************************************************************************
            ***************** SharedByValue<TRAITS>::ReadOnlyReference *********************
            ********************************************************************************
            */
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::ReadOnlyReference::ReadOnlyReference (const SharedByValue<TRAITS>& sp)
                : fSharedPtr_ (sp.fSharedImpl_)
            {
                RequireNotNull (fSharedPtr_);
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::ReadOnlyReference::ReadOnlyReference (const ReadOnlyReference&& r)
                : fSharedPtr_ (move (r.fSharedPtr_))
            {
            }
            template    <typename TRAITS>
            inline  typename SharedByValue<TRAITS>::ReadOnlyReference& SharedByValue<TRAITS>::ReadOnlyReference::operator= (const ReadOnlyReference && rhs)
            {
                fSharedPtr_ = move (rhs.fSharedPtr_);
                return *this;
            }
            template    <typename TRAITS>
            inline  const typename SharedByValue<TRAITS>::element_type*     SharedByValue<TRAITS>::ReadOnlyReference::get () const
            {
                EnsureNotNull (fSharedPtr_);
                return fSharedPtr_.get ();
            }
            template    <typename TRAITS>
            const typename SharedByValue<TRAITS>::element_type&     SharedByValue<TRAITS>::ReadOnlyReference::operator* () const
            {
                EnsureNotNull (fSharedPtr_);
                return *fSharedPtr_.get ();
            }

        }
    }
}
#endif  /*_Stroika_Foundation_Memory_SharedByValue_inl_*/
<commit_msg>Minor fix to SharedByValue<TRAITS>::ReadOnlyReference::ReadOnlyReference atomicload code<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#ifndef _Stroika_Foundation_Memory_SharedByValue_inl_
#define _Stroika_Foundation_Memory_SharedByValue_inl_   1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */

#include    "../Debug/Trace.h"

namespace   Stroika {
    namespace   Foundation {
        namespace   Memory {

            /*
            ********************************************************************************
            ************** SharedByValue_CopyByFunction<T,SHARED_IMLP> *********************
            ********************************************************************************
            */
#if     qCompilerAndStdLib_lambda_default_argument_with_template_param_as_function_cast_Buggy
            template    <typename   T, typename SHARED_IMLP>
            SHARED_IMLP  SharedByValue_CopyByFunction<T, SHARED_IMLP>::DefaultElementCopier_ (const T& t)
            {
                return SHARED_IMLP (new T (t));
            }
#endif
            template    <typename   T, typename SHARED_IMLP>
            inline  SharedByValue_CopyByFunction<T, SHARED_IMLP>::SharedByValue_CopyByFunction (SHARED_IMLP (*copier) (const T&)) noexcept
:
            fCopier (copier)
            {
                RequireNotNull (copier);
            }
            template    <typename   T, typename SHARED_IMLP>
            inline  SHARED_IMLP  SharedByValue_CopyByFunction<T, SHARED_IMLP>::Copy (const T& t) const
            {
                AssertNotNull (fCopier);
                return (*fCopier) (t);
            }

            /*
            ********************************************************************************
            *************** SharedByValue_CopyByDefault<T,SHARED_IMLP> *********************
            ********************************************************************************
            */
            template    <typename   T, typename SHARED_IMLP>
            inline  SHARED_IMLP  SharedByValue_CopyByDefault<T, SHARED_IMLP>::Copy (const T& t)
            {
                return SHARED_IMLP (new T (t));
            }

            /*
            ********************************************************************************
            ****** SharedByValue_CopySharedPtrExternallySynchonized<T,SHARED_IMLP> *********
            ********************************************************************************
            */
            template    <typename   T, typename SHARED_IMLP>
            inline  SHARED_IMLP     SharedByValue_CopySharedPtrExternallySynchonized<T, SHARED_IMLP>::Load (const SHARED_IMLP& copyFrom)
            {
                return copyFrom;
            }
            template    <typename   T, typename SHARED_IMLP>
            inline  void            SharedByValue_CopySharedPtrExternallySynchonized<T, SHARED_IMLP>::Store (SHARED_IMLP* storeTo, SHARED_IMLP o)
            {
                RequireNotNull (storeTo);
                *storeTo = o;
            }

            /*
            ********************************************************************************
            ********* SharedByValue_CopySharedPtrAtomicSynchonized<T,SHARED_IMLP> **********
            ********************************************************************************
            */
            template    <typename   T, typename SHARED_IMLP>
            inline  SHARED_IMLP     SharedByValue_CopySharedPtrAtomicSynchonized<T, SHARED_IMLP>::Load (const SHARED_IMLP& copyFrom)
            {
                return atomic_load (&copyFrom);
            }
            template    <typename   T, typename SHARED_IMLP>
            inline  void            SharedByValue_CopySharedPtrAtomicSynchonized<T, SHARED_IMLP>::Store (SHARED_IMLP* storeTo, SHARED_IMLP o)
            {
                RequireNotNull (storeTo);
                atomic_store (storeTo, o);
            }

            /*
            ********************************************************************************
            ****************************** SharedByValue<TRAITS> ***************************
            ********************************************************************************
            */
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue () noexcept
:
            fCopier_ (element_copier_type ())
            , fSharedImpl_ ()
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue (nullptr_t n) noexcept
:
            fCopier_ (element_copier_type ())
            , fSharedImpl_ ()
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue (const SharedByValue<TRAITS>& from) noexcept
:
            fCopier_ (from.fCopier_)
            , fSharedImpl_ (shared_impl_copier_type::Load (from.fSharedImpl_))
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue (SharedByValue<TRAITS>&& from) noexcept
:
            fCopier_ (from.fCopier_)
            , fSharedImpl_ (std::move (from.fSharedImpl_))
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue (const shared_ptr_type& from, const element_copier_type& copier) noexcept
:
            fCopier_ (copier)
            , fSharedImpl_ (shared_impl_copier_type::Load (from))
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue (shared_ptr_type&& from, const element_copier_type&& copier) noexcept
:
            fCopier_ (move (copier))
            , fSharedImpl_ (move (from))
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue (element_type* from, const element_copier_type& copier)
                : fCopier_ (copier)
                , fSharedImpl_ (from)
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>& SharedByValue<TRAITS>::operator= (const SharedByValue<TRAITS>& src)
            {
                if (this != &src) {
                    fCopier_ = src.fCopier_;
                    shared_impl_copier_type::Store (&fSharedImpl_, shared_impl_copier_type::Load (src.fSharedImpl_));
                }
                return *this;
            }
            template    <typename TRAITS>
            inline  const typename SharedByValue<TRAITS>::element_type*    SharedByValue<TRAITS>::get () const
            {
                return fSharedImpl_.get ();
            }
            template    <typename TRAITS>
            template    <typename... COPY_ARGS>
            inline  typename SharedByValue<TRAITS>::element_type* SharedByValue<TRAITS>::get (COPY_ARGS&& ... copyArgs)
            {
                element_type*  ptr =   fSharedImpl_.get ();
                /*
                 * For non-const pointing, we must clone ourselves (if there are
                 * extra referneces). If we are a nullptr pointer, nobody could actually
                 * rereference it anyhow, so don't bother with the Assure1Reference()
                 * in that case.
                 */
                if (ptr != nullptr) {
                    Assure1Reference (forward<COPY_ARGS> (copyArgs)...);
                    ptr = fSharedImpl_.get ();
                    EnsureNotNull (ptr);
                }
                return ptr;
            }
            template    <typename TRAITS>
            inline  const typename SharedByValue<TRAITS>::element_type*    SharedByValue<TRAITS>::cget () const
            {
                return get ();
            }
            template    <typename TRAITS>
            inline  const typename SharedByValue<TRAITS>::element_type*    SharedByValue<TRAITS>::operator-> () const
            {
                return fSharedImpl_.get ();
            }
            template    <typename TRAITS>
            inline  typename SharedByValue<TRAITS>::element_type* SharedByValue<TRAITS>::operator-> ()
            {
                return get ();
            }
            template    <typename TRAITS>
            inline  const typename SharedByValue<TRAITS>::element_type&    SharedByValue<TRAITS>::operator* () const
            {
                const element_type*  ptr =   get ();
                EnsureNotNull (ptr);
                return *ptr;
            }
            template    <typename TRAITS>
            inline  typename SharedByValue<TRAITS>::element_type&   SharedByValue<TRAITS>::operator* ()
            {
                /*
                 * For non-const dereferencing, we must clone ourselves (if there are
                 * extra referneces).
                 */
                Assure1Reference ();
                element_type*  ptr =   get ();
                EnsureNotNull (ptr);
                return *ptr;
            }
            template    <typename TRAITS>
            inline  bool    SharedByValue<TRAITS>::operator== (const SharedByValue<TRAITS>& rhs) const
            {
                return fSharedImpl_ == rhs.fSharedImpl_;
            }
            template    <typename TRAITS>
            inline  bool    SharedByValue<TRAITS>::operator!= (const SharedByValue<TRAITS>& rhs) const
            {
                return fSharedImpl_ != rhs.fSharedImpl_;
            }
            template    <typename TRAITS>
            inline  SharedByValue_State    SharedByValue<TRAITS>::GetSharingState () const
            {
                switch (fSharedImpl_.use_count ()) {
                    case 0:
                        Assert (fSharedImpl_.get () == nullptr);
                        return SharedByValue_State::eNull;
                    case 1:
                        Assert (fSharedImpl_.get () != nullptr);
                        Assert (fSharedImpl_.unique ());
                        return SharedByValue_State::eSolo;
                    default:
                        Assert (fSharedImpl_.get () != nullptr);
                        Assert (not fSharedImpl_.unique ());
                        return SharedByValue_State::eShared;
                }
            }
            template    <typename TRAITS>
            inline  bool    SharedByValue<TRAITS>::unique () const
            {
                return fSharedImpl_.unique ();
            }
            template    <typename TRAITS>
            template    <typename... COPY_ARGS>
            inline  void    SharedByValue<TRAITS>::Assure1Reference (COPY_ARGS&& ... copyArgs)
            {
                if (not fSharedImpl_.unique ()) {
                    BreakReferences_ (forward<COPY_ARGS> (copyArgs)...);
                }
            }
            template    <typename TRAITS>
            template    <typename... COPY_ARGS>
            void    SharedByValue<TRAITS>::BreakReferences_ (COPY_ARGS&& ... copyArgs)
            {
                shared_ptr_type     ptr2Clone   { shared_impl_copier_type::Load (fSharedImpl_) };       // other thread could change this (if other thread accesses same envelope)
                // but this copy prevents the bare ptr from possibly becoming invalidated
                element_type*  ptr =   ptr2Clone.get ();
                RequireNotNull (ptr);
                /*
                 *      For a valid pointer that is reference counted and multiply shared,
                 *  make a copy of that pointer via our fCloner function, and assign
                 *  that cloned reference to this.
                 *
                 *      Note that by doing so, we remove any references to the current
                 *  item, and end up with our having the sole reference to the new copy of fPtr.
                 *
                 *      Since we will be cloning the given pointer, we assume(assert) that
                 *  it is non-nullptr.
                 */
                //Require (!SHARED_IMLP::unique ());    This is not NECESSARILY so. Another thread could have just released this pointer, in which case
                // the creation of a new object was pointless, but harmless, as the assignemnt should decrement to zero the old
                // value and it should go away.
                *this = SharedByValue<TRAITS> (fCopier_.Copy (*ptr, forward<COPY_ARGS>(copyArgs)...), fCopier_);

#if     qDebug
                //Ensure (fSharedImpl_.unique ());
                // technically not 100% gauranteed if two threads did this at the same time, but so rare interesting if ever triggered.
                // may need to lose this assert - maybe replace with #if qDebug DbgTrace
                if (not fSharedImpl_.unique ()) {
                    DbgTrace ("probably a bug, but not necessarily...");
                }
#endif
            }

            /*
            ********************************************************************************
            ***************** SharedByValue<TRAITS>::ReadOnlyReference *********************
            ********************************************************************************
            */
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::ReadOnlyReference::ReadOnlyReference (const SharedByValue<TRAITS>& sp)
                : fSharedPtr_ (shared_impl_copier_type::Load (sp.fSharedImpl_))
            {
                RequireNotNull (fSharedPtr_);
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::ReadOnlyReference::ReadOnlyReference (const ReadOnlyReference&& r)
                : fSharedPtr_ (move (r.fSharedPtr_))
            {
            }
            template    <typename TRAITS>
            inline  typename SharedByValue<TRAITS>::ReadOnlyReference& SharedByValue<TRAITS>::ReadOnlyReference::operator= (const ReadOnlyReference && rhs)
            {
                fSharedPtr_ = move (rhs.fSharedPtr_);
                return *this;
            }
            template    <typename TRAITS>
            inline  const typename SharedByValue<TRAITS>::element_type*     SharedByValue<TRAITS>::ReadOnlyReference::get () const
            {
                EnsureNotNull (fSharedPtr_);
                return fSharedPtr_.get ();
            }
            template    <typename TRAITS>
            const typename SharedByValue<TRAITS>::element_type&     SharedByValue<TRAITS>::ReadOnlyReference::operator* () const
            {
                EnsureNotNull (fSharedPtr_);
                return *fSharedPtr_.get ();
            }

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


<commit_before>/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#include <memory.hpp>
#include <cuda.h>
#include <cuda_runtime_api.h>
#include <cuda_runtime.h>
#include <err_cuda.hpp>
#include <types.hpp>
#include <map>
#include <dispatch.hpp>
#include <platform.hpp>

namespace cuda
{
    static void garbageCollect();
    static void pinnedGarbageCollect();

    // Manager Class
    // Dummy used to call garbage collection at the end of the program
    class Manager
    {
        public:
        static bool initialized;
        Manager()
        {
            initialized = true;
        }

        ~Manager()
        {
            for(int i = 0; i < getDeviceCount(); i++) {
                setDevice(i);
                garbageCollect();
            }
            pinnedGarbageCollect();
        }
    };

    bool Manager::initialized = false;

    static void managerInit()
    {
        if(Manager::initialized == false)
            static Manager pm = Manager();
    }

    template<typename T>
    static void cudaFreeWrapper(T *ptr)
    {
        cudaError_t err = cudaFree(ptr);
        if (err != cudaErrorCudartUnloading) // see issue #167
            CUDA_CHECK(err);
    }

    template<typename T>
    static void pinnedFreeWrapper(T *ptr)
    {
        cudaError_t err = cudaFreeHost(ptr);
        if (err != cudaErrorCudartUnloading) // see issue #167
            CUDA_CHECK(err);
    }

#ifdef CUDA_MEM_DEBUG

    template<typename T>
    T* memAlloc(const size_t &elements)
    {
        T* ptr = NULL;
        CUDA_CHECK(cudaMalloc(&ptr, elements * sizeof(T)));
        return ptr;
    }

    template<typename T>
    void memFree(T *ptr)
    {
        cudaFreeWrapper(ptr); // Free it because we are not sure what the size is
    }

    template<typename T>
    T* pinnedAlloc(const size_t &elements)
    {
        T* ptr = NULL;
        CUDA_CHECK(cudaMallocHost((void **)(&ptr), alloc_bytes));
        return (T*)ptr;
    }

    template<typename T>
    void pinnedFree(T *ptr)
    {
        pinnedFreeWrapper(ptr); // Free it because we are not sure what the size is
    }

#else

    static const unsigned MAX_BUFFERS   = 100;
    static const unsigned MAX_BYTES     = (1 << 30);

    typedef struct
    {
        bool is_free;
        size_t bytes;
    } mem_info;

    static size_t used_bytes = 0;
    typedef std::map<void *, mem_info> mem_t;
    typedef mem_t::iterator mem_iter;

    mem_t memory_maps[DeviceManager::MAX_DEVICES];

    static void garbageCollect()
    {
        int n = getActiveDeviceId();
        for(mem_iter iter = memory_maps[n].begin(); iter != memory_maps[n].end(); iter++) {
            if ((iter->second).is_free) cudaFreeWrapper(iter->first);
        }

        mem_iter memory_curr = memory_maps[n].begin();
        mem_iter memory_end  = memory_maps[n].end();

        while(memory_curr != memory_end) {
            if (memory_curr->second.is_free) {
                memory_maps[n].erase(memory_curr++);
            } else {
                ++memory_curr;
            }
        }
    }

    template<typename T>
    T* memAlloc(const size_t &elements)
    {
        managerInit();
        int n = getActiveDeviceId();
        T* ptr = NULL;
        size_t alloc_bytes = divup(sizeof(T) * elements, 1024) * 1024;

        if (elements > 0) {

            // FIXME: Add better checks for garbage collection
            // Perhaps look at total memory available as a metric
            if (memory_maps[n].size() >= MAX_BUFFERS || used_bytes >= MAX_BYTES) {
                garbageCollect();
            }

            for(mem_iter iter = memory_maps[n].begin();
                iter != memory_maps[n].end(); iter++) {

                mem_info info = iter->second;
                if (info.is_free && info.bytes == alloc_bytes) {
                    iter->second.is_free = false;
                    used_bytes += alloc_bytes;
                    return (T *)iter->first;
                }
            }

            // Perform garbage collection if memory can not be allocated
            if (cudaMalloc((void **)&ptr, alloc_bytes) != cudaSuccess) {
                garbageCollect();
                CUDA_CHECK(cudaMalloc((void **)(&ptr), alloc_bytes));
            }

            mem_info info = {false, alloc_bytes};
            memory_maps[n][ptr] = info;
            used_bytes += alloc_bytes;
        }
        return ptr;
    }

    template<typename T>
    void memFree(T *ptr)
    {
        int n = getActiveDeviceId();
        mem_iter iter = memory_maps[n].find((void *)ptr);

        if (iter != memory_maps[n].end()) {
            iter->second.is_free = true;
            used_bytes -= iter->second.bytes;
        } else {
            cudaFreeWrapper(ptr); // Free it because we are not sure what the size is
        }
    }

    //////////////////////////////////////////////////////////////////////////////
    mem_t pinned_maps;
    static size_t pinned_used_bytes = 0;

    static void pinnedGarbageCollect()
    {
        for(mem_iter iter = pinned_maps.begin(); iter != pinned_maps.end(); iter++) {
            if ((iter->second).is_free) pinnedFreeWrapper(iter->first);
        }

        mem_iter memory_curr = pinned_maps.begin();
        mem_iter memory_end  = pinned_maps.end();

        while(memory_curr != memory_end) {
            if (memory_curr->second.is_free) {
                pinned_maps.erase(memory_curr++);
            } else {
                ++memory_curr;
            }
        }
    }

    template<typename T>
    T* pinnedAlloc(const size_t &elements)
    {
        managerInit();
        T* ptr = NULL;
        // Allocate the higher megabyte. Overhead of creating pinned memory is
        // more so we want more resuable memory.
        size_t alloc_bytes = divup(sizeof(T) * elements, 1048576) * 1048576;

        if (elements > 0) {

            // FIXME: Add better checks for garbage collection
            // Perhaps look at total memory available as a metric
            if (pinned_maps.size() >= MAX_BUFFERS || pinned_used_bytes >= MAX_BYTES) {
                pinnedGarbageCollect();
            }

            for(mem_iter iter = pinned_maps.begin();
                iter != pinned_maps.end(); iter++) {

                mem_info info = iter->second;
                if (info.is_free && info.bytes == alloc_bytes) {
                    iter->second.is_free = false;
                    pinned_used_bytes += alloc_bytes;
                    return (T *)iter->first;
                }
            }

            // Perform garbage collection if memory can not be allocated
            if (cudaMallocHost((void **)&ptr, alloc_bytes) != cudaSuccess) {
                pinnedGarbageCollect();
                CUDA_CHECK(cudaMallocHost((void **)(&ptr), alloc_bytes));
            }

            mem_info info = {false, alloc_bytes};
            pinned_maps[ptr] = info;
            pinned_used_bytes += alloc_bytes;
        }
        return (T*)ptr;
    }

    template<typename T>
    void pinnedFree(T *ptr)
    {
        mem_iter iter = pinned_maps.find((void *)ptr);

        if (iter != pinned_maps.end()) {
            iter->second.is_free = true;
            pinned_used_bytes -= iter->second.bytes;
        } else {
            pinnedFreeWrapper(ptr); // Free it because we are not sure what the size is
        }
    }

#endif

#define INSTANTIATE(T)                              \
    template T* memAlloc(const size_t &elements);   \
    template void memFree(T* ptr);                  \
    template T* pinnedAlloc(const size_t &elements);\
    template void pinnedFree(T* ptr);               \

    INSTANTIATE(float)
    INSTANTIATE(cfloat)
    INSTANTIATE(double)
    INSTANTIATE(cdouble)
    INSTANTIATE(int)
    INSTANTIATE(uint)
    INSTANTIATE(char)
    INSTANTIATE(uchar)
    INSTANTIATE(intl)
    INSTANTIATE(uintl)

}
<commit_msg>Cleaning up memory.cpp in cuda backend<commit_after>/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#include <memory.hpp>
#include <cuda.h>
#include <cuda_runtime_api.h>
#include <cuda_runtime.h>
#include <err_cuda.hpp>
#include <types.hpp>
#include <map>
#include <dispatch.hpp>
#include <platform.hpp>

namespace cuda
{
    template<typename T>
    static void cudaFreeWrapper(T *ptr)
    {
        cudaError_t err = cudaFree(ptr);
        if (err != cudaErrorCudartUnloading) // see issue #167
            CUDA_CHECK(err);
    }

    template<typename T>
    static void pinnedFreeWrapper(T *ptr)
    {
        cudaError_t err = cudaFreeHost(ptr);
        if (err != cudaErrorCudartUnloading) // see issue #167
            CUDA_CHECK(err);
    }

#ifdef AF_CUDA_MEM_DEBUG

    template<typename T>
    T* memAlloc(const size_t &elements)
    {
        T* ptr = NULL;
        CUDA_CHECK(cudaMalloc(&ptr, elements * sizeof(T)));
        return ptr;
    }

    template<typename T>
    void memFree(T *ptr)
    {
        cudaFreeWrapper(ptr); // Free it because we are not sure what the size is
    }

    template<typename T>
    T* pinnedAlloc(const size_t &elements)
    {
        T* ptr = NULL;
        CUDA_CHECK(cudaMallocHost((void **)(&ptr), elements * sizeof(T)));
        return (T*)ptr;
    }

    template<typename T>
    void pinnedFree(T *ptr)
    {
        pinnedFreeWrapper(ptr); // Free it because we are not sure what the size is
    }

#else

        static void garbageCollect();
    static void pinnedGarbageCollect();

    // Manager Class
    // Dummy used to call garbage collection at the end of the program
    class Manager
    {
        public:
        static bool initialized;
        Manager()
        {
            initialized = true;
        }

        ~Manager()
        {
            for(int i = 0; i < getDeviceCount(); i++) {
                setDevice(i);
                garbageCollect();
            }
            pinnedGarbageCollect();
        }
    };

    bool Manager::initialized = false;

    static void managerInit()
    {
        if(Manager::initialized == false)
            static Manager pm = Manager();
    }

    static const unsigned MAX_BUFFERS   = 100;
    static const unsigned MAX_BYTES     = (1 << 30);

    typedef struct
    {
        bool is_free;
        size_t bytes;
    } mem_info;

    static size_t used_bytes = 0;
    typedef std::map<void *, mem_info> mem_t;
    typedef mem_t::iterator mem_iter;

    mem_t memory_maps[DeviceManager::MAX_DEVICES];

    static void garbageCollect()
    {
        int n = getActiveDeviceId();
        for(mem_iter iter = memory_maps[n].begin(); iter != memory_maps[n].end(); iter++) {
            if ((iter->second).is_free) cudaFreeWrapper(iter->first);
        }

        mem_iter memory_curr = memory_maps[n].begin();
        mem_iter memory_end  = memory_maps[n].end();

        while(memory_curr != memory_end) {
            if (memory_curr->second.is_free) {
                memory_maps[n].erase(memory_curr++);
            } else {
                ++memory_curr;
            }
        }
    }

    template<typename T>
    T* memAlloc(const size_t &elements)
    {
        managerInit();
        int n = getActiveDeviceId();
        T* ptr = NULL;
        size_t alloc_bytes = divup(sizeof(T) * elements, 1024) * 1024;

        if (elements > 0) {

            // FIXME: Add better checks for garbage collection
            // Perhaps look at total memory available as a metric
            if (memory_maps[n].size() >= MAX_BUFFERS || used_bytes >= MAX_BYTES) {
                garbageCollect();
            }

            for(mem_iter iter = memory_maps[n].begin();
                iter != memory_maps[n].end(); iter++) {

                mem_info info = iter->second;
                if (info.is_free && info.bytes == alloc_bytes) {
                    iter->second.is_free = false;
                    used_bytes += alloc_bytes;
                    return (T *)iter->first;
                }
            }

            // Perform garbage collection if memory can not be allocated
            if (cudaMalloc((void **)&ptr, alloc_bytes) != cudaSuccess) {
                garbageCollect();
                CUDA_CHECK(cudaMalloc((void **)(&ptr), alloc_bytes));
            }

            mem_info info = {false, alloc_bytes};
            memory_maps[n][ptr] = info;
            used_bytes += alloc_bytes;
        }
        return ptr;
    }

    template<typename T>
    void memFree(T *ptr)
    {
        int n = getActiveDeviceId();
        mem_iter iter = memory_maps[n].find((void *)ptr);

        if (iter != memory_maps[n].end()) {
            iter->second.is_free = true;
            used_bytes -= iter->second.bytes;
        } else {
            cudaFreeWrapper(ptr); // Free it because we are not sure what the size is
        }
    }

    //////////////////////////////////////////////////////////////////////////////
    mem_t pinned_maps;
    static size_t pinned_used_bytes = 0;

    static void pinnedGarbageCollect()
    {
        for(mem_iter iter = pinned_maps.begin(); iter != pinned_maps.end(); iter++) {
            if ((iter->second).is_free) pinnedFreeWrapper(iter->first);
        }

        mem_iter memory_curr = pinned_maps.begin();
        mem_iter memory_end  = pinned_maps.end();

        while(memory_curr != memory_end) {
            if (memory_curr->second.is_free) {
                pinned_maps.erase(memory_curr++);
            } else {
                ++memory_curr;
            }
        }
    }

    template<typename T>
    T* pinnedAlloc(const size_t &elements)
    {
        managerInit();
        T* ptr = NULL;
        // Allocate the higher megabyte. Overhead of creating pinned memory is
        // more so we want more resuable memory.
        size_t alloc_bytes = divup(sizeof(T) * elements, 1048576) * 1048576;

        if (elements > 0) {

            // FIXME: Add better checks for garbage collection
            // Perhaps look at total memory available as a metric
            if (pinned_maps.size() >= MAX_BUFFERS || pinned_used_bytes >= MAX_BYTES) {
                pinnedGarbageCollect();
            }

            for(mem_iter iter = pinned_maps.begin();
                iter != pinned_maps.end(); iter++) {

                mem_info info = iter->second;
                if (info.is_free && info.bytes == alloc_bytes) {
                    iter->second.is_free = false;
                    pinned_used_bytes += alloc_bytes;
                    return (T *)iter->first;
                }
            }

            // Perform garbage collection if memory can not be allocated
            if (cudaMallocHost((void **)&ptr, alloc_bytes) != cudaSuccess) {
                pinnedGarbageCollect();
                CUDA_CHECK(cudaMallocHost((void **)(&ptr), alloc_bytes));
            }

            mem_info info = {false, alloc_bytes};
            pinned_maps[ptr] = info;
            pinned_used_bytes += alloc_bytes;
        }
        return (T*)ptr;
    }

    template<typename T>
    void pinnedFree(T *ptr)
    {
        mem_iter iter = pinned_maps.find((void *)ptr);

        if (iter != pinned_maps.end()) {
            iter->second.is_free = true;
            pinned_used_bytes -= iter->second.bytes;
        } else {
            pinnedFreeWrapper(ptr); // Free it because we are not sure what the size is
        }
    }

#endif

#define INSTANTIATE(T)                              \
    template T* memAlloc(const size_t &elements);   \
    template void memFree(T* ptr);                  \
    template T* pinnedAlloc(const size_t &elements);\
    template void pinnedFree(T* ptr);               \

    INSTANTIATE(float)
    INSTANTIATE(cfloat)
    INSTANTIATE(double)
    INSTANTIATE(cdouble)
    INSTANTIATE(int)
    INSTANTIATE(uint)
    INSTANTIATE(char)
    INSTANTIATE(uchar)
    INSTANTIATE(intl)
    INSTANTIATE(uintl)

}
<|endoftext|>


<commit_before>// The libMesh Finite Element Library.
// Copyright (C) 2002-2016 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public  License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// Local Includes -----------------------------------
#include "libmesh/default_coupling.h"

#include "libmesh/elem.h"
#include "libmesh/periodic_boundaries.h"
#include "libmesh/remote_elem.h"

namespace libMesh
{

void DefaultCoupling::mesh_reinit()
{
  // Unless we have periodic boundary conditions, we don't need
  // to cache anything.
  if (!_periodic_bcs || _periodic_bcs->empty())
    return;

  // If we do have periodic boundary conditions, we'll need a master
  // point locator, so we'd better have a mesh to build it on.
  libmesh_assert(_mesh);

  // Make sure a master point locator has been constructed; we'll need
  // to grab sub-locators soon.
  _mesh->sub_point_locator();
}

void DefaultCoupling::operator()
  (const MeshBase::const_element_iterator & range_begin,
   const MeshBase::const_element_iterator & range_end,
   processor_id_type p,
   map_type & coupled_elements)
{
  LOG_SCOPE("operator()", "DefaultCoupling");

  UniquePtr<PointLocatorBase> point_locator;
  if (_periodic_bcs)
    {
      libmesh_assert(_mesh);
      point_locator = _mesh->sub_point_locator();
    }

  for (MeshBase::const_element_iterator elem_it = range_begin;
       elem_it != range_end; ++elem_it)
    {
      std::vector<const Elem *> active_neighbors;

      const Elem * const elem = *elem_it;

      if (elem->processor_id() != p)
        coupled_elements.insert (std::make_pair(elem,_dof_coupling));

      if (_couple_neighbor_dofs)
        for (unsigned int s=0; s<elem->n_sides(); s++)
          {
            const Elem *neigh = elem->neighbor_ptr(s);

            // If we have a neighbor here
            if (neigh)
              {
                // Mesh ghosting might ask us about what we want to
                // distribute along with non-local elements, and those
                // non-local elements might have remote neighbors, and
                // if they do then we can't say anything about them.
                if (neigh == remote_elem)
                  continue;
              }
#ifdef LIBMESH_ENABLE_PERIODIC
            // We might still have a periodic neighbor here
            else if (_periodic_bcs)
              {
                libmesh_assert(_mesh);

                neigh = elem->topological_neighbor
                  (s, *_mesh, *point_locator, _periodic_bcs);
              }
#endif

            // With no regular *or* periodic neighbors we have nothing
            // to do.
            if (!neigh)
              continue;

	    // With any kind of neighbor, we need to couple to all the
	    // active descendants on our side.
#ifdef LIBMESH_ENABLE_AMR
            neigh->active_family_tree_by_neighbor(active_neighbors,elem);
#else
            active_neighbors.clear();
            active_neighbors.push_back(neigh);
#endif

            for (std::size_t a=0; a != active_neighbors.size(); ++a)
              {
                const Elem * neighbor = active_neighbors[a];

                if (neighbor->processor_id() != p)
                  coupled_elements.insert
                    (std::make_pair(neighbor, _dof_coupling));
              }
          }
    }
}

} // namespace libMesh
<commit_msg>Use active_family_tree_by_topological_neighbor<commit_after>// The libMesh Finite Element Library.
// Copyright (C) 2002-2016 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public  License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// Local Includes -----------------------------------
#include "libmesh/default_coupling.h"

#include "libmesh/elem.h"
#include "libmesh/periodic_boundaries.h"
#include "libmesh/remote_elem.h"

namespace libMesh
{

void DefaultCoupling::mesh_reinit()
{
  // Unless we have periodic boundary conditions, we don't need
  // to cache anything.
  if (!_periodic_bcs || _periodic_bcs->empty())
    return;

  // If we do have periodic boundary conditions, we'll need a master
  // point locator, so we'd better have a mesh to build it on.
  libmesh_assert(_mesh);

  // Make sure a master point locator has been constructed; we'll need
  // to grab sub-locators soon.
  _mesh->sub_point_locator();
}

void DefaultCoupling::operator()
  (const MeshBase::const_element_iterator & range_begin,
   const MeshBase::const_element_iterator & range_end,
   processor_id_type p,
   map_type & coupled_elements)
{
  LOG_SCOPE("operator()", "DefaultCoupling");

  UniquePtr<PointLocatorBase> point_locator;
  if (_periodic_bcs)
    {
      libmesh_assert(_mesh);
      point_locator = _mesh->sub_point_locator();
    }

  for (MeshBase::const_element_iterator elem_it = range_begin;
       elem_it != range_end; ++elem_it)
    {
      std::vector<const Elem *> active_neighbors;

      const Elem * const elem = *elem_it;

      if (elem->processor_id() != p)
        coupled_elements.insert (std::make_pair(elem,_dof_coupling));

      if (_couple_neighbor_dofs)
        for (unsigned int s=0; s<elem->n_sides(); s++)
          {
            const Elem *neigh = elem->neighbor_ptr(s);

            // If we have a neighbor here
            if (neigh)
              {
                // Mesh ghosting might ask us about what we want to
                // distribute along with non-local elements, and those
                // non-local elements might have remote neighbors, and
                // if they do then we can't say anything about them.
                if (neigh == remote_elem)
                  continue;
              }
#ifdef LIBMESH_ENABLE_PERIODIC
            // We might still have a periodic neighbor here
            else if (_periodic_bcs)
              {
                libmesh_assert(_mesh);

                neigh = elem->topological_neighbor
                  (s, *_mesh, *point_locator, _periodic_bcs);
              }
#endif

            // With no regular *or* periodic neighbors we have nothing
            // to do.
            if (!neigh)
              continue;

	    // With any kind of neighbor, we need to couple to all the
	    // active descendants on our side.
#ifdef LIBMESH_ENABLE_AMR
            if (neigh == elem->neighbor_ptr(s))
              neigh->active_family_tree_by_neighbor(active_neighbors,elem);
            else
              neigh->active_family_tree_by_topological_neighbor
                (active_neighbors,elem,*_mesh,*point_locator,_periodic_bcs);
#else
            active_neighbors.clear();
            active_neighbors.push_back(neigh);
#endif

            for (std::size_t a=0; a != active_neighbors.size(); ++a)
              {
                const Elem * neighbor = active_neighbors[a];

                if (neighbor->processor_id() != p)
                  coupled_elements.insert
                    (std::make_pair(neighbor, _dof_coupling));
              }
          }
    }
}

} // namespace libMesh
<|endoftext|>


<commit_before>#include <bashclass/BashClass.h>
#include <iostream>
#include <sstream>

BashClass::BashClass() {
    m_global = std::make_shared<BGlobal>();
    m_scopeStack.push(m_global);
    m_focusScope = nullptr;
    m_focusVariable = nullptr;
    initHandlers();
}

void BashClass::printStructure() {
    std::cout << m_global->getStructure().str() << std::endl;
}

void BashClass::initHandlers() {
    m_startClass = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE) {
            auto newClass = m_scopeStack.top()->createClass(lexicalVector[index]);
            m_scopeStack.push(newClass);
            m_focusScope = newClass;
        } else if(phase == BashClass::PHASE_EVAL_GEN) {
            auto newClass = m_scopeStack.top()->getScope(lexicalVector[index]);
            m_scopeStack.push(newClass);
            m_focusScope = newClass;
        }
    };

    m_className = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE) {

            // Check if class already exists
            const char* className = lexicalVector[index]->getValue().c_str();
            auto getClass = m_scopeStack.top()->getParentScope()->findAllClasses(className);
            if(!getClass.empty()) {
                std::cerr << "Class '" << className << "' is defined multiple times" << std::endl;
            }

            // Set class name
            auto createdClass = std::dynamic_pointer_cast<BClass>(m_focusScope);
            createdClass->setName(lexicalVector[index]->getValue());
        }
    };

    m_endClass = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE || phase == BashClass::PHASE_EVAL_GEN) {
            m_scopeStack.pop();
            m_focusScope = nullptr;
        }
    };

    m_startFunction = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE) {
            auto newFunction = m_scopeStack.top()->createFunction(lexicalVector[index]);
            m_scopeStack.push(newFunction);
            m_focusScope = newFunction;
        } else if(phase == BashClass::PHASE_EVAL_GEN) {
            auto newFunction = m_scopeStack.top()->getScope(lexicalVector[index]);
            m_scopeStack.push(newFunction);
            m_focusScope = newFunction;
        }
    };

    m_functionType = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE) {
            auto createdFunction = std::dynamic_pointer_cast<BFunction>(m_focusScope);
            createdFunction->setType(lexicalVector[index]->getValue());
        }
    };

    m_functionName = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE) {

            // Check if function already exists in the current scope and has the same number of params
            const char* funcName = lexicalVector[index]->getValue().c_str();
            auto getFunc = m_scopeStack.top()->getParentScope()->findAllFunctions(funcName);
            if(!getFunc.empty()) {
                std::cerr << "Function '" << funcName << "' is defined multiple times in the same scope" << std::endl;
            }

            auto createdFunction = std::dynamic_pointer_cast<BFunction>(m_focusScope);
            createdFunction->setName(lexicalVector[index]->getValue());
        }
    };

    m_endFunction = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE || phase == BashClass::PHASE_EVAL_GEN) {
            m_scopeStack.pop();
            m_focusScope = nullptr;
        }
    };

    m_startVar = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE) {
            auto variable = m_scopeStack.top()->createVariable(lexicalVector[index]);
            m_focusVariable = variable;
        }
    };

    m_varType = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE) {
            m_focusVariable->setType(lexicalVector[index]->getValue());
        }
    };

    m_varName = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE) {

            // Check if variable already exists in the current scope
            const char* varName = lexicalVector[index]->getValue().c_str();
            auto getVar = m_scopeStack.top()->findAllVariables(varName);
            if(!getVar.empty()) {
                std::cerr << "Variable '" << varName << "' is defined multiple times in the same scope" << std::endl;
            }

            m_focusVariable->setName(lexicalVector[index]->getValue());
        }
    };

    m_endVar = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE) {
            m_focusVariable = nullptr;
        }
    };

    m_startParam = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE) {
            auto createdVar = m_scopeStack.top()->createVariable(lexicalVector[index]);
            createdVar->setIsParam(true);
        }
    };

    m_paramType = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE) {
            const auto &variables = m_scopeStack.top()->findAllVariables();
            variables[variables.size()-1]->setType(lexicalVector[index]->getValue());
        }
    };

    m_paramName = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE) {
            const auto &variables = m_scopeStack.top()->findAllVariables();
            variables[variables.size()-1]->setName(lexicalVector[index]->getValue());
        }
    };

    m_endParam = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE) {
            m_focusVariable = nullptr;
        }
    };
}
<commit_msg>Added comments to separate actions<commit_after>#include <bashclass/BashClass.h>
#include <iostream>
#include <sstream>

BashClass::BashClass() {
    m_global = std::make_shared<BGlobal>();
    m_scopeStack.push(m_global);
    m_focusScope = nullptr;
    m_focusVariable = nullptr;
    initHandlers();
}

void BashClass::printStructure() {
    std::cout << m_global->getStructure().str() << std::endl;
}

void BashClass::initHandlers() {

    /**************************************
     *          CLASSES
     **************************************/
    m_startClass = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE) {
            auto newClass = m_scopeStack.top()->createClass(lexicalVector[index]);
            m_scopeStack.push(newClass);
            m_focusScope = newClass;
        } else if(phase == BashClass::PHASE_EVAL_GEN) {
            auto newClass = m_scopeStack.top()->getScope(lexicalVector[index]);
            m_scopeStack.push(newClass);
            m_focusScope = newClass;
        }
    };

    m_className = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE) {

            // Check if class already exists
            const char* className = lexicalVector[index]->getValue().c_str();
            auto getClass = m_scopeStack.top()->getParentScope()->findAllClasses(className);
            if(!getClass.empty()) {
                std::cerr << "Class '" << className << "' is defined multiple times" << std::endl;
            }

            // Set class name
            auto createdClass = std::dynamic_pointer_cast<BClass>(m_focusScope);
            createdClass->setName(lexicalVector[index]->getValue());
        }
    };

    m_endClass = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE || phase == BashClass::PHASE_EVAL_GEN) {
            m_scopeStack.pop();
            m_focusScope = nullptr;
        }
    };

    m_startFunction = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE) {
            auto newFunction = m_scopeStack.top()->createFunction(lexicalVector[index]);
            m_scopeStack.push(newFunction);
            m_focusScope = newFunction;
        } else if(phase == BashClass::PHASE_EVAL_GEN) {
            auto newFunction = m_scopeStack.top()->getScope(lexicalVector[index]);
            m_scopeStack.push(newFunction);
            m_focusScope = newFunction;
        }
    };

    /**************************************
     *          FUNCTIONS
     **************************************/
    m_functionType = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE) {
            auto createdFunction = std::dynamic_pointer_cast<BFunction>(m_focusScope);
            createdFunction->setType(lexicalVector[index]->getValue());
        }
    };

    m_functionName = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE) {

            // Check if function already exists in the current scope and has the same number of params
            const char* funcName = lexicalVector[index]->getValue().c_str();
            auto getFunc = m_scopeStack.top()->getParentScope()->findAllFunctions(funcName);
            if(!getFunc.empty()) {
                std::cerr << "Function '" << funcName << "' is defined multiple times in the same scope" << std::endl;
            }

            auto createdFunction = std::dynamic_pointer_cast<BFunction>(m_focusScope);
            createdFunction->setName(lexicalVector[index]->getValue());
        }
    };

    m_endFunction = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE || phase == BashClass::PHASE_EVAL_GEN) {
            m_scopeStack.pop();
            m_focusScope = nullptr;
        }
    };

    /**************************************
     *          VARIABLES
     **************************************/
    m_startVar = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE) {
            auto variable = m_scopeStack.top()->createVariable(lexicalVector[index]);
            m_focusVariable = variable;
        }
    };

    m_varType = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE) {
            m_focusVariable->setType(lexicalVector[index]->getValue());
        }
    };

    m_varName = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE) {

            // Check if variable already exists in the current scope
            const char* varName = lexicalVector[index]->getValue().c_str();
            auto getVar = m_scopeStack.top()->findAllVariables(varName);
            if(!getVar.empty()) {
                std::cerr << "Variable '" << varName << "' is defined multiple times in the same scope" << std::endl;
            }

            m_focusVariable->setName(lexicalVector[index]->getValue());
        }
    };

    m_endVar = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE) {
            m_focusVariable = nullptr;
        }
    };

    /**************************************
     *          PARAMETERS
     **************************************/
    m_startParam = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE) {
            auto createdVar = m_scopeStack.top()->createVariable(lexicalVector[index]);
            createdVar->setIsParam(true);
        }
    };

    m_paramType = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE) {
            const auto &variables = m_scopeStack.top()->findAllVariables();
            variables[variables.size()-1]->setType(lexicalVector[index]->getValue());
        }
    };

    m_paramName = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE) {
            const auto &variables = m_scopeStack.top()->findAllVariables();
            variables[variables.size()-1]->setName(lexicalVector[index]->getValue());
        }
    };

    m_endParam = [&](int phase, LexicalTokens &lexicalVector, int index, bool stable){
        if(phase == BashClass::PHASE_CREATE) {
            m_focusVariable = nullptr;
        }
    };
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 The Bitcoin Core developers
// Copyright (c) 2015-2019 The Bitcoin Unlimited developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "bench.h"

#include "crypto/sha256.h"
#include "key.h"
#include "main.h"
#include "sync.h"
#include "util.h"

#ifdef DEBUG_LOCKORDER
std::atomic<bool> lockdataDestructed{false};
LockData lockdata;
#endif

int main(int argc, char **argv)
{
    SHA256AutoDetect();
    RandomInit();
    ECC_Start();
    SetupEnvironment();
    fPrintToDebugLog = false; // don't want to write to debug.log file

    benchmark::BenchRunner::RunAll();

    ECC_Stop();
}
<commit_msg>Remove deadlock detector variable definition in bench_bitcoin<commit_after>// Copyright (c) 2015 The Bitcoin Core developers
// Copyright (c) 2015-2019 The Bitcoin Unlimited developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "bench.h"

#include "crypto/sha256.h"
#include "key.h"
#include "main.h"
#include "sync.h"
#include "util.h"

int main(int argc, char **argv)
{
    SHA256AutoDetect();
    RandomInit();
    ECC_Start();
    SetupEnvironment();
    fPrintToDebugLog = false; // don't want to write to debug.log file

    benchmark::BenchRunner::RunAll();

    ECC_Stop();
}
<|endoftext|>


<commit_before>#include <sys/time.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <stdio.h>
#include <stdlib.h>

#include <iostream>
#include <fstream>
#include <map>

#include <CoreFoundation/CoreFoundation.h>

namespace {
  CFStringRef applicationID = CFSTR("org.pqrs.PCKeyboardHack");

  // ============================================================
  // SAVE & LOAD
  CFMutableDictionaryRef dict_sysctl = NULL;
  std::map<std::string, int> map_reset;

  void
  save(const char *name)
  {
    if (! dict_sysctl) return;

    char entry[512];
    snprintf(entry, sizeof(entry), "pckeyboardhack.%s", name);

    int value;
    size_t len = sizeof(value);
    if (sysctlbyname(entry, &value, &len, NULL, 0) == -1) return;

    CFStringRef key = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8);
    CFNumberRef val = CFNumberCreate(NULL, kCFNumberIntType, &value);

    typeof(map_reset.end()) it = map_reset.find(name);
    if (it == map_reset.end()) return;
    CFNumberRef defaultval = CFNumberCreate(NULL, kCFNumberIntType, &(it->second));

    if (CFNumberCompare(val, defaultval, NULL) != 0) {
      CFDictionarySetValue(dict_sysctl, key, val);
    }
  }

  void
  load(const char *name)
  {
    if (! dict_sysctl) return;
    CFStringRef key = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8);

    CFNumberRef val = reinterpret_cast<CFNumberRef>(CFDictionaryGetValue(dict_sysctl, key));
    if (! val) return;

    int value;
    if (! CFNumberGetValue(val, kCFNumberIntType, &value)) return;

    char cmd[512];
    snprintf(cmd, sizeof(cmd), "/Library/org.pqrs/PCKeyboardHack/bin/PCKeyboardHack_sysctl_set %s %d", name, value);
    system(cmd);
  }

  void
  scanLines(const char *filename, void (*func)(const char *))
  {
    std::ifstream ifs(filename);
    if (! ifs) return;

    while (! ifs.eof()) {
      char line[512];

      ifs.getline(line, sizeof(line));

      const char *tag[] = { "enable", "keycode", NULL };
      for (int i = 0; ; ++i) {
        if (tag[i] == NULL) break;

        char sysctl_begin[512];
        char sysctl_end[512];
        snprintf(sysctl_begin, sizeof(sysctl_begin), "<%s>", tag[i]);
        snprintf(sysctl_end, sizeof(sysctl_end), "</%s>", tag[i]);

        char *begin = strstr(line, sysctl_begin);
        if (! begin) continue;
        char *end = strstr(line, sysctl_end);
        if (! end) continue;

        begin += strlen(sysctl_begin);
        *end = '\0';

        func(begin);
      }
    }
  }

  bool
  makeMapReset(void)
  {
    std::ifstream ifs("/Library/org.pqrs/PCKeyboardHack/share/reset");
    if (! ifs) return false;

    while (! ifs.eof()) {
      char line[512];

      ifs.getline(line, sizeof(line));

      char *p = strchr(line, ' ');
      if (! p) continue;
      *p = '\0';

      int value = atoi(p + 1);

      map_reset[line] = value;
    }

    return true;
  }

  bool
  saveToFile(const char **targetFiles)
  {
    if (! makeMapReset()) return false;

    dict_sysctl = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
    if (! dict_sysctl) return false;

    for (int i = 0; ; ++i) {
      const char *filename = targetFiles[i];
      if (! filename) break;
      scanLines(filename, save);
    }
    CFPreferencesSetAppValue(CFSTR("sysctl"), dict_sysctl, applicationID);

    CFRelease(dict_sysctl); dict_sysctl = NULL;
    return true;
  }

  bool
  loadFromFile(const char **targetFiles)
  {
    dict_sysctl = reinterpret_cast<CFMutableDictionaryRef>(const_cast<void *>(CFPreferencesCopyAppValue(CFSTR("sysctl"), applicationID)));
    if (! dict_sysctl) return false;

    for (int i = 0; ; ++i) {
      const char *filename = targetFiles[i];
      if (! filename) break;
      scanLines(filename, load);
    }

    CFRelease(dict_sysctl); dict_sysctl = NULL;
    return true;
  }
}

int
main(int argc, char **argv)
{
  if (argc == 1) {
    fprintf(stderr, "Usage: %s (save|load) [params]\n", argv[0]);
    return 1;
  }

  bool isSuccess = false;
  if ((strcmp(argv[1], "save") == 0) || (strcmp(argv[1], "load") == 0)) {
    const char *targetFiles[] = {
      "/Library/org.pqrs/PCKeyboardHack/prefpane/sysctl.xml",
      NULL,
    };
    if (strcmp(argv[1], "save") == 0) {
      isSuccess = saveToFile(targetFiles);
    }
    if (strcmp(argv[1], "load") == 0) {
      system("/Library/org.pqrs/PCKeyboardHack/bin/PCKeyboardHack_sysctl_reset");
      isSuccess = loadFromFile(targetFiles);
    }
  }

  CFPreferencesAppSynchronize(applicationID);

  if (isSuccess) {
    fprintf(stderr, "[DONE]\n");
  } else {
    fprintf(stderr, "[ERROR]\n");
  }

  return 0;
}
<commit_msg>apply util/uncrustify<commit_after>#include <sys/time.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <stdio.h>
#include <stdlib.h>

#include <iostream>
#include <fstream>
#include <map>

#include <CoreFoundation/CoreFoundation.h>

namespace {
  CFStringRef applicationID = CFSTR("org.pqrs.PCKeyboardHack");

  // ============================================================
  // SAVE & LOAD
  CFMutableDictionaryRef dict_sysctl = NULL;
  std::map<std::string, int> map_reset;

  void
  save(const char* name)
  {
    if (! dict_sysctl) return;

    char entry[512];
    snprintf(entry, sizeof(entry), "pckeyboardhack.%s", name);

    int value;
    size_t len = sizeof(value);
    if (sysctlbyname(entry, &value, &len, NULL, 0) == -1) return;

    CFStringRef key = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8);
    CFNumberRef val = CFNumberCreate(NULL, kCFNumberIntType, &value);

    std::map<std::string, int>::iterator it = map_reset.find(name);
    if (it == map_reset.end()) return;
    CFNumberRef defaultval = CFNumberCreate(NULL, kCFNumberIntType, &(it->second));

    if (CFNumberCompare(val, defaultval, NULL) != 0) {
      CFDictionarySetValue(dict_sysctl, key, val);
    }
  }

  void
  load(const char* name)
  {
    if (! dict_sysctl) return;
    CFStringRef key = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8);

    CFNumberRef val = reinterpret_cast<CFNumberRef>(CFDictionaryGetValue(dict_sysctl, key));
    if (! val) return;

    int value;
    if (! CFNumberGetValue(val, kCFNumberIntType, &value)) return;

    char cmd[512];
    snprintf(cmd, sizeof(cmd), "/Library/org.pqrs/PCKeyboardHack/bin/PCKeyboardHack_sysctl_set %s %d", name, value);
    system(cmd);
  }

  void
  scanLines(const char* filename, void (* func)(const char*))
  {
    std::ifstream ifs(filename);
    if (! ifs) return;

    while (! ifs.eof()) {
      char line[512];

      ifs.getline(line, sizeof(line));

      const char* tag[] = { "enable", "keycode", NULL };
      for (int i = 0;; ++i) {
        if (tag[i] == NULL) break;

        char sysctl_begin[512];
        char sysctl_end[512];
        snprintf(sysctl_begin, sizeof(sysctl_begin), "<%s>", tag[i]);
        snprintf(sysctl_end, sizeof(sysctl_end), "</%s>", tag[i]);

        char* begin = strstr(line, sysctl_begin);
        if (! begin) continue;
        char* end = strstr(line, sysctl_end);
        if (! end) continue;

        begin += strlen(sysctl_begin);
        *end = '\0';

        func(begin);
      }
    }
  }

  bool
  makeMapReset(void)
  {
    std::ifstream ifs("/Library/org.pqrs/PCKeyboardHack/share/reset");
    if (! ifs) return false;

    while (! ifs.eof()) {
      char line[512];

      ifs.getline(line, sizeof(line));

      char* p = strchr(line, ' ');
      if (! p) continue;
      *p = '\0';

      int value = atoi(p + 1);

      map_reset[line] = value;
    }

    return true;
  }

  bool
  saveToFile(const char** targetFiles)
  {
    if (! makeMapReset()) return false;

    dict_sysctl = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
    if (! dict_sysctl) return false;

    for (int i = 0;; ++i) {
      const char* filename = targetFiles[i];
      if (! filename) break;
      scanLines(filename, save);
    }
    CFPreferencesSetAppValue(CFSTR("sysctl"), dict_sysctl, applicationID);

    CFRelease(dict_sysctl); dict_sysctl = NULL;
    return true;
  }

  bool
  loadFromFile(const char** targetFiles)
  {
    dict_sysctl = reinterpret_cast<CFMutableDictionaryRef>(const_cast<void*>(CFPreferencesCopyAppValue(CFSTR("sysctl"), applicationID)));
    if (! dict_sysctl) return false;

    for (int i = 0;; ++i) {
      const char* filename = targetFiles[i];
      if (! filename) break;
      scanLines(filename, load);
    }

    CFRelease(dict_sysctl); dict_sysctl = NULL;
    return true;
  }
}

int
main(int argc, char** argv)
{
  if (argc == 1) {
    fprintf(stderr, "Usage: %s (save|load) [params]\n", argv[0]);
    return 1;
  }

  bool isSuccess = false;
  if ((strcmp(argv[1], "save") == 0) || (strcmp(argv[1], "load") == 0)) {
    const char* targetFiles[] = {
      "/Library/org.pqrs/PCKeyboardHack/prefpane/sysctl.xml",
      NULL,
    };
    if (strcmp(argv[1], "save") == 0) {
      isSuccess = saveToFile(targetFiles);
    }
    if (strcmp(argv[1], "load") == 0) {
      system("/Library/org.pqrs/PCKeyboardHack/bin/PCKeyboardHack_sysctl_reset");
      isSuccess = loadFromFile(targetFiles);
    }
  }

  CFPreferencesAppSynchronize(applicationID);

  if (isSuccess) {
    fprintf(stderr, "[DONE]\n");
  } else {
    fprintf(stderr, "[ERROR]\n");
  }

  return 0;
}
<|endoftext|>


<commit_before>#include "uploadplugin.h"

#include <QDebug>
#include <QFile>
#include <QUuid>
#include <QFileInfo>
#include <QTimer>
#include <QBuffer>

#include "json.h"
using QtJson::JsonObject;
using QtJson::JsonArray;

UploadPlugin::UploadPlugin(QObject * parent)
    : UploadInterface (parent)
{

}

Q_EXPORT_PLUGIN2(UploadPlugin, UploadPlugin)

UploadPlugin::~UploadPlugin()
{

}

QString UploadPlugin::name(void) const
{
    return "UploadPlugin";
}

QString UploadPlugin::version() const
{
    return "1.0";
}

void UploadPlugin::setDefaultParameters()
{
    m_uploadProtocol == UploadInterface::ProtocolTus;
    m_userAgent = "UploadPlugin/0.0.2";
    m_chunkSize = 50*1024;
    m_bandwidthLimit = 30*1024;
    m_queueSize = 2;
}

void UploadPlugin::append(const QString &file)
{
    QFileInfo fi(file);

    qDebug() << "upload append" << file;

    UploadItem item;
    item.key = fi.fileName();
    item.path = file;

    if (uploadQueue.isEmpty())
        QTimer::singleShot(0, this, SLOT(startNextUpload()));

    uploadQueue.enqueue(item);
}

void UploadPlugin::append(const QStringList &fileList)
{
    foreach (QString file, fileList){
        append(file);
    }

    if (uploadQueue.isEmpty())
        QTimer::singleShot(0, this, SIGNAL(finishedAll()));
}

void UploadPlugin::pause(const QString &url)
{
    stopUpload(url, true);
}

void UploadPlugin::pause(const QStringList &urlList)
{
    foreach (QString url, urlList){
        pause(url);
    }
}

void UploadPlugin::resume(const QString &url)
{
    append(url);
}

void UploadPlugin::resume(const QStringList & urlList)
{
    foreach (QString url, urlList){
        resume(url);
    }
}

void UploadPlugin::stop(const QString &url)
{
    stopUpload(url, false);
}

void UploadPlugin::stop(const QStringList &urlList)
{
    foreach (QString url, urlList){
        stop(url);
    }
}

void UploadPlugin::stopUpload(const QString &url, bool pause)
{

}

void UploadPlugin::connectSignals(QNetworkReply *reply)
{
    connect(reply, SIGNAL(uploadProgress(qint64,qint64)),
            this, SLOT(uploadProgress(qint64,qint64)));
    connect(reply, SIGNAL(finished()),
            this, SLOT(uploadFinished()));
    connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
            this, SLOT(uploadError(QNetworkReply::NetworkError)));
    connect(reply, SIGNAL(sslErrors(QList<QSslError>)),
            this, SLOT(uploadSslErrors(QList<QSslError>)));
}

void UploadPlugin::uploadChunk(QNetworkReply *reply)
{
    UploadItem item = uploadHash[reply];

    if (item.chunkCounter == 0) {
        item.time.start();
        item.start = 0;
        item.end = 0;
    }

    if (item.start < item.size)
    {
        item.end = item.start + m_chunkSize;
        if (item.end > item.size)
        {
            item.end = item.size;
        }

        qint64 size = item.end - item.start;
        item.sent = item.start;

        qDebug() << item.start << item.end;

        QByteArray offset;
        offset.setNum(item.start);

        QByteArray length;
        length.setNum(item.end - item.start);

        uchar *buf = item.file->map(item.start, size);
        QBuffer * buffer = new QBuffer();
        buffer->setData(reinterpret_cast<const char*>(buf), size);
        buffer->close();

        QNetworkRequest request(QUrl(item.submitUrl));
        request.setRawHeader("User-Agent", m_userAgent);
        request.setRawHeader("Connection", "keep-alive");
        request.setRawHeader("Offset", offset);
        request.setRawHeader("Content-Length", length);
        request.setRawHeader("Content-Type", "application/offset+octet-stream");

        // remove previous reply
        uploadHash.remove(reply);

        QNetworkReply * reply = manager.sendCustomRequest(request, "PATCH", buffer);
        connectSignals(reply);

        item.file->unmap(buf);
        item.start += size;

        uploadHash[reply] = item;
        urlHash[item.path] = reply;
    }
    else
    {
        qDebug() << "DONE. Me think";
        item.file->close();
        item.file->deleteLater();

        completedList.append(item);

        emit status(item.path, "Complete", "Upload file completed", item.submitUrl);
        emit finished(item.path, item.submitUrl);

        uploadHash.remove(reply);
        urlHash.remove(item.path);

        startNextUpload();
    }
}

void UploadPlugin::startNextUpload()
{
    if (uploadQueue.isEmpty()) {
        emit finishedAll();
        return;
    }

    if (uploadHash.size() < m_queueSize)
    {
        UploadItem item = uploadQueue.dequeue();

        if (m_uploadProtocol == UploadInterface::ProtocolTus) {

            item.file = new QFile(item.path);
            item.file->open(QIODevice::ReadOnly);
            item.size = item.file->size();
            qDebug() << "size" << item.size;
            item.stage = 0;
            item.final = false;
            item.sent = 0;
            item.start = 0;

            QNetworkRequest request(m_uploadUrl);
            request.setRawHeader("User-Agent", m_userAgent);
            QByteArray fileLength;
            fileLength.setNum(item.size);
            request.setRawHeader("Final-Length", fileLength);
            QByteArray contentLength;
            contentLength.setNum(0);
            request.setRawHeader("Content-Length", contentLength);
            request.setRawHeader("Content-Type", "application/octet-stream");

            QNetworkReply * reply = manager.post(request, "");
            connectSignals(reply);

            emit status(item.path, "Register", "Start registering file", m_uploadUrl.toString());

            uploadHash[reply] = item;
            urlHash[item.path] = reply;

        }
        else if (m_uploadProtocol == UploadInterface::ProtocolMultipart) {

            QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);

            item.file = new QFile(item.path);
            item.file->open(QIODevice::ReadOnly);
            item.stage = 0;

            QHttpPart imagePart;
            imagePart.setHeader(QNetworkRequest::ContentDispositionHeader,
                                QVariant("form-data; name=\"document\"; filename=\""+ item.key +"\""));
            imagePart.setBodyDevice(item.file);
            item.file->setParent(multiPart);
            multiPart->append(imagePart);

            QNetworkRequest request(m_uploadUrl);
            request.setRawHeader("User-Agent", m_userAgent);

            QNetworkReply * reply = manager.post(request, multiPart);
            multiPart->setParent(reply);

            item.time.start();
            uploadHash[reply] = item;
            urlHash[item.path] = reply;
        }
        else
        {
            qDebug() << m_uploadProtocol;
            qDebug() << "No one knows";
        }

        startNextUpload();
    }
}

void UploadPlugin::uploadProgress(qint64 bytesSent, qint64 bytesTotal)
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    UploadItem item = uploadHash[reply];
    qint64 actualSent = item.sent + bytesSent;
    double speed = actualSent * 1000.0 / item.time.elapsed();
    QString unit;
    if (speed < 1024) {
        unit = "bytes/sec";
    } else if (speed < 1024*1024) {
        speed /= 1024;
        unit = "kB/s";
    } else {
        speed /= 1024*1024;
        unit = "MB/s";
    }
    int percent = actualSent * 100 / item.size;

    if (item.stage > 0) {
        //qDebug() << "upload" << item.path << actualSent << item.size << percent << speed << unit;
        emit progress(item.path, actualSent, item.size, percent, speed, unit);
    }
}

void UploadPlugin::uploadFinished()
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    UploadItem item = uploadHash[reply];
    int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    QByteArray customVerb = reply->request().attribute(QNetworkRequest::CustomVerbAttribute).toByteArray();

    //qDebug() << statusCode << customVerb;

    if(reply->error() == QNetworkReply::NoError)
    {
        if (m_uploadProtocol == UploadInterface::ProtocolTus)
        {
            if (item.stage == 0)
            {
                if (statusCode == 201)
                {
                    QByteArray location = reply->rawHeader("Location");

                    qDebug() << "Get submit url" << location;

                    item.submitUrl = location;
                    item.stage = 1;
                    item.chunkCounter = 0;

                    emit urlSet(item.path, item.submitUrl);

                    //qDebug() << "uploadFinished" << reply;
                    uploadHash[reply] = item;
                    uploadChunk(reply);
                }
                else
                {
                    qDebug() << "statusCode" << statusCode;
                }
            }
            else
            {
                //qDebug() << "uploadFinished" << "chunk" << reply;
                item.chunkCounter = item.chunkCounter + 1;
                uploadHash[reply] = item;
                uploadChunk(reply);
            }
        }
        else if (m_uploadProtocol == UploadInterface::ProtocolMultipart) {

        }
        else {
            qDebug() << "No one knows";
        }
    }

    reply->deleteLater();
}

void UploadPlugin::uploadError(QNetworkReply::NetworkError)
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    UploadItem item = uploadHash[reply];
    qDebug() << "uploadError: " << item.submitUrl << reply->errorString();

    emit status(item.path, "Error", reply->errorString(), item.submitUrl);
    emit progress(item.path, 0, 0, 0, 0, "bytes/sec");
}

void UploadPlugin::uploadSslErrors(QList<QSslError>)
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    reply->ignoreSslErrors();
}

void UploadPlugin::setBandwidthLimit(int size)
{
}

void UploadPlugin::addSocket(QIODevice *socket)
{
}

void UploadPlugin::removeSocket(QIODevice *socket)
{
}

void UploadPlugin::transfer()
{
}

void UploadPlugin::scheduleTransfer()
{
}

QString UploadPlugin::getStatus() const
{
    return "";
}
<commit_msg>Changes: modify debug messages<commit_after>#include "uploadplugin.h"

#include <QDebug>
#include <QFile>
#include <QUuid>
#include <QFileInfo>
#include <QTimer>
#include <QBuffer>

#include "json.h"
using QtJson::JsonObject;
using QtJson::JsonArray;

UploadPlugin::UploadPlugin(QObject * parent)
    : UploadInterface (parent)
{

}

Q_EXPORT_PLUGIN2(UploadPlugin, UploadPlugin)

UploadPlugin::~UploadPlugin()
{

}

QString UploadPlugin::name(void) const
{
    return "UploadPlugin";
}

QString UploadPlugin::version() const
{
    return "1.0";
}

void UploadPlugin::setDefaultParameters()
{
    m_uploadProtocol = UploadInterface::ProtocolTus;
    m_userAgent = "UploadPlugin/0.0.2";
    m_chunkSize = 50*1024;
    m_bandwidthLimit = 30*1024;
    m_queueSize = 2;
}

void UploadPlugin::append(const QString &file)
{
    QFileInfo fi(file);

    qDebug() << "upload append" << file;

    UploadItem item;
    item.key = fi.fileName();
    item.path = file;

    if (uploadQueue.isEmpty())
        QTimer::singleShot(0, this, SLOT(startNextUpload()));

    uploadQueue.enqueue(item);
}

void UploadPlugin::append(const QStringList &fileList)
{
    foreach (QString file, fileList){
        append(file);
    }

    if (uploadQueue.isEmpty())
        QTimer::singleShot(0, this, SIGNAL(finishedAll()));
}

void UploadPlugin::pause(const QString &url)
{
    stopUpload(url, true);
}

void UploadPlugin::pause(const QStringList &urlList)
{
    foreach (QString url, urlList){
        pause(url);
    }
}

void UploadPlugin::resume(const QString &url)
{
    append(url);
}

void UploadPlugin::resume(const QStringList & urlList)
{
    foreach (QString url, urlList){
        resume(url);
    }
}

void UploadPlugin::stop(const QString &url)
{
    stopUpload(url, false);
}

void UploadPlugin::stop(const QStringList &urlList)
{
    foreach (QString url, urlList){
        stop(url);
    }
}

void UploadPlugin::stopUpload(const QString &url, bool pause)
{

}

void UploadPlugin::connectSignals(QNetworkReply *reply)
{
    connect(reply, SIGNAL(uploadProgress(qint64,qint64)),
            this, SLOT(uploadProgress(qint64,qint64)));
    connect(reply, SIGNAL(finished()),
            this, SLOT(uploadFinished()));
    connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
            this, SLOT(uploadError(QNetworkReply::NetworkError)));
    connect(reply, SIGNAL(sslErrors(QList<QSslError>)),
            this, SLOT(uploadSslErrors(QList<QSslError>)));
}

void UploadPlugin::uploadChunk(QNetworkReply *reply)
{
    UploadItem item = uploadHash[reply];

    if (item.chunkCounter == 0) {
        item.time.start();
        item.start = 0;
        item.end = 0;
    }

    if (item.start < item.size)
    {
        item.end = item.start + m_chunkSize;
        if (item.end > item.size)
        {
            item.end = item.size;
        }

        qint64 size = item.end - item.start;
        item.sent = item.start;

        //qDebug() << item.start << item.end;

        QByteArray offset;
        offset.setNum(item.start);

        QByteArray length;
        length.setNum(item.end - item.start);

        uchar *buf = item.file->map(item.start, size);
        QBuffer * buffer = new QBuffer();
        buffer->setData(reinterpret_cast<const char*>(buf), size);
        buffer->close();

        QNetworkRequest request(QUrl(item.submitUrl));
        request.setRawHeader("User-Agent", m_userAgent);
        request.setRawHeader("Connection", "keep-alive");
        request.setRawHeader("Offset", offset);
        request.setRawHeader("Content-Length", length);
        request.setRawHeader("Content-Type", "application/offset+octet-stream");

        // remove previous reply
        uploadHash.remove(reply);

        QNetworkReply * reply = manager.sendCustomRequest(request, "PATCH", buffer);
        connectSignals(reply);

        item.file->unmap(buf);
        item.start += size;

        uploadHash[reply] = item;
        urlHash[item.path] = reply;
    }
    else
    {
        qDebug() << "DONE. Uploaded" << item.path << "to" << item.submitUrl;
        item.file->close();
        item.file->deleteLater();

        completedList.append(item);

        emit status(item.path, "Complete", "Upload file completed", item.submitUrl);
        emit finished(item.path, item.submitUrl);

        uploadHash.remove(reply);
        urlHash.remove(item.path);

        startNextUpload();
    }
}

void UploadPlugin::startNextUpload()
{
    if (uploadQueue.isEmpty()) {
        emit finishedAll();
        return;
    }

    if (uploadHash.size() < m_queueSize)
    {
        UploadItem item = uploadQueue.dequeue();

        if (m_uploadProtocol == UploadInterface::ProtocolTus) {

            item.file = new QFile(item.path);
            item.file->open(QIODevice::ReadOnly);
            item.size = item.file->size();
            //qDebug() << "size" << item.size;
            item.stage = 0;
            item.final = false;
            item.sent = 0;
            item.start = 0;

            QNetworkRequest request(m_uploadUrl);
            request.setRawHeader("User-Agent", m_userAgent);
            QByteArray fileLength;
            fileLength.setNum(item.size);
            request.setRawHeader("Final-Length", fileLength);
            QByteArray contentLength;
            contentLength.setNum(0);
            request.setRawHeader("Content-Length", contentLength);
            request.setRawHeader("Content-Type", "application/octet-stream");

            QNetworkReply * reply = manager.post(request, "");
            connectSignals(reply);

            emit status(item.path, "Register", "Start registering file", m_uploadUrl.toString());

            uploadHash[reply] = item;
            urlHash[item.path] = reply;

        }
        else if (m_uploadProtocol == UploadInterface::ProtocolMultipart) {

            QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);

            item.file = new QFile(item.path);
            item.file->open(QIODevice::ReadOnly);
            item.stage = 0;

            QHttpPart imagePart;
            imagePart.setHeader(QNetworkRequest::ContentDispositionHeader,
                                QVariant("form-data; name=\"document\"; filename=\""+ item.key +"\""));
            imagePart.setBodyDevice(item.file);
            item.file->setParent(multiPart);
            multiPart->append(imagePart);

            QNetworkRequest request(m_uploadUrl);
            request.setRawHeader("User-Agent", m_userAgent);

            QNetworkReply * reply = manager.post(request, multiPart);
            multiPart->setParent(reply);

            item.time.start();
            uploadHash[reply] = item;
            urlHash[item.path] = reply;
        }
        else
        {
            qDebug() << m_uploadProtocol;
            qDebug() << "No one knows";
        }

        startNextUpload();
    }
}

void UploadPlugin::uploadProgress(qint64 bytesSent, qint64 bytesTotal)
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    UploadItem item = uploadHash[reply];
    qint64 actualSent = item.sent + bytesSent;
    double speed = actualSent * 1000.0 / item.time.elapsed();
    QString unit;
    if (speed < 1024) {
        unit = "bytes/sec";
    } else if (speed < 1024*1024) {
        speed /= 1024;
        unit = "kB/s";
    } else {
        speed /= 1024*1024;
        unit = "MB/s";
    }
    int percent = actualSent * 100 / item.size;

    if (item.stage > 0) {
        //qDebug() << "upload" << item.path << actualSent << item.size << percent << speed << unit;
        emit progress(item.path, actualSent, item.size, percent, speed, unit);
    }
}

void UploadPlugin::uploadFinished()
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    UploadItem item = uploadHash[reply];
    int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    QByteArray customVerb = reply->request().attribute(QNetworkRequest::CustomVerbAttribute).toByteArray();

    //qDebug() << statusCode << customVerb;

    if(reply->error() == QNetworkReply::NoError)
    {
        if (m_uploadProtocol == UploadInterface::ProtocolTus)
        {
            if (item.stage == 0)
            {
                if (statusCode == 201)
                {
                    QByteArray location = reply->rawHeader("Location");

                    qDebug() << "Get submit url" << location;

                    item.submitUrl = location;
                    item.stage = 1;
                    item.chunkCounter = 0;

                    emit urlSet(item.path, item.submitUrl);

                    //qDebug() << "uploadFinished" << reply;
                    uploadHash[reply] = item;
                    uploadChunk(reply);
                }
                else
                {
                    qDebug() << "statusCode" << statusCode;
                }
            }
            else
            {
                //qDebug() << "uploadFinished" << "chunk" << reply;
                item.chunkCounter = item.chunkCounter + 1;
                uploadHash[reply] = item;
                uploadChunk(reply);
            }
        }
        else if (m_uploadProtocol == UploadInterface::ProtocolMultipart) {

        }
        else {
            qDebug() << "No one knows";
        }
    }

    reply->deleteLater();
}

void UploadPlugin::uploadError(QNetworkReply::NetworkError)
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    UploadItem item = uploadHash[reply];
    qDebug() << "uploadError: " << item.submitUrl << reply->errorString();

    emit status(item.path, "Error", reply->errorString(), item.submitUrl);
    emit progress(item.path, 0, 0, 0, 0, "bytes/sec");
}

void UploadPlugin::uploadSslErrors(QList<QSslError>)
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    reply->ignoreSslErrors();
}

void UploadPlugin::setBandwidthLimit(int size)
{
}

void UploadPlugin::addSocket(QIODevice *socket)
{
}

void UploadPlugin::removeSocket(QIODevice *socket)
{
}

void UploadPlugin::transfer()
{
}

void UploadPlugin::scheduleTransfer()
{
}

QString UploadPlugin::getStatus() const
{
    return "";
}
<|endoftext|>