Orocos Real-Time Toolkit  2.5.0
TsPool.hpp
00001 /***************************************************************************
00002   tag: The SourceWorks  Tue Sep 7 00:55:18 CEST 2010  TsPool.hpp
00003 
00004                         TsPool.hpp -  description
00005                            -------------------
00006     begin                : Tue September 07 2010
00007     copyright            : (C) 2010 The SourceWorks
00008     email                : peter@thesourceworks.com
00009 
00010  ***************************************************************************
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU General Public                   *
00013  *   License as published by the Free Software Foundation;                 *
00014  *   version 2 of the License.                                             *
00015  *                                                                         *
00016  *   As a special exception, you may use this file as part of a free       *
00017  *   software library without restriction.  Specifically, if other files   *
00018  *   instantiate templates or use macros or inline functions from this     *
00019  *   file, or you compile this file and link it with other files to        *
00020  *   produce an executable, this file does not by itself cause the         *
00021  *   resulting executable to be covered by the GNU General Public          *
00022  *   License.  This exception does not however invalidate any other        *
00023  *   reasons why the executable file might be covered by the GNU General   *
00024  *   Public License.                                                       *
00025  *                                                                         *
00026  *   This library is distributed in the hope that it will be useful,       *
00027  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00028  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00029  *   Lesser General Public License for more details.                       *
00030  *                                                                         *
00031  *   You should have received a copy of the GNU General Public             *
00032  *   License along with this library; if not, write to the Free Software   *
00033  *   Foundation, Inc., 59 Temple Place,                                    *
00034  *   Suite 330, Boston, MA  02111-1307  USA                                *
00035  *                                                                         *
00036  ***************************************************************************/
00037 
00038 
00039 /*
00040  * TsPool.hpp
00041  *
00042  *  Created on: Jul 10, 2010
00043  *      Author: Butch Slayer
00044  */
00045 
00046 #ifndef RTT_TSPOOL_HPP_
00047 #define RTT_TSPOOL_HPP_
00048 
00049 #include "../os/CAS.hpp"
00050 #include <assert.h>
00051 
00052 namespace RTT
00053 {
00054     namespace internal
00055     {
00056 
00061         template<typename T>
00062         class TsPool
00063         {
00064         public:
00065             typedef T value_t;
00066         private:
00067             union Pointer_t
00068             {
00069                 unsigned int value;
00070                 struct _ptr_type
00071                 {
00072                     unsigned short tag;
00073                     unsigned short index;
00074                 } ptr;
00075             };
00076 
00082             struct Item
00083             {
00084                 value_t value;
00085                 volatile Pointer_t next;
00086 
00087                 Item() :
00088                     value(value_t())
00089                 {
00090                     next.value = 0;
00091                 }
00092             };
00093 
00094             Item* pool;
00095             Item head;
00096 
00097             unsigned int pool_size, pool_capacity;
00098         public:
00099 
00100             typedef unsigned int size_type;
00105             TsPool(unsigned int ssize, const T& sample = T()) :
00106                 pool_size(0), pool_capacity(ssize)
00107             {
00108                 pool = new Item[ssize];
00109                 data_sample( sample );
00110             }
00111 
00112             ~TsPool()
00113             {
00114 #ifndef NDEBUG
00115                 /*Check pool consistency.*/
00116                 unsigned int i = 0, endseen = 0;
00117                 for (; i < pool_capacity; i++)
00118                 {
00119                     if (pool[i].next.ptr.index == (unsigned short) -1)
00120                     {
00121                         ++endseen;
00122                     }
00123                 }
00124                 assert( endseen == 1);
00125                 assert( size() == pool_capacity && "TsPool: not all pieces were deallocated !" );
00126 #endif
00127                 delete[] pool;
00128             }
00129 
00137             void clear()
00138             {
00139                 for (unsigned int i = 0; i < pool_capacity; i++)
00140                 {
00141                     pool[i].next.ptr.index = i + 1;
00142                 }
00143                 pool[pool_capacity - 1].next.ptr.index = (unsigned short) -1;
00144                 head.next.ptr.index = 0;
00145             }
00146 
00153             void data_sample(const T& sample) {
00154                 for (unsigned int i = 0; i < pool_capacity; i++)
00155                     pool[i].value = sample;
00156                 clear();
00157             }
00158 
00159             value_t* allocate()
00160             {
00161                 volatile Pointer_t oldval;
00162                 volatile Pointer_t newval;
00163                 Item* item;
00164                 do
00165                 {
00166                     oldval.value = head.next.value;
00167                     //List empty?
00168                     if (oldval.ptr.index == (unsigned short) -1)
00169                     {
00170                         return 0;
00171                     }
00172                     item = &pool[oldval.ptr.index];
00173                     newval.ptr.index = item->next.ptr.index;
00174                     newval.ptr.tag = oldval.ptr.tag + 1;
00175                 } while (!os::CAS(&head.next.value, oldval.value, newval.value));
00176                 return &item->value;
00177             }
00178 
00179             bool deallocate(T* Value)
00180             {
00181                 if (Value == 0)
00182                 {
00183                     return false;
00184                 }
00185                 assert(Value >= (T*) &pool[0] && Value <= (T*) &pool[pool_capacity]);
00186                 volatile Pointer_t oldval;
00187                 Pointer_t head_next;
00188                 Item* item = reinterpret_cast<Item*> (Value);
00189                 do
00190                 {
00191                     oldval.value = head.next.value;
00192                     item->next.value = oldval.value;
00193                     head_next.ptr.index = (item - pool);
00194                     head_next.ptr.tag = oldval.ptr.tag + 1;
00195                 } while (!os::CAS(&head.next.value, oldval.value, head_next.value));
00196                 return true;
00197             }
00198 
00205             unsigned int size()
00206             {
00207                 unsigned int ret = 0;
00208                 volatile Item* oldval;
00209                 oldval = &head;
00210                 while ( oldval->next.ptr.index != (unsigned short) -1) {
00211                     ++ret;
00212                     oldval = &pool[oldval->next.ptr.index];
00213                     assert(ret <= pool_capacity); // abort on corruption due to concurrency.
00214                 }
00215                 return ret;
00216             }
00217 
00222             unsigned int capacity()
00223             {
00224                 return pool_capacity;
00225             }
00226 
00227         private:
00228 
00229         };
00230     }
00231 }
00232 
00233 #endif /* RTT_TSPOOL_HPP_ */