//
// Copyright (C) 2000, 2001 GRACE development team  <grace@msu.ru>
//
// GRACE is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// GRACE 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with GRACE; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// $Source: /usr/local/cvs/grace/src/gr_tval.hh,v $
// $Revision: 1.19 $
// $Date: 2001/05/22 11:08:55 $

#ifndef __gr_tval_hh__
#define __gr_tval_hh__

#include "gr_continuation.hh"
#include "gr_shared_allocator.hh"
#include "pxx_spinlock.hh"

namespace grace
{

//------------------------------------------------------------------------------
//! T-values flags
//------------------------------------------------------------------------------
#define GR_TVAL_READY     (unsigned(0x0001))
#define GR_TVAL_LAZY      (unsigned(0x0002))
#define GR_TVAL_TOUCHED   (unsigned(0x0004))

template <typename val_t> class T_Ptr ;

//------------------------------------------------------------------------------
//! T-value template
//------------------------------------------------------------------------------
//! \todo Implement lazy semantic
//! \todo Add copy ctor
/*! \todo For memory saving reasons flags should be packed into lower bits of
 *        continuation pointer */

template <typename val_t>
class T_Val :
  public pxx::Spinlock
{

private:

  //
  //! Pointer to a continuation
  mutable ContinuationBase* cont ;
  //
  //! Flags
  unsigned flags ;
  //
  //! We have either a real value or pointer to another t-val
  union
  {
    //
    //! Pointer to result
    T_Val<val_t> const* res ;
    //
    // FIXME: Really here must be an object of type val_t, but due to union
    // limitations in C++ we can not do this :-(((
    //! Real object value
    mutable char value[sizeof(val_t)] ;
  };

public:

  //
  //! Default constructor
  inline T_Val (bool _lazy = false) ;
  //
  //! Constructor from a real value
  inline T_Val (val_t const& _value, bool _lazy = false) ;
  //
  //! Constructor from a pointer to continuation
  inline T_Val (ContinuationBase* _cont, bool _lazy = false) ;
  //
  //! Destructor
  inline ~T_Val () ;
  //
  //! Assignment from a real value
  inline T_Val& operator = (val_t const& _value) ;
  //
  //! Assignment from another t-val
  T_Val& operator = (T_Val const& _value) ;
  //
  //! Return (probably waiting when it becomes ready) an object value
  operator val_t const& () ;
  //
  //! Returns an object value  value (const variant)
  inline operator val_t const& () const ;
  //
  //! Returns a value (alias to operator val_t const& ())
  inline val_t const& get_value () ;
  //
  //! Returns a value (alias to operator val_t const& () const)
  inline val_t const& get_value () const ;
  //
  //! Returns a reference to contained object
  inline val_t& get_ref () ;
  //
  //! Returns a reference to contained object
  inline val_t& _get_ref () ;
  //
  //! Returns a pointer to continuation bound to t-val
  inline ContinuationBase* get_continuation () const;
  //
  //! Set a pointer to continuation bound to t-val
  inline void set_continuation (ContinuationBase* _cont) ;
  //
  //! Check if a value is ready
  inline bool is_ready () const ;
  //
  //! Make a value ready if it is touched
  inline bool validate () ;
  //
  //! Bind a continuation to t-val
  inline void bind (ContinuationBase* _cont) ;
  //
  //! Maybe drop a reference to continuation
  inline void unlink () const ;
  //
  //! Get t-val flags
  inline unsigned& get_flags () ;
  //
  //! Overloaded operator new
  OVERLOAD_NEW
  //
  //! Overloaded operator delete
  OVERLOAD_DELETE

private:

  //
  //! Check if a value is ready (not synchronized)
  inline bool _is_ready () const ;

};

}

#endif // __gr_tval_hh__