gatelib  2.1
g_cont_lst_priv.h
1 #pragma once
2 
3 #include "g_cont_cont_with_positioner.h"
4 #include "g_cont_vect.h"
5 #include "g_cont_common.h"
6 #include "g_cont_AllocationPolicyAbstract.h"
7 #include "g_cont_private_data_pointer.h"
8 
9 #ifndef NULL
10 #define NULL 0
11 #endif
12 
13 #define LIST_ALLOCATOR_DELTA 16
14 namespace g
15 {
16 namespace cont
17 {
18 namespace priv
19 {
20 #if G_AUTOPTION_ON_GCC
21 # pragma GCC diagnostic push
22 # pragma GCC diagnostic ignored "-Wstrict-aliasing"
23 #endif
24 
25 template < class T > struct list_node
26 {
27  bool isNodeBusy () const{ return currentIndex >= 0; }
28 
29  void release ( )
30  {
31  currentIndex = G_CONT_INDEX_NOT_VALID;
32  }
33 
34  int prevIndex;
35  int nextIndex;
36  int currentIndex;
37 
38  void setContent ( const T& aT )
39  {
40  new(reinterpret_cast<T*>(mContBuff))T(aT);
41  }
42 
43  operator const T& ( ) const { return *(reinterpret_cast<const T*>( mContBuff )); }
44  operator T& ( ) { return *(reinterpret_cast<T*>( mContBuff )); }
45 
46  void callContentDestructor ( )
47  {
48  ( reinterpret_cast<T*> ( mContBuff ) )->~T();
49  }
50 
51  // Trick for obtain list_node address from the (TRUE item )
52  static list_node* nodeFromItem ( const T* aItemIndex )
53  {
54  static list_node* dummy = 0;
55  static size_t delta = ( size_t )&dummy->mContBuff;
56 
57  return ( list_node* ) ( ( char* )aItemIndex - delta );
58  }
59 
61  {
62  public:
63  typedef list_node Node_t;
65 
66  data_instanciable():mSize(0){}
67 
69  {
70  if ( mSize > 0 )
71  {
72  ( reinterpret_cast<ListNodesDataPointer_t*> (mData) )->~ListNodesDataPointer_t();
73  }
74  }
75 
76  operator Node_t* ( ) { return (Node_t*)*( reinterpret_cast<ListNodesDataPointer_t*> (mData) ); }
77 
78  operator ListNodesDataPointer_t& ( ) { return *( reinterpret_cast<ListNodesDataPointer_t*> (mData) ); }
79  operator const ListNodesDataPointer_t& ( ) { return *( reinterpret_cast<const ListNodesDataPointer_t*> (mData) ); }
80 
81  void instanciate ( AllocationPolicyAbstract* aAllocPolicyP , size_t size )
82  {
83  ListNodesDataPointer_t* data_p = new (mData) ListNodesDataPointer_t ( aAllocPolicyP );
84 
85  data_p->allocate ( mSize = size , 0 );
86 
87  //set the page to not valid
88  for ( size_t i = 0 ; i < mSize ; i++ )
89  {
90  ( *data_p )[i].currentIndex = G_CONT_INDEX_NOT_VALID;
91  }
92  }
93 
94  size_t getSize ( ) const { return mSize; }
95 
96  private:
97  char mData[sizeof(priv::data_pointer<Node_t>)];
98  size_t mSize;
99  };
100 
101 private:
102  char mContBuff[sizeof(T)];
103 };
104 
105 
106 template < class T > class list_node_page
107 {
108 #define G_LOCAL_CLASS "list_node_page<T>::"
109 
110 public:
111  list_node_page ( const list_node_page& )
112  {
113  G_EXC_SET_CONTEXT ( G_LOCAL_CLASS "::list_node_page(const list_node_page& o )" );
114 
115  G_EXC_FATAL_ACTION ("Prohibited copy constructor declared for compatibility only!");
116  }
117 
119  typedef list_node<T> Node_t;
120 
121  list_node_page() : numUsed(0),firstFreeNodeIndex(0) { }
122 
123  typename Node_t::data_instanciable nodes;
124 
125  Node_t* getFreeNodeAndMakeBusy ( )
126  {
127  G_EXC_SET_CONTEXT ( "Node_t* " G_LOCAL_CLASS "::getFreeNodeAndMakeBusy ( )" );
128 
129  int pos_out = firstFreeNodeIndex;
130 
131  //if all nodes are used
132  if ( ++numUsed < nodes.getSize() )
133  {
134  for ( int i = firstFreeNodeIndex + 1 ; i < (int)nodes.getSize() ; i++ )
135  {
136  if ( !nodes[i].isNodeBusy ( ) )
137  {
138  firstFreeNodeIndex = i;
139  goto out;
140  }
141  }
142 
143  G_EXC_FATAL_ACTION ( "First free index is not reassigned but the page is not full!" );
144  }
145  else
146  {
147  firstFreeNodeIndex = (int)nodes.getSize();
148  }
149 
150 out:
151  nodes[pos_out].currentIndex = pos_out;
152 
153  return (Node_t*)nodes + pos_out;
154  }
155 
156  //releases the node and update firstFreeNodeIndex
157  void releaseNodeUpdateFirstFree ( int aPageNodeIndex )
158  {
159  nodes[aPageNodeIndex].release ( );
160  numUsed--;
161 
162  if ( aPageNodeIndex < firstFreeNodeIndex )
163  {
164  firstFreeNodeIndex = aPageNodeIndex;
165  }
166  }
167 
168  size_t numUsed;
169  int firstFreeNodeIndex;
170 
171  int isPageBusy () const { return numUsed >= nodes.getSize(); }
172 #undef G_LOCAL_CLASS
173 };
174 
175 template < class T > class list_content
176 {
177 public:
178  typedef typename list_node_page<T>::Vect_t PageVector_t;
179  typedef list_node<T> Node_t;
180 
181  list_content (
182  AllocationPolicyAbstract* aAllocPolicyP , //pointer to allocation policy
183  int aListPageRightBits , //list page size in number of bits ( page size = 1<<aListPageRightBits )
184  int aPageVectorAllocDelta ) :
185  firstIndex (G_CONT_INDEX_NOT_VALID),
186  lastIndex(G_CONT_INDEX_NOT_VALID),
187  size(0),
188  allocPolicyP(aAllocPolicyP),
189  pages(aAllocPolicyP,aPageVectorAllocDelta),
190  pageRightbits(aListPageRightBits),
191  firstFreePage(-1){}
192 
193  ~list_content( ) { erase ( ); }
194 
195  int firstIndex;
196  int lastIndex;
197  size_t size;
198  AllocationPolicyAbstract* allocPolicyP;
199  PageVector_t pages;
200  int pageRightbits;
201  int firstFreePage;
202 
203  void erase ( )
204  {
205  empty ( );
206  pages.eraseMemory ( );
207  firstFreePage = -1;
208  }
209 
210  Node_t* getNodeFromIndex ( int aItemIndex )
211  {
212  return &( pages[ (aItemIndex>>pageRightbits) ].nodes[aItemIndex & ( (1<<pageRightbits) - 1 ) ] );
213  }
214 
215  T remove ( int aItemIndex )
216  {
217  Node_t* n_p = getNodeFromIndex ( aItemIndex );
218  T result = *n_p;
219 
220  if ( aItemIndex == firstIndex )
221  {
222  firstIndex = n_p->nextIndex;
223  }
224  else if ( n_p->prevIndex != G_CONT_INDEX_NOT_VALID )
225  {
226  Node_t* prev_node_p = getNodeFromIndex ( n_p->prevIndex );
227  prev_node_p->nextIndex = n_p->nextIndex;
228  }
229 
230  if ( aItemIndex == lastIndex )
231  {
232  lastIndex = n_p->prevIndex;
233  }
234  else if ( n_p->nextIndex != G_CONT_INDEX_NOT_VALID )
235  {
236  Node_t* next_node_p = getNodeFromIndex ( n_p->nextIndex );
237  next_node_p->prevIndex = n_p->prevIndex;
238  }
239 
240  size--;
241 
242  int current_page = ( aItemIndex >> pageRightbits );
243 
244  pages[current_page].releaseNodeUpdateFirstFree ( aItemIndex & ( (1<<pageRightbits) - 1 ) );
245 
246  if ( current_page < firstFreePage )
247  {
248  firstFreePage = current_page;
249  }
250 
251  n_p->callContentDestructor ( );
252 
253  return result;
254  }
255 
256  void empty ( )
257  {
258  int node_index = firstIndex;
259 
260  while ( node_index != G_CONT_INDEX_NOT_VALID )
261  {
262  pages[node_index >> pageRightbits].releaseNodeUpdateFirstFree ( node_index & ( ( 1<<pageRightbits) - 1 ) );
263 
264  Node_t* node_p = getNodeFromIndex ( node_index );
265 
266  node_p->callContentDestructor ( );
267 
268  node_index = node_p->nextIndex;
269  }
270 
271  //zeroes
272  firstIndex = G_CONT_INDEX_NOT_VALID;
273  lastIndex = G_CONT_INDEX_NOT_VALID;
274  size = 0;
275 
276  firstFreePage = ( pages.getSize( )>0 )?0:-1;
277  }
278 
279  void appendPage ( )
280  {
281  size_t new_size = pages.getSize()+1;
282 
283  pages.reSize(new_size);
284  pages[(int)new_size-1].nodes.instanciate ( allocPolicyP , 1<<pageRightbits );
285  }
286 
287  Node_t* getAndSetFreeNode ( const T& aT )
288  {
289  if ( firstFreePage == -1 )//not initialised
290  {
291  appendPage ( );
292  firstFreePage++;
293  }
294 
295  int current_page_index = firstFreePage;
296 
297  list_node_page<T>& free_page_ref = pages[firstFreePage];
298 
299  Node_t* n_p = free_page_ref.getFreeNodeAndMakeBusy ( );
300 
301  //search next free page
302  if ( free_page_ref.isPageBusy( ) )
303  {
304  //search fro a free page
305  for ( ++firstFreePage ; firstFreePage < (int)pages.getSize() ; firstFreePage++ )
306  {
307  if ( !pages[firstFreePage].isPageBusy ( ) )
308  {
309  break;
310  }
311  }
312 
313  if ( firstFreePage >= (int)pages.getSize ( ) )
314  {
315  appendPage ( );
316  }
317  }
318 
319  n_p->currentIndex |= ( current_page_index << pageRightbits );
320  n_p->setContent ( aT );
321 
322  return n_p;
323  }
324 
325  void pushNewNodeAfter ( const T& aItem , int aIndexBeingPrevious )
326  {
327  Node_t* new_node_p = getAndSetFreeNode ( aItem );
328  Node_t* prev_node_p = NULL;
329  Node_t* next_node_p = NULL;
330 
331  if ( aIndexBeingPrevious == G_CONT_INDEX_NOT_VALID )
332  {
333  //at tail
334  if ( lastIndex != G_CONT_INDEX_NOT_VALID )
335  {
336  prev_node_p = getNodeFromIndex ( lastIndex );
337  }
338  }
339  else
340  {
341  prev_node_p = getNodeFromIndex ( aIndexBeingPrevious );
342 
343  if ( prev_node_p->nextIndex != G_CONT_INDEX_NOT_VALID )
344  {
345  next_node_p = getNodeFromIndex ( prev_node_p->nextIndex );
346  }
347  }
348 
349  mPushNewNodeAfter ( new_node_p , prev_node_p , next_node_p );
350  }
351 
352  void pushNewNodeBefore ( const T& aItem , int aIndexBeingNext )
353  {
354  Node_t* new_node_p = getAndSetFreeNode ( aItem );
355 
356  Node_t* prev_node_p = NULL;
357  Node_t* next_node_p = NULL;
358 
359  if ( aIndexBeingNext == G_CONT_INDEX_NOT_VALID )
360  {
361  //at tail
362  if ( firstIndex != G_CONT_INDEX_NOT_VALID )
363  {
364  next_node_p = getNodeFromIndex ( firstIndex );
365  }
366  }
367  else
368  {
369  next_node_p = getNodeFromIndex ( aIndexBeingNext );
370 
371  if ( next_node_p->prevIndex != G_CONT_INDEX_NOT_VALID )
372  {
373  prev_node_p = getNodeFromIndex ( next_node_p->prevIndex );
374  }
375  }
376 
377  mPushNewNodeAfter ( new_node_p , prev_node_p , next_node_p );
378  }
379 
380 private:
381  //new_node_p->prevIndex and new_node_p->nextIndex are supposed to be initialised
382  void mPushNewNodeAfter ( Node_t* new_node_p , Node_t* before_node_p , Node_t* after_node_p )
383  {
384  if ( after_node_p )
385  {
386  after_node_p->prevIndex = new_node_p->currentIndex;
387  new_node_p->nextIndex = after_node_p->currentIndex;
388  }
389  else
390  {
391  //becomes tail
392  new_node_p->nextIndex = G_CONT_INDEX_NOT_VALID;
393  lastIndex = new_node_p->currentIndex;
394  }
395 
396  if ( before_node_p )
397  {
398  before_node_p->nextIndex = new_node_p->currentIndex;
399  new_node_p->prevIndex = before_node_p->currentIndex;
400  }
401  else
402  {
403  //becomes head
404  new_node_p->prevIndex = G_CONT_INDEX_NOT_VALID;
405  firstIndex = new_node_p->currentIndex;
406  }
407 
408  size++;
409  }
410 };
411 
412 template < class T > class list_positioner : public positioner_abstract<T>
413 {
414 public:
415  list_positioner ( list_content<T>* aLstContentP ) : lstContentP (aLstContentP) {}
416  virtual ~list_positioner ( ) {}
417 
418  virtual int first ( ) const { return lstContentP->firstIndex; }
419  virtual int last ( ) const { return lstContentP->lastIndex; }
420 
421  virtual bool isIn ( int aItemIndex ) const
422  {
423  return aItemIndex != G_CONT_INDEX_NOT_VALID;
424  }
425 
426  virtual void forward ( int& aItemIndex , GUint32_t inc ) const
427  {
428  if ( aItemIndex != G_CONT_INDEX_NOT_VALID )
429  {
430  list_node<T>* n_p = lstContentP->getNodeFromIndex(aItemIndex);
431 
432  for(GUint32_t i = 0 ; i < inc ; i++)
433  {
434  if ( n_p->nextIndex != G_CONT_INDEX_NOT_VALID )
435  {
436  n_p = lstContentP->getNodeFromIndex(n_p->nextIndex);
437  }
438  else
439  {
440  aItemIndex = G_CONT_INDEX_NOT_VALID;
441  return;
442  }
443  }
444 
445  aItemIndex = n_p->currentIndex;
446  }
447  }
448 
449  virtual T* getPtr ( int aItemIndex ) const
450  {
451  //T* temp = &((T&)*lstContentP->getNodeFromIndex(aItemIndex)); UNCOMMENT FOR DBG PURPOSES
452 
453  return &((T&)*lstContentP->getNodeFromIndex(aItemIndex));
454  }
455 
456  virtual void backward ( int& aItemIndex , GUint32_t dec ) const
457  {
458  if ( aItemIndex != G_CONT_INDEX_NOT_VALID )
459  {
460  list_node<T>* n_p = lstContentP->getNodeFromIndex(aItemIndex);
461 
462  for(GUint32_t i = 0 ; i < dec ; i++)
463  {
464  if ( n_p->prevIndex != G_CONT_INDEX_NOT_VALID )
465  {
466  n_p = lstContentP->getNodeFromIndex(n_p->prevIndex);
467  }
468  else
469  {
470  aItemIndex = G_CONT_INDEX_NOT_VALID;
471  return;
472  }
473  }
474 
475  aItemIndex = n_p->currentIndex;
476  }
477  }
478 
479  list_content<T>* lstContentP;
480 };
481 
482 #if G_AUTOPTION_ON_GCC
483 # pragma GCC diagnostic pop
484 #endif
485 
486 }//namespace priv
487 }//namespace cont
488 }//namespace g
489 
Definition: g_cont_lst_priv.h:106
Definition: g_cont_lst_priv.h:412
Definition: g_cont_AllocationPolicyAbstract.h:16
Definition: g.mthread.ThreadSimpleEvent.h:5
Definition: g_cont_lst_priv.h:25
Definition: g_cont_lst_priv.h:175
#define G_EXC_FATAL_ACTION(amessage)
Executes the fatal action ( showing an exception box, then quitting application ) specifying a fatal ...
Definition: g_exception_macros.h:64
Definition: g_cont_common.h:52
Definition: g_cont_lst_priv.h:60
Definition: g_cont_vect.h:15
Definition: g_cont_private_data_pointer.h:14
#define G_EXC_SET_CONTEXT(acontextstr)
Sets the method context.
Definition: g_exception_macros.h:52