Zero  0.1.0
w_list.h
Go to the documentation of this file.
1 /* -*- mode:C++; c-basic-offset:4 -*-
2  Shore-MT -- Multi-threaded port of the SHORE storage manager
3 
4  Copyright (c) 2007-2009
5  Data Intensive Applications and Systems Labaratory (DIAS)
6  Ecole Polytechnique Federale de Lausanne
7 
8  All Rights Reserved.
9 
10  Permission to use, copy, modify and distribute this software and
11  its documentation is hereby granted, provided that both the
12  copyright notice and this permission notice appear in all copies of
13  the software, derivative works or modified versions, and any
14  portions thereof, and that both notices appear in supporting
15  documentation.
16 
17  This code is distributed in the hope that it will be useful, but
18  WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS
20  DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
21  RESULTING FROM THE USE OF THIS SOFTWARE.
22 */
23 
24 /*<std-header orig-src='shore' incl-file-exclusion='W_LIST_H'>
25 
26  $Id: w_list.h,v 1.56 2010/07/26 23:37:09 nhall Exp $
27 
28 SHORE -- Scalable Heterogeneous Object REpository
29 
30 Copyright (c) 1994-99 Computer Sciences Department, University of
31  Wisconsin -- Madison
32 All Rights Reserved.
33 
34 Permission to use, copy, modify and distribute this software and its
35 documentation is hereby granted, provided that both the copyright
36 notice and this permission notice appear in all copies of the
37 software, derivative works or modified versions, and any portions
38 thereof, and that both notices appear in supporting documentation.
39 
40 THE AUTHORS AND THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY
41 OF WISCONSIN - MADISON ALLOW FREE USE OF THIS SOFTWARE IN ITS
42 "AS IS" CONDITION, AND THEY DISCLAIM ANY LIABILITY OF ANY KIND
43 FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
44 
45 This software was developed with support by the Advanced Research
46 Project Agency, ARPA order number 018 (formerly 8230), monitored by
47 the U.S. Army Research Laboratory under contract DAAB07-91-C-Q518.
48 Further funding for this work was provided by DARPA through
49 Rome Research Laboratory Contract No. F30602-97-2-0247.
50 
51 */
52 
53 #ifndef __W_LIST_H
54 #define __W_LIST_H
55 
56 #include "w_defines.h"
57 
58 /* -- do not edit anything above this line -- </std-header>*/
59 
60 #ifndef __W_BASE_H
61 #include "w_base.h"
62 #endif // __W_BASE_H
63 
64 #include <iostream>
65 
72 class w_list_base_t;
73 
74 template<class T, class LOCK> class w_list_t;
75 
76 template<class T, class LOCK> class w_list_i;
77 
78 template<class T, class LOCK, class K> class w_hash_t;
79 
91 
92 unsafe_list_dummy_lock_t* const unsafe_nolock = nullptr; // instantiate with this
93 
94 
104 class w_link_t {
105 public:
106  w_link_t();
107 
108  ~w_link_t();
109 
110  w_link_t(const w_link_t&);
111 
112  w_link_t& operator=(const w_link_t&);
113 
116  void attach(w_link_t* prev_link);
117 
118  void check() {
119  w_assert9(_prev == this && _next == this); // not in a list
120  }
121 
123  w_link_t* detach();
124 
125  w_list_base_t* member_of() const;
126 
127  w_link_t* next() const;
128 
129  w_link_t* prev() const;
130 
131 private:
133 
135 
137 
138  friend class w_list_base_t;
139 };
140 
144 class w_list_base_t : public w_vbase_t {
145 
146 public:
147  bool is_empty() const;
148 
149  uint32_t num_members() const;
150 
151  void dump();
152 
153 protected:
154  w_list_base_t();
155 
156  w_list_base_t(uint32_t offset);
157 
158  ~w_list_base_t();
159 
160  void set_offset(uint32_t offset);
161 
163 
164  uint32_t _cnt;
165 
166  uint32_t _adj;
167 
168 private:
169  w_list_base_t(w_list_base_t&); // disabled
170 
171  w_list_base_t& operator=(w_list_base_t&);
172 
173  friend class w_link_t;
174 };
175 
177  _list(0) {
178  _next = this;
179  _prev = this;
180  /* empty body */
181 }
182 
184  w_assert1(_next == this && _prev == this && _list == 0);
185 }
186 
187 inline w_link_t::w_link_t(const w_link_t&) :
188  _list(0) {
189  _next = _prev = this;
190 }
191 
193  _list = 0;
194  return *(_next = _prev = this);
195 }
196 
198  return _list;
199 }
200 
201 inline w_link_t* w_link_t::prev() const {
202  return _prev;
203 }
204 
205 inline w_link_t* w_link_t::next() const {
206  return _next;
207 }
208 
210  _cnt(0),
211  _adj(uint4_max) { // _adj must be set by a later call
212 // to set_offset(). We init _adj with a large number to detect
213 // errors
214  _tail._list = 0;
215  w_assert9(_tail._next == &_tail && _tail._prev == &_tail);
216 }
217 
218 inline w_list_base_t::w_list_base_t(uint32_t offset) :
219  _cnt(0),
220  _adj(offset) {
221  _tail._list = this;
222  w_assert9(_tail._next == &_tail && _tail._prev == &_tail);
223 }
224 
225 inline void w_list_base_t::set_offset(uint32_t offset) {
226  w_assert9(_cnt == 0 && _adj == uint4_max && _tail._list == 0);
227  _tail._list = this;
228  _adj = offset;
229 }
230 
232  _tail._list = 0;
233  w_assert9(_cnt == 0);
234 }
235 
236 inline bool w_list_base_t::is_empty() const {
237  return _cnt == 0;
238 }
239 
240 inline uint32_t w_list_base_t::num_members() const {
241  return _cnt;
242 }
243 
244 template<class T, class L> class w_list_t;
245 
246 BIND_FRIEND_OPERATOR_PART_1(T, L, w_list_t<T, L>)
247 
248 
257 template<class T, class LOCK>
258 class w_list_t : public w_list_base_t {
259 protected:
263  w_assert3(t);
264  return CAST(w_link_t*, CAST(char * , t) + _adj);
265  }
266 
268  const w_link_t* link_of(const T* t) const {
269  w_assert3(t);
270  return CAST(w_link_t*, CAST(char * , t) + _adj);
271  }
272 
274  T* base_of(w_link_t* p) const {
275  w_assert3(p);
276  return CAST(T*, CAST(char * , p) - _adj);
277  }
278 
280  const T* base_of(const w_link_t* p) const {
281  w_assert3(p);
282  return CAST(T*, CAST(char * , p) - _adj);
283  }
284 
285 private:
286  LOCK* lock;
287 
288 public:
289 
303  w_list_t(uint32_t link_offset, LOCK* l) :
304  w_list_base_t(link_offset),
305  lock(l) {
306 #ifdef __GNUC__
307 #else
308  w_assert2(link_offset + sizeof(w_link_t) <= sizeof(T));
309 #endif
310  }
311 
312 public:
315  // This is used by w_hash_t and the lock manager's list of lock heads
316  w_list_t() : lock(nullptr) {}
317 
318 public:
319 
321 
326  void set_offset(uint32_t link_offset) {
327  w_list_base_t::set_offset(link_offset);
328  }
329 
332  virtual void put_in_order(T* t) {
334  }
335 
336  // a set of consistent and intuitive names
337  // TODO: replace throughout the SM
339  return push(t);
340  }
341 
343  return append(t);
344  }
345 
346  T* front() {
347  return top();
348  }
349 
350  T* back() {
351  return bottom();
352  }
353 
355  return pop();
356  }
357 
358  T* pop_back() {
359  return chop();
360  }
361 
364  link_of(t)->attach(&_tail);
365  return *this;
366  }
367 
370  link_of(t)->attach(_tail.prev());
371  return *this;
372  }
373 
374  // Insert t after pos (for log buffer)
375  void insert_after(T* t, T* pos) {
376  link_of(t)->attach(link_of(pos));
377  }
378 
379  // Insert t before pos (for log buffer)
380  void insert_before(T* t, T* pos) {
381  link_of(t)->attach(link_of(pos)->prev());
382  }
383 
385  T* pop() {
386  return _cnt ? base_of(_tail.next()->detach()) : 0;
387  }
388 
390  T* chop() {
391  return _cnt ? base_of(_tail.prev()->detach()) : 0;
392  }
393 
394  // Remove t (for log buffer)
395  void remove(T* t) {
396  link_of(t)->detach();
397  }
398 
400  T* top() {
401  return _cnt ? base_of(_tail.next()) : 0;
402  }
403 
405  T* bottom() {
406  return _cnt ? base_of(_tail.prev()) : 0;
407  }
408 
410  T* next(w_link_t* p) {
411  w_assert1(p->member_of() == this);
412  return base_of(p->next());
413  }
414 
416  T* prev(w_link_t* p) {
417  w_assert1(p->member_of() == this);
418  return base_of(p->prev());
419  }
420 
421  // Get next (for log buffer)
422  T* next_of(T* t) {
423  w_link_t* p = link_of(t);
424  w_assert1(p->member_of() == this);
425  if (p->next() != &_tail) {
426  return base_of(p->next());
427  } else {
428  return nullptr;
429  }
430  }
431 
432  // Get prev (for log buffer)
433  T* prev_of(T* t) {
434  w_link_t* p = link_of(t);
435  w_assert1(p->member_of() == this);
436  if (p->prev() != &_tail) {
437  return base_of(p->prev());
438  } else {
439  return nullptr;
440  }
441  }
442 
443  // Get count
444  uint32_t count() {
445  return this->_cnt;
446  }
447 
449  friend ostream& operator<<BIND_FRIEND_OPERATOR_PART_2(T, LOCK)(
450  ostream& o,
452 
453 private:
454  // disabled
455  w_list_t(const w_list_t<T, LOCK>& x);
456 
458 
459  friend class w_list_i<T, LOCK>;
460 };
461 
463 #define W_LIST_ARG(class, member) w_offsetof(class,member)
464 
491 template<class T, class LOCK>
492 class w_list_i : public w_base_t {
493 public:
498  : _list(0),
499  _next(0),
500  _curr(0),
501  _backwards(false) {};
502 
505  w_list_i(const w_list_t<T, LOCK>& l, bool backwards = false)
506  : _list(&l),
507  _curr(0),
508  _backwards(backwards) {
509  _next = (backwards ? l._tail.prev() : l._tail.next());
510  }
511 
512  virtual ~w_list_i() {};
513 
516  void reset(const w_list_t<T, LOCK>& l, bool backwards = false) {
517  _list = &l;
518  _curr = 0;
519  _backwards = backwards;
520  _next = (_backwards ? l._tail.prev() : l._tail.next());
521  }
522 
528  T* next() {
529  if (_next) {
530  _curr = (_next == &(_list->_tail)) ? 0 : _list->base_of(_next);
531  _next = (_backwards ? _next->prev() : _next->next());
532  // Note: once we ever had anything in the list, next() will
533  // be non-null. We will return NULL when _curr hits the tail.
534  // _next can be null only if we started with an empty list.
535  w_assert1(_next != nullptr);
536  }
537  return _curr;
538  }
539 
546  T* curr() const {
547  return _curr;
548  }
549 
550 protected:
552 
553 private:
555 
557 
559 
560  // disabled
562 
564 };
565 
571 template<class T, class LOCK>
572 class w_list_const_i : public w_list_i<T, LOCK> {
573 public:
575 
577  w_list_i<T, LOCK>(*(w_list_t<T, LOCK>*)(&l)) {};
578 
580 
581  void reset(const w_list_t<T, LOCK>& l) {
583  }
584 
585  const T* next() {
586  return w_list_i<T, LOCK>::next();
587  }
588 
589  const T* curr() const {
590  return w_list_i<T, LOCK>::curr();
591  }
592 
593 private:
594  // disabled
596 
598 };
599 
605 template<class T, class LOCK, class K>
606 class w_keyed_list_t : public w_list_t<T, LOCK> {
607 public:
608  T* first() {
609  return w_list_t<T, LOCK>::top();
610  }
611 
612  T* last() {
613  return w_list_t<T, LOCK>::bottom();
614  }
615 
616  virtual T* search(const K& k);
617 
618  w_keyed_list_t(LOCK* lock);
619 
620  w_keyed_list_t(uint32_t key_offset, uint32_t link_offset,
621  LOCK* lock);
622 
624 
625  void set_offset(uint32_t key_offset, uint32_t link_offset);
626 
627 protected:
628  const K& key_of(const T& t) {
629  return *(K*)(((const char*)&t) + _key_offset);
630  }
631 
634 
635 private:
636  // disabled
638 
639  uint32_t _key_offset;
640 
641  // disabled
642  w_list_t<T, LOCK>& push(T* t);
643 
644  w_list_t<T, LOCK>& append(T* t);
645 
646  T* chop();
647 
648  T* top();
649 
650  T* bottom();
651 };
652 
653 #define W_KEYED_ARG(class, key, link) \
654  W_LIST_ARG(class,key), W_LIST_ARG(class,link)
655 
662 template<class T, class LOCK, class K>
663 class w_ascend_list_t : public w_keyed_list_t<T, LOCK, K> {
666 
667 public:
668  w_ascend_list_t(uint32_t key_offset, uint32_t link_offset,
669  LOCK* lock) :
670  w_keyed_list_t<T, LOCK, K>(key_offset, link_offset, lock) {};
671 
673 
674  virtual T* search(const K& k);
675 
676  virtual void put_in_order(T* t);
677 
678 private:
679  w_ascend_list_t(const w_ascend_list_t<T, LOCK, K>&); // disabled
680 };
681 
688 template<class T, class LOCK, class K>
689 class w_descend_list_t : public w_keyed_list_t<T, LOCK, K> {
692 
693 public:
694  w_descend_list_t(uint32_t key_offset, uint32_t link_offset,
695  LOCK* l) :
696  w_keyed_list_t<T, LOCK, K>(key_offset, link_offset, l) {};
697 
699 
700  virtual T* search(const K& k);
701 
702  virtual void put_in_order(T* t);
703 
704 private:
706 };
707 
708 template<class T, class LOCK>
709 ostream& operator<<(ostream& o, const w_list_t<T, LOCK>& l) {
710  const w_link_t* p = l._tail.next();
711 
712  cout << "cnt = " << l.num_members();
713 
714  while (p != &l._tail) {
715  const T* t = l.base_of(p);
716  if (!(o << endl << '\t' << *t)) {
717  break;
718  }
719  p = p->next();
720  }
721  return o;
722 }
723 
724 template<class T, class LOCK, class K>
726  uint32_t key_offset,
727  uint32_t link_offset,
728  LOCK* lock
729  )
730  : w_list_t<T, LOCK>(link_offset, lock),
731  _key_offset(key_offset) {
732 #ifdef __GNUC__
733 #else
734  w_assert9(key_offset + sizeof(K) <= sizeof(T));
735 #endif
736 }
737 
738 template<class T, class LOCK, class K>
740  w_list_t<T, LOCK>(0, l),
741  _key_offset(0) {}
742 
743 template<class T, class LOCK, class K>
744 void
746  uint32_t link_offset) {
747  w_assert3(_key_offset == 0);
748  w_list_t<T, LOCK>::set_offset(link_offset);
749  _key_offset = key_offset;
750 }
751 
752 template<class T, class LOCK, class K>
753 T*
755  w_link_t* p;
756  for (p = _tail.next();
757  p != &_tail && (key_of(*base_of(p)) != k);
758  p = p->next()) {}
759  return (p && (p != &_tail)) ? base_of(p) : 0;
760 }
761 
762 template<class T, class LOCK, class K>
763 T*
765  w_link_t* p;
766  for (p = _tail.next();
767  p != &_tail && (this->key_of(*base_of(p)) < k);
768  p = p->next()) {}
769 
770  return p ? base_of(p) : 0;
771 }
772 
773 template<class T, class LOCK, class K>
774 void
776  w_link_t* p;
777  for (p = _tail.next();
778  p != &_tail && (this->key_of(*base_of(p)) <= this->key_of(*t));
779  p = p->next()) {}
780 
781  if (p) {
782  this->link_of(t)->attach(p->prev());
783  } else {
784  this->link_of(t)->attach(_tail.prev());
785  }
786 }
787 
788 template<class T, class LOCK, class K>
789 T*
791  w_link_t* p;
792  for (p = _tail.next();
793  p != &_tail && (this->key_of(*base_of(p)) > k);
794  p = p->next()) {}
795 
796  return p ? base_of(p) : 0;
797 }
798 
799 template<class T, class LOCK, class K>
800 void
802  w_link_t* p;
803  for (p = _tail.next();
804  p != &_tail && (this->key_of(*base_of(p)) >= this->key_of(*t));
805  p = p->next()) {}
806 
807  if (p) {
808  this->link_of(t)->attach(p->prev());
809  } else {
810  this->link_of(t)->attach(_tail.prev());
811  }
812 }
813 /*<std-footer incl-file-exclusion='W_LIST_H'> -- do not edit anything below this line -- */
814 
815 #endif // __W_LIST_H /*</std-footer>*/
uint32_t _key_offset
Definition: w_list.h:639
Class that adds virtual destructor to w_base_t.
Definition: w_base.h:466
void insert_before(T *t, T *pos)
Definition: w_list.h:380
uint32_t num_members() const
Definition: w_list.h:240
const T * next()
Definition: w_list.h:585
~w_list_t()
Definition: w_list.h:320
T * next(w_link_t *p)
Get next.
Definition: w_list.h:410
uint32_t _adj
Definition: w_list.h:166
#define w_assert1(x)
Level 1 should not add significant extra time.
Definition: w_base.h:198
Const iterator for a list.
Definition: w_list.h:572
void set_offset(uint32_t offset)
Definition: w_list.h:225
static const uint32_t uint4_max
Definition: w_base.h:316
void set_offset(uint32_t link_offset)
Definition: w_list.h:326
~w_keyed_list_t()
Definition: w_list.h:623
T * pop()
Remove.
Definition: w_list.h:385
T * first()
Definition: w_list.h:608
w_list_base_t & operator=(w_list_base_t &)
Definition: w_list.h:78
#define w_assert3(x)
Level 3 definitely adds significant time.
Definition: w_base.h:214
T * top()
Get first but don&#39;t remove.
Definition: w_list.h:400
List maintained in ascending order.
Definition: w_list.h:663
T * pop_front()
Definition: w_list.h:354
#define w_assert2(x)
Level 2 adds some time.
Definition: w_base.h:206
const K & key_of(const T &t)
Definition: w_list.h:628
w_list_const_i()
Definition: w_list.h:574
T * bottom()
Get last but don&#39;t remove.
Definition: w_list.h:405
w_list_t< T, LOCK > & append(T *t)
Insert at tail.
Definition: w_list.h:369
T * base_of(w_link_t *p) const
return object of which the given link is a member
Definition: w_list.h:274
Definition: w_base.h:266
w_keyed_list_t(LOCK *lock)
Definition: w_list.h:739
List maintained in descending order.
Definition: w_list.h:689
w_list_i()
Definition: w_list.h:497
w_list_t< T, LOCK > & push(T *t)
Insert.
Definition: w_list.h:363
Base class for sorted lists.
Definition: w_list.h:606
unsafe_list_dummy_lock_t *const unsafe_nolock
Definition: w_list.h:92
virtual T * search(const K &k)
Definition: w_list.h:764
T * last()
Definition: w_list.h:612
Iterator for a list.
Definition: w_list.h:76
T * front()
Definition: w_list.h:346
~w_list_const_i()
Definition: w_list.h:579
void reset(const w_list_t< T, LOCK > &l, bool backwards=false)
Definition: w_list.h:516
virtual void put_in_order(T *t)
Definition: w_list.h:332
virtual void put_in_order(T *t)
Definition: w_list.h:775
w_list_t< T, LOCK > & push_back(T *t)
Definition: w_list.h:342
w_link_t * link_of(T *t)
Definition: w_list.h:262
void insert_after(T *t, T *pos)
Definition: w_list.h:375
const w_list_t< T, LOCK > * _list
Definition: w_list.h:551
uint32_t count()
Definition: w_list.h:444
T * prev(w_link_t *p)
Get prev.
Definition: w_list.h:416
bool is_empty() const
Definition: w_list.h:236
You can instantiate unsafe lists by using this type.
Definition: w_list.h:90
const w_link_t * link_of(const T *t) const
const version of the above
Definition: w_list.h:268
virtual void put_in_order(T *t)
Definition: w_list.h:801
w_descend_list_t(uint32_t key_offset, uint32_t link_offset, LOCK *l)
Definition: w_list.h:694
~w_ascend_list_t()
Definition: w_list.h:672
LOCK * lock
Definition: w_list.h:286
Templated list of type T.
Definition: w_list.h:74
virtual ~w_list_i()
Definition: w_list.h:512
T * next()
Definition: w_list.h:528
friend ostream const w_list_t< T, LOCK > & l
Definition: w_list.h:451
T * prev_of(T *t)
Definition: w_list.h:433
uint32_t _cnt
Definition: w_list.h:164
w_list_t< T, LOCK > & push_front(T *t)
Definition: w_list.h:338
~w_descend_list_t()
Definition: w_list.h:698
T * _curr
Definition: w_list.h:556
#define w_assert9(x)
changing an assert to an assert9 turns it off.
Definition: w_base.h:243
bool _backwards
Definition: w_list.h:558
T * next_of(T *t)
Definition: w_list.h:422
T * back()
Definition: w_list.h:350
~w_list_base_t()
Definition: w_list.h:231
void reset(const w_list_t< T, LOCK > &l)
Definition: w_list.h:581
w_list_i(const w_list_t< T, LOCK > &l, bool backwards=false)
Definition: w_list.h:505
virtual T * search(const K &k)
Definition: w_list.h:790
w_link_t * _next
Definition: w_list.h:554
w_list_const_i(const w_list_t< T, LOCK > &l)
Definition: w_list.h:576
w_ascend_list_t(uint32_t key_offset, uint32_t link_offset, LOCK *lock)
Definition: w_list.h:668
w_list_t(uint32_t link_offset, LOCK *l)
Linked list constructor.
Definition: w_list.h:303
w_link_t _tail
Definition: w_list.h:162
T * chop()
Remove from rear.
Definition: w_list.h:390
void set_offset(uint32_t key_offset, uint32_t link_offset)
Definition: w_list.h:745
w_list_t()
Definition: w_list.h:316
const T * base_of(const w_link_t *p) const
const version of the above
Definition: w_list.h:280
const T * curr() const
Definition: w_list.h:589
#define T
Definition: w_okvl_inl.h:45
w_list_base_t()
Definition: w_list.h:209
T * pop_back()
Definition: w_list.h:358
T * curr() const
Return the current item in the list.
Definition: w_list.h:546
virtual T * search(const K &k)
Definition: w_list.h:754
#define CAST(t, o)
Definition: w_base.h:88
Base class for various list classes.
Definition: w_list.h:144