text: ////////////////////////////////////////////////////////////////////////
  // Copyright (c) 2010-2015, University of Washington and Battelle
  // Memorial Institute.  All rights reserved.
  //
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions
  // are met:
  //     * Redistributions of source code must retain the above
  //       copyright notice, this list of conditions and the following
  //       disclaimer.
  //     * Redistributions in binary form must reproduce the above
  //       copyright notice, this list of conditions and the following
  //       disclaimer in the documentation and/or other materials
  //       provided with the distribution.
  //     * Neither the name of the University of Washington, Battelle
  //       Memorial Institute, or the names of their contributors may be
  //       used to endorse or promote products derived from this
  //       software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  // UNIVERSITY OF WASHINGTON OR BATTELLE MEMORIAL INSTITUTE BE LIABLE
  // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  // OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  // DAMAGE.
  ////////////////////////////////////////////////////////////////////////
  // Energy. The Government has certain rights in the software.
  
  #pragma once
  
  #include "FullEmptyLocal.hpp"
  #include "Delegate.hpp"
  
  namespace Grappa {
    
    /// @addtogroup Synchronization
    /// @{
    
    template< typename T >
    void fill_remote(GlobalAddress<FullEmpty<T>> result_addr, const T& val) {
      send_heap_message(result_addr.core(), [result_addr,val]{
        result_addr->writeXF(val);
      });
    }
  
    /// Remote version of readFF method. Suspend until FullEmpty is full, and then return its contents, leaving it full. @see FullEmpty::readFF
    template< typename T >
    T readFF(GlobalAddress<FullEmpty<T>> fe_addr) {
      if (fe_addr.core() == mycore()) {
        DVLOG(2) << "local";
        return fe_addr.pointer()->readFF();
      }
      
      FullEmpty<T> result;
      auto result_addr = make_global(&result);
      
      send_message(fe_addr.core(), [fe_addr,result_addr]{
        auto& fe = *fe_addr.pointer();
        
        if (fe.full()) {
          // DVLOG(2) << "no need to block";
          fill_remote(result_addr, fe.readFF());
          return;
        }
        
        DVLOG(2) << "setting up to block (" << fe_addr << ")";
        auto* c = SuspendedDelegate::create([&fe,result_addr]{
          VLOG(0) << "suspended_delegate!";
          fill_remote(result_addr, fe.readFF());
        });
        add_waiter(&fe, c);
      });
      
      return result.readFF();
    }
  
    /// Remote, blocking version of writeXF method. Writes data to FullEmpty no matter what its current state, leaving it full. Existing contents are overwritten. @see FullEmpty::writeXF
    template< typename T, typename U >
    void writeXF(GlobalAddress<FullEmpty<T>> fe_addr, const U& val) {
      delegate::call(fe_addr, [val](FullEmpty<T> * fe){
        fe->writeXF(val);
        // DVLOG(2) << "writeXF(" << make_global(fe) << ", " << val << ") done";
      });
    }
    
    /// @}
  }
  