~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_list.h

Blackhole, CSV, Pool of Threads,Single Thread, Multi Thread.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems, Inc.
 
4
 *  Copyright (C) 2008 Sun Microsystems
5
5
 *
6
6
 *  This program is free software; you can redistribute it and/or modify
7
7
 *  it under the terms of the GNU General Public License as published by
20
20
#ifndef DRIZZLED_SQL_LIST_H
21
21
#define DRIZZLED_SQL_LIST_H
22
22
 
23
 
#include <cstdlib>
24
 
#include <cassert>
 
23
 
25
24
#include <utility>
26
25
#include <algorithm>
27
 
#include <drizzled/memory/sql_alloc.h>
28
 
#include <drizzled/visibility.h>
29
 
 
30
 
namespace drizzled {
31
 
 
32
 
typedef struct st_sql_list 
33
 
{
 
26
#include <stdlib.h>
 
27
#include <drizzled/sql_alloc.h>
 
28
 
 
29
/** Struct to handle simple linked lists. */
 
30
typedef struct st_sql_list {
34
31
  uint32_t elements;
35
32
  unsigned char *first;
36
33
  unsigned char **next;
37
34
 
38
 
  inline void clear()
 
35
  st_sql_list() {}                              /* Remove gcc warning */
 
36
  inline void empty()
39
37
  {
40
38
    elements=0;
41
39
    first=0;
51
49
  inline void save_and_clear(struct st_sql_list *save)
52
50
  {
53
51
    *save= *this;
54
 
    clear();
 
52
    empty();
55
53
  }
56
54
  inline void push_front(struct st_sql_list *save)
57
55
  {
86
84
  @note We never call a destructor for instances of this class.
87
85
*/
88
86
 
89
 
struct list_node : public memory::SqlAlloc
 
87
struct list_node :public Sql_alloc
90
88
{
91
89
  list_node *next;
92
90
  void *info;
101
99
};
102
100
 
103
101
 
104
 
extern DRIZZLED_API list_node end_of_list;
 
102
extern list_node end_of_list;
105
103
 
106
 
class base_list :public memory::SqlAlloc
 
104
class base_list :public Sql_alloc
107
105
{
108
106
protected:
109
107
  list_node *first,**last;
111
109
public:
112
110
  uint32_t elements;
113
111
 
114
 
  inline void clear() { elements=0; first= &end_of_list; last=&first;}
115
 
  inline base_list() { clear(); }
 
112
  inline void empty() { elements=0; first= &end_of_list; last=&first;}
 
113
  inline base_list() { empty(); }
116
114
  /**
117
115
    This is a shallow copy constructor that implicitly passes the ownership
118
116
    from the source list to the new instance. The old instance is not
122
120
    relies on this behaviour. This logic is quite tricky: please do not use
123
121
    it in any new code.
124
122
  */
125
 
  inline base_list(const base_list &tmp) :memory::SqlAlloc()
 
123
  inline base_list(const base_list &tmp) :Sql_alloc()
126
124
  {
127
125
    elements= tmp.elements;
128
126
    first= tmp.first;
139
137
    }
140
138
    return 1;
141
139
  }
142
 
  inline bool push_back(void *info, memory::Root *mem_root)
 
140
  inline bool push_back(void *info, MEM_ROOT *mem_root)
143
141
  {
144
142
    if (((*last)=new (mem_root) list_node(info, &end_of_list)))
145
143
    {
230
228
  inline bool is_empty() { return first == &end_of_list ; }
231
229
  inline list_node *last_ref() { return &end_of_list; }
232
230
  friend class base_list_iterator;
 
231
  friend class error_list;
 
232
  friend class error_list_iterator;
233
233
 
234
234
#ifdef LIST_EXTRA_DEBUG
235
235
  /*
291
291
protected:
292
292
  base_list *list;
293
293
  list_node **el,**prev,*current;
294
 
public:
295
294
  void sublist(base_list &ls, uint32_t elm)
296
295
  {
297
296
    ls.first= *el;
298
297
    ls.last= list->last;
299
298
    ls.elements= elm;
300
299
  }
 
300
public:
301
301
  base_list_iterator()
302
302
    :list(0), el(0), prev(0), current(0)
303
303
  {}
304
304
 
305
 
  base_list_iterator(base_list &list_par, list_node** el0)
306
 
    :list(&list_par), el(el0), prev(0), current(0)
 
305
  base_list_iterator(base_list &list_par)
 
306
  { init(list_par); }
 
307
 
 
308
  inline void init(base_list &list_par)
307
309
  {
 
310
    list= &list_par;
 
311
    el= &list_par.first;
 
312
    prev= 0;
 
313
    current= 0;
308
314
  }
309
315
 
310
316
  inline void *next(void)
314
320
    el= &current->next;
315
321
    return current->info;
316
322
  }
 
323
  inline void *next_fast(void)
 
324
  {
 
325
    list_node *tmp;
 
326
    tmp= *el;
 
327
    el= &tmp->next;
 
328
    return tmp->info;
 
329
  }
 
330
  inline void rewind(void)
 
331
  {
 
332
    el= &list->first;
 
333
  }
317
334
  inline void *replace(void *element)
318
335
  {                                             // Return old element
319
336
    void *tmp=current->info;
355
372
  {
356
373
    return el == &list->last_ref()->next;
357
374
  }
 
375
  friend class error_list_iterator;
358
376
};
359
377
 
360
 
template <class T> class List_iterator;
361
 
 
362
378
template <class T> class List :public base_list
363
379
{
364
380
public:
365
 
  typedef List_iterator<T> iterator;
366
 
 
367
 
  friend class List_iterator<T>;
368
 
 
369
381
  inline List() :base_list() {}
370
382
  inline List(const List<T> &tmp) :base_list(tmp) {}
371
 
  inline List(const List<T> &tmp, memory::Root *mem_root) :
 
383
  inline List(const List<T> &tmp, MEM_ROOT *mem_root) :
372
384
    base_list(tmp, mem_root) {}
373
385
  inline bool push_back(T *a) { return base_list::push_back(a); }
374
 
  inline bool push_back(T *a, memory::Root *mem_root)
 
386
  inline bool push_back(T *a, MEM_ROOT *mem_root)
375
387
  { return base_list::push_back(a, mem_root); }
376
388
  inline bool push_front(T *a) { return base_list::push_front(a); }
377
 
  inline T* head() {return static_cast<T*>(base_list::head()); }
378
 
  inline T* pop()  {return static_cast<T*>(base_list::pop()); }
 
389
  inline T* head() {return (T*) base_list::head(); }
 
390
  inline T** head_ref() {return (T**) base_list::head_ref(); }
 
391
  inline T* pop()  {return (T*) base_list::pop(); }
379
392
  inline void concat(List<T> *list) { base_list::concat(list); }
380
393
  inline void disjoin(List<T> *list) { base_list::disjoin(list); }
381
394
  inline void prepand(List<T> *list) { base_list::prepand(list); }
387
400
      next=element->next;
388
401
      delete (T*) element->info;
389
402
    }
390
 
    clear();
391
 
  }
392
 
 
393
 
  iterator begin()
394
 
  {
395
 
    return iterator(*this, &first);
 
403
    empty();
396
404
  }
397
405
};
398
406
 
400
408
template <class T> class List_iterator :public base_list_iterator
401
409
{
402
410
public:
403
 
  List_iterator(List<T>& a, list_node** b) : base_list_iterator(a, b) {};
404
 
  List_iterator() {};
 
411
  List_iterator(List<T> &a) : base_list_iterator(a) {}
 
412
  List_iterator() : base_list_iterator() {}
 
413
  inline void init(List<T> &a) { base_list_iterator::init(a); }
405
414
  inline T* operator++(int) { return (T*) base_list_iterator::next(); }
406
415
  inline T *replace(T *a)   { return (T*) base_list_iterator::replace(a); }
407
416
  inline T *replace(List<T> &a) { return (T*) base_list_iterator::replace(a); }
 
417
  inline void rewind(void)  { base_list_iterator::rewind(); }
 
418
  inline void remove()      { base_list_iterator::remove(); }
 
419
  inline void after(T *a)   { base_list_iterator::after(a); }
408
420
  inline T** ref(void)      { return (T**) base_list_iterator::ref(); }
409
421
};
410
422
 
 
423
 
 
424
template <class T> class List_iterator_fast :public base_list_iterator
 
425
{
 
426
protected:
 
427
  inline T *replace(T *)   { return (T*) 0; }
 
428
  inline T *replace(List<T> &) { return (T*) 0; }
 
429
  inline void remove(void)  { }
 
430
  inline void after(T *a)   { }
 
431
  inline T** ref(void)      { return (T**) 0; }
 
432
 
 
433
public:
 
434
  inline List_iterator_fast(List<T> &a) : base_list_iterator(a) {}
 
435
  inline List_iterator_fast() : base_list_iterator() {}
 
436
  inline void init(List<T> &a) { base_list_iterator::init(a); }
 
437
  inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); }
 
438
  inline void rewind(void)  { base_list_iterator::rewind(); }
 
439
  void sublist(List<T> &list_arg, uint32_t el_arg)
 
440
  {
 
441
    base_list_iterator::sublist(list_arg, el_arg);
 
442
  }
 
443
};
 
444
 
 
445
 
 
446
/*
 
447
  A simple intrusive list which automaticly removes element from list
 
448
  on delete (for Session element)
 
449
*/
 
450
 
 
451
struct ilink
 
452
{
 
453
  struct ilink **prev,*next;
 
454
  static void *operator new(size_t size)
 
455
  {
 
456
    return (void*)malloc((uint32_t)size);
 
457
  }
 
458
  static void operator delete(void* ptr_arg, size_t)
 
459
  {
 
460
     free((unsigned char*)ptr_arg);
 
461
  }
 
462
 
 
463
  inline ilink()
 
464
  {
 
465
    prev=0; next=0;
 
466
  }
 
467
  inline void unlink()
 
468
  {
 
469
    /* Extra tests because element doesn't have to be linked */
 
470
    if (prev) *prev= next;
 
471
    if (next) next->prev=prev;
 
472
    prev=0 ; next=0;
 
473
  }
 
474
  virtual ~ilink() { unlink(); }                /*lint -e1740 */
 
475
};
 
476
 
 
477
 
 
478
/* Needed to be able to have an I_List of char* strings in mysqld.cc. */
 
479
 
 
480
class i_string: public ilink
 
481
{
 
482
public:
 
483
  const char* ptr;
 
484
  i_string():ptr(0) { }
 
485
  i_string(const char* s) : ptr(s) {}
 
486
};
 
487
 
 
488
/* needed for linked list of two strings for replicate-rewrite-db */
 
489
class i_string_pair: public ilink
 
490
{
 
491
public:
 
492
  const char* key;
 
493
  const char* val;
 
494
  i_string_pair():key(0),val(0) { }
 
495
  i_string_pair(const char* key_arg, const char* val_arg) :
 
496
    key(key_arg),val(val_arg) {}
 
497
};
 
498
 
 
499
 
 
500
template <class T> class I_List_iterator;
 
501
 
 
502
/*
 
503
  WARNING: copy constructor of this class does not create a usable
 
504
  copy, as its members may point at each other.
 
505
*/
 
506
 
 
507
class base_ilist
 
508
{
 
509
public:
 
510
  struct ilink *first,last;
 
511
  inline void empty() { first= &last; last.prev= &first; }
 
512
  base_ilist() { empty(); }
 
513
  inline bool is_empty() {  return first == &last; }
 
514
  inline void append(ilink *a)
 
515
  {
 
516
    first->prev= &a->next;
 
517
    a->next=first; a->prev= &first; first=a;
 
518
  }
 
519
  inline void push_back(ilink *a)
 
520
  {
 
521
    *last.prev= a;
 
522
    a->next= &last;
 
523
    a->prev= last.prev;
 
524
    last.prev= &a->next;
 
525
  }
 
526
  inline struct ilink *get()
 
527
  {
 
528
    struct ilink *first_link=first;
 
529
    if (first_link == &last)
 
530
      return 0;
 
531
    first_link->unlink();                       // Unlink from list
 
532
    return first_link;
 
533
  }
 
534
  inline struct ilink *head()
 
535
  {
 
536
    return (first != &last) ? first : 0;
 
537
  }
 
538
  friend class base_list_iterator;
 
539
};
 
540
 
 
541
 
 
542
class base_ilist_iterator
 
543
{
 
544
  base_ilist *list;
 
545
  struct ilink **el,*current;
 
546
public:
 
547
  base_ilist_iterator(base_ilist &list_par) :list(&list_par),
 
548
    el(&list_par.first),current(0) {}
 
549
  void *next(void)
 
550
  {
 
551
    /* This is coded to allow push_back() while iterating */
 
552
    current= *el;
 
553
    if (current == &list->last) return 0;
 
554
    el= &current->next;
 
555
    return current;
 
556
  }
 
557
};
 
558
 
 
559
 
 
560
template <class T>
 
561
class I_List :private base_ilist
 
562
{
 
563
public:
 
564
  I_List() :base_ilist()        {}
 
565
  inline void empty()           { base_ilist::empty(); }
 
566
  inline bool is_empty()        { return base_ilist::is_empty(); }
 
567
  inline void append(T* a)      { base_ilist::append(a); }
 
568
  inline void push_back(T* a)   { base_ilist::push_back(a); }
 
569
  inline T* get()               { return (T*) base_ilist::get(); }
 
570
  inline T* head()              { return (T*) base_ilist::head(); }
 
571
#ifndef _lint
 
572
  friend class I_List_iterator<T>;
 
573
#endif
 
574
};
 
575
 
 
576
 
 
577
template <class T> class I_List_iterator :public base_ilist_iterator
 
578
{
 
579
public:
 
580
  I_List_iterator(I_List<T> &a) : base_ilist_iterator(a) {}
 
581
  inline T* operator++(int) { return (T*) base_ilist_iterator::next(); }
 
582
};
 
583
 
411
584
/**
412
585
  Make a deep copy of each list element.
413
586
 
424
597
*/
425
598
 
426
599
template <typename T>
427
 
void list_copy_and_replace_each_value(List<T> &list, memory::Root *mem_root)
 
600
inline
 
601
void
 
602
list_copy_and_replace_each_value(List<T> &list, MEM_ROOT *mem_root)
428
603
{
429
604
  /* Make a deep copy of each element */
430
 
  typename List<T>::iterator it(list.begin());
 
605
  List_iterator<T> it(list);
431
606
  T *el;
432
607
  while ((el= it++))
433
608
    it.replace(el->clone(mem_root));
434
609
}
435
610
 
436
 
} /* namespace drizzled */
437
611
 
438
612
#endif /* DRIZZLED_SQL_LIST_H */