home *** CD-ROM | disk | FTP | other *** search
/ Hackers Magazine 57 / CdHackersMagazineNr57.iso / Software / Multimedia / k3d-setup-0.7.11.0.exe / include / k3d / k3dsdk / pointer_demand_storage.h < prev    next >
Encoding:
C/C++ Source or Header  |  2008-11-07  |  4.3 KB  |  156 lines

  1. #ifndef K3DSDK_POINTER_DEMAND_STORAGE_H
  2. #define K3DSDK_POINTER_DEMAND_STORAGE_H
  3.  
  4. // K-3D
  5. // Copyright (c) 1995-2008, Timothy M. Shead
  6. //
  7. // Contact: tshead@k-3d.com
  8. //
  9. // This program is free software; you can redistribute it and/or
  10. // modify it under the terms of the GNU General Public
  11. // License as published by the Free Software Foundation; either
  12. // version 2 of the License, or (at your option) any later version.
  13. //
  14. // This program is distributed in the hope that it will be useful,
  15. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17. // General Public License for more details.
  18. //
  19. // You should have received a copy of the GNU General Public
  20. // License along with this program; if not, write to the Free Software
  21. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  22.  
  23. #include "ihint.h"
  24. #include "signal_system.h"
  25. #include "utility.h"
  26.  
  27. #include <boost/scoped_ptr.hpp>
  28. #include <boost/static_assert.hpp>
  29. #include <boost/type_traits.hpp>
  30.  
  31. #include <algorithm>
  32. #include <vector>
  33.  
  34. namespace k3d
  35. {
  36.  
  37. namespace data
  38. {
  39.  
  40. /////////////////////////////////////////////////////////////////////////////
  41. // pointer_demand_storage
  42.  
  43. /// Read-only storage policy that stores a value by pointer, created on-demand
  44. template<typename pointer_t, typename signal_policy_t>
  45. class pointer_demand_storage :
  46.     public signal_policy_t
  47. {
  48.     // This policy only works for data stored by-pointer
  49.     BOOST_STATIC_ASSERT((boost::is_pointer<pointer_t>::value));
  50.  
  51. public:
  52.     typedef typename boost::remove_pointer<pointer_t>::type non_pointer_t;
  53.     typedef pointer_demand_storage<pointer_t, signal_policy_t> this_t;
  54.     typedef std::vector<ihint*> pending_hints_t;
  55.  
  56.     /// Set the slot that will be called to bring the underlying data up-to-date
  57.     void set_update_slot(const sigc::slot<void, const pending_hints_t&, non_pointer_t&>& Slot)
  58.     {
  59.         m_update_slot = Slot;
  60.         update();
  61.     }
  62.  
  63.     /// Returns a slot that will invoke the update() method
  64.     sigc::slot<void, ihint*> make_slot()
  65.     {
  66.         return sigc::mem_fun(*this, &this_t::update);
  67.     }
  68.  
  69.     /// Store an object as the new value, taking control of its lifetime
  70.     void reset(pointer_t NewValue = 0, ihint* const Hint = 0)
  71.     {
  72.         // Prevent updates while we're executing ...
  73.         if(m_executing)
  74.             return;
  75.  
  76.         if(NewValue)
  77.         {
  78.             // If the new value is non-NULL, cancel any pending updates ...
  79.             std::for_each(m_pending_hints.begin(), m_pending_hints.end(), delete_object());
  80.             m_pending_hints.clear();
  81.         }
  82.         else
  83.         {
  84.             // Otherwise, ensure that we execute next time we're called ...
  85.             m_pending_hints.push_back(Hint ? Hint->clone() : static_cast<ihint*>(0));
  86.         }
  87.  
  88.         m_value.reset(NewValue);
  89.         signal_policy_t::set_value(Hint);
  90.     }
  91.  
  92.     /// Schedule an update for the value the next time it's read
  93.     void update(ihint* const Hint = 0)
  94.     {
  95.         // Prevent updates while we're executing ...
  96.         if(m_executing)
  97.             return;
  98.  
  99.         m_pending_hints.push_back(Hint ? Hint->clone() : static_cast<ihint*>(0));
  100.         signal_policy_t::set_value(Hint);
  101.     }
  102.  
  103.     /// Accesses the underlying value, creating it if it doesn't already exist
  104.     pointer_t internal_value()
  105.     {
  106.         if(!m_value.get())
  107.             m_value.reset(new non_pointer_t());
  108.  
  109.         if(!m_pending_hints.empty())
  110.         {
  111.             m_executing = true;
  112.  
  113.             // Create a temporary copy of pending hints in-case we are updated while executing ...
  114.             const pending_hints_t pending_hints(m_pending_hints);
  115.             m_update_slot(pending_hints, *m_value);
  116.             
  117.             std::for_each(m_pending_hints.begin(), m_pending_hints.end(), delete_object());
  118.             m_pending_hints.clear();
  119.  
  120.             m_executing = false;
  121.         }
  122.  
  123.         return m_value.get();
  124.     }
  125.  
  126. protected:
  127.     template<typename init_t>
  128.     pointer_demand_storage(const init_t& Init) :
  129.         signal_policy_t(Init),
  130.         m_executing(false)
  131.     {
  132.     }
  133.  
  134.     ~pointer_demand_storage()
  135.     {
  136.         std::for_each(m_pending_hints.begin(), m_pending_hints.end(), delete_object());
  137.     }
  138.  
  139. private:
  140.     /// Storage for this policy's value
  141.     boost::scoped_ptr<non_pointer_t> m_value;
  142.     /// Stores a slot that will be called to bring this policy's value up-to-date
  143.     sigc::slot<void, const pending_hints_t&, non_pointer_t&> m_update_slot;
  144.     /// Stores a collection of pending hints to be updated
  145.     pending_hints_t m_pending_hints;
  146.     /// Used to prevent problems with recursion while executing
  147.     bool_t m_executing;
  148. };
  149.  
  150. } // namespace data
  151.  
  152. } // namespace k3d
  153.  
  154. #endif // !K3DSDK_POINTER_DEMAND_STORAGE_H
  155.  
  156.