/*
 * Copyright Staffan Gimåker 2007-2010.
 *
 * ---
 *
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or copy at
 * http://www.boost.org/LICENSE_1_0.txt)
 */

#ifndef PEEKABOT_CLIENT_OPERATION_RESULT_HH_INCLUDED
#define PEEKABOT_CLIENT_OPERATION_RESULT_HH_INCLUDED


#include <stdexcept>
#include <boost/thread/mutex.hpp>

#include "../Any.hh"
#include "OperationStatus.hh"
#include "../Visibility.hh"


namespace peekabot
{
    namespace client
    {
        /**
         * \internal
         *
         * \brief Provides internal storage for and interaction with results.
         *
         *
         * All methods lock the OperationResult but functionality inherited 
         * from OperationStatus can still be used simultaneously.
         *
         * \sa Result, OperationStatus
         */
        class OperationResult : public OperationStatus
        {
        public:
            OperationResult();

            virtual ~OperationResult();

            /**
             * \brief Set the result data contained in the object.
             *
             * \pre In order to ensure correct behaviour,
             * Status::set_outcome(OperationOutcome, const std::string &)
             * must not have been called prior to calling this method.
             *
             * \param result The result of the operation.
             */
            void set_result(const Any &result);

            /**
             * \brief Return a copy of the stored result.
             *
             * \pre get_outcome() == OPERATION_SUCCEEDED, otherwise an
             * exception will be thrown.
             *
             * \throw std::logic_error Thrown if 1) the operation failed or 2)
             * the outcome operation is still pending.
             */
            PEEKABOT_API Any get_result() const;


        private:
            /**
             * \brief Governs \e all (read and write) access to \e any member.
             */
            mutable boost::mutex m_result_mutex;

            /**
             * \brief The result data.
             */
            Any m_result;

            /**
             * \brief Set to \c true when the result data member (m_result) has
             * been set. Used for error checking purposes only.
             */
            bool m_result_is_set;
        };
    }
}


#endif // PEEKABOT_CLIENT_OPERATION_RESULT_HH_INCLUDED
