MezzanineEngine 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
doublebufferedresource.h
Go to the documentation of this file.
1 // The DAGFrameScheduler is a Multi-Threaded lock free and wait free scheduling library.
2 // © Copyright 2010 - 2014 BlackTopp Studios Inc.
3 /* This file is part of The DAGFrameScheduler.
4 
5  The DAGFrameScheduler is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  The DAGFrameScheduler is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with The DAGFrameScheduler. If not, see <http://www.gnu.org/licenses/>.
17 */
18 /* The original authors have included a copy of the license specified above in the
19  'doc' folder. See 'gpl.txt'
20 */
21 /* We welcome the use of the DAGFrameScheduler to anyone, including companies who wish to
22  Build professional software and charge for their product.
23 
24  However there are some practical restrictions, so if your project involves
25  any of the following you should contact us and we will try to work something
26  out:
27  - DRM or Copy Protection of any kind(except Copyrights)
28  - Software Patents You Do Not Wish to Freely License
29  - Any Kind of Linking to Non-GPL licensed Works
30  - Are Currently In Violation of Another Copyright Holder's GPL License
31  - If You want to change our code and not add a few hundred MB of stuff to
32  your distribution
33 
34  These and other limitations could cause serious legal problems if you ignore
35  them, so it is best to simply contact us or the Free Software Foundation, if
36  you have any questions.
37 
38  Joseph Toppi - toppij@gmail.com
39  John Blackwood - makoenergy02@gmail.com
40 */
41 #ifndef _doublebufferedresource_h
42 #define _doublebufferedresource_h
43 
44 #include "datatypes.h"
45 
46 /// @file
47 /// @brief This file defines the template double buffered resources that can be attached to a thread.
48 
49 namespace Mezzanine
50 {
51  namespace Threading
52  {
53 #ifndef SWIG
54  /// @brief Double buffered resources are identified by a @ref Whole which is their type ID, This number identifies an invalid entry.
55  const static Whole DBRInvalid = 10000000;
56 
57  /// @brief Double buffered resources are identified by a @ref Whole which is their type ID, This number identifies logging.
58  const static Whole DBRLogger = 0;
59 
60  /// @brief Double buffered resources are identified by a @ref Whole which is their type ID, All System Type IDs will be less than this amount.
61  /// @note Do not use the value of this directly, it is subject to change. In code using this, use: @code const static whole FreshDBRType = BDRUser+YourValue; @endcode
62  const static Whole DBRUser = 1;
63 #endif
64  /// @brief A thread specific resource that uses double buffering to avoid multithreaded synchronization mechanisms.
65  /// @details It is intended for a Mezzanine::Threading::iWorkUnit "iWorkUnit" like the to provide asynchronous
66  /// access to resources that to not need immediate atomicity. For example, it is ok if logs are gathered asynchronously
67  /// and aggregated later as long no log messages are damaged, lost or taken out of order. This allows IO and other potentially
68  /// expensive tasks to be used without blocking the current thread.
69  template<typename T>
71  {
72  private:
73  /// @brief One of the resources to be buffered
74  T* ResourceA;
75 
76  /// @brief The other of the resources to be buffered
77  T* ResourceB;
78 
79  public:
80  /// @brief A Constructor that creates default versions of the resources.
81  /// @details This calls the default constructors for type T.
82  DoubleBufferedResource() : ResourceA(0), ResourceB(0)
83  {
84  try
85  {
86  ResourceA = new T;
87  ResourceB = new T;
88  }catch(std::exception& e){
89  if (ResourceA)
90  { delete ResourceA; ResourceA=0; }
91  if (ResourceB)
92  { delete ResourceB; ResourceB=0; }
93  throw e;
94  }
95 
96  }
97 
98  /// @brief A constructor that takes ownership of the the resources passed.
99  /// @param Current This will be used as the first resource for threads to use.
100  /// @param Buffer This will wait for the other thread
101  DoubleBufferedResource(T* Current, T* Buffer) : ResourceA(Current), ResourceB(Buffer)
102  {}
103 
104  /// @brief Make the buffered resource the active and vice versa.
106  { std::swap(ResourceA,ResourceB); }
107 
108  /// @brief Get a pointer to the resource that can be used
109  /// @return A pointer to the usable resource
110  T* GetUsablePointer() const
111  { return ResourceA; }
112 
113  /// @brief Get a pointer to the resource that can be committed.
114  /// @return A pointer to the commitable resource
116  { return ResourceB; }
117 
118  /// @brief Get a reference to the resource that can be used
119  /// @return A reference to the usable resource
121  { return *ResourceA; }
122 
123  /// @brief Get a reference to the resource that can be committed.
124  /// @return A reference to the commitable resource
126  { return *ResourceB; }
127 
128  /// @brief Destructor, this deletes both the resources managed. Regardless of how it got a hold of the pointers.
130  {
131  delete ResourceA;
132  delete ResourceB;
133  }
134  };//DoubleBufferedResource
135 
136 
137  /// @brief A better default name for the Default Logger instance.
139 
140  // forward declarations
141  class FrameScheduler;
142 
143  /// @brief A thread specific collection of double-buffered and algorithm specific resources.
144  /// @details This class is intended to be expanded via derived classes if it is to return extra resource types
146  {
147  private:
148  /// @brief Stores the pounters to the thread local resources.
149  std::vector<ConvertiblePointer> ThreadResources;
150 
151  /// @brief A pointer to the FrameScheduler that this belongs to.
152  FrameScheduler* Scheduler;
153 
154  public:
155  /// @brief A constructor that automatically creates the resources it supports
157  Scheduler(Scheduler_)
158  {
159  this->ThreadResources.push_back((ConvertiblePointer)new DoubleBufferedLogger); // must comes first so it lands in spot 0
160  }
161 
162  /// @brief Get a Specific kind of double buffered resource.
163  /// @param ResourceID The ID the resource provided.
164  /// @return A reference to the resource if it exists, or undefined behavior and maybe an exception if it doesn't.
165  template <typename DBR>
166  DBR& GetResource(const Whole& ResourceID)
167  { return *((DBR*)(this->ThreadResources[ResourceID])); }
168 
169  /// @brief Get the usable logger for this thread specific resource
170  /// @return A reference to the logger.
171  /// @note A function like this should be provided for any other resources added to derived versions of this class. This encourages getting resources for this thread, and not providing a method to get the commitable resource gently discourages doing it unless its really required.
173  { return GetResource<DoubleBufferedLogger>(DBRLogger).GetUsable(); }
174 
175  /// @brief Get a pointer to the FrameScheduler that owns this resource.
176  /// @details This is not required very often by application code, but is used
177  /// in places in this scheduler library. This is primarily used to gain access
178  /// to commitable parts of double buffered resources. This pointer does not
179  /// confer ownership.
180  /// @return A pointer to the FrameScheduler that owns this resource.
182  { return Scheduler; }
183 
184  /// @brief The commitable and usable version of every double buffered resource for this thread specific storage will be swapped.
186  { GetResource<DoubleBufferedLogger>(DBRLogger).SwapUsableAndCommitable(); }
187 
188  /// @brief Deletes all the resources.
190  {
191  delete (DoubleBufferedLogger*)this->ThreadResources[DBRLogger]; // Items must wind up in the correct spot in the vector for this to work. Be careful to get the order right if you overload this.
192  }
193 
194  };//ThreadSpecificStorage
195 
196  /// @brief Use this to change the default resource type.
197  /// @details use "DefaultThreadSpecificStorage::Type" as Type to instantiate an instance of whatever type this is.
199  {
200  /// @brief A single point at which all the thread specific resources can be changed.
202  };//DefaultThreadSpecificStorage
203  }//Threading
204 }//Mezzanine
205 
206 #endif